| ... | ... | @@ -2073,41 +2073,41 @@ fn airCall(self: *Self, inst: Air.Inst.Index) !void { |
| 2073 | 2073 | var info = try self.resolveCallingConventionValues(fn_ty); |
| 2074 | 2074 | defer info.deinit(self); |
| 2075 | 2075 | |
| 2076 | | // Due to incremental compilation, how function calls are generated depends |
| 2077 | | // on linking. |
| 2078 | | if (self.bin_file.tag == link.File.Elf.base_tag or self.bin_file.tag == link.File.Coff.base_tag) { |
| 2079 | | for (info.args) |mc_arg, arg_i| { |
| 2080 | | const arg = args[arg_i]; |
| 2081 | | const arg_ty = self.air.typeOf(arg); |
| 2082 | | const arg_mcv = try self.resolveInst(args[arg_i]); |
| 2083 | | |
| 2084 | | switch (mc_arg) { |
| 2085 | | .none => continue, |
| 2086 | | .undef => unreachable, |
| 2087 | | .immediate => unreachable, |
| 2088 | | .unreach => unreachable, |
| 2089 | | .dead => unreachable, |
| 2090 | | .embedded_in_code => unreachable, |
| 2091 | | .memory => unreachable, |
| 2092 | | .compare_flags_signed => unreachable, |
| 2093 | | .compare_flags_unsigned => unreachable, |
| 2094 | | .register => |reg| { |
| 2095 | | try self.register_manager.getReg(reg, null); |
| 2096 | | try self.genSetReg(arg_ty, reg, arg_mcv); |
| 2097 | | }, |
| 2098 | | .stack_offset => { |
| 2099 | | return self.fail("TODO implement calling with parameters in memory", .{}); |
| 2100 | | }, |
| 2101 | | .ptr_stack_offset => { |
| 2102 | | return self.fail("TODO implement calling with MCValue.ptr_stack_offset arg", .{}); |
| 2103 | | }, |
| 2104 | | .ptr_embedded_in_code => { |
| 2105 | | return self.fail("TODO implement calling with MCValue.ptr_embedded_in_code arg", .{}); |
| 2106 | | }, |
| 2107 | | } |
| 2076 | for (info.args) |mc_arg, arg_i| { |
| 2077 | const arg = args[arg_i]; |
| 2078 | const arg_ty = self.air.typeOf(arg); |
| 2079 | const arg_mcv = try self.resolveInst(args[arg_i]); |
| 2080 | |
| 2081 | switch (mc_arg) { |
| 2082 | .none => continue, |
| 2083 | .undef => unreachable, |
| 2084 | .immediate => unreachable, |
| 2085 | .unreach => unreachable, |
| 2086 | .dead => unreachable, |
| 2087 | .embedded_in_code => unreachable, |
| 2088 | .memory => unreachable, |
| 2089 | .compare_flags_signed => unreachable, |
| 2090 | .compare_flags_unsigned => unreachable, |
| 2091 | .register => |reg| { |
| 2092 | try self.register_manager.getReg(reg, null); |
| 2093 | try self.genSetReg(arg_ty, reg, arg_mcv); |
| 2094 | }, |
| 2095 | .stack_offset => { |
| 2096 | return self.fail("TODO implement calling with parameters in memory", .{}); |
| 2097 | }, |
| 2098 | .ptr_stack_offset => { |
| 2099 | return self.fail("TODO implement calling with MCValue.ptr_stack_offset arg", .{}); |
| 2100 | }, |
| 2101 | .ptr_embedded_in_code => { |
| 2102 | return self.fail("TODO implement calling with MCValue.ptr_embedded_in_code arg", .{}); |
| 2103 | }, |
| 2108 | 2104 | } |
| 2105 | } |
| 2109 | 2106 | |
| 2110 | | if (self.air.value(callee)) |func_value| { |
| 2107 | // Due to incremental compilation, how function calls are generated depends |
| 2108 | // on linking. |
| 2109 | if (self.air.value(callee)) |func_value| { |
| 2110 | if (self.bin_file.tag == link.File.Elf.base_tag or self.bin_file.tag == link.File.Coff.base_tag) { |
| 2111 | 2111 | if (func_value.castTag(.function)) |func_payload| { |
| 2112 | 2112 | const func = func_payload.data; |
| 2113 | 2113 | const ptr_bits = self.target.cpu.arch.ptrBitWidth(); |
| ... | ... | @@ -2131,52 +2131,7 @@ fn airCall(self: *Self, inst: Air.Inst.Index) !void { |
| 2131 | 2131 | } else { |
| 2132 | 2132 | return self.fail("TODO implement calling bitcasted functions", .{}); |
| 2133 | 2133 | } |
| 2134 | | } else { |
| 2135 | | assert(ty.zigTypeTag() == .Pointer); |
| 2136 | | const mcv = try self.resolveInst(callee); |
| 2137 | | try self.genSetReg(Type.initTag(.usize), .x30, mcv); |
| 2138 | | |
| 2139 | | _ = try self.addInst(.{ |
| 2140 | | .tag = .blr, |
| 2141 | | .data = .{ .reg = .x30 }, |
| 2142 | | }); |
| 2143 | | } |
| 2144 | | } else if (self.bin_file.cast(link.File.MachO)) |macho_file| { |
| 2145 | | for (info.args) |mc_arg, arg_i| { |
| 2146 | | const arg = args[arg_i]; |
| 2147 | | const arg_ty = self.air.typeOf(arg); |
| 2148 | | const arg_mcv = try self.resolveInst(args[arg_i]); |
| 2149 | | // Here we do not use setRegOrMem even though the logic is similar, because |
| 2150 | | // the function call will move the stack pointer, so the offsets are different. |
| 2151 | | switch (mc_arg) { |
| 2152 | | .none => continue, |
| 2153 | | .register => |reg| { |
| 2154 | | try self.register_manager.getReg(reg, null); |
| 2155 | | try self.genSetReg(arg_ty, reg, arg_mcv); |
| 2156 | | }, |
| 2157 | | .stack_offset => { |
| 2158 | | // Here we need to emit instructions like this: |
| 2159 | | // mov qword ptr [rsp + stack_offset], x |
| 2160 | | return self.fail("TODO implement calling with parameters in memory", .{}); |
| 2161 | | }, |
| 2162 | | .ptr_stack_offset => { |
| 2163 | | return self.fail("TODO implement calling with MCValue.ptr_stack_offset arg", .{}); |
| 2164 | | }, |
| 2165 | | .ptr_embedded_in_code => { |
| 2166 | | return self.fail("TODO implement calling with MCValue.ptr_embedded_in_code arg", .{}); |
| 2167 | | }, |
| 2168 | | .undef => unreachable, |
| 2169 | | .immediate => unreachable, |
| 2170 | | .unreach => unreachable, |
| 2171 | | .dead => unreachable, |
| 2172 | | .embedded_in_code => unreachable, |
| 2173 | | .memory => unreachable, |
| 2174 | | .compare_flags_signed => unreachable, |
| 2175 | | .compare_flags_unsigned => unreachable, |
| 2176 | | } |
| 2177 | | } |
| 2178 | | |
| 2179 | | if (self.air.value(callee)) |func_value| { |
| 2134 | } else if (self.bin_file.cast(link.File.MachO)) |macho_file| { |
| 2180 | 2135 | if (func_value.castTag(.function)) |func_payload| { |
| 2181 | 2136 | const func = func_payload.data; |
| 2182 | 2137 | // TODO I'm hacking my way through here by repurposing .memory for storing |
| ... | ... | @@ -2212,41 +2167,7 @@ fn airCall(self: *Self, inst: Air.Inst.Index) !void { |
| 2212 | 2167 | } else { |
| 2213 | 2168 | return self.fail("TODO implement calling bitcasted functions", .{}); |
| 2214 | 2169 | } |
| 2215 | | } else { |
| 2216 | | return self.fail("TODO implement calling runtime known function pointer", .{}); |
| 2217 | | } |
| 2218 | | } else if (self.bin_file.cast(link.File.Plan9)) |p9| { |
| 2219 | | for (info.args) |mc_arg, arg_i| { |
| 2220 | | const arg = args[arg_i]; |
| 2221 | | const arg_ty = self.air.typeOf(arg); |
| 2222 | | const arg_mcv = try self.resolveInst(args[arg_i]); |
| 2223 | | |
| 2224 | | switch (mc_arg) { |
| 2225 | | .none => continue, |
| 2226 | | .undef => unreachable, |
| 2227 | | .immediate => unreachable, |
| 2228 | | .unreach => unreachable, |
| 2229 | | .dead => unreachable, |
| 2230 | | .embedded_in_code => unreachable, |
| 2231 | | .memory => unreachable, |
| 2232 | | .compare_flags_signed => unreachable, |
| 2233 | | .compare_flags_unsigned => unreachable, |
| 2234 | | .register => |reg| { |
| 2235 | | try self.register_manager.getReg(reg, null); |
| 2236 | | try self.genSetReg(arg_ty, reg, arg_mcv); |
| 2237 | | }, |
| 2238 | | .stack_offset => { |
| 2239 | | return self.fail("TODO implement calling with parameters in memory", .{}); |
| 2240 | | }, |
| 2241 | | .ptr_stack_offset => { |
| 2242 | | return self.fail("TODO implement calling with MCValue.ptr_stack_offset arg", .{}); |
| 2243 | | }, |
| 2244 | | .ptr_embedded_in_code => { |
| 2245 | | return self.fail("TODO implement calling with MCValue.ptr_embedded_in_code arg", .{}); |
| 2246 | | }, |
| 2247 | | } |
| 2248 | | } |
| 2249 | | if (self.air.value(callee)) |func_value| { |
| 2170 | } else if (self.bin_file.cast(link.File.Plan9)) |p9| { |
| 2250 | 2171 | if (func_value.castTag(.function)) |func_payload| { |
| 2251 | 2172 | try p9.seeDecl(func_payload.data.owner_decl); |
| 2252 | 2173 | const ptr_bits = self.target.cpu.arch.ptrBitWidth(); |
| ... | ... | @@ -2266,10 +2187,17 @@ fn airCall(self: *Self, inst: Air.Inst.Index) !void { |
| 2266 | 2187 | } else { |
| 2267 | 2188 | return self.fail("TODO implement calling bitcasted functions", .{}); |
| 2268 | 2189 | } |
| 2269 | | } else { |
| 2270 | | return self.fail("TODO implement calling runtime known function pointer", .{}); |
| 2271 | | } |
| 2272 | | } else unreachable; |
| 2190 | } else unreachable; |
| 2191 | } else { |
| 2192 | assert(ty.zigTypeTag() == .Pointer); |
| 2193 | const mcv = try self.resolveInst(callee); |
| 2194 | try self.genSetReg(ty, .x30, mcv); |
| 2195 | |
| 2196 | _ = try self.addInst(.{ |
| 2197 | .tag = .blr, |
| 2198 | .data = .{ .reg = .x30 }, |
| 2199 | }); |
| 2200 | } |
| 2273 | 2201 | |
| 2274 | 2202 | const result: MCValue = result: { |
| 2275 | 2203 | switch (info.return_value) { |