| ... | @@ -502,10 +502,10 @@ fn genBody(self: *Self, body: []const Air.Inst.Index) InnerError!void { | ... | @@ -502,10 +502,10 @@ fn genBody(self: *Self, body: []const Air.Inst.Index) InnerError!void { |
| 502 | | 502 | |
| 503 | switch (air_tags[inst]) { | 503 | switch (air_tags[inst]) { |
| 504 | // zig fmt: off | 504 | // zig fmt: off |
| 505 | .add, .ptr_add => try self.airAdd(inst), | 505 | .add, .ptr_add => try self.airBinOp(inst), |
| 506 | .addwrap => try self.airAddWrap(inst), | 506 | .addwrap => try self.airAddWrap(inst), |
| 507 | .add_sat => try self.airAddSat(inst), | 507 | .add_sat => try self.airAddSat(inst), |
| 508 | .sub, .ptr_sub => try self.airSub(inst), | 508 | .sub, .ptr_sub => try self.airBinOp(inst), |
| 509 | .subwrap => try self.airSubWrap(inst), | 509 | .subwrap => try self.airSubWrap(inst), |
| 510 | .sub_sat => try self.airSubSat(inst), | 510 | .sub_sat => try self.airSubSat(inst), |
| 511 | .mul => try self.airMul(inst), | 511 | .mul => try self.airMul(inst), |
| ... | @@ -943,9 +943,15 @@ fn airSlice(self: *Self, inst: Air.Inst.Index) !void { | ... | @@ -943,9 +943,15 @@ fn airSlice(self: *Self, inst: Air.Inst.Index) !void { |
| 943 | return self.finishAir(inst, result, .{ bin_op.lhs, bin_op.rhs, .none }); | 943 | return self.finishAir(inst, result, .{ bin_op.lhs, bin_op.rhs, .none }); |
| 944 | } | 944 | } |
| 945 | | 945 | |
| 946 | fn airAdd(self: *Self, inst: Air.Inst.Index) !void { | 946 | fn airBinOp(self: *Self, inst: Air.Inst.Index) !void { |
| | 947 | const tag = self.air.instructions.items(.tag)[inst]; |
| 947 | const bin_op = self.air.instructions.items(.data)[inst].bin_op; | 948 | const bin_op = self.air.instructions.items(.data)[inst].bin_op; |
| 948 | const result: MCValue = if (self.liveness.isUnused(inst)) .dead else try self.genBinOp(inst, bin_op.lhs, bin_op.rhs, .add); | 949 | const lhs = try self.resolveInst(bin_op.lhs); |
| | 950 | const rhs = try self.resolveInst(bin_op.rhs); |
| | 951 | const lhs_ty = self.air.typeOf(bin_op.lhs); |
| | 952 | const rhs_ty = self.air.typeOf(bin_op.rhs); |
| | 953 | |
| | 954 | const result: MCValue = if (self.liveness.isUnused(inst)) .dead else try self.binOp(tag, inst, lhs, rhs, lhs_ty, rhs_ty); |
| 949 | return self.finishAir(inst, result, .{ bin_op.lhs, bin_op.rhs, .none }); | 955 | return self.finishAir(inst, result, .{ bin_op.lhs, bin_op.rhs, .none }); |
| 950 | } | 956 | } |
| 951 | | 957 | |
| ... | @@ -961,12 +967,6 @@ fn airAddSat(self: *Self, inst: Air.Inst.Index) !void { | ... | @@ -961,12 +967,6 @@ fn airAddSat(self: *Self, inst: Air.Inst.Index) !void { |
| 961 | return self.finishAir(inst, result, .{ bin_op.lhs, bin_op.rhs, .none }); | 967 | return self.finishAir(inst, result, .{ bin_op.lhs, bin_op.rhs, .none }); |
| 962 | } | 968 | } |
| 963 | | 969 | |
| 964 | fn airSub(self: *Self, inst: Air.Inst.Index) !void { | | |
| 965 | const bin_op = self.air.instructions.items(.data)[inst].bin_op; | | |
| 966 | const result: MCValue = if (self.liveness.isUnused(inst)) .dead else try self.genBinOp(inst, bin_op.lhs, bin_op.rhs, .sub); | | |
| 967 | return self.finishAir(inst, result, .{ bin_op.lhs, bin_op.rhs, .none }); | | |
| 968 | } | | |
| 969 | | | |
| 970 | fn airSubWrap(self: *Self, inst: Air.Inst.Index) !void { | 970 | fn airSubWrap(self: *Self, inst: Air.Inst.Index) !void { |
| 971 | const bin_op = self.air.instructions.items(.data)[inst].bin_op; | 971 | const bin_op = self.air.instructions.items(.data)[inst].bin_op; |
| 972 | const result: MCValue = if (self.liveness.isUnused(inst)) .dead else return self.fail("TODO implement subwrap for {}", .{self.target.cpu.arch}); | 972 | const result: MCValue = if (self.liveness.isUnused(inst)) .dead else return self.fail("TODO implement subwrap for {}", .{self.target.cpu.arch}); |
| ... | @@ -1311,18 +1311,14 @@ fn airSliceElemVal(self: *Self, inst: Air.Inst.Index) !void { | ... | @@ -1311,18 +1311,14 @@ fn airSliceElemVal(self: *Self, inst: Air.Inst.Index) !void { |
| 1311 | assert(offset_mcv == .register); // result of multiplication should always be register | 1311 | assert(offset_mcv == .register); // result of multiplication should always be register |
| 1312 | self.register_manager.freezeRegs(&.{offset_mcv.register}); | 1312 | self.register_manager.freezeRegs(&.{offset_mcv.register}); |
| 1313 | | 1313 | |
| 1314 | const addr_reg = try self.register_manager.allocReg(null); | 1314 | const addr_mcv = try self.binOp(.add, null, base_mcv, offset_mcv, Type.usize, Type.usize); |
| 1315 | self.register_manager.freezeRegs(&.{addr_reg}); | | |
| 1316 | defer self.register_manager.unfreezeRegs(&.{addr_reg}); | | |
| 1317 | | | |
| 1318 | try self.genBinOpCode(addr_reg, base_mcv, offset_mcv, false, .add, .unsigned); | | |
| 1319 | | 1315 | |
| 1320 | // At this point in time, neither the base register | 1316 | // At this point in time, neither the base register |
| 1321 | // nor the offset register contains any valuable data | 1317 | // nor the offset register contains any valuable data |
| 1322 | // anymore. | 1318 | // anymore. |
| 1323 | self.register_manager.unfreezeRegs(&.{ base_mcv.register, offset_mcv.register }); | 1319 | self.register_manager.unfreezeRegs(&.{ base_mcv.register, offset_mcv.register }); |
| 1324 | | 1320 | |
| 1325 | try self.load(dst_mcv, .{ .register = addr_reg }, slice_ptr_field_type); | 1321 | try self.load(dst_mcv, addr_mcv, slice_ptr_field_type); |
| 1326 | | 1322 | |
| 1327 | break :result dst_mcv; | 1323 | break :result dst_mcv; |
| 1328 | }, | 1324 | }, |
| ... | @@ -1652,16 +1648,16 @@ fn structFieldPtr(self: *Self, inst: Air.Inst.Index, operand: Air.Inst.Ref, inde | ... | @@ -1652,16 +1648,16 @@ fn structFieldPtr(self: *Self, inst: Air.Inst.Index, operand: Air.Inst.Ref, inde |
| 1652 | self.register_manager.freezeRegs(&.{addr_reg}); | 1648 | self.register_manager.freezeRegs(&.{addr_reg}); |
| 1653 | defer self.register_manager.unfreezeRegs(&.{addr_reg}); | 1649 | defer self.register_manager.unfreezeRegs(&.{addr_reg}); |
| 1654 | | 1650 | |
| 1655 | const dst_reg = try self.register_manager.allocReg(inst); | 1651 | const dest = try self.binOp( |
| 1656 | try self.genBinOpCode( | 1652 | .add, |
| 1657 | dst_reg, | 1653 | null, |
| 1658 | .{ .register = addr_reg }, | 1654 | .{ .register = addr_reg }, |
| 1659 | .{ .register = offset_reg }, | 1655 | .{ .register = offset_reg }, |
| 1660 | false, | 1656 | Type.usize, |
| 1661 | .add, | 1657 | Type.usize, |
| 1662 | .unsigned, | | |
| 1663 | ); | 1658 | ); |
| 1664 | break :result MCValue{ .register = dst_reg }; | 1659 | |
| | 1660 | break :result dest; |
| 1665 | }, | 1661 | }, |
| 1666 | } | 1662 | } |
| 1667 | }; | 1663 | }; |
| ... | @@ -1699,6 +1695,273 @@ fn airStructFieldVal(self: *Self, inst: Air.Inst.Index) !void { | ... | @@ -1699,6 +1695,273 @@ fn airStructFieldVal(self: *Self, inst: Air.Inst.Index) !void { |
| 1699 | return self.finishAir(inst, result, .{ extra.struct_operand, .none, .none }); | 1695 | return self.finishAir(inst, result, .{ extra.struct_operand, .none, .none }); |
| 1700 | } | 1696 | } |
| 1701 | | 1697 | |
| | 1698 | /// Don't call this function directly. Use binOp instead. |
| | 1699 | /// |
| | 1700 | /// Calling this function signals an intention to generate a Mir |
| | 1701 | /// instruction of the form |
| | 1702 | /// |
| | 1703 | /// op dest, lhs, rhs |
| | 1704 | /// |
| | 1705 | /// Asserts that generating an instruction of that form is possible. |
| | 1706 | fn binOpRegister( |
| | 1707 | self: *Self, |
| | 1708 | tag: Air.Inst.Tag, |
| | 1709 | maybe_inst: ?Air.Inst.Index, |
| | 1710 | lhs: MCValue, |
| | 1711 | rhs: MCValue, |
| | 1712 | lhs_ty: Type, |
| | 1713 | rhs_ty: Type, |
| | 1714 | ) !MCValue { |
| | 1715 | const lhs_is_register = lhs == .register; |
| | 1716 | const rhs_is_register = rhs == .register; |
| | 1717 | |
| | 1718 | if (lhs_is_register) self.register_manager.freezeRegs(&.{lhs.register}); |
| | 1719 | if (rhs_is_register) self.register_manager.freezeRegs(&.{rhs.register}); |
| | 1720 | |
| | 1721 | const branch = &self.branch_stack.items[self.branch_stack.items.len - 1]; |
| | 1722 | |
| | 1723 | const lhs_reg = if (lhs_is_register) lhs.register else blk: { |
| | 1724 | const track_inst: ?Air.Inst.Index = if (maybe_inst) |inst| inst: { |
| | 1725 | const bin_op = self.air.instructions.items(.data)[inst].bin_op; |
| | 1726 | break :inst Air.refToIndex(bin_op.lhs).?; |
| | 1727 | } else null; |
| | 1728 | |
| | 1729 | const reg = try self.register_manager.allocReg(track_inst); |
| | 1730 | self.register_manager.freezeRegs(&.{reg}); |
| | 1731 | |
| | 1732 | if (track_inst) |inst| branch.inst_table.putAssumeCapacity(inst, .{ .register = reg }); |
| | 1733 | |
| | 1734 | break :blk reg; |
| | 1735 | }; |
| | 1736 | defer self.register_manager.unfreezeRegs(&.{lhs_reg}); |
| | 1737 | |
| | 1738 | const rhs_reg = if (rhs_is_register) rhs.register else blk: { |
| | 1739 | const track_inst: ?Air.Inst.Index = if (maybe_inst) |inst| inst: { |
| | 1740 | const bin_op = self.air.instructions.items(.data)[inst].bin_op; |
| | 1741 | break :inst Air.refToIndex(bin_op.rhs).?; |
| | 1742 | } else null; |
| | 1743 | |
| | 1744 | const reg = try self.register_manager.allocReg(track_inst); |
| | 1745 | self.register_manager.freezeRegs(&.{reg}); |
| | 1746 | |
| | 1747 | if (track_inst) |inst| branch.inst_table.putAssumeCapacity(inst, .{ .register = reg }); |
| | 1748 | |
| | 1749 | break :blk reg; |
| | 1750 | }; |
| | 1751 | defer self.register_manager.unfreezeRegs(&.{rhs_reg}); |
| | 1752 | |
| | 1753 | const dest_reg = if (maybe_inst) |inst| blk: { |
| | 1754 | const bin_op = self.air.instructions.items(.data)[inst].bin_op; |
| | 1755 | |
| | 1756 | if (lhs_is_register and self.reuseOperand(inst, bin_op.lhs, 0, lhs)) { |
| | 1757 | break :blk lhs_reg; |
| | 1758 | } else if (rhs_is_register and self.reuseOperand(inst, bin_op.rhs, 1, rhs)) { |
| | 1759 | break :blk rhs_reg; |
| | 1760 | } else { |
| | 1761 | break :blk try self.register_manager.allocReg(inst); |
| | 1762 | } |
| | 1763 | } else try self.register_manager.allocReg(null); |
| | 1764 | |
| | 1765 | if (!lhs_is_register) try self.genSetReg(lhs_ty, lhs_reg, lhs); |
| | 1766 | if (!rhs_is_register) try self.genSetReg(rhs_ty, rhs_reg, rhs); |
| | 1767 | |
| | 1768 | const mir_tag: Mir.Inst.Tag = switch (tag) { |
| | 1769 | .add, .ptr_add => .add, |
| | 1770 | .sub, .ptr_sub => .sub, |
| | 1771 | else => unreachable, |
| | 1772 | }; |
| | 1773 | const mir_data: Mir.Inst.Data = switch (tag) { |
| | 1774 | .add, |
| | 1775 | .sub, |
| | 1776 | .ptr_add, |
| | 1777 | .ptr_sub, |
| | 1778 | => .{ .rr_op = .{ |
| | 1779 | .rd = dest_reg, |
| | 1780 | .rn = lhs_reg, |
| | 1781 | .op = Instruction.Operand.reg(rhs_reg, Instruction.Operand.Shift.none), |
| | 1782 | } }, |
| | 1783 | else => unreachable, |
| | 1784 | }; |
| | 1785 | |
| | 1786 | _ = try self.addInst(.{ |
| | 1787 | .tag = mir_tag, |
| | 1788 | .data = mir_data, |
| | 1789 | }); |
| | 1790 | |
| | 1791 | return MCValue{ .register = dest_reg }; |
| | 1792 | } |
| | 1793 | |
| | 1794 | /// Don't call this function directly. Use binOp instead. |
| | 1795 | /// |
| | 1796 | /// Calling this function signals an intention to generate a Mir |
| | 1797 | /// instruction of the form |
| | 1798 | /// |
| | 1799 | /// op dest, lhs, #rhs_imm |
| | 1800 | /// |
| | 1801 | /// Set lhs_and_rhs_swapped to true iff inst.bin_op.lhs corresponds to |
| | 1802 | /// rhs and vice versa. This parameter is only used when maybe_inst != |
| | 1803 | /// null. |
| | 1804 | /// |
| | 1805 | /// Asserts that generating an instruction of that form is possible. |
| | 1806 | fn binOpImmediate( |
| | 1807 | self: *Self, |
| | 1808 | tag: Air.Inst.Tag, |
| | 1809 | maybe_inst: ?Air.Inst.Index, |
| | 1810 | lhs: MCValue, |
| | 1811 | rhs: MCValue, |
| | 1812 | lhs_ty: Type, |
| | 1813 | lhs_and_rhs_swapped: bool, |
| | 1814 | ) !MCValue { |
| | 1815 | const lhs_is_register = lhs == .register; |
| | 1816 | |
| | 1817 | if (lhs_is_register) self.register_manager.freezeRegs(&.{lhs.register}); |
| | 1818 | |
| | 1819 | const branch = &self.branch_stack.items[self.branch_stack.items.len - 1]; |
| | 1820 | |
| | 1821 | const lhs_reg = if (lhs_is_register) lhs.register else blk: { |
| | 1822 | const track_inst: ?Air.Inst.Index = if (maybe_inst) |inst| inst: { |
| | 1823 | const bin_op = self.air.instructions.items(.data)[inst].bin_op; |
| | 1824 | break :inst Air.refToIndex( |
| | 1825 | if (lhs_and_rhs_swapped) bin_op.rhs else bin_op.lhs, |
| | 1826 | ).?; |
| | 1827 | } else null; |
| | 1828 | |
| | 1829 | const reg = try self.register_manager.allocReg(track_inst); |
| | 1830 | self.register_manager.freezeRegs(&.{reg}); |
| | 1831 | |
| | 1832 | if (track_inst) |inst| branch.inst_table.putAssumeCapacity(inst, .{ .register = reg }); |
| | 1833 | |
| | 1834 | break :blk reg; |
| | 1835 | }; |
| | 1836 | defer self.register_manager.unfreezeRegs(&.{lhs_reg}); |
| | 1837 | |
| | 1838 | const dest_reg = if (maybe_inst) |inst| blk: { |
| | 1839 | const bin_op = self.air.instructions.items(.data)[inst].bin_op; |
| | 1840 | |
| | 1841 | if (lhs_is_register and self.reuseOperand( |
| | 1842 | inst, |
| | 1843 | if (lhs_and_rhs_swapped) bin_op.rhs else bin_op.lhs, |
| | 1844 | if (lhs_and_rhs_swapped) 1 else 0, |
| | 1845 | lhs, |
| | 1846 | )) { |
| | 1847 | break :blk lhs_reg; |
| | 1848 | } else { |
| | 1849 | break :blk try self.register_manager.allocReg(inst); |
| | 1850 | } |
| | 1851 | } else try self.register_manager.allocReg(null); |
| | 1852 | |
| | 1853 | if (!lhs_is_register) try self.genSetReg(lhs_ty, lhs_reg, lhs); |
| | 1854 | |
| | 1855 | const mir_tag: Mir.Inst.Tag = switch (tag) { |
| | 1856 | .add => .add, |
| | 1857 | .sub => .sub, |
| | 1858 | else => unreachable, |
| | 1859 | }; |
| | 1860 | const mir_data: Mir.Inst.Data = switch (tag) { |
| | 1861 | .add, |
| | 1862 | .sub, |
| | 1863 | => .{ .rr_op = .{ |
| | 1864 | .rd = dest_reg, |
| | 1865 | .rn = lhs_reg, |
| | 1866 | .op = Instruction.Operand.fromU32(rhs.immediate).?, |
| | 1867 | } }, |
| | 1868 | else => unreachable, |
| | 1869 | }; |
| | 1870 | |
| | 1871 | _ = try self.addInst(.{ |
| | 1872 | .tag = mir_tag, |
| | 1873 | .data = mir_data, |
| | 1874 | }); |
| | 1875 | |
| | 1876 | return MCValue{ .register = dest_reg }; |
| | 1877 | } |
| | 1878 | |
| | 1879 | /// For all your binary operation needs, this function will generate |
| | 1880 | /// the corresponding Mir instruction(s). Returns the location of the |
| | 1881 | /// result. |
| | 1882 | /// |
| | 1883 | /// If the binary operation itself happens to be an Air instruction, |
| | 1884 | /// pass the corresponding index in the inst parameter. That helps |
| | 1885 | /// this function do stuff like reusing operands. |
| | 1886 | /// |
| | 1887 | /// This function does not do any lowering to Mir itself, but instead |
| | 1888 | /// looks at the lhs and rhs and determines which kind of lowering |
| | 1889 | /// would be best suitable and then delegates the lowering to other |
| | 1890 | /// functions. |
| | 1891 | fn binOp( |
| | 1892 | self: *Self, |
| | 1893 | tag: Air.Inst.Tag, |
| | 1894 | maybe_inst: ?Air.Inst.Index, |
| | 1895 | lhs: MCValue, |
| | 1896 | rhs: MCValue, |
| | 1897 | lhs_ty: Type, |
| | 1898 | rhs_ty: Type, |
| | 1899 | ) !MCValue { |
| | 1900 | switch (tag) { |
| | 1901 | .add, |
| | 1902 | .sub, |
| | 1903 | => { |
| | 1904 | switch (lhs_ty.zigTypeTag()) { |
| | 1905 | .Float => return self.fail("TODO ARM binary operations on floats", .{}), |
| | 1906 | .Vector => return self.fail("TODO ARM binary operations on vectors", .{}), |
| | 1907 | .Int => { |
| | 1908 | assert(lhs_ty.eql(rhs_ty)); |
| | 1909 | const int_info = lhs_ty.intInfo(self.target.*); |
| | 1910 | if (int_info.bits <= 32) { |
| | 1911 | // Only say yes if the operation is |
| | 1912 | // commutative, i.e. we can swap both of the |
| | 1913 | // operands |
| | 1914 | const lhs_immediate_ok = switch (tag) { |
| | 1915 | .add => lhs == .immediate and Instruction.Operand.fromU32(lhs.immediate) != null, |
| | 1916 | .sub => false, |
| | 1917 | else => unreachable, |
| | 1918 | }; |
| | 1919 | const rhs_immediate_ok = switch (tag) { |
| | 1920 | .add, |
| | 1921 | .sub, |
| | 1922 | => rhs == .immediate and Instruction.Operand.fromU32(rhs.immediate) != null, |
| | 1923 | else => unreachable, |
| | 1924 | }; |
| | 1925 | |
| | 1926 | if (rhs_immediate_ok) { |
| | 1927 | return try self.binOpImmediate(tag, maybe_inst, lhs, rhs, lhs_ty, false); |
| | 1928 | } else if (lhs_immediate_ok) { |
| | 1929 | // swap lhs and rhs |
| | 1930 | return try self.binOpImmediate(tag, maybe_inst, rhs, lhs, rhs_ty, true); |
| | 1931 | } else { |
| | 1932 | return try self.binOpRegister(tag, maybe_inst, lhs, rhs, lhs_ty, rhs_ty); |
| | 1933 | } |
| | 1934 | } else { |
| | 1935 | return self.fail("TODO ARM binary operations on integers > u32/i32", .{}); |
| | 1936 | } |
| | 1937 | }, |
| | 1938 | else => unreachable, |
| | 1939 | } |
| | 1940 | }, |
| | 1941 | .ptr_add, |
| | 1942 | .ptr_sub, |
| | 1943 | => { |
| | 1944 | switch (lhs_ty.zigTypeTag()) { |
| | 1945 | .Pointer => { |
| | 1946 | const ptr_ty = lhs_ty; |
| | 1947 | const pointee_ty = switch (ptr_ty.ptrSize()) { |
| | 1948 | .One => ptr_ty.childType().childType(), // ptr to array, so get array element type |
| | 1949 | else => ptr_ty.childType(), |
| | 1950 | }; |
| | 1951 | |
| | 1952 | if (pointee_ty.abiSize(self.target.*) > 1) { |
| | 1953 | return self.fail("TODO ptr_add, ptr_sub with more element sizes", .{}); |
| | 1954 | } |
| | 1955 | |
| | 1956 | return try self.binOpRegister(tag, maybe_inst, lhs, rhs, lhs_ty, rhs_ty); |
| | 1957 | }, |
| | 1958 | else => unreachable, |
| | 1959 | } |
| | 1960 | }, |
| | 1961 | else => unreachable, |
| | 1962 | } |
| | 1963 | } |
| | 1964 | |
| 1702 | fn armOperandShouldBeRegister(self: *Self, mcv: MCValue) !bool { | 1965 | fn armOperandShouldBeRegister(self: *Self, mcv: MCValue) !bool { |
| 1703 | return switch (mcv) { | 1966 | return switch (mcv) { |
| 1704 | .none => unreachable, | 1967 | .none => unreachable, |
| ... | @@ -1730,8 +1993,6 @@ fn genBinOp(self: *Self, inst: Air.Inst.Index, op_lhs: Air.Inst.Ref, op_rhs: Air | ... | @@ -1730,8 +1993,6 @@ fn genBinOp(self: *Self, inst: Air.Inst.Index, op_lhs: Air.Inst.Ref, op_rhs: Air |
| 1730 | const ty = self.air.typeOf(op_lhs); | 1993 | const ty = self.air.typeOf(op_lhs); |
| 1731 | | 1994 | |
| 1732 | switch (ty.zigTypeTag()) { | 1995 | switch (ty.zigTypeTag()) { |
| 1733 | .Float => return self.fail("TODO ARM binary operations on floats", .{}), | | |
| 1734 | .Vector => return self.fail("TODO ARM binary operations on vectors", .{}), | | |
| 1735 | .Bool => { | 1996 | .Bool => { |
| 1736 | return self.genBinIntOp(inst, op_lhs, op_rhs, op, 1, .unsigned); | 1997 | return self.genBinIntOp(inst, op_lhs, op_rhs, op, 1, .unsigned); |
| 1737 | }, | 1998 | }, |
| ... | @@ -1896,7 +2157,6 @@ fn genBinOpCode( | ... | @@ -1896,7 +2157,6 @@ fn genBinOpCode( |
| 1896 | }; | 2157 | }; |
| 1897 | | 2158 | |
| 1898 | switch (op) { | 2159 | switch (op) { |
| 1899 | .add, | | |
| 1900 | .bool_and, | 2160 | .bool_and, |
| 1901 | .bit_and, | 2161 | .bit_and, |
| 1902 | .bool_or, | 2162 | .bool_or, |
| ... | @@ -1905,7 +2165,6 @@ fn genBinOpCode( | ... | @@ -1905,7 +2165,6 @@ fn genBinOpCode( |
| 1905 | .xor, | 2165 | .xor, |
| 1906 | => { | 2166 | => { |
| 1907 | const tag: Mir.Inst.Tag = switch (op) { | 2167 | const tag: Mir.Inst.Tag = switch (op) { |
| 1908 | .add => .add, | | |
| 1909 | .bool_and, .bit_and => .@"and", | 2168 | .bool_and, .bit_and => .@"and", |
| 1910 | .bool_or, .bit_or => .orr, | 2169 | .bool_or, .bit_or => .orr, |
| 1911 | .not, .xor => .eor, | 2170 | .not, .xor => .eor, |
| ... | @@ -1921,18 +2180,6 @@ fn genBinOpCode( | ... | @@ -1921,18 +2180,6 @@ fn genBinOpCode( |
| 1921 | } }, | 2180 | } }, |
| 1922 | }); | 2181 | }); |
| 1923 | }, | 2182 | }, |
| 1924 | .sub => { | | |
| 1925 | const tag: Mir.Inst.Tag = if (swap_lhs_and_rhs) .rsb else .sub; | | |
| 1926 | | | |
| 1927 | _ = try self.addInst(.{ | | |
| 1928 | .tag = tag, | | |
| 1929 | .data = .{ .rr_op = .{ | | |
| 1930 | .rd = dst_reg, | | |
| 1931 | .rn = op1, | | |
| 1932 | .op = operand, | | |
| 1933 | } }, | | |
| 1934 | }); | | |
| 1935 | }, | | |
| 1936 | .cmp_eq => { | 2183 | .cmp_eq => { |
| 1937 | _ = try self.addInst(.{ | 2184 | _ = try self.addInst(.{ |
| 1938 | .tag = .cmp, | 2185 | .tag = .cmp, |