authorgravatar for luuk@degram.devLuuk de Gram <luuk@degram.dev> 2022-06-16 20:22:14+02:00
committergravatar for luuk@degram.devLuuk de Gram <luuk@degram.dev> 2022-06-19 14:30:17+02:00
log53831442ef7e87c32501967f13dfb5fb9b0d0b0f
tree28a150a2f1b66ada6227d4b9ed8e5b14b0397fed
parentce5d934f5f713a0dbc8787d9ffe58b4962042f8f
signaturelock-open Commit is signed but in an unrecognized format.

wasm: saturating shift-left for unsigned integers


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

src/arch/wasm/CodeGen.zig+55-1
...@@ -1454,6 +1454,7 @@ fn genInst(self: *Self, inst: Air.Inst.Index) !WValue {...@@ -1454,6 +1454,7 @@ fn genInst(self: *Self, inst: Air.Inst.Index) !WValue {
1454 .rem => self.airBinOp(inst, .rem),1454 .rem => self.airBinOp(inst, .rem),
1455 .shl => self.airWrapBinOp(inst, .shl),1455 .shl => self.airWrapBinOp(inst, .shl),
1456 .shl_exact => self.airBinOp(inst, .shl),1456 .shl_exact => self.airBinOp(inst, .shl),
1457 .shl_sat => self.airShlSat(inst),
1457 .shr, .shr_exact => self.airBinOp(inst, .shr),1458 .shr, .shr_exact => self.airBinOp(inst, .shr),
1458 .xor => self.airBinOp(inst, .xor),1459 .xor => self.airBinOp(inst, .xor),
1459 .max => self.airMaxMin(inst, .max),1460 .max => self.airMaxMin(inst, .max),
...@@ -1588,7 +1589,6 @@ fn genInst(self: *Self, inst: Air.Inst.Index) !WValue {...@@ -1588,7 +1589,6 @@ fn genInst(self: *Self, inst: Air.Inst.Index) !WValue {
1588 .mul_sat,1589 .mul_sat,
1589 .mod,1590 .mod,
1590 .assembly,1591 .assembly,
1591 .shl_sat,
1592 .ret_addr,1592 .ret_addr,
1593 .frame_addr,1593 .frame_addr,
1594 .bit_reverse,1594 .bit_reverse,
...@@ -4988,3 +4988,57 @@ fn signedSat(self: *Self, lhs_operand: WValue, rhs_operand: WValue, ty: Type, op...@@ -4988,3 +4988,57 @@ fn signedSat(self: *Self, lhs_operand: WValue, rhs_operand: WValue, ty: Type, op
4988 return bin_result;4988 return bin_result;
4989 }4989 }
4990}4990}
4991
4992fn airShlSat(self: *Self, inst: Air.Inst.Index) InnerError!WValue {
4993 if (self.liveness.isUnused(inst)) return WValue{ .none = {} };
4994
4995 const bin_op = self.air.instructions.items(.data)[inst].bin_op;
4996 const ty = self.air.typeOfIndex(inst);
4997 const int_info = ty.intInfo(self.target);
4998 if (int_info.bits > 64) {
4999 return self.fail("TODO: Saturating shifting left for integers with bitsize '{d}'", .{int_info.bits});
5000 }
5001
5002 const lhs = try self.resolveInst(bin_op.lhs);
5003 const rhs = try self.resolveInst(bin_op.rhs);
5004 if (int_info.signedness == .signed) {}
5005 const wasm_bits = toWasmBits(int_info.bits).?;
5006 const result = try self.allocLocal(ty);
5007
5008 if (wasm_bits == int_info.bits) {
5009 const shl = try self.binOp(lhs, rhs, ty, .shl);
5010 const shr = try self.binOp(shl, rhs, ty, .shr);
5011 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)));
5016 try self.emitWValue(shl);
5017 try self.emitWValue(cmp_result);
5018 try self.addTag(.select);
5019 try self.addLabel(.local_set, result.local);
5020 return result;
5021 } else {
5022 const shift_size = wasm_bits - int_info.bits;
5023 const shift_value = switch (wasm_bits) {
5024 32 => WValue{ .imm32 = shift_size },
5025 64 => WValue{ .imm64 = shift_size },
5026 else => unreachable,
5027 };
5028
5029 const shl_res = try self.binOp(lhs, shift_value, ty, .shl);
5030 const shl = try self.binOp(shl_res, rhs, ty, .shl);
5031 const shr = try self.binOp(shl, rhs, ty, .shr);
5032
5033 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)));
5038 try self.emitWValue(shl);
5039 try self.emitWValue(cmp_result);
5040 try self.addTag(.select);
5041 try self.addLabel(.local_set, result.local);
5042 return self.binOp(result, shift_value, ty, .shr);
5043 }
5044}