diff --git a/src/arch/wasm/CodeGen.zig b/src/arch/wasm/CodeGen.zig index 14d2cf95c4..af54043f7a 100644 --- a/src/arch/wasm/CodeGen.zig +++ b/src/arch/wasm/CodeGen.zig @@ -4160,7 +4160,7 @@ fn airIntcast(func: *CodeGen, inst: Air.Inst.Index) InnerError!void { const op_bits = toWasmBits(@as(u16, @intCast(operand_ty.bitSize(mod)))).?; const wanted_bits = toWasmBits(@as(u16, @intCast(ty.bitSize(mod)))).?; - const result = if (op_bits == wanted_bits) + const result = if (op_bits == wanted_bits and !ty.isSignedInt(mod)) func.reuseOperand(ty_op.operand, operand) else try (try func.intcast(operand, operand_ty, ty)).toLocal(func, ty); @@ -4181,7 +4181,19 @@ fn intcast(func: *CodeGen, operand: WValue, given: Type, wanted: Type) InnerErro const op_bits = toWasmBits(given_bitsize).?; const wanted_bits = toWasmBits(wanted_bitsize).?; - if (op_bits == wanted_bits) return operand; + if (op_bits == wanted_bits) { + if (given.isSignedInt(mod)) { + if (given_bitsize < wanted_bitsize) { + // signed integers are stored as two's complement, + // when we upcast from a smaller integer to larger + // integers, we must get its absolute value similar to + // i64_extend_i32_s instruction. + return func.signAbsValue(operand, given); + } + return func.wrapOperand(operand, wanted); + } + return operand; + } if (op_bits > 32 and op_bits <= 64 and wanted_bits == 32) { try func.emitWValue(operand); diff --git a/test/behavior/cast_int.zig b/test/behavior/cast_int.zig index 6d4f530409..09733d00a0 100644 --- a/test/behavior/cast_int.zig +++ b/test/behavior/cast_int.zig @@ -14,3 +14,18 @@ test "@intCast i32 to u7" { var z = x >> @as(u7, @intCast(y)); try expect(z == 0xff); } + +test "coerce i8 to i32 and @intCast back" { + if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO + if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO + if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO + if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; + + var x: i8 = -5; + var y: i32 = -5; + try expect(y == x); + + var x2: i32 = -5; + var y2: i8 = -5; + try expect(y2 == @as(i8, @intCast(x2))); +}