diff --git a/lib/std/wasm.zig b/lib/std/wasm.zig index 8922b3c83e..aebbb3b163 100644 --- a/lib/std/wasm.zig +++ b/lib/std/wasm.zig @@ -162,8 +162,14 @@ pub const Opcode = enum(u8) { i32_wrap_i64 = 0xA7, i32_trunc_f32_s = 0xA8, i32_trunc_f32_u = 0xA9, - i32_trunc_f64_s = 0xB0, - i32_trunc_f64_u = 0xB1, + i32_trunc_f64_s = 0xAA, + i32_trunc_f64_u = 0xAB, + i64_extend_i32_s = 0xAC, + i64_extend_i32_u = 0xAD, + i64_trunc_f32_s = 0xAE, + i64_trunc_f32_u = 0xAF, + i64_trunc_f64_s = 0xB0, + i64_trunc_f64_u = 0xB1, f32_convert_i32_s = 0xB2, f32_convert_i32_u = 0xB3, f32_convert_i64_s = 0xB4, diff --git a/src/codegen/wasm.zig b/src/codegen/wasm.zig index 2f1632e0fc..1a23a8fa35 100644 --- a/src/codegen/wasm.zig +++ b/src/codegen/wasm.zig @@ -591,7 +591,7 @@ pub const Context = struct { .ErrorSet, => wasm.Valtype.i32, .Struct, .ErrorUnion => unreachable, // Multi typed, must be handled individually. - else => self.fail("TODO - Wasm valtype for type '{s}'", .{ty.zigTypeTag()}), + else => |tag| self.fail("TODO - Wasm valtype for type '{s}'", .{tag}), }; } @@ -800,8 +800,11 @@ pub const Context = struct { const air_tags = self.air.instructions.items(.tag); return switch (air_tags[inst]) { .add => self.airBinOp(inst, .add), + .addwrap => self.airBinOp(inst, .add), .sub => self.airBinOp(inst, .sub), + .subwrap => self.airBinOp(inst, .sub), .mul => self.airBinOp(inst, .mul), + .mulwrap => self.airBinOp(inst, .mul), .div => self.airBinOp(inst, .div), .bit_and => self.airBinOp(inst, .@"and"), .bit_or => self.airBinOp(inst, .@"or"), @@ -826,6 +829,7 @@ pub const Context = struct { .cond_br => self.airCondBr(inst), .constant => unreachable, .dbg_stmt => WValue.none, + .intcast => self.airIntcast(inst), .is_err => self.airIsErr(inst, .i32_ne), .is_non_err => self.airIsErr(inst, .i32_eq), .load => self.airLoad(inst), @@ -1494,4 +1498,27 @@ pub const Context = struct { const ty_op = self.air.instructions.items(.data)[inst].ty_op; return self.resolveInst(ty_op.operand); } + + fn airIntcast(self: *Context, inst: Air.Inst.Index) InnerError!WValue { + const ty_op = self.air.instructions.items(.data)[inst].ty_op; + const ty = self.air.getRefType(ty_op.ty); + const operand = self.resolveInst(ty_op.operand); + const ref_ty = self.air.typeOf(ty_op.operand); + const ref_info = ref_ty.intInfo(self.target); + const op_bits = ref_info.bits; + const wanted_bits = ty.intInfo(self.target).bits; + + try self.emitWValue(operand); + if (op_bits > 32 and wanted_bits <= 32) { + try self.code.append(wasm.opcode(.i32_wrap_i64)); + } else if (op_bits <= 32 and wanted_bits > 32) { + try self.code.append(wasm.opcode(switch (ref_info.signedness) { + .signed => .i64_extend_i32_s, + .unsigned => .i64_extend_i32_u, + })); + } + + // other cases are no-op + return .none; + } };