| ... | ... | @@ -1601,7 +1601,6 @@ fn allocReg(self: *Self) !struct { Register, RegisterLock } { |
| 1601 | 1601 | } |
| 1602 | 1602 | |
| 1603 | 1603 | fn elemOffset(self: *Self, index_ty: Type, index: MCValue, elem_size: u64) !Register { |
| 1604 | | log.debug("elemOffset: {}", .{index}); |
| 1605 | 1604 | const reg: Register = blk: { |
| 1606 | 1605 | switch (index) { |
| 1607 | 1606 | .immediate => |imm| { |
| ... | ... | @@ -1616,14 +1615,14 @@ fn elemOffset(self: *Self, index_ty: Type, index: MCValue, elem_size: u64) !Regi |
| 1616 | 1615 | const lock = self.register_manager.lockRegAssumeUnused(reg); |
| 1617 | 1616 | defer self.register_manager.unlockReg(lock); |
| 1618 | 1617 | |
| 1619 | | try self.binOpMir( |
| 1618 | const result = try self.binOp( |
| 1620 | 1619 | .mul, |
| 1621 | | null, |
| 1622 | | index_ty, |
| 1623 | 1620 | .{ .register = reg }, |
| 1621 | index_ty, |
| 1624 | 1622 | .{ .immediate = elem_size }, |
| 1623 | index_ty, |
| 1625 | 1624 | ); |
| 1626 | | break :blk reg; |
| 1625 | break :blk result.register; |
| 1627 | 1626 | }, |
| 1628 | 1627 | } |
| 1629 | 1628 | }; |
| ... | ... | @@ -1817,24 +1816,10 @@ fn airBinOp(self: *Self, inst: Air.Inst.Index, tag: Air.Inst.Tag) !void { |
| 1817 | 1816 | const lhs_ty = self.typeOf(bin_op.lhs); |
| 1818 | 1817 | const rhs_ty = self.typeOf(bin_op.rhs); |
| 1819 | 1818 | |
| 1820 | | const result: MCValue = if (self.liveness.isUnused(inst)) .unreach else try self.binOp(tag, inst, lhs, rhs, lhs_ty, rhs_ty); |
| 1821 | | return self.finishAir(inst, result, .{ bin_op.lhs, bin_op.rhs, .none }); |
| 1822 | | } |
| 1823 | | |
| 1824 | | fn supportImmediate(tag: Air.Inst.Tag) bool { |
| 1825 | | return switch (tag) { |
| 1826 | | .add, |
| 1827 | | .sub, |
| 1828 | | .cmp_eq, |
| 1829 | | .cmp_neq, |
| 1830 | | .cmp_gt, |
| 1831 | | .cmp_gte, |
| 1832 | | .cmp_lt, |
| 1833 | | .cmp_lte, |
| 1834 | | => true, |
| 1835 | | |
| 1836 | | else => false, |
| 1819 | const result: MCValue = if (self.liveness.isUnused(inst)) .unreach else result: { |
| 1820 | break :result try self.binOp(tag, lhs, lhs_ty, rhs, rhs_ty); |
| 1837 | 1821 | }; |
| 1822 | return self.finishAir(inst, result, .{ bin_op.lhs, bin_op.rhs, .none }); |
| 1838 | 1823 | } |
| 1839 | 1824 | |
| 1840 | 1825 | /// For all your binary operation needs, this function will generate |
| ... | ... | @@ -1854,10 +1839,9 @@ fn supportImmediate(tag: Air.Inst.Tag) bool { |
| 1854 | 1839 | fn binOp( |
| 1855 | 1840 | self: *Self, |
| 1856 | 1841 | tag: Air.Inst.Tag, |
| 1857 | | maybe_inst: ?Air.Inst.Index, |
| 1858 | 1842 | lhs: MCValue, |
| 1859 | | rhs: MCValue, |
| 1860 | 1843 | lhs_ty: Type, |
| 1844 | rhs: MCValue, |
| 1861 | 1845 | rhs_ty: Type, |
| 1862 | 1846 | ) InnerError!MCValue { |
| 1863 | 1847 | const zcu = self.bin_file.comp.module.?; |
| ... | ... | @@ -1881,15 +1865,12 @@ fn binOp( |
| 1881 | 1865 | assert(lhs_ty.eql(rhs_ty, zcu)); |
| 1882 | 1866 | const int_info = lhs_ty.intInfo(zcu); |
| 1883 | 1867 | if (int_info.bits <= 64) { |
| 1884 | | if (rhs == .immediate and supportImmediate(tag)) { |
| 1885 | | return self.binOpImm(tag, maybe_inst, lhs, rhs, lhs_ty, rhs_ty); |
| 1886 | | } |
| 1887 | | return self.binOpRegister(tag, maybe_inst, lhs, rhs, lhs_ty, rhs_ty); |
| 1868 | return self.binOpRegister(tag, lhs, lhs_ty, rhs, rhs_ty); |
| 1888 | 1869 | } else { |
| 1889 | 1870 | return self.fail("TODO binary operations on int with bits > 64", .{}); |
| 1890 | 1871 | } |
| 1891 | 1872 | }, |
| 1892 | | else => |x| return self.fail("TOOD: binOp {s}", .{@tagName(x)}), |
| 1873 | else => |x| return std.debug.panic("TOOD: binOp {s}", .{@tagName(x)}), |
| 1893 | 1874 | } |
| 1894 | 1875 | }, |
| 1895 | 1876 | |
| ... | ... | @@ -1912,23 +1893,21 @@ fn binOp( |
| 1912 | 1893 | else => unreachable, |
| 1913 | 1894 | }; |
| 1914 | 1895 | |
| 1915 | | return try self.binOpRegister(base_tag, maybe_inst, lhs, rhs, lhs_ty, rhs_ty); |
| 1896 | return try self.binOpRegister(base_tag, lhs, lhs_ty, rhs, rhs_ty); |
| 1916 | 1897 | } else { |
| 1917 | 1898 | const offset = try self.binOp( |
| 1918 | 1899 | .mul, |
| 1919 | | null, |
| 1920 | 1900 | rhs, |
| 1921 | | .{ .immediate = elem_size }, |
| 1922 | 1901 | Type.usize, |
| 1902 | .{ .immediate = elem_size }, |
| 1923 | 1903 | Type.usize, |
| 1924 | 1904 | ); |
| 1925 | 1905 | |
| 1926 | 1906 | const addr = try self.binOp( |
| 1927 | 1907 | tag, |
| 1928 | | null, |
| 1929 | 1908 | lhs, |
| 1930 | | offset, |
| 1931 | 1909 | Type.manyptr_u8, |
| 1910 | offset, |
| 1932 | 1911 | Type.usize, |
| 1933 | 1912 | ); |
| 1934 | 1913 | return addr; |
| ... | ... | @@ -1948,10 +1927,7 @@ fn binOp( |
| 1948 | 1927 | .Int => { |
| 1949 | 1928 | const int_info = lhs_ty.intInfo(zcu); |
| 1950 | 1929 | if (int_info.bits <= 64) { |
| 1951 | | if (rhs == .immediate) { |
| 1952 | | return self.binOpImm(tag, maybe_inst, lhs, rhs, lhs_ty, rhs_ty); |
| 1953 | | } |
| 1954 | | return self.binOpRegister(tag, maybe_inst, lhs, rhs, lhs_ty, rhs_ty); |
| 1930 | return self.binOpRegister(tag, lhs, lhs_ty, rhs, rhs_ty); |
| 1955 | 1931 | } else { |
| 1956 | 1932 | return self.fail("TODO binary operations on int with bits > 64", .{}); |
| 1957 | 1933 | } |
| ... | ... | @@ -1973,14 +1949,11 @@ fn binOp( |
| 1973 | 1949 | fn binOpRegister( |
| 1974 | 1950 | self: *Self, |
| 1975 | 1951 | tag: Air.Inst.Tag, |
| 1976 | | maybe_inst: ?Air.Inst.Index, |
| 1977 | 1952 | lhs: MCValue, |
| 1978 | | rhs: MCValue, |
| 1979 | 1953 | lhs_ty: Type, |
| 1954 | rhs: MCValue, |
| 1980 | 1955 | rhs_ty: Type, |
| 1981 | 1956 | ) !MCValue { |
| 1982 | | _ = maybe_inst; |
| 1983 | | |
| 1984 | 1957 | const lhs_reg, const lhs_lock = blk: { |
| 1985 | 1958 | if (lhs == .register) break :blk .{ lhs.register, null }; |
| 1986 | 1959 | |
| ... | ... | @@ -2006,164 +1979,79 @@ fn binOpRegister( |
| 2006 | 1979 | .add => .add, |
| 2007 | 1980 | .sub => .sub, |
| 2008 | 1981 | .mul => .mul, |
| 2009 | | .cmp_eq => .cmp_eq, |
| 2010 | | .cmp_neq => .cmp_neq, |
| 2011 | | .cmp_gt => .cmp_gt, |
| 2012 | | .cmp_gte => .cmp_gte, |
| 2013 | | .cmp_lt => .cmp_lt, |
| 1982 | |
| 2014 | 1983 | .shl => .sllw, |
| 2015 | 1984 | .shr => .srlw, |
| 2016 | | else => return self.fail("TODO: binOpRegister {s}", .{@tagName(tag)}), |
| 2017 | | }; |
| 2018 | | |
| 2019 | | _ = try self.addInst(.{ |
| 2020 | | .tag = mir_tag, |
| 2021 | | .ops = .rrr, |
| 2022 | | .data = .{ |
| 2023 | | .r_type = .{ |
| 2024 | | .rd = dest_reg, |
| 2025 | | .rs1 = lhs_reg, |
| 2026 | | .rs2 = rhs_reg, |
| 2027 | | }, |
| 2028 | | }, |
| 2029 | | }); |
| 2030 | | |
| 2031 | | // generate the struct for OF checks |
| 2032 | 1985 | |
| 2033 | | return MCValue{ .register = dest_reg }; |
| 2034 | | } |
| 2035 | | |
| 2036 | | /// Don't call this function directly. Use binOp instead. |
| 2037 | | /// |
| 2038 | | /// Call this function if rhs is an immediate. Generates I version of binops. |
| 2039 | | /// |
| 2040 | | /// Asserts that rhs is an immediate MCValue |
| 2041 | | fn binOpImm( |
| 2042 | | self: *Self, |
| 2043 | | tag: Air.Inst.Tag, |
| 2044 | | maybe_inst: ?Air.Inst.Index, |
| 2045 | | lhs: MCValue, |
| 2046 | | rhs: MCValue, |
| 2047 | | lhs_ty: Type, |
| 2048 | | rhs_ty: Type, |
| 2049 | | ) !MCValue { |
| 2050 | | assert(rhs == .immediate); |
| 2051 | | _ = maybe_inst; |
| 2052 | | |
| 2053 | | // TODO: use `maybe_inst` to track instead of forcing a lock. |
| 2054 | | |
| 2055 | | const lhs_reg, const lhs_lock = blk: { |
| 2056 | | if (lhs == .register) break :blk .{ lhs.register, null }; |
| 2057 | | |
| 2058 | | const lhs_reg, const lhs_lock = try self.allocReg(); |
| 2059 | | try self.genSetReg(lhs_ty, lhs_reg, lhs); |
| 2060 | | break :blk .{ lhs_reg, lhs_lock }; |
| 2061 | | }; |
| 2062 | | defer if (lhs_lock) |lock| self.register_manager.unlockReg(lock); |
| 2063 | | |
| 2064 | | const dest_reg, const dest_lock = try self.allocReg(); |
| 2065 | | defer self.register_manager.unlockReg(dest_lock); |
| 1986 | .cmp_eq, |
| 1987 | .cmp_neq, |
| 1988 | .cmp_gt, |
| 1989 | .cmp_gte, |
| 1990 | .cmp_lt, |
| 1991 | => .pseudo, |
| 2066 | 1992 | |
| 2067 | | const mir_tag: Mir.Inst.Tag = switch (tag) { |
| 2068 | | .shl => .slli, |
| 2069 | | .shr => .srli, |
| 2070 | | .cmp_gte => .cmp_imm_gte, |
| 2071 | | .cmp_eq => .cmp_imm_eq, |
| 2072 | | .cmp_neq => .cmp_imm_neq, |
| 2073 | | .cmp_lte => .cmp_imm_lte, |
| 2074 | | .cmp_lt => .cmp_imm_lt, |
| 2075 | | .add => .addi, |
| 2076 | | .sub => .addiw, |
| 2077 | | else => return self.fail("TODO: binOpImm {s}", .{@tagName(tag)}), |
| 1993 | else => return self.fail("TODO: binOpRegister {s}", .{@tagName(tag)}), |
| 2078 | 1994 | }; |
| 2079 | 1995 | |
| 2080 | | // apply some special operations needed |
| 2081 | 1996 | switch (mir_tag) { |
| 2082 | | .slli, |
| 2083 | | .srli, |
| 2084 | | .addi, |
| 2085 | | .cmp_imm_eq, |
| 2086 | | .cmp_imm_neq, |
| 2087 | | .cmp_imm_lte, |
| 2088 | | .cmp_imm_lt, |
| 1997 | .add, |
| 1998 | .sub, |
| 1999 | .mul, |
| 2000 | .sllw, |
| 2001 | .srlw, |
| 2089 | 2002 | => { |
| 2090 | | _ = try self.addInst(.{ |
| 2091 | | .tag = mir_tag, |
| 2092 | | .ops = .rri, |
| 2093 | | .data = .{ .i_type = .{ |
| 2094 | | .rd = dest_reg, |
| 2095 | | .rs1 = lhs_reg, |
| 2096 | | .imm12 = Immediate.s(math.cast(i12, rhs.immediate) orelse { |
| 2097 | | return self.fail("TODO: binOpImm larger than i12 i_type payload", .{}); |
| 2098 | | }), |
| 2099 | | } }, |
| 2100 | | }); |
| 2101 | | }, |
| 2102 | | .addiw => { |
| 2103 | | _ = try self.addInst(.{ |
| 2104 | | .tag = mir_tag, |
| 2105 | | .ops = .rri, |
| 2106 | | .data = .{ .i_type = .{ |
| 2107 | | .rd = dest_reg, |
| 2108 | | .rs1 = lhs_reg, |
| 2109 | | .imm12 = Immediate.s(-(math.cast(i12, rhs.immediate) orelse { |
| 2110 | | return self.fail("TODO: binOpImm larger than i12 i_type payload", .{}); |
| 2111 | | })), |
| 2112 | | } }, |
| 2113 | | }); |
| 2114 | | }, |
| 2115 | | .cmp_imm_gte => { |
| 2116 | | const imm_reg = try self.copyToTmpRegister(rhs_ty, .{ .immediate = rhs.immediate - 1 }); |
| 2117 | | |
| 2118 | 2003 | _ = try self.addInst(.{ |
| 2119 | 2004 | .tag = mir_tag, |
| 2120 | 2005 | .ops = .rrr, |
| 2121 | | .data = .{ .r_type = .{ |
| 2122 | | .rd = dest_reg, |
| 2123 | | .rs1 = imm_reg, |
| 2124 | | .rs2 = lhs_reg, |
| 2125 | | } }, |
| 2006 | .data = .{ |
| 2007 | .r_type = .{ |
| 2008 | .rd = dest_reg, |
| 2009 | .rs1 = lhs_reg, |
| 2010 | .rs2 = rhs_reg, |
| 2011 | }, |
| 2012 | }, |
| 2126 | 2013 | }); |
| 2127 | 2014 | }, |
| 2128 | | else => unreachable, |
| 2129 | | } |
| 2130 | 2015 | |
| 2131 | | return MCValue{ .register = dest_reg }; |
| 2132 | | } |
| 2133 | | |
| 2134 | | fn binOpMir( |
| 2135 | | self: *Self, |
| 2136 | | mir_tag: Mir.Inst.Tag, |
| 2137 | | maybe_inst: ?Air.Inst.Index, |
| 2138 | | ty: Type, |
| 2139 | | dst_mcv: MCValue, |
| 2140 | | src_mcv: MCValue, |
| 2141 | | ) !void { |
| 2142 | | const zcu = self.bin_file.comp.module.?; |
| 2143 | | const abi_size: u32 = @intCast(ty.abiSize(zcu)); |
| 2144 | | |
| 2145 | | _ = abi_size; |
| 2146 | | _ = maybe_inst; |
| 2147 | | |
| 2148 | | switch (dst_mcv) { |
| 2149 | | .register => |dst_reg| { |
| 2150 | | const src_reg = try self.copyToTmpRegister(ty, src_mcv); |
| 2016 | .pseudo => { |
| 2017 | const pseudo_op = switch (tag) { |
| 2018 | .cmp_eq, |
| 2019 | .cmp_neq, |
| 2020 | .cmp_gt, |
| 2021 | .cmp_gte, |
| 2022 | .cmp_lt, |
| 2023 | => .pseudo_compare, |
| 2024 | else => unreachable, |
| 2025 | }; |
| 2151 | 2026 | |
| 2152 | 2027 | _ = try self.addInst(.{ |
| 2153 | | .tag = mir_tag, |
| 2154 | | .ops = .rrr, |
| 2028 | .tag = .pseudo, |
| 2029 | .ops = pseudo_op, |
| 2155 | 2030 | .data = .{ |
| 2156 | | .r_type = .{ |
| 2157 | | .rd = dst_reg, |
| 2158 | | .rs1 = dst_reg, |
| 2159 | | .rs2 = src_reg, |
| 2031 | .compare = .{ |
| 2032 | .rd = dest_reg, |
| 2033 | .rs1 = lhs_reg, |
| 2034 | .rs2 = rhs_reg, |
| 2035 | .op = switch (tag) { |
| 2036 | .cmp_eq => .eq, |
| 2037 | .cmp_neq => .neq, |
| 2038 | .cmp_gt => .gt, |
| 2039 | .cmp_gte => .gte, |
| 2040 | .cmp_lt => .lt, |
| 2041 | .cmp_lte => .lte, |
| 2042 | else => unreachable, |
| 2043 | }, |
| 2160 | 2044 | }, |
| 2161 | 2045 | }, |
| 2162 | 2046 | }); |
| 2163 | 2047 | }, |
| 2164 | 2048 | |
| 2165 | | else => return self.fail("TODO: binOpMir {s}", .{@tagName(dst_mcv)}), |
| 2049 | else => unreachable, |
| 2166 | 2050 | } |
| 2051 | |
| 2052 | // generate the struct for OF checks |
| 2053 | |
| 2054 | return MCValue{ .register = dest_reg }; |
| 2167 | 2055 | } |
| 2168 | 2056 | |
| 2169 | 2057 | fn airPtrArithmetic(self: *Self, inst: Air.Inst.Index, tag: Air.Inst.Tag) !void { |
| ... | ... | @@ -2174,7 +2062,9 @@ fn airPtrArithmetic(self: *Self, inst: Air.Inst.Index, tag: Air.Inst.Tag) !void |
| 2174 | 2062 | const lhs_ty = self.typeOf(bin_op.lhs); |
| 2175 | 2063 | const rhs_ty = self.typeOf(bin_op.rhs); |
| 2176 | 2064 | |
| 2177 | | const result: MCValue = if (self.liveness.isUnused(inst)) .unreach else try self.binOp(tag, inst, lhs, rhs, lhs_ty, rhs_ty); |
| 2065 | const result: MCValue = if (self.liveness.isUnused(inst)) .unreach else result: { |
| 2066 | break :result try self.binOp(tag, lhs, lhs_ty, rhs, rhs_ty); |
| 2067 | }; |
| 2178 | 2068 | return self.finishAir(inst, result, .{ bin_op.lhs, bin_op.rhs, .none }); |
| 2179 | 2069 | } |
| 2180 | 2070 | |
| ... | ... | @@ -2200,7 +2090,7 @@ fn airSubWrap(self: *Self, inst: Air.Inst.Index) !void { |
| 2200 | 2090 | const lhs_ty = self.typeOf(bin_op.lhs); |
| 2201 | 2091 | const rhs_ty = self.typeOf(bin_op.rhs); |
| 2202 | 2092 | |
| 2203 | | break :result try self.binOp(.sub, inst, lhs, rhs, lhs_ty, rhs_ty); |
| 2093 | break :result try self.binOp(.sub, lhs, lhs_ty, rhs, rhs_ty); |
| 2204 | 2094 | }; |
| 2205 | 2095 | return self.finishAir(inst, result, .{ bin_op.lhs, bin_op.rhs, .none }); |
| 2206 | 2096 | } |
| ... | ... | @@ -2240,7 +2130,7 @@ fn airAddWithOverflow(self: *Self, inst: Air.Inst.Index) !void { |
| 2240 | 2130 | const lhs_ty = self.typeOf(extra.lhs); |
| 2241 | 2131 | const rhs_ty = self.typeOf(extra.rhs); |
| 2242 | 2132 | |
| 2243 | | const add_result_mcv = try self.binOp(.add, null, lhs, rhs, lhs_ty, rhs_ty); |
| 2133 | const add_result_mcv = try self.binOp(.add, lhs, lhs_ty, rhs, rhs_ty); |
| 2244 | 2134 | const add_result_lock = self.register_manager.lockRegAssumeUnused(add_result_mcv.register); |
| 2245 | 2135 | defer self.register_manager.unlockReg(add_result_lock); |
| 2246 | 2136 | |
| ... | ... | @@ -2291,10 +2181,9 @@ fn airAddWithOverflow(self: *Self, inst: Air.Inst.Index) !void { |
| 2291 | 2181 | |
| 2292 | 2182 | const overflow_mcv = try self.binOp( |
| 2293 | 2183 | .cmp_neq, |
| 2294 | | null, |
| 2295 | 2184 | .{ .register = overflow_reg }, |
| 2296 | | .{ .register = add_reg }, |
| 2297 | 2185 | lhs_ty, |
| 2186 | .{ .register = add_reg }, |
| 2298 | 2187 | lhs_ty, |
| 2299 | 2188 | ); |
| 2300 | 2189 | |
| ... | ... | @@ -2347,7 +2236,7 @@ fn airMulWithOverflow(self: *Self, inst: Air.Inst.Index) !void { |
| 2347 | 2236 | switch (int_info.bits) { |
| 2348 | 2237 | 1...32 => { |
| 2349 | 2238 | if (self.hasFeature(.m)) { |
| 2350 | | const dest = try self.binOp(.mul, null, lhs, rhs, lhs_ty, rhs_ty); |
| 2239 | const dest = try self.binOp(.mul, lhs, lhs_ty, rhs, rhs_ty); |
| 2351 | 2240 | |
| 2352 | 2241 | const add_result_lock = self.register_manager.lockRegAssumeUnused(dest.register); |
| 2353 | 2242 | defer self.register_manager.unlockReg(add_result_lock); |
| ... | ... | @@ -2393,10 +2282,9 @@ fn airMulWithOverflow(self: *Self, inst: Air.Inst.Index) !void { |
| 2393 | 2282 | |
| 2394 | 2283 | const overflow_mcv = try self.binOp( |
| 2395 | 2284 | .cmp_neq, |
| 2396 | | null, |
| 2397 | 2285 | .{ .register = overflow_reg }, |
| 2398 | | .{ .register = add_reg }, |
| 2399 | 2286 | lhs_ty, |
| 2287 | .{ .register = add_reg }, |
| 2400 | 2288 | lhs_ty, |
| 2401 | 2289 | ); |
| 2402 | 2290 | |
| ... | ... | @@ -2479,7 +2367,7 @@ fn airShl(self: *Self, inst: Air.Inst.Index) !void { |
| 2479 | 2367 | const lhs_ty = self.typeOf(bin_op.lhs); |
| 2480 | 2368 | const rhs_ty = self.typeOf(bin_op.rhs); |
| 2481 | 2369 | |
| 2482 | | break :result try self.binOp(.shl, inst, lhs, rhs, lhs_ty, rhs_ty); |
| 2370 | break :result try self.binOp(.shl, lhs, lhs_ty, rhs, rhs_ty); |
| 2483 | 2371 | }; |
| 2484 | 2372 | return self.finishAir(inst, result, .{ bin_op.lhs, bin_op.rhs, .none }); |
| 2485 | 2373 | } |
| ... | ... | @@ -2543,10 +2431,9 @@ fn airUnwrapErrErr(self: *Self, inst: Air.Inst.Index) !void { |
| 2543 | 2431 | if (err_off > 0) { |
| 2544 | 2432 | result = try self.binOp( |
| 2545 | 2433 | .shr, |
| 2546 | | null, |
| 2547 | 2434 | result, |
| 2548 | | .{ .immediate = @as(u6, @intCast(err_off * 8)) }, |
| 2549 | 2435 | err_union_ty, |
| 2436 | .{ .immediate = @as(u6, @intCast(err_off * 8)) }, |
| 2550 | 2437 | Type.u8, |
| 2551 | 2438 | ); |
| 2552 | 2439 | } |
| ... | ... | @@ -2593,10 +2480,9 @@ fn genUnwrapErrUnionPayloadMir( |
| 2593 | 2480 | if (payload_off > 0) { |
| 2594 | 2481 | result = try self.binOp( |
| 2595 | 2482 | .shr, |
| 2596 | | null, |
| 2597 | 2483 | result, |
| 2598 | | .{ .immediate = @as(u6, @intCast(payload_off * 8)) }, |
| 2599 | 2484 | err_union_ty, |
| 2485 | .{ .immediate = @as(u6, @intCast(payload_off * 8)) }, |
| 2600 | 2486 | Type.u8, |
| 2601 | 2487 | ); |
| 2602 | 2488 | } |
| ... | ... | @@ -2837,7 +2723,7 @@ fn airSliceElemVal(self: *Self, inst: Air.Inst.Index) !void { |
| 2837 | 2723 | }; |
| 2838 | 2724 | |
| 2839 | 2725 | const dest = try self.allocRegOrMem(inst, true); |
| 2840 | | const addr = try self.binOp(.ptr_add, null, base_mcv, index_mcv, slice_ptr_field_type, Type.usize); |
| 2726 | const addr = try self.binOp(.ptr_add, base_mcv, slice_ptr_field_type, index_mcv, Type.usize); |
| 2841 | 2727 | try self.load(dest, addr, slice_ptr_field_type); |
| 2842 | 2728 | |
| 2843 | 2729 | break :result dest; |
| ... | ... | @@ -2885,13 +2771,14 @@ fn airArrayElemVal(self: *Self, inst: Air.Inst.Index) !void { |
| 2885 | 2771 | defer self.register_manager.unlockReg(offset_lock); |
| 2886 | 2772 | |
| 2887 | 2773 | const dst_mcv = try self.allocRegOrMem(inst, false); |
| 2888 | | try self.binOpMir( |
| 2889 | | .add, |
| 2890 | | null, |
| 2891 | | Type.usize, |
| 2892 | | .{ .register = addr_reg }, |
| 2893 | | .{ .register = offset_reg }, |
| 2894 | | ); |
| 2774 | _ = try self.addInst(.{ |
| 2775 | .tag = .add, |
| 2776 | .ops = .rr, |
| 2777 | .data = .{ .rr = .{ |
| 2778 | .rd = addr_reg, |
| 2779 | .rs = offset_reg, |
| 2780 | } }, |
| 2781 | }); |
| 2895 | 2782 | try self.genCopy(elem_ty, dst_mcv, .{ .indirect = .{ .reg = addr_reg } }); |
| 2896 | 2783 | break :result dst_mcv; |
| 2897 | 2784 | }; |
| ... | ... | @@ -3046,7 +2933,7 @@ fn airByteSwap(self: *Self, inst: Air.Inst.Index) !void { |
| 3046 | 2933 | |
| 3047 | 2934 | switch (int_bits) { |
| 3048 | 2935 | 16 => { |
| 3049 | | const temp = try self.binOp(.shr, null, dest_mcv, .{ .immediate = 8 }, ty, Type.u8); |
| 2936 | const temp = try self.binOp(.shr, dest_mcv, ty, .{ .immediate = 8 }, Type.u8); |
| 3050 | 2937 | assert(temp == .register); |
| 3051 | 2938 | _ = try self.addInst(.{ |
| 3052 | 2939 | .tag = .slli, |
| ... | ... | @@ -3752,7 +3639,7 @@ fn airCmp(self: *Self, inst: Air.Inst.Index) !void { |
| 3752 | 3639 | |
| 3753 | 3640 | const int_info = int_ty.intInfo(zcu); |
| 3754 | 3641 | if (int_info.bits <= 64) { |
| 3755 | | break :result try self.binOp(tag, null, lhs, rhs, int_ty, int_ty); |
| 3642 | break :result try self.binOp(tag, lhs, int_ty, rhs, int_ty); |
| 3756 | 3643 | } else { |
| 3757 | 3644 | return self.fail("TODO riscv cmp for ints > 64 bits", .{}); |
| 3758 | 3645 | } |
| ... | ... | @@ -4033,20 +3920,19 @@ fn isErr(self: *Self, maybe_inst: ?Air.Inst.Index, eu_ty: Type, eu_mcv: MCValue) |
| 4033 | 3920 | if (err_off > 0) { |
| 4034 | 3921 | return_mcv = try self.binOp( |
| 4035 | 3922 | .shr, |
| 4036 | | null, |
| 4037 | 3923 | return_mcv, |
| 4038 | | .{ .immediate = @as(u6, @intCast(err_off * 8)) }, |
| 4039 | 3924 | eu_ty, |
| 3925 | .{ .immediate = @as(u6, @intCast(err_off * 8)) }, |
| 4040 | 3926 | Type.u8, |
| 4041 | 3927 | ); |
| 4042 | 3928 | } |
| 4043 | 3929 | |
| 4044 | | try self.binOpMir( |
| 3930 | return_mcv = try self.binOp( |
| 4045 | 3931 | .cmp_neq, |
| 4046 | | null, |
| 4047 | | Type.anyerror, |
| 4048 | 3932 | return_mcv, |
| 3933 | Type.u16, |
| 4049 | 3934 | .{ .immediate = 0 }, |
| 3935 | Type.u16, |
| 4050 | 3936 | ); |
| 4051 | 3937 | |
| 4052 | 3938 | return return_mcv; |
| ... | ... | @@ -4070,8 +3956,8 @@ fn isNonErr(self: *Self, inst: Air.Inst.Index, eu_ty: Type, eu_mcv: MCValue) !MC |
| 4070 | 3956 | switch (is_err_res) { |
| 4071 | 3957 | .register => |reg| { |
| 4072 | 3958 | _ = try self.addInst(.{ |
| 4073 | | .tag = .not, |
| 4074 | | .ops = .rr, |
| 3959 | .tag = .pseudo, |
| 3960 | .ops = .pseudo_not, |
| 4075 | 3961 | .data = .{ |
| 4076 | 3962 | .rr = .{ |
| 4077 | 3963 | .rd = reg, |
| ... | ... | @@ -4440,9 +4326,7 @@ fn genCopy(self: *Self, ty: Type, dst_mcv: MCValue, src_mcv: MCValue) !void { |
| 4440 | 4326 | dst_mcv, |
| 4441 | 4327 | try self.resolveInst(src_ref), |
| 4442 | 4328 | ), |
| 4443 | | else => return self.fail("TODO implement genCopy for {s} of {}", .{ |
| 4444 | | @tagName(src_mcv), ty.fmt(zcu), |
| 4445 | | }), |
| 4329 | else => unreachable, |
| 4446 | 4330 | }; |
| 4447 | 4331 | defer if (src_info) |info| self.register_manager.unlockReg(info.addr_lock); |
| 4448 | 4332 | |