aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorLuuk de Gram <luuk@degram.dev>2023-07-21 21:18:58 +0200
committerLuuk de Gram <luuk@degram.dev>2023-07-22 02:12:07 +0200
commit619140c0d2abd22da668747820f0ee80b497eb24 (patch)
tree9ea7d8506956202bc7560d87990b8f47b424b881 /src
parent8924f81d8cd96f5a69a54d87119a748247079a09 (diff)
downloadzig-619140c0d2abd22da668747820f0ee80b497eb24.tar.gz
zig-619140c0d2abd22da668747820f0ee80b497eb24.zip
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.
Diffstat (limited to 'src')
-rw-r--r--src/arch/wasm/CodeGen.zig16
1 files changed, 14 insertions, 2 deletions
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);