| ... | @@ -4309,10 +4309,10 @@ fn airAddSubWithOverflow(self: *Self, inst: Air.Inst.Index, op: Op) InnerError!W | ... | @@ -4309,10 +4309,10 @@ fn airAddSubWithOverflow(self: *Self, inst: Air.Inst.Index, op: Op) InnerError!W |
| 4309 | // for signed integers, we first apply signed shifts by the difference in bits | 4309 | // for signed integers, we first apply signed shifts by the difference in bits |
| 4310 | // to get the signed value, as we store it internally as 2's complement. | 4310 | // to get the signed value, as we store it internally as 2's complement. |
| 4311 | const lhs = if (wasm_bits != int_info.bits and is_signed) blk: { | 4311 | const lhs = if (wasm_bits != int_info.bits and is_signed) blk: { |
| 4312 | break :blk try self.signAbsValue(lhs_op, lhs_ty); | 4312 | break :blk try (try self.signAbsValue(lhs_op, lhs_ty)).toLocal(self, lhs_ty); |
| 4313 | } else lhs_op; | 4313 | } else lhs_op; |
| 4314 | const rhs = if (wasm_bits != int_info.bits and is_signed) blk: { | 4314 | const rhs = if (wasm_bits != int_info.bits and is_signed) blk: { |
| 4315 | break :blk try self.signAbsValue(rhs_op, lhs_ty); | 4315 | break :blk try (try self.signAbsValue(rhs_op, lhs_ty)).toLocal(self, lhs_ty); |
| 4316 | } else rhs_op; | 4316 | } else rhs_op; |
| 4317 | | 4317 | |
| 4318 | const bin_op = try (try self.binOp(lhs, rhs, lhs_ty, op)).toLocal(self, lhs_ty); | 4318 | const bin_op = try (try self.binOp(lhs, rhs, lhs_ty, op)).toLocal(self, lhs_ty); |
| ... | @@ -4420,9 +4420,9 @@ fn airShlWithOverflow(self: *Self, inst: Air.Inst.Index) InnerError!WValue { | ... | @@ -4420,9 +4420,9 @@ fn airShlWithOverflow(self: *Self, inst: Air.Inst.Index) InnerError!WValue { |
| 4420 | } else shl; | 4420 | } else shl; |
| 4421 | | 4421 | |
| 4422 | const overflow_bit = if (wasm_bits != int_info.bits and is_signed) blk: { | 4422 | const overflow_bit = if (wasm_bits != int_info.bits and is_signed) blk: { |
| 4423 | const abs = try self.signAbsValue(shl, lhs_ty); | | |
| 4424 | // emit lhs to stack to we can keep 'wrapped' on the stack also | 4423 | // emit lhs to stack to we can keep 'wrapped' on the stack also |
| 4425 | try self.emitWValue(lhs); | 4424 | try self.emitWValue(lhs); |
| | 4425 | const abs = try self.signAbsValue(shl, lhs_ty); |
| 4426 | const wrapped = try self.wrapBinOp(abs, rhs, lhs_ty, .shr); | 4426 | const wrapped = try self.wrapBinOp(abs, rhs, lhs_ty, .shr); |
| 4427 | break :blk try self.cmp(.{ .stack = {} }, wrapped, lhs_ty, .neq); | 4427 | break :blk try self.cmp(.{ .stack = {} }, wrapped, lhs_ty, .neq); |
| 4428 | } else blk: { | 4428 | } else blk: { |
| ... | @@ -4909,10 +4909,10 @@ fn airDivFloor(self: *Self, inst: Air.Inst.Index) InnerError!WValue { | ... | @@ -4909,10 +4909,10 @@ fn airDivFloor(self: *Self, inst: Air.Inst.Index) InnerError!WValue { |
| 4909 | return self.fail("TODO: `@divFloor` for signed integers larger than '{d}' bits", .{int_bits}); | 4909 | return self.fail("TODO: `@divFloor` for signed integers larger than '{d}' bits", .{int_bits}); |
| 4910 | }; | 4910 | }; |
| 4911 | const lhs_res = if (wasm_bits != int_bits) blk: { | 4911 | const lhs_res = if (wasm_bits != int_bits) blk: { |
| 4912 | break :blk try self.signAbsValue(lhs, ty); | 4912 | break :blk try (try self.signAbsValue(lhs, ty)).toLocal(self, ty); |
| 4913 | } else lhs; | 4913 | } else lhs; |
| 4914 | const rhs_res = if (wasm_bits != int_bits) blk: { | 4914 | const rhs_res = if (wasm_bits != int_bits) blk: { |
| 4915 | break :blk try self.signAbsValue(rhs, ty); | 4915 | break :blk try (try self.signAbsValue(rhs, ty)).toLocal(self, ty); |
| 4916 | } else rhs; | 4916 | } else rhs; |
| 4917 | | 4917 | |
| 4918 | const zero = switch (wasm_bits) { | 4918 | const zero = switch (wasm_bits) { |
| ... | @@ -4994,10 +4994,9 @@ fn divSigned(self: *Self, lhs: WValue, rhs: WValue, ty: Type) InnerError!WValue | ... | @@ -4994,10 +4994,9 @@ fn divSigned(self: *Self, lhs: WValue, rhs: WValue, ty: Type) InnerError!WValue |
| 4994 | } | 4994 | } |
| 4995 | | 4995 | |
| 4996 | if (wasm_bits != int_bits) { | 4996 | if (wasm_bits != int_bits) { |
| 4997 | const lhs_abs = try self.signAbsValue(lhs, ty); | 4997 | // Leave both values on the stack |
| 4998 | const rhs_abs = try self.signAbsValue(rhs, ty); | 4998 | _ = try self.signAbsValue(lhs, ty); |
| 4999 | try self.emitWValue(lhs_abs); | 4999 | _ = try self.signAbsValue(rhs, ty); |
| 5000 | try self.emitWValue(rhs_abs); | | |
| 5001 | } else { | 5000 | } else { |
| 5002 | try self.emitWValue(lhs); | 5001 | try self.emitWValue(lhs); |
| 5003 | try self.emitWValue(rhs); | 5002 | try self.emitWValue(rhs); |
| ... | @@ -5009,6 +5008,8 @@ fn divSigned(self: *Self, lhs: WValue, rhs: WValue, ty: Type) InnerError!WValue | ... | @@ -5009,6 +5008,8 @@ fn divSigned(self: *Self, lhs: WValue, rhs: WValue, ty: Type) InnerError!WValue |
| 5009 | return result; | 5008 | return result; |
| 5010 | } | 5009 | } |
| 5011 | | 5010 | |
| | 5011 | /// Retrieves the absolute value of a signed integer |
| | 5012 | /// NOTE: Leaves the result value on the stack. |
| 5012 | fn signAbsValue(self: *Self, operand: WValue, ty: Type) InnerError!WValue { | 5013 | fn signAbsValue(self: *Self, operand: WValue, ty: Type) InnerError!WValue { |
| 5013 | const int_bits = ty.intInfo(self.target).bits; | 5014 | const int_bits = ty.intInfo(self.target).bits; |
| 5014 | const wasm_bits = toWasmBits(int_bits) orelse { | 5015 | const wasm_bits = toWasmBits(int_bits) orelse { |
| ... | @@ -5037,9 +5038,8 @@ fn signAbsValue(self: *Self, operand: WValue, ty: Type) InnerError!WValue { | ... | @@ -5037,9 +5038,8 @@ fn signAbsValue(self: *Self, operand: WValue, ty: Type) InnerError!WValue { |
| 5037 | }, | 5038 | }, |
| 5038 | else => unreachable, | 5039 | else => unreachable, |
| 5039 | } | 5040 | } |
| 5040 | const result = try self.allocLocal(ty); | 5041 | |
| 5041 | try self.addLabel(.local_set, result.local); | 5042 | return WValue{ .stack = {} }; |
| 5042 | return result; | | |
| 5043 | } | 5043 | } |
| 5044 | | 5044 | |
| 5045 | fn airCeilFloorTrunc(self: *Self, inst: Air.Inst.Index, op: Op) InnerError!WValue { | 5045 | fn airCeilFloorTrunc(self: *Self, inst: Air.Inst.Index, op: Op) InnerError!WValue { |
| ... | @@ -5130,8 +5130,12 @@ fn signedSat(self: *Self, lhs_operand: WValue, rhs_operand: WValue, ty: Type, op | ... | @@ -5130,8 +5130,12 @@ fn signedSat(self: *Self, lhs_operand: WValue, rhs_operand: WValue, ty: Type, op |
| 5130 | const wasm_bits = toWasmBits(int_info.bits).?; | 5130 | const wasm_bits = toWasmBits(int_info.bits).?; |
| 5131 | const is_wasm_bits = wasm_bits == int_info.bits; | 5131 | const is_wasm_bits = wasm_bits == int_info.bits; |
| 5132 | | 5132 | |
| 5133 | const lhs = if (!is_wasm_bits) try self.signAbsValue(lhs_operand, ty) else lhs_operand; | 5133 | const lhs = if (!is_wasm_bits) lhs: { |
| 5134 | const rhs = if (!is_wasm_bits) try self.signAbsValue(rhs_operand, ty) else rhs_operand; | 5134 | break :lhs try (try self.signAbsValue(lhs_operand, ty)).toLocal(self, ty); |
| | 5135 | } else lhs_operand; |
| | 5136 | const rhs = if (!is_wasm_bits) rhs: { |
| | 5137 | break :rhs try (try self.signAbsValue(rhs_operand, ty)).toLocal(self, ty); |
| | 5138 | } else rhs_operand; |
| 5135 | | 5139 | |
| 5136 | const max_val: u64 = @intCast(u64, (@as(u65, 1) << @intCast(u7, int_info.bits - 1)) - 1); | 5140 | const max_val: u64 = @intCast(u64, (@as(u65, 1) << @intCast(u7, int_info.bits - 1)) - 1); |
| 5137 | const min_val: i64 = (-@intCast(i64, @intCast(u63, max_val))) - 1; | 5141 | const min_val: i64 = (-@intCast(i64, @intCast(u63, max_val))) - 1; |