authorgravatar for luuk@degram.devLuuk de Gram <luuk@degram.dev> 2023-07-21 21:18:58+02:00
committergravatar for luuk@degram.devLuuk de Gram <luuk@degram.dev> 2023-07-22 02:12:07+02:00
log619140c0d2abd22da668747820f0ee80b497eb24
tree9ea7d8506956202bc7560d87990b8f47b424b881
parent8924f81d8cd96f5a69a54d87119a748247079a09

wasm: correctly intcast signed integers

When a signed integer's bitsize is not 32 or 64, but the given bitsize and wanted bitsize are either both represented by Wasm's i32 or i64, we must either sign extend or wrap the integer.

2 files changed, 29 insertions(+), 2 deletions(-)

src/arch/wasm/CodeGen.zig+14-2
......@@ -4160,7 +4160,7 @@ fn airIntcast(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {
41604160
41614161 const op_bits = toWasmBits(@as(u16, @intCast(operand_ty.bitSize(mod)))).?;
41624162 const wanted_bits = toWasmBits(@as(u16, @intCast(ty.bitSize(mod)))).?;
4163 const result = if (op_bits == wanted_bits)
4163 const result = if (op_bits == wanted_bits and !ty.isSignedInt(mod))
41644164 func.reuseOperand(ty_op.operand, operand)
41654165 else
41664166 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
41814181
41824182 const op_bits = toWasmBits(given_bitsize).?;
41834183 const wanted_bits = toWasmBits(wanted_bitsize).?;
4184 if (op_bits == wanted_bits) return operand;
4184 if (op_bits == wanted_bits) {
4185 if (given.isSignedInt(mod)) {
4186 if (given_bitsize < wanted_bitsize) {
4187 // signed integers are stored as two's complement,
4188 // when we upcast from a smaller integer to larger
4189 // integers, we must get its absolute value similar to
4190 // i64_extend_i32_s instruction.
4191 return func.signAbsValue(operand, given);
4192 }
4193 return func.wrapOperand(operand, wanted);
4194 }
4195 return operand;
4196 }
41854197
41864198 if (op_bits > 32 and op_bits <= 64 and wanted_bits == 32) {
41874199 try func.emitWValue(operand);
test/behavior/cast_int.zig+15
......@@ -14,3 +14,18 @@ test "@intCast i32 to u7" {
1414 var z = x >> @as(u7, @intCast(y));
1515 try expect(z == 0xff);
1616}
17
18test "coerce i8 to i32 and @intCast back" {
19 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
20 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
21 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
22 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
23
24 var x: i8 = -5;
25 var y: i32 = -5;
26 try expect(y == x);
27
28 var x2: i32 = -5;
29 var y2: i8 = -5;
30 try expect(y2 == @as(i8, @intCast(x2)));
31}