diff options
| author | Luuk de Gram <luuk@degram.dev> | 2022-03-07 21:58:40 +0100 |
|---|---|---|
| committer | Andrew Kelley <andrew@ziglang.org> | 2022-03-09 13:53:10 -0700 |
| commit | d01bfa032dd21a2464ca6be850053f68387acea8 (patch) | |
| tree | 3b02c4a430db71e384f98bb3a9b6bb0fbbcfb241 /src | |
| parent | 684b81f366566353aeca18a7431f8df3304f439b (diff) | |
| download | zig-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.zig | 51 | ||||
| -rw-r--r-- | src/arch/wasm/Emit.zig | 1 | ||||
| -rw-r--r-- | src/arch/wasm/Mir.zig | 2 |
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, |
