authorgravatar for joachim.schmidt557@outlook.comJoachim Schmidt <joachim.schmidt557@outlook.com> 2022-02-13 11:01:15+01:00
committergravatar for joachim.schmidt557@outlook.comJoachim Schmidt <joachim.schmidt557@outlook.com> 2022-02-14 22:09:44+01:00
log98c71cc88a2d472dded057a4a6f1d610dad9e491
tree2208afdba610259e0ee44be5f5ce653e7cb50c75
parent783e216e7d49ce30032cd768ca266f5f08773bf4
signaturelock-open Commit is signed but in an unrecognized format.

stage2 AArch64: Implement calling function pointers


1 files changed, 46 insertions(+), 118 deletions(-)

src/arch/aarch64/CodeGen.zig+46-118
...@@ -2073,41 +2073,41 @@ fn airCall(self: *Self, inst: Air.Inst.Index) !void {...@@ -2073,41 +2073,41 @@ fn airCall(self: *Self, inst: Air.Inst.Index) !void {
2073 var info = try self.resolveCallingConventionValues(fn_ty);2073 var info = try self.resolveCallingConventionValues(fn_ty);
2074 defer info.deinit(self);2074 defer info.deinit(self);
20752075
2076 // Due to incremental compilation, how function calls are generated depends2076 for (info.args) |mc_arg, arg_i| {
2077 // on linking.2077 const arg = args[arg_i];
2078 if (self.bin_file.tag == link.File.Elf.base_tag or self.bin_file.tag == link.File.Coff.base_tag) {2078 const arg_ty = self.air.typeOf(arg);
2079 for (info.args) |mc_arg, arg_i| {2079 const arg_mcv = try self.resolveInst(args[arg_i]);
2080 const arg = args[arg_i];2080
2081 const arg_ty = self.air.typeOf(arg);2081 switch (mc_arg) {
2082 const arg_mcv = try self.resolveInst(args[arg_i]);2082 .none => continue,
20832083 .undef => unreachable,
2084 switch (mc_arg) {2084 .immediate => unreachable,
2085 .none => continue,2085 .unreach => unreachable,
2086 .undef => unreachable,2086 .dead => unreachable,
2087 .immediate => unreachable,2087 .embedded_in_code => unreachable,
2088 .unreach => unreachable,2088 .memory => unreachable,
2089 .dead => unreachable,2089 .compare_flags_signed => unreachable,
2090 .embedded_in_code => unreachable,2090 .compare_flags_unsigned => unreachable,
2091 .memory => unreachable,2091 .register => |reg| {
2092 .compare_flags_signed => unreachable,2092 try self.register_manager.getReg(reg, null);
2093 .compare_flags_unsigned => unreachable,2093 try self.genSetReg(arg_ty, reg, arg_mcv);
2094 .register => |reg| {2094 },
2095 try self.register_manager.getReg(reg, null);2095 .stack_offset => {
2096 try self.genSetReg(arg_ty, reg, arg_mcv);2096 return self.fail("TODO implement calling with parameters in memory", .{});
2097 },2097 },
2098 .stack_offset => {2098 .ptr_stack_offset => {
2099 return self.fail("TODO implement calling with parameters in memory", .{});2099 return self.fail("TODO implement calling with MCValue.ptr_stack_offset arg", .{});
2100 },2100 },
2101 .ptr_stack_offset => {2101 .ptr_embedded_in_code => {
2102 return self.fail("TODO implement calling with MCValue.ptr_stack_offset arg", .{});2102 return self.fail("TODO implement calling with MCValue.ptr_embedded_in_code arg", .{});
2103 },2103 },
2104 .ptr_embedded_in_code => {
2105 return self.fail("TODO implement calling with MCValue.ptr_embedded_in_code arg", .{});
2106 },
2107 }
2108 }2104 }
2105 }
21092106
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 if (func_value.castTag(.function)) |func_payload| {2111 if (func_value.castTag(.function)) |func_payload| {
2112 const func = func_payload.data;2112 const func = func_payload.data;
2113 const ptr_bits = self.target.cpu.arch.ptrBitWidth();2113 const ptr_bits = self.target.cpu.arch.ptrBitWidth();
...@@ -2131,52 +2131,7 @@ fn airCall(self: *Self, inst: Air.Inst.Index) !void {...@@ -2131,52 +2131,7 @@ fn airCall(self: *Self, inst: Air.Inst.Index) !void {
2131 } else {2131 } else {
2132 return self.fail("TODO implement calling bitcasted functions", .{});2132 return self.fail("TODO implement calling bitcasted functions", .{});
2133 }2133 }
2134 } else {2134 } else if (self.bin_file.cast(link.File.MachO)) |macho_file| {
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| {
2180 if (func_value.castTag(.function)) |func_payload| {2135 if (func_value.castTag(.function)) |func_payload| {
2181 const func = func_payload.data;2136 const func = func_payload.data;
2182 // TODO I'm hacking my way through here by repurposing .memory for storing2137 // 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,41 +2167,7 @@ fn airCall(self: *Self, inst: Air.Inst.Index) !void {
2212 } else {2167 } else {
2213 return self.fail("TODO implement calling bitcasted functions", .{});2168 return self.fail("TODO implement calling bitcasted functions", .{});
2214 }2169 }
2215 } else {2170 } else if (self.bin_file.cast(link.File.Plan9)) |p9| {
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| {
2250 if (func_value.castTag(.function)) |func_payload| {2171 if (func_value.castTag(.function)) |func_payload| {
2251 try p9.seeDecl(func_payload.data.owner_decl);2172 try p9.seeDecl(func_payload.data.owner_decl);
2252 const ptr_bits = self.target.cpu.arch.ptrBitWidth();2173 const ptr_bits = self.target.cpu.arch.ptrBitWidth();
...@@ -2266,10 +2187,17 @@ fn airCall(self: *Self, inst: Air.Inst.Index) !void {...@@ -2266,10 +2187,17 @@ fn airCall(self: *Self, inst: Air.Inst.Index) !void {
2266 } else {2187 } else {
2267 return self.fail("TODO implement calling bitcasted functions", .{});2188 return self.fail("TODO implement calling bitcasted functions", .{});
2268 }2189 }
2269 } else {2190 } else unreachable;
2270 return self.fail("TODO implement calling runtime known function pointer", .{});2191 } else {
2271 }2192 assert(ty.zigTypeTag() == .Pointer);
2272 } else unreachable;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 }
22732201
2274 const result: MCValue = result: {2202 const result: MCValue = result: {
2275 switch (info.return_value) {2203 switch (info.return_value) {