| ... | ... | @@ -2962,7 +2962,7 @@ fn intcast(self: *Self, operand: WValue, given: Type, wanted: Type) InnerError!W |
| 2962 | 2962 | try self.store(stack_ptr, .{ .imm64 = 0 }, Type.u64, 8); |
| 2963 | 2963 | } |
| 2964 | 2964 | return stack_ptr; |
| 2965 | | } else unreachable; |
| 2965 | } else return self.fail("todo Wasm @intCast to 128bit integers", .{}); |
| 2966 | 2966 | |
| 2967 | 2967 | const result = try self.allocLocal(wanted); |
| 2968 | 2968 | try self.addLabel(.local_set, result.local); |
| ... | ... | @@ -3710,35 +3710,44 @@ fn cmpOptionals(self: *Self, lhs: WValue, rhs: WValue, operand_ty: Type, op: std |
| 3710 | 3710 | } |
| 3711 | 3711 | |
| 3712 | 3712 | /// Compares big integers by checking both its high bits and low bits. |
| 3713 | | /// TODO: Lower this to compiler_rt call |
| 3713 | /// TODO: Lower this to compiler_rt call when bitsize > 128 |
| 3714 | 3714 | fn cmpBigInt(self: *Self, lhs: WValue, rhs: WValue, operand_ty: Type, op: std.math.CompareOperator) InnerError!WValue { |
| 3715 | 3715 | if (operand_ty.intInfo(self.target).bits > 128) { |
| 3716 | 3716 | return self.fail("TODO: Support cmpBigInt for integer bitsize: '{d}'", .{operand_ty.intInfo(self.target).bits}); |
| 3717 | 3717 | } |
| 3718 | 3718 | |
| 3719 | | const result = try self.allocLocal(Type.initTag(.i32)); |
| 3720 | | { |
| 3721 | | try self.startBlock(.block, wasm.block_empty); |
| 3722 | | const lhs_high_bit = try self.load(lhs, Type.u64, 0); |
| 3723 | | const lhs_low_bit = try self.load(lhs, Type.u64, 8); |
| 3724 | | const rhs_high_bit = try self.load(rhs, Type.u64, 0); |
| 3725 | | const rhs_low_bit = try self.load(rhs, Type.u64, 8); |
| 3726 | | try self.emitWValue(lhs_high_bit); |
| 3727 | | try self.emitWValue(rhs_high_bit); |
| 3728 | | try self.addTag(.i64_ne); |
| 3729 | | try self.addLabel(.br_if, 0); |
| 3730 | | try self.emitWValue(lhs_low_bit); |
| 3731 | | try self.emitWValue(rhs_low_bit); |
| 3732 | | try self.addTag(.i64_ne); |
| 3733 | | try self.addLabel(.br_if, 0); |
| 3734 | | try self.addImm32(1); |
| 3735 | | try self.addLabel(.local_set, result.local); |
| 3736 | | try self.endBlock(); |
| 3719 | const lhs_high_bit = try self.load(lhs, Type.u64, 0); |
| 3720 | const lhs_low_bit = try self.load(lhs, Type.u64, 8); |
| 3721 | const rhs_high_bit = try self.load(rhs, Type.u64, 0); |
| 3722 | const rhs_low_bit = try self.load(rhs, Type.u64, 8); |
| 3723 | |
| 3724 | try self.emitWValue(or_result); |
| 3725 | switch (op) { |
| 3726 | .eq, .neq => { |
| 3727 | const xor_high = try self.binOp(lhs_high_bit, rhs_high_bit, Type.u64, .xor); |
| 3728 | const xor_low = try self.binOp(lhs_low_bit, rhs_low_bit, Type.u64, .xor); |
| 3729 | const or_result = try self.binOp(xor_high, xor_low, Type.u64, .@"or"); |
| 3730 | |
| 3731 | switch (op) { |
| 3732 | .eq => try self.addTag(.i64_eqz), |
| 3733 | .neq => return self.cmp(or_result, .{ .imm32 = 0 }, Type.u32, .neq), |
| 3734 | else => unreachable, |
| 3735 | } |
| 3736 | }, |
| 3737 | else => { |
| 3738 | const ty = if (operand_ty.isSignedInt()) Type.i64 else Type.u64; |
| 3739 | const low_bit_eql = try self.cmp(lhs_low_bit, rhs_low_bit, ty, .eq); |
| 3740 | const high_bit_cmp = try self.cmp(lhs_high_bit, rhs_high_bit, ty, op); |
| 3741 | const low_bit_cmp = try self.cmp(lhs_low_bit, rhs_low_bit, ty, op); |
| 3742 | |
| 3743 | try self.emitWValue(low_bit_cmp); |
| 3744 | try self.emitWValue(high_bit_cmp); |
| 3745 | try self.emitWValue(low_bit_eql); |
| 3746 | try self.addTag(.select); |
| 3747 | }, |
| 3737 | 3748 | } |
| 3738 | 3749 | |
| 3739 | | try self.emitWValue(result); |
| 3740 | | try self.addImm32(0); |
| 3741 | | try self.addTag(if (op == .eq) .i32_ne else .i32_eq); |
| 3750 | const result = try self.allocLocal(Type.initTag(.i32)); |
| 3742 | 3751 | try self.addLabel(.local_set, result.local); |
| 3743 | 3752 | return result; |
| 3744 | 3753 | } |