| ... | ... | @@ -1444,7 +1444,7 @@ fn genInst(self: *Self, inst: Air.Inst.Index) !WValue { |
| 1444 | 1444 | .div_float, |
| 1445 | 1445 | .div_exact, |
| 1446 | 1446 | .div_trunc, |
| 1447 | | => self.airBinOp(inst, .div), |
| 1447 | => self.airDiv(inst), |
| 1448 | 1448 | .div_floor => self.airDivFloor(inst), |
| 1449 | 1449 | .bit_and => self.airBinOp(inst, .@"and"), |
| 1450 | 1450 | .bit_or => self.airBinOp(inst, .@"or"), |
| ... | ... | @@ -4759,6 +4759,20 @@ fn airByteSwap(self: *Self, inst: Air.Inst.Index) InnerError!WValue { |
| 4759 | 4759 | } |
| 4760 | 4760 | } |
| 4761 | 4761 | |
| 4762 | fn 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 | |
| 4762 | 4776 | fn airDivFloor(self: *Self, inst: Air.Inst.Index) InnerError!WValue { |
| 4763 | 4777 | if (self.liveness.isUnused(inst)) return WValue{ .none = {} }; |
| 4764 | 4778 | |
| ... | ... | @@ -4785,3 +4799,36 @@ fn airDivFloor(self: *Self, inst: Air.Inst.Index) InnerError!WValue { |
| 4785 | 4799 | try self.addLabel(.local_set, result.local); |
| 4786 | 4800 | return result; |
| 4787 | 4801 | } |
| 4802 | |
| 4803 | fn 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 | } |