authorgravatar for luuk@degram.devLuuk de Gram <luuk@degram.dev> 2022-03-07 21:58:40+01:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2022-03-09 13:53:10-07:00
logd01bfa032dd21a2464ca6be850053f68387acea8
tree3b02c4a430db71e384f98bb3a9b6bb0fbbcfb241
parent684b81f366566353aeca18a7431f8df3304f439b

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).

3 files changed, 37 insertions(+), 17 deletions(-)

src/arch/wasm/CodeGen.zig+34-17
......@@ -1220,6 +1220,7 @@ fn genInst(self: *Self, inst: Air.Inst.Index) !WValue {
12201220 .cond_br => self.airCondBr(inst),
12211221 .dbg_stmt => WValue.none,
12221222 .intcast => self.airIntcast(inst),
1223 .fptrunc => self.airFptrunc(inst),
12231224 .fpext => self.airFpext(inst),
12241225 .float_to_int => self.airFloatToInt(inst),
12251226 .get_union_tag => self.airGetUnionTag(inst),
......@@ -1300,7 +1301,6 @@ fn genInst(self: *Self, inst: Air.Inst.Index) !WValue {
13001301 .bit_reverse,
13011302 .is_err_ptr,
13021303 .is_non_err_ptr,
1303 .fptrunc,
13041304 .unwrap_errunion_payload_ptr,
13051305 .unwrap_errunion_err_ptr,
13061306
......@@ -3189,23 +3189,40 @@ fn airFpext(self: *Self, inst: Air.Inst.Index) InnerError!WValue {
31893189 if (self.liveness.isUnused(inst)) return WValue{ .none = {} };
31903190
31913191 const ty_op = self.air.instructions.items(.data)[inst].ty_op;
3192 const ty = self.air.typeOfIndex(inst);
3193 const wanted_bits = ty.floatBits(self.target);
3194 const have_bits = self.air.typeOf(ty_op.operand).floatBits(self.target);
3192 const dest_ty = self.air.typeOfIndex(inst);
3193 const dest_bits = dest_ty.floatBits(self.target);
3194 const src_bits = self.air.typeOf(ty_op.operand).floatBits(self.target);
31953195 const operand = try self.resolveInst(ty_op.operand);
31963196
3197 const have = toWasmBits(have_bits) orelse {
3198 return self.fail("TODO: Implement 'fpext' for floats with bitsize: {d}", .{have_bits});
3199 };
3200 const wanted = toWasmBits(wanted_bits) orelse {
3201 return self.fail("TODO: Implement 'fpext' for floats with bitsize: {d}", .{wanted_bits});
3202 };
3203 if (have == wanted) return operand;
3197 if (dest_bits == 64 and src_bits == 32) {
3198 const result = try self.allocLocal(dest_ty);
3199 try self.emitWValue(operand);
3200 try self.addTag(.f64_promote_f32);
3201 try self.addLabel(.local_set, result.local);
3202 return result;
3203 } else {
3204 // TODO: Emit a call to compiler-rt to extend the float. e.g. __extendhfsf2
3205 return self.fail("TODO: Implement 'fpext' for floats with bitsize: {d}", .{dest_bits});
3206 }
3207}
32043208
3205 assert(have < wanted);
3206 const result = try self.allocLocal(ty);
3207 try self.emitWValue(operand);
3208 try self.addTag(.f64_promote_f32);
3209 try self.addLabel(.local_set, result.local);
3210 return result;
3209fn airFptrunc(self: *Self, inst: Air.Inst.Index) InnerError!WValue {
3210 if (self.liveness.isUnused(inst)) return WValue{ .none = {} };
3211
3212 const ty_op = self.air.instructions.items(.data)[inst].ty_op;
3213 const dest_ty = self.air.typeOfIndex(inst);
3214 const dest_bits = dest_ty.floatBits(self.target);
3215 const src_bits = self.air.typeOf(ty_op.operand).floatBits(self.target);
3216 const operand = try self.resolveInst(ty_op.operand);
3217
3218 if (dest_bits == 32 and src_bits == 64) {
3219 const result = try self.allocLocal(dest_ty);
3220 try self.emitWValue(operand);
3221 try self.addTag(.f32_demote_f64);
3222 try self.addLabel(.local_set, result.local);
3223 return result;
3224 } else {
3225 // TODO: Emit a call to compiler-rt to trunc the float. e.g. __truncdfhf2
3226 return self.fail("TODO: Implement 'fptrunc' for floats with bitsize: {d}", .{dest_bits});
3227 }
32113228}
src/arch/wasm/Emit.zig+1
......@@ -161,6 +161,7 @@ pub fn emitMir(emit: *Emit) InnerError!void {
161161 .i64_extend8_s => try emit.emitTag(tag),
162162 .i64_extend16_s => try emit.emitTag(tag),
163163 .i64_extend32_s => try emit.emitTag(tag),
164 .f32_demote_f64 => try emit.emitTag(tag),
164165 .f64_promote_f32 => try emit.emitTag(tag),
165166 .i32_reinterpret_f32 => try emit.emitTag(tag),
166167 .i64_reinterpret_f64 => try emit.emitTag(tag),
src/arch/wasm/Mir.zig+2
......@@ -391,6 +391,8 @@ pub const Inst = struct {
391391 /// Uses `tag`
392392 i64_trunc_f64_u = 0xB1,
393393 /// Uses `tag`
394 f32_demote_f64 = 0xB6,
395 /// Uses `tag`
394396 f64_promote_f32 = 0xBB,
395397 /// Uses `tag`
396398 i32_reinterpret_f32 = 0xBC,