authorgravatar for luuk@degram.devLuuk de Gram <luuk@degram.dev> 2022-06-10 20:37:31+02:00
committergravatar for luuk@degram.devLuuk de Gram <luuk@degram.dev> 2022-06-11 19:38:00+02:00
log3011ef2d82fe29d47b9c6877b6a8bbea0938d7c4
treedeff7ceaf9426c81e0e7b49017d21fb1d9e5942a
parent9b84f29503ede2088238e39daa4cf17a571ed790

wasm: signed integer division (non-floor)

Implements the non-floor variants of signed integer division.

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

src/arch/wasm/CodeGen.zig+48-1
......@@ -1444,7 +1444,7 @@ fn genInst(self: *Self, inst: Air.Inst.Index) !WValue {
14441444 .div_float,
14451445 .div_exact,
14461446 .div_trunc,
1447 => self.airBinOp(inst, .div),
1447 => self.airDiv(inst),
14481448 .div_floor => self.airDivFloor(inst),
14491449 .bit_and => self.airBinOp(inst, .@"and"),
14501450 .bit_or => self.airBinOp(inst, .@"or"),
......@@ -4759,6 +4759,20 @@ fn airByteSwap(self: *Self, inst: Air.Inst.Index) InnerError!WValue {
47594759 }
47604760}
47614761
4762fn airDiv(self: *Self, inst: Air.Inst.Index) InnerError!WValue {
4763 if (self.liveness.isUnused(inst)) return WValue{ .none = {} };
4764
4765 const bin_op = self.air.instructions.items(.data)[inst].bin_op;
4766 const ty = self.air.typeOfIndex(inst);
4767 const lhs = try self.resolveInst(bin_op.lhs);
4768 const rhs = try self.resolveInst(bin_op.rhs);
4769
4770 if (ty.isSignedInt()) {
4771 return self.divSigned(lhs, rhs, ty);
4772 }
4773 return self.binOp(lhs, rhs, ty, .div);
4774}
4775
47624776fn airDivFloor(self: *Self, inst: Air.Inst.Index) InnerError!WValue {
47634777 if (self.liveness.isUnused(inst)) return WValue{ .none = {} };
47644778
......@@ -4785,3 +4799,36 @@ fn airDivFloor(self: *Self, inst: Air.Inst.Index) InnerError!WValue {
47854799 try self.addLabel(.local_set, result.local);
47864800 return result;
47874801}
4802
4803fn divSigned(self: *Self, lhs: WValue, rhs: WValue, ty: Type) InnerError!WValue {
4804 const int_bits = ty.intInfo(self.target).bits;
4805 const wasm_bits = toWasmBits(int_bits) orelse {
4806 return self.fail("TODO: Implement signed division for integers with bitsize '{d}'", .{int_bits});
4807 };
4808
4809 if (wasm_bits == 128) {
4810 return self.fail("TODO: Implement signed division for 128-bit integerrs", .{});
4811 }
4812
4813 if (wasm_bits != int_bits) {
4814 const shift_val = switch (wasm_bits) {
4815 32 => WValue{ .imm32 = wasm_bits - int_bits },
4816 64 => WValue{ .imm64 = wasm_bits - int_bits },
4817 else => unreachable,
4818 };
4819 const shl_lhs = try self.binOp(lhs, shift_val, ty, .shl);
4820 const shr_lhs = try self.binOp(shl_lhs, shift_val, ty, .shr);
4821 const shl_rhs = try self.binOp(rhs, shift_val, ty, .shl);
4822 const shr_rhs = try self.binOp(shl_rhs, shift_val, ty, .shr);
4823 try self.emitWValue(shr_lhs);
4824 try self.emitWValue(shr_rhs);
4825 } else {
4826 try self.emitWValue(lhs);
4827 try self.emitWValue(rhs);
4828 }
4829 try self.addTag(.i32_div_s);
4830
4831 const result = try self.allocLocal(ty);
4832 try self.addLabel(.local_set, result.local);
4833 return result;
4834}