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