authorgravatar for joachim.schmidt557@outlook.comJoachim Schmidt <joachim.schmidt557@outlook.com> 2023-01-23 21:08:43+01:00
committergravatar for joachim.schmidt557@outlook.comJoachim Schmidt <joachim.schmidt557@outlook.com> 2023-01-29 20:00:53+01:00
log090186a0c26447d99417dad9f1ba8bde49579191
tree53b0057cf209e317ae61b7fbfb95a4af40ba84a1
parent599b3ef9e947f044799d11aecf0dfe659f9a7728

stage2 AArch64: move copy-register-arg-to-stack code to fn prologue

This enhances the debugging experience as upon encountering a breakpoint in a function, all arguments passed as registers have already been moved to the stack, ready to be inspected by the debugger.

1 files changed, 27 insertions(+), 30 deletions(-)

src/arch/aarch64/CodeGen.zig+27-30
...@@ -181,6 +181,7 @@ const DbgInfoReloc = struct {...@@ -181,6 +181,7 @@ const DbgInfoReloc = struct {
181 else => unreachable,181 else => unreachable,
182 }182 }
183 }183 }
184
184 fn genArgDbgInfo(reloc: DbgInfoReloc, function: Self) error{OutOfMemory}!void {185 fn genArgDbgInfo(reloc: DbgInfoReloc, function: Self) error{OutOfMemory}!void {
185 switch (function.debug_output) {186 switch (function.debug_output) {
186 .dwarf => |dw| {187 .dwarf => |dw| {
...@@ -527,6 +528,28 @@ fn gen(self: *Self) !void {...@@ -527,6 +528,28 @@ fn gen(self: *Self) !void {
527 self.ret_mcv = MCValue{ .stack_offset = stack_offset };528 self.ret_mcv = MCValue{ .stack_offset = stack_offset };
528 }529 }
529530
531 for (self.args) |*arg, arg_index| {
532 // Copy register arguments to the stack
533 switch (arg.*) {
534 .register => |reg| {
535 // The first AIR instructions of the main body are guaranteed
536 // to be the functions arguments
537 const inst = self.air.getMainBody()[arg_index];
538 assert(self.air.instructions.items(.tag)[inst] == .arg);
539
540 const ty = self.air.typeOfIndex(inst);
541
542 const abi_size = @intCast(u32, ty.abiSize(self.target.*));
543 const abi_align = ty.abiAlignment(self.target.*);
544 const stack_offset = try self.allocMem(abi_size, abi_align, inst);
545 try self.genSetStack(ty, stack_offset, MCValue{ .register = reg });
546
547 arg.* = MCValue{ .stack_offset = stack_offset };
548 },
549 else => {},
550 }
551 }
552
530 _ = try self.addInst(.{553 _ = try self.addInst(.{
531 .tag = .dbg_prologue_end,554 .tag = .dbg_prologue_end,
532 .data = .{ .nop = {} },555 .data = .{ .nop = {} },
...@@ -4163,45 +4186,19 @@ fn airArg(self: *Self, inst: Air.Inst.Index) !void {...@@ -4163,45 +4186,19 @@ fn airArg(self: *Self, inst: Air.Inst.Index) !void {
4163 self.arg_index += 1;4186 self.arg_index += 1;
41644187
4165 const ty = self.air.typeOfIndex(inst);4188 const ty = self.air.typeOfIndex(inst);
4166 const result = self.args[arg_index];4189 const tag = self.air.instructions.items(.tag)[inst];
4167 const src_index = self.air.instructions.items(.data)[inst].arg.src_index;4190 const src_index = self.air.instructions.items(.data)[inst].arg.src_index;
4168 const name = self.mod_fn.getParamName(self.bin_file.options.module.?, src_index);4191 const name = self.mod_fn.getParamName(self.bin_file.options.module.?, src_index);
41694192
4170 const mcv = switch (result) {
4171 // Copy registers to the stack
4172 .register => |reg| blk: {
4173 const mod = self.bin_file.options.module.?;
4174 const abi_size = math.cast(u32, ty.abiSize(self.target.*)) orelse {
4175 return self.fail("type '{}' too big to fit into stack frame", .{ty.fmt(mod)});
4176 };
4177 const abi_align = ty.abiAlignment(self.target.*);
4178 const stack_offset = try self.allocMem(abi_size, abi_align, inst);
4179 try self.genSetStack(ty, stack_offset, MCValue{ .register = reg });
4180
4181 break :blk MCValue{ .stack_offset = stack_offset };
4182 },
4183 else => result,
4184 };
4185
4186 const tag = self.air.instructions.items(.tag)[inst];
4187 try self.dbg_info_relocs.append(self.gpa, .{4193 try self.dbg_info_relocs.append(self.gpa, .{
4188 .tag = tag,4194 .tag = tag,
4189 .ty = ty,4195 .ty = ty,
4190 .name = name,4196 .name = name,
4191 .mcv = result,4197 .mcv = self.args[arg_index],
4192 });4198 });
41934199
4194 if (self.liveness.isUnused(inst))4200 const result: MCValue = if (self.liveness.isUnused(inst)) .dead else self.args[arg_index];
4195 return self.finishAirBookkeeping();4201 return self.finishAir(inst, result, .{ .none, .none, .none });
4196
4197 switch (mcv) {
4198 .register => |reg| {
4199 self.register_manager.getRegAssumeFree(reg, inst);
4200 },
4201 else => {},
4202 }
4203
4204 return self.finishAir(inst, mcv, .{ .none, .none, .none });
4205}4202}
42064203
4207fn airBreakpoint(self: *Self) !void {4204fn airBreakpoint(self: *Self) !void {