aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorLuuk de Gram <luuk@degram.dev>2022-03-07 21:58:40 +0100
committerAndrew Kelley <andrew@ziglang.org>2022-03-09 13:53:10 -0700
commitd01bfa032dd21a2464ca6be850053f68387acea8 (patch)
tree3b02c4a430db71e384f98bb3a9b6bb0fbbcfb241 /src
parent684b81f366566353aeca18a7431f8df3304f439b (diff)
downloadzig-d01bfa032dd21a2464ca6be850053f68387acea8.tar.gz
zig-d01bfa032dd21a2464ca6be850053f68387acea8.zip
wasm: Preliminary `fptrunc` support
This implements the initial fptrunc instruction. For all other floating-point truncating, a call to compiler-rt is required. (This also updates fpext to emit the same error).
Diffstat (limited to 'src')
-rw-r--r--src/arch/wasm/CodeGen.zig51
-rw-r--r--src/arch/wasm/Emit.zig1
-rw-r--r--src/arch/wasm/Mir.zig2
3 files changed, 37 insertions, 17 deletions
diff --git a/src/arch/wasm/CodeGen.zig b/src/arch/wasm/CodeGen.zig
index 8d00aec2fa..ce05a9652d 100644
--- a/src/arch/wasm/CodeGen.zig
+++ b/src/arch/wasm/CodeGen.zig
@@ -1220,6 +1220,7 @@ fn genInst(self: *Self, inst: Air.Inst.Index) !WValue {
.cond_br => self.airCondBr(inst),
.dbg_stmt => WValue.none,
.intcast => self.airIntcast(inst),
+ .fptrunc => self.airFptrunc(inst),
.fpext => self.airFpext(inst),
.float_to_int => self.airFloatToInt(inst),
.get_union_tag => self.airGetUnionTag(inst),
@@ -1300,7 +1301,6 @@ fn genInst(self: *Self, inst: Air.Inst.Index) !WValue {
.bit_reverse,
.is_err_ptr,
.is_non_err_ptr,
- .fptrunc,
.unwrap_errunion_payload_ptr,
.unwrap_errunion_err_ptr,
@@ -3189,23 +3189,40 @@ fn airFpext(self: *Self, inst: Air.Inst.Index) InnerError!WValue {
if (self.liveness.isUnused(inst)) return WValue{ .none = {} };
const ty_op = self.air.instructions.items(.data)[inst].ty_op;
- const ty = self.air.typeOfIndex(inst);
- const wanted_bits = ty.floatBits(self.target);
- const have_bits = self.air.typeOf(ty_op.operand).floatBits(self.target);
+ const dest_ty = self.air.typeOfIndex(inst);
+ const dest_bits = dest_ty.floatBits(self.target);
+ const src_bits = self.air.typeOf(ty_op.operand).floatBits(self.target);
const operand = try self.resolveInst(ty_op.operand);
- const have = toWasmBits(have_bits) orelse {
- return self.fail("TODO: Implement 'fpext' for floats with bitsize: {d}", .{have_bits});
- };
- const wanted = toWasmBits(wanted_bits) orelse {
- return self.fail("TODO: Implement 'fpext' for floats with bitsize: {d}", .{wanted_bits});
- };
- if (have == wanted) return operand;
+ if (dest_bits == 64 and src_bits == 32) {
+ const result = try self.allocLocal(dest_ty);
+ try self.emitWValue(operand);
+ try self.addTag(.f64_promote_f32);
+ try self.addLabel(.local_set, result.local);
+ return result;
+ } else {
+ // TODO: Emit a call to compiler-rt to extend the float. e.g. __extendhfsf2
+ return self.fail("TODO: Implement 'fpext' for floats with bitsize: {d}", .{dest_bits});
+ }
+}
- assert(have < wanted);
- const result = try self.allocLocal(ty);
- try self.emitWValue(operand);
- try self.addTag(.f64_promote_f32);
- try self.addLabel(.local_set, result.local);
- return result;
+fn airFptrunc(self: *Self, inst: Air.Inst.Index) InnerError!WValue {
+ if (self.liveness.isUnused(inst)) return WValue{ .none = {} };
+
+ const ty_op = self.air.instructions.items(.data)[inst].ty_op;
+ const dest_ty = self.air.typeOfIndex(inst);
+ const dest_bits = dest_ty.floatBits(self.target);
+ const src_bits = self.air.typeOf(ty_op.operand).floatBits(self.target);
+ const operand = try self.resolveInst(ty_op.operand);
+
+ if (dest_bits == 32 and src_bits == 64) {
+ const result = try self.allocLocal(dest_ty);
+ try self.emitWValue(operand);
+ try self.addTag(.f32_demote_f64);
+ try self.addLabel(.local_set, result.local);
+ return result;
+ } else {
+ // TODO: Emit a call to compiler-rt to trunc the float. e.g. __truncdfhf2
+ return self.fail("TODO: Implement 'fptrunc' for floats with bitsize: {d}", .{dest_bits});
+ }
}
diff --git a/src/arch/wasm/Emit.zig b/src/arch/wasm/Emit.zig
index ead5c22bf4..d8539a5959 100644
--- a/src/arch/wasm/Emit.zig
+++ b/src/arch/wasm/Emit.zig
@@ -161,6 +161,7 @@ pub fn emitMir(emit: *Emit) InnerError!void {
.i64_extend8_s => try emit.emitTag(tag),
.i64_extend16_s => try emit.emitTag(tag),
.i64_extend32_s => try emit.emitTag(tag),
+ .f32_demote_f64 => try emit.emitTag(tag),
.f64_promote_f32 => try emit.emitTag(tag),
.i32_reinterpret_f32 => try emit.emitTag(tag),
.i64_reinterpret_f64 => try emit.emitTag(tag),
diff --git a/src/arch/wasm/Mir.zig b/src/arch/wasm/Mir.zig
index 857b8ae8c9..d5d45142de 100644
--- a/src/arch/wasm/Mir.zig
+++ b/src/arch/wasm/Mir.zig
@@ -391,6 +391,8 @@ pub const Inst = struct {
/// Uses `tag`
i64_trunc_f64_u = 0xB1,
/// Uses `tag`
+ f32_demote_f64 = 0xB6,
+ /// Uses `tag`
f64_promote_f32 = 0xBB,
/// Uses `tag`
i32_reinterpret_f32 = 0xBC,