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 {
20732073 var info = try self.resolveCallingConventionValues(fn_ty);
20742074 defer info.deinit(self);
20752075
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 },
21082104 }
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) {
21112111 if (func_value.castTag(.function)) |func_payload| {
21122112 const func = func_payload.data;
21132113 const ptr_bits = self.target.cpu.arch.ptrBitWidth();
......@@ -2131,52 +2131,7 @@ fn airCall(self: *Self, inst: Air.Inst.Index) !void {
21312131 } else {
21322132 return self.fail("TODO implement calling bitcasted functions", .{});
21332133 }
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| {
21802135 if (func_value.castTag(.function)) |func_payload| {
21812136 const func = func_payload.data;
21822137 // 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 {
22122167 } else {
22132168 return self.fail("TODO implement calling bitcasted functions", .{});
22142169 }
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| {
22502171 if (func_value.castTag(.function)) |func_payload| {
22512172 try p9.seeDecl(func_payload.data.owner_decl);
22522173 const ptr_bits = self.target.cpu.arch.ptrBitWidth();
......@@ -2266,10 +2187,17 @@ fn airCall(self: *Self, inst: Air.Inst.Index) !void {
22662187 } else {
22672188 return self.fail("TODO implement calling bitcasted functions", .{});
22682189 }
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 }
22732201
22742202 const result: MCValue = result: {
22752203 switch (info.return_value) {