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.
This commit is contained in:
joachimschmidt557 2023-01-23 21:08:43 +01:00 committed by Joachim Schmidt
parent 599b3ef9e9
commit 090186a0c2

View File

@ -181,6 +181,7 @@ const DbgInfoReloc = struct {
else => unreachable,
}
}
fn genArgDbgInfo(reloc: DbgInfoReloc, function: Self) error{OutOfMemory}!void {
switch (function.debug_output) {
.dwarf => |dw| {
@ -527,6 +528,28 @@ fn gen(self: *Self) !void {
self.ret_mcv = MCValue{ .stack_offset = stack_offset };
}
for (self.args) |*arg, arg_index| {
// Copy register arguments to the stack
switch (arg.*) {
.register => |reg| {
// The first AIR instructions of the main body are guaranteed
// to be the functions arguments
const inst = self.air.getMainBody()[arg_index];
assert(self.air.instructions.items(.tag)[inst] == .arg);
const ty = self.air.typeOfIndex(inst);
const abi_size = @intCast(u32, ty.abiSize(self.target.*));
const abi_align = ty.abiAlignment(self.target.*);
const stack_offset = try self.allocMem(abi_size, abi_align, inst);
try self.genSetStack(ty, stack_offset, MCValue{ .register = reg });
arg.* = MCValue{ .stack_offset = stack_offset };
},
else => {},
}
}
_ = try self.addInst(.{
.tag = .dbg_prologue_end,
.data = .{ .nop = {} },
@ -4163,45 +4186,19 @@ fn airArg(self: *Self, inst: Air.Inst.Index) !void {
self.arg_index += 1;
const ty = self.air.typeOfIndex(inst);
const result = self.args[arg_index];
const tag = self.air.instructions.items(.tag)[inst];
const src_index = self.air.instructions.items(.data)[inst].arg.src_index;
const name = self.mod_fn.getParamName(self.bin_file.options.module.?, src_index);
const mcv = switch (result) {
// Copy registers to the stack
.register => |reg| blk: {
const mod = self.bin_file.options.module.?;
const abi_size = math.cast(u32, ty.abiSize(self.target.*)) orelse {
return self.fail("type '{}' too big to fit into stack frame", .{ty.fmt(mod)});
};
const abi_align = ty.abiAlignment(self.target.*);
const stack_offset = try self.allocMem(abi_size, abi_align, inst);
try self.genSetStack(ty, stack_offset, MCValue{ .register = reg });
break :blk MCValue{ .stack_offset = stack_offset };
},
else => result,
};
const tag = self.air.instructions.items(.tag)[inst];
try self.dbg_info_relocs.append(self.gpa, .{
.tag = tag,
.ty = ty,
.name = name,
.mcv = result,
.mcv = self.args[arg_index],
});
if (self.liveness.isUnused(inst))
return self.finishAirBookkeeping();
switch (mcv) {
.register => |reg| {
self.register_manager.getRegAssumeFree(reg, inst);
},
else => {},
}
return self.finishAir(inst, mcv, .{ .none, .none, .none });
const result: MCValue = if (self.liveness.isUnused(inst)) .dead else self.args[arg_index];
return self.finishAir(inst, result, .{ .none, .none, .none });
}
fn airBreakpoint(self: *Self) !void {