aboutsummaryrefslogtreecommitdiff
path: root/src/arch/wasm/CodeGen.zig
diff options
context:
space:
mode:
Diffstat (limited to 'src/arch/wasm/CodeGen.zig')
-rw-r--r--src/arch/wasm/CodeGen.zig51
1 files changed, 12 insertions, 39 deletions
diff --git a/src/arch/wasm/CodeGen.zig b/src/arch/wasm/CodeGen.zig
index 41ca7d3a7b..02a955d8a6 100644
--- a/src/arch/wasm/CodeGen.zig
+++ b/src/arch/wasm/CodeGen.zig
@@ -4162,22 +4162,14 @@ fn airAddSubWithOverflow(self: *Self, inst: Air.Inst.Index, op: Op) InnerError!W
64 => WValue{ .imm64 = 0 },
else => unreachable,
};
- const shift_amt = wasm_bits - int_info.bits;
- const shift_val = switch (wasm_bits) {
- 32 => WValue{ .imm32 = shift_amt },
- 64 => WValue{ .imm64 = shift_amt },
- else => unreachable,
- };
// for signed integers, we first apply signed shifts by the difference in bits
// to get the signed value, as we store it internally as 2's complement.
const lhs = if (wasm_bits != int_info.bits and is_signed) blk: {
- const shl = try self.binOp(lhs_op, shift_val, lhs_ty, .shl);
- break :blk try self.binOp(shl, shift_val, lhs_ty, .shr);
+ break :blk try self.signAbsValue(lhs_op, lhs_ty);
} else lhs_op;
const rhs = if (wasm_bits != int_info.bits and is_signed) blk: {
- const shl = try self.binOp(rhs_op, shift_val, lhs_ty, .shl);
- break :blk try self.binOp(shl, shift_val, lhs_ty, .shr);
+ break :blk try self.signAbsValue(rhs_op, lhs_ty);
} else rhs_op;
const bin_op = try self.binOp(lhs, rhs, lhs_ty, op);
@@ -4192,9 +4184,8 @@ fn airAddSubWithOverflow(self: *Self, inst: Air.Inst.Index, op: Op) InnerError!W
const lt = try self.cmp(bin_op, lhs, lhs_ty, .lt);
break :blk try self.binOp(cmp_zero, lt, Type.u32, .xor); // result of cmp_zero and lt is always 32bit
}
- const shl = try self.binOp(bin_op, shift_val, lhs_ty, .shl);
- const shr = try self.binOp(shl, shift_val, lhs_ty, .shr);
- break :blk try self.cmp(shr, bin_op, lhs_ty, .neq);
+ const abs = try self.signAbsValue(bin_op, lhs_ty);
+ break :blk try self.cmp(abs, bin_op, lhs_ty, .neq);
} else if (wasm_bits == int_info.bits)
try self.cmp(bin_op, lhs, lhs_ty, cmp_op)
else
@@ -4289,17 +4280,9 @@ fn airShlWithOverflow(self: *Self, inst: Air.Inst.Index) InnerError!WValue {
} else shl;
const overflow_bit = if (wasm_bits != int_info.bits and is_signed) blk: {
- const shift_amt = wasm_bits - int_info.bits;
- const shift_val = switch (wasm_bits) {
- 32 => WValue{ .imm32 = shift_amt },
- 64 => WValue{ .imm64 = shift_amt },
- else => unreachable,
- };
-
- const secondary_shl = try self.binOp(shl, shift_val, lhs_ty, .shl);
- const initial_shr = try self.binOp(secondary_shl, shift_val, lhs_ty, .shr);
- const shr = try self.wrapBinOp(initial_shr, rhs, lhs_ty, .shr);
- break :blk try self.cmp(lhs, shr, lhs_ty, .neq);
+ const abs = try self.signAbsValue(shl, lhs_ty);
+ const wrapped = try self.wrapBinOp(abs, rhs, lhs_ty, .shr);
+ break :blk try self.cmp(lhs, wrapped, lhs_ty, .neq);
} else blk: {
const shr = try self.binOp(result, rhs, lhs_ty, .shr);
break :blk try self.cmp(lhs, shr, lhs_ty, .neq);
@@ -4367,21 +4350,11 @@ fn airMulWithOverflow(self: *Self, inst: Air.Inst.Index) InnerError!WValue {
break :blk down_cast;
}
} else if (int_info.signedness == .signed) blk: {
- const shift_imm = if (wasm_bits == 32)
- WValue{ .imm32 = wasm_bits - int_info.bits }
- else
- WValue{ .imm64 = wasm_bits - int_info.bits };
-
- const lhs_shl = try self.binOp(lhs, shift_imm, lhs_ty, .shl);
- const lhs_shr = try self.binOp(lhs_shl, shift_imm, lhs_ty, .shr);
- const rhs_shl = try self.binOp(rhs, shift_imm, lhs_ty, .shl);
- const rhs_shr = try self.binOp(rhs_shl, shift_imm, lhs_ty, .shr);
-
- const bin_op = try self.binOp(lhs_shr, rhs_shr, lhs_ty, .mul);
- const shl = try self.binOp(bin_op, shift_imm, lhs_ty, .shl);
- const shr = try self.binOp(shl, shift_imm, lhs_ty, .shr);
-
- const cmp_op = try self.cmp(shr, bin_op, lhs_ty, .neq);
+ const lhs_abs = try self.signAbsValue(lhs, lhs_ty);
+ const rhs_abs = try self.signAbsValue(rhs, lhs_ty);
+ const bin_op = try self.binOp(lhs_abs, rhs_abs, lhs_ty, .mul);
+ const mul_abs = try self.signAbsValue(bin_op, lhs_ty);
+ const cmp_op = try self.cmp(mul_abs, bin_op, lhs_ty, .neq);
try self.emitWValue(cmp_op);
try self.addLabel(.local_set, overflow_bit.local);
break :blk try self.wrapOperand(bin_op, lhs_ty);