authorgravatar for luuk@degram.devLuuk de Gram <luuk@degram.dev> 2022-06-19 15:50:03+02:00
committergravatar for luuk@degram.devLuuk de Gram <luuk@degram.dev> 2022-06-19 15:50:03+02:00
log05600a6d8438595bf7fc40ea21d0c47076d2935d
tree16877371e41351d7b1681d795084b2a9c186cdcc
parent53831442ef7e87c32501967f13dfb5fb9b0d0b0f
signaturelock-open Commit is signed but in an unrecognized format.

wasm: saturating shift-left for signed integers


1 files changed, 55 insertions(+), 10 deletions(-)

src/arch/wasm/CodeGen.zig+55-10
......@@ -4995,13 +4995,13 @@ fn airShlSat(self: *Self, inst: Air.Inst.Index) InnerError!WValue {
49954995 const bin_op = self.air.instructions.items(.data)[inst].bin_op;
49964996 const ty = self.air.typeOfIndex(inst);
49974997 const int_info = ty.intInfo(self.target);
4998 const is_signed = int_info.signedness == .signed;
49984999 if (int_info.bits > 64) {
49995000 return self.fail("TODO: Saturating shifting left for integers with bitsize '{d}'", .{int_info.bits});
50005001 }
50015002
50025003 const lhs = try self.resolveInst(bin_op.lhs);
50035004 const rhs = try self.resolveInst(bin_op.rhs);
5004 if (int_info.signedness == .signed) {}
50055005 const wasm_bits = toWasmBits(int_info.bits).?;
50065006 const result = try self.allocLocal(ty);
50075007
......@@ -5009,10 +5009,32 @@ fn airShlSat(self: *Self, inst: Air.Inst.Index) InnerError!WValue {
50095009 const shl = try self.binOp(lhs, rhs, ty, .shl);
50105010 const shr = try self.binOp(shl, rhs, ty, .shr);
50115011 const cmp_result = try self.cmp(lhs, shr, ty, .neq);
5012 if (wasm_bits == 32)
5013 try self.addImm32(-1)
5014 else
5015 try self.addImm64(@bitCast(u64, @as(i64, -1)));
5012
5013 switch (wasm_bits) {
5014 32 => blk: {
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 }
50165038 try self.emitWValue(shl);
50175039 try self.emitWValue(cmp_result);
50185040 try self.addTag(.select);
......@@ -5029,12 +5051,35 @@ fn airShlSat(self: *Self, inst: Air.Inst.Index) InnerError!WValue {
50295051 const shl_res = try self.binOp(lhs, shift_value, ty, .shl);
50305052 const shl = try self.binOp(shl_res, rhs, ty, .shl);
50315053 const shr = try self.binOp(shl, rhs, ty, .shr);
5032
50335054 const cmp_result = try self.cmp(shl_res, shr, ty, .neq);
5034 if (wasm_bits == 32)
5035 try self.addImm32(-1)
5036 else
5037 try self.addImm64(@bitCast(u64, @as(i64, -1)));
5055
5056 switch (wasm_bits) {
5057 32 => blk: {
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 }
50385083 try self.emitWValue(shl);
50395084 try self.emitWValue(cmp_result);
50405085 try self.addTag(.select);