Commit 619140c0d2
Changed files (2)
src
arch
wasm
test
behavior
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);
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)));
+}