| ... | @@ -561,33 +561,38 @@ fn genBody(self: *Self, body: []const Air.Inst.Index) InnerError!void { | ... | @@ -561,33 +561,38 @@ fn genBody(self: *Self, body: []const Air.Inst.Index) InnerError!void { |
| 561 | | 561 | |
| 562 | switch (air_tags[inst]) { | 562 | switch (air_tags[inst]) { |
| 563 | // zig fmt: off | 563 | // zig fmt: off |
| 564 | .add => try self.airBinOp(inst, .add), | 564 | .add => try self.airBinOp(inst, .add), |
| 565 | .addwrap => try self.airBinOp(inst, .addwrap), | 565 | .addwrap => try self.airBinOp(inst, .addwrap), |
| 566 | .sub => try self.airBinOp(inst, .sub), | 566 | .sub => try self.airBinOp(inst, .sub), |
| 567 | .subwrap => try self.airBinOp(inst, .subwrap), | 567 | .subwrap => try self.airBinOp(inst, .subwrap), |
| 568 | .mul => try self.airBinOp(inst, .mul), | 568 | .mul => try self.airBinOp(inst, .mul), |
| 569 | .mulwrap => try self.airBinOp(inst, .mulwrap), | 569 | .mulwrap => try self.airBinOp(inst, .mulwrap), |
| 570 | .shl => try self.airBinOp(inst, .shl), | 570 | .shl => try self.airBinOp(inst, .shl), |
| 571 | .shl_exact => try self.airBinOp(inst, .shl_exact), | 571 | .shl_exact => try self.airBinOp(inst, .shl_exact), |
| 572 | .bool_and => try self.airBinOp(inst, .bool_and), | 572 | .bool_and => try self.airBinOp(inst, .bool_and), |
| 573 | .bool_or => try self.airBinOp(inst, .bool_or), | 573 | .bool_or => try self.airBinOp(inst, .bool_or), |
| 574 | .bit_and => try self.airBinOp(inst, .bit_and), | 574 | .bit_and => try self.airBinOp(inst, .bit_and), |
| 575 | .bit_or => try self.airBinOp(inst, .bit_or), | 575 | .bit_or => try self.airBinOp(inst, .bit_or), |
| 576 | .xor => try self.airBinOp(inst, .xor), | 576 | .xor => try self.airBinOp(inst, .xor), |
| 577 | .shr => try self.airBinOp(inst, .shr), | 577 | .shr => try self.airBinOp(inst, .shr), |
| 578 | .shr_exact => try self.airBinOp(inst, .shr_exact), | 578 | .shr_exact => try self.airBinOp(inst, .shr_exact), |
| 579 | | 579 | .div_float => try self.airBinOp(inst, .div_float), |
| 580 | .ptr_add => try self.airPtrArithmetic(inst, .ptr_add), | 580 | .div_trunc => try self.airBinOp(inst, .div_trunc), |
| 581 | .ptr_sub => try self.airPtrArithmetic(inst, .ptr_sub), | 581 | .div_floor => try self.airBinOp(inst, .div_floor), |
| | 582 | .div_exact => try self.airBinOp(inst, .div_exact), |
| | 583 | .rem => try self.airBinOp(inst, .rem), |
| | 584 | .mod => try self.airBinOp(inst, .mod), |
| | 585 | |
| | 586 | .ptr_add => try self.airPtrArithmetic(inst, .ptr_add), |
| | 587 | .ptr_sub => try self.airPtrArithmetic(inst, .ptr_sub), |
| | 588 | |
| | 589 | .min => try self.airMin(inst), |
| | 590 | .max => try self.airMax(inst), |
| 582 | | 591 | |
| 583 | .add_sat => try self.airAddSat(inst), | 592 | .add_sat => try self.airAddSat(inst), |
| 584 | .sub_sat => try self.airSubSat(inst), | 593 | .sub_sat => try self.airSubSat(inst), |
| 585 | .mul_sat => try self.airMulSat(inst), | 594 | .mul_sat => try self.airMulSat(inst), |
| 586 | .rem => try self.airRem(inst), | | |
| 587 | .mod => try self.airMod(inst), | | |
| 588 | .shl_sat => try self.airShlSat(inst), | 595 | .shl_sat => try self.airShlSat(inst), |
| 589 | .min => try self.airMin(inst), | | |
| 590 | .max => try self.airMax(inst), | | |
| 591 | .slice => try self.airSlice(inst), | 596 | .slice => try self.airSlice(inst), |
| 592 | | 597 | |
| 593 | .sqrt, | 598 | .sqrt, |
| ... | @@ -612,8 +617,6 @@ fn genBody(self: *Self, body: []const Air.Inst.Index) InnerError!void { | ... | @@ -612,8 +617,6 @@ fn genBody(self: *Self, body: []const Air.Inst.Index) InnerError!void { |
| 612 | .mul_with_overflow => try self.airMulWithOverflow(inst), | 617 | .mul_with_overflow => try self.airMulWithOverflow(inst), |
| 613 | .shl_with_overflow => try self.airShlWithOverflow(inst), | 618 | .shl_with_overflow => try self.airShlWithOverflow(inst), |
| 614 | | 619 | |
| 615 | .div_float, .div_trunc, .div_floor, .div_exact => try self.airDiv(inst), | | |
| 616 | | | |
| 617 | .cmp_lt => try self.airCmp(inst, .lt), | 620 | .cmp_lt => try self.airCmp(inst, .lt), |
| 618 | .cmp_lte => try self.airCmp(inst, .lte), | 621 | .cmp_lte => try self.airCmp(inst, .lte), |
| 619 | .cmp_eq => try self.airCmp(inst, .eq), | 622 | .cmp_eq => try self.airCmp(inst, .eq), |
| ... | @@ -1391,6 +1394,8 @@ fn binOpRegister( | ... | @@ -1391,6 +1394,8 @@ fn binOpRegister( |
| 1391 | .lsl_register, | 1394 | .lsl_register, |
| 1392 | .asr_register, | 1395 | .asr_register, |
| 1393 | .lsr_register, | 1396 | .lsr_register, |
| | 1397 | .sdiv, |
| | 1398 | .udiv, |
| 1394 | => .{ .rrr = .{ | 1399 | => .{ .rrr = .{ |
| 1395 | .rd = dest_reg, | 1400 | .rd = dest_reg, |
| 1396 | .rn = lhs_reg, | 1401 | .rn = lhs_reg, |
| ... | @@ -1629,6 +1634,67 @@ fn binOp( | ... | @@ -1629,6 +1634,67 @@ fn binOp( |
| 1629 | else => unreachable, | 1634 | else => unreachable, |
| 1630 | } | 1635 | } |
| 1631 | }, | 1636 | }, |
| | 1637 | .div_float => { |
| | 1638 | switch (lhs_ty.zigTypeTag()) { |
| | 1639 | .Float => return self.fail("TODO div_float", .{}), |
| | 1640 | .Vector => return self.fail("TODO div_float on vectors", .{}), |
| | 1641 | else => unreachable, |
| | 1642 | } |
| | 1643 | }, |
| | 1644 | .div_trunc, .div_floor, .div_exact => { |
| | 1645 | switch (lhs_ty.zigTypeTag()) { |
| | 1646 | .Float => return self.fail("TODO div on floats", .{}), |
| | 1647 | .Vector => return self.fail("TODO div on vectors", .{}), |
| | 1648 | .Int => { |
| | 1649 | assert(lhs_ty.eql(rhs_ty, mod)); |
| | 1650 | const int_info = lhs_ty.intInfo(self.target.*); |
| | 1651 | if (int_info.bits <= 64) { |
| | 1652 | switch (int_info.signedness) { |
| | 1653 | .signed => { |
| | 1654 | switch (tag) { |
| | 1655 | .div_trunc, .div_exact => { |
| | 1656 | // TODO optimize integer division by constants |
| | 1657 | return try self.binOpRegister(.sdiv, lhs, rhs, lhs_ty, rhs_ty, metadata); |
| | 1658 | }, |
| | 1659 | .div_floor => return self.fail("TODO div_floor on signed integers", .{}), |
| | 1660 | else => unreachable, |
| | 1661 | } |
| | 1662 | }, |
| | 1663 | .unsigned => { |
| | 1664 | // TODO optimize integer division by constants |
| | 1665 | return try self.binOpRegister(.udiv, lhs, rhs, lhs_ty, rhs_ty, metadata); |
| | 1666 | }, |
| | 1667 | } |
| | 1668 | } else { |
| | 1669 | return self.fail("TODO integer division for ints with bits > 64", .{}); |
| | 1670 | } |
| | 1671 | }, |
| | 1672 | else => unreachable, |
| | 1673 | } |
| | 1674 | }, |
| | 1675 | .rem, .mod => { |
| | 1676 | switch (lhs_ty.zigTypeTag()) { |
| | 1677 | .Float => return self.fail("TODO rem/mod on floats", .{}), |
| | 1678 | .Vector => return self.fail("TODO rem/mod on vectors", .{}), |
| | 1679 | .Int => { |
| | 1680 | assert(lhs_ty.eql(rhs_ty, mod)); |
| | 1681 | const int_info = lhs_ty.intInfo(self.target.*); |
| | 1682 | if (int_info.bits <= 32) { |
| | 1683 | switch (int_info.signedness) { |
| | 1684 | .signed => { |
| | 1685 | return self.fail("TODO rem/mod on signed integers", .{}); |
| | 1686 | }, |
| | 1687 | .unsigned => { |
| | 1688 | return self.fail("TODO rem/mod on unsigned integers", .{}); |
| | 1689 | }, |
| | 1690 | } |
| | 1691 | } else { |
| | 1692 | return self.fail("TODO rem/mod for integers with bits > 64", .{}); |
| | 1693 | } |
| | 1694 | }, |
| | 1695 | else => unreachable, |
| | 1696 | } |
| | 1697 | }, |
| 1632 | .addwrap, | 1698 | .addwrap, |
| 1633 | .subwrap, | 1699 | .subwrap, |
| 1634 | .mulwrap, | 1700 | .mulwrap, |
| ... | @@ -2300,24 +2366,6 @@ fn airShlWithOverflow(self: *Self, inst: Air.Inst.Index) !void { | ... | @@ -2300,24 +2366,6 @@ fn airShlWithOverflow(self: *Self, inst: Air.Inst.Index) !void { |
| 2300 | return self.finishAir(inst, result, .{ extra.lhs, extra.rhs, .none }); | 2366 | return self.finishAir(inst, result, .{ extra.lhs, extra.rhs, .none }); |
| 2301 | } | 2367 | } |
| 2302 | | 2368 | |
| 2303 | fn airDiv(self: *Self, inst: Air.Inst.Index) !void { | | |
| 2304 | const bin_op = self.air.instructions.items(.data)[inst].bin_op; | | |
| 2305 | const result: MCValue = if (self.liveness.isUnused(inst)) .dead else return self.fail("TODO implement div for {}", .{self.target.cpu.arch}); | | |
| 2306 | return self.finishAir(inst, result, .{ bin_op.lhs, bin_op.rhs, .none }); | | |
| 2307 | } | | |
| 2308 | | | |
| 2309 | fn airRem(self: *Self, inst: Air.Inst.Index) !void { | | |
| 2310 | const bin_op = self.air.instructions.items(.data)[inst].bin_op; | | |
| 2311 | const result: MCValue = if (self.liveness.isUnused(inst)) .dead else return self.fail("TODO implement rem for {}", .{self.target.cpu.arch}); | | |
| 2312 | return self.finishAir(inst, result, .{ bin_op.lhs, bin_op.rhs, .none }); | | |
| 2313 | } | | |
| 2314 | | | |
| 2315 | fn airMod(self: *Self, inst: Air.Inst.Index) !void { | | |
| 2316 | const bin_op = self.air.instructions.items(.data)[inst].bin_op; | | |
| 2317 | const result: MCValue = if (self.liveness.isUnused(inst)) .dead else return self.fail("TODO implement mod for {}", .{self.target.cpu.arch}); | | |
| 2318 | return self.finishAir(inst, result, .{ bin_op.lhs, bin_op.rhs, .none }); | | |
| 2319 | } | | |
| 2320 | | | |
| 2321 | fn airShlSat(self: *Self, inst: Air.Inst.Index) !void { | 2369 | fn airShlSat(self: *Self, inst: Air.Inst.Index) !void { |
| 2322 | const bin_op = self.air.instructions.items(.data)[inst].bin_op; | 2370 | const bin_op = self.air.instructions.items(.data)[inst].bin_op; |
| 2323 | const result: MCValue = if (self.liveness.isUnused(inst)) .dead else return self.fail("TODO implement shl_sat for {}", .{self.target.cpu.arch}); | 2371 | const result: MCValue = if (self.liveness.isUnused(inst)) .dead else return self.fail("TODO implement shl_sat for {}", .{self.target.cpu.arch}); |