| ... | @@ -4995,13 +4995,13 @@ fn airShlSat(self: *Self, inst: Air.Inst.Index) InnerError!WValue { | ... | @@ -4995,13 +4995,13 @@ fn airShlSat(self: *Self, inst: Air.Inst.Index) InnerError!WValue { |
| 4995 | const bin_op = self.air.instructions.items(.data)[inst].bin_op; | 4995 | const bin_op = self.air.instructions.items(.data)[inst].bin_op; |
| 4996 | const ty = self.air.typeOfIndex(inst); | 4996 | const ty = self.air.typeOfIndex(inst); |
| 4997 | const int_info = ty.intInfo(self.target); | 4997 | const int_info = ty.intInfo(self.target); |
| | 4998 | const is_signed = int_info.signedness == .signed; |
| 4998 | if (int_info.bits > 64) { | 4999 | if (int_info.bits > 64) { |
| 4999 | return self.fail("TODO: Saturating shifting left for integers with bitsize '{d}'", .{int_info.bits}); | 5000 | return self.fail("TODO: Saturating shifting left for integers with bitsize '{d}'", .{int_info.bits}); |
| 5000 | } | 5001 | } |
| 5001 | | 5002 | |
| 5002 | const lhs = try self.resolveInst(bin_op.lhs); | 5003 | const lhs = try self.resolveInst(bin_op.lhs); |
| 5003 | const rhs = try self.resolveInst(bin_op.rhs); | 5004 | const rhs = try self.resolveInst(bin_op.rhs); |
| 5004 | if (int_info.signedness == .signed) {} | | |
| 5005 | const wasm_bits = toWasmBits(int_info.bits).?; | 5005 | const wasm_bits = toWasmBits(int_info.bits).?; |
| 5006 | const result = try self.allocLocal(ty); | 5006 | const result = try self.allocLocal(ty); |
| 5007 | | 5007 | |
| ... | @@ -5009,10 +5009,32 @@ fn airShlSat(self: *Self, inst: Air.Inst.Index) InnerError!WValue { | ... | @@ -5009,10 +5009,32 @@ fn airShlSat(self: *Self, inst: Air.Inst.Index) InnerError!WValue { |
| 5009 | const shl = try self.binOp(lhs, rhs, ty, .shl); | 5009 | const shl = try self.binOp(lhs, rhs, ty, .shl); |
| 5010 | const shr = try self.binOp(shl, rhs, ty, .shr); | 5010 | const shr = try self.binOp(shl, rhs, ty, .shr); |
| 5011 | const cmp_result = try self.cmp(lhs, shr, ty, .neq); | 5011 | const cmp_result = try self.cmp(lhs, shr, ty, .neq); |
| 5012 | if (wasm_bits == 32) | 5012 | |
| 5013 | try self.addImm32(-1) | 5013 | switch (wasm_bits) { |
| 5014 | else | 5014 | 32 => blk: { |
| 5015 | try self.addImm64(@bitCast(u64, @as(i64, -1))); | 5015 | if (!is_signed) { |
| | 5016 | try self.addImm32(-1); |
| | 5017 | break :blk; |
| | 5018 | } |
| | 5019 | const less_than_zero = try self.cmp(lhs, .{ .imm32 = 0 }, ty, .lt); |
| | 5020 | try self.addImm32(std.math.minInt(i32)); |
| | 5021 | try self.addImm32(std.math.maxInt(i32)); |
| | 5022 | try self.emitWValue(less_than_zero); |
| | 5023 | try self.addTag(.select); |
| | 5024 | }, |
| | 5025 | 64 => blk: { |
| | 5026 | if (!is_signed) { |
| | 5027 | try self.addImm64(@bitCast(u64, @as(i64, -1))); |
| | 5028 | break :blk; |
| | 5029 | } |
| | 5030 | const less_than_zero = try self.cmp(lhs, .{ .imm64 = 0 }, ty, .lt); |
| | 5031 | try self.addImm64(@bitCast(u64, @as(i64, std.math.minInt(i64)))); |
| | 5032 | try self.addImm64(@bitCast(u64, @as(i64, std.math.maxInt(i64)))); |
| | 5033 | try self.emitWValue(less_than_zero); |
| | 5034 | try self.addTag(.select); |
| | 5035 | }, |
| | 5036 | else => unreachable, |
| | 5037 | } |
| 5016 | try self.emitWValue(shl); | 5038 | try self.emitWValue(shl); |
| 5017 | try self.emitWValue(cmp_result); | 5039 | try self.emitWValue(cmp_result); |
| 5018 | try self.addTag(.select); | 5040 | try self.addTag(.select); |
| ... | @@ -5029,12 +5051,35 @@ fn airShlSat(self: *Self, inst: Air.Inst.Index) InnerError!WValue { | ... | @@ -5029,12 +5051,35 @@ fn airShlSat(self: *Self, inst: Air.Inst.Index) InnerError!WValue { |
| 5029 | const shl_res = try self.binOp(lhs, shift_value, ty, .shl); | 5051 | const shl_res = try self.binOp(lhs, shift_value, ty, .shl); |
| 5030 | const shl = try self.binOp(shl_res, rhs, ty, .shl); | 5052 | const shl = try self.binOp(shl_res, rhs, ty, .shl); |
| 5031 | const shr = try self.binOp(shl, rhs, ty, .shr); | 5053 | const shr = try self.binOp(shl, rhs, ty, .shr); |
| 5032 | | | |
| 5033 | const cmp_result = try self.cmp(shl_res, shr, ty, .neq); | 5054 | const cmp_result = try self.cmp(shl_res, shr, ty, .neq); |
| 5034 | if (wasm_bits == 32) | 5055 | |
| 5035 | try self.addImm32(-1) | 5056 | switch (wasm_bits) { |
| 5036 | else | 5057 | 32 => blk: { |
| 5037 | try self.addImm64(@bitCast(u64, @as(i64, -1))); | 5058 | if (!is_signed) { |
| | 5059 | try self.addImm32(-1); |
| | 5060 | break :blk; |
| | 5061 | } |
| | 5062 | |
| | 5063 | const less_than_zero = try self.cmp(shl_res, .{ .imm32 = 0 }, ty, .lt); |
| | 5064 | try self.addImm32(std.math.minInt(i32)); |
| | 5065 | try self.addImm32(std.math.maxInt(i32)); |
| | 5066 | try self.emitWValue(less_than_zero); |
| | 5067 | try self.addTag(.select); |
| | 5068 | }, |
| | 5069 | 64 => blk: { |
| | 5070 | if (!is_signed) { |
| | 5071 | try self.addImm64(@bitCast(u64, @as(i64, -1))); |
| | 5072 | break :blk; |
| | 5073 | } |
| | 5074 | |
| | 5075 | const less_than_zero = try self.cmp(shl_res, .{ .imm64 = 0 }, ty, .lt); |
| | 5076 | try self.addImm64(@bitCast(u64, @as(i64, std.math.minInt(i64)))); |
| | 5077 | try self.addImm64(@bitCast(u64, @as(i64, std.math.maxInt(i64)))); |
| | 5078 | try self.emitWValue(less_than_zero); |
| | 5079 | try self.addTag(.select); |
| | 5080 | }, |
| | 5081 | else => unreachable, |
| | 5082 | } |
| 5038 | try self.emitWValue(shl); | 5083 | try self.emitWValue(shl); |
| 5039 | try self.emitWValue(cmp_result); | 5084 | try self.emitWValue(cmp_result); |
| 5040 | try self.addTag(.select); | 5085 | try self.addTag(.select); |