aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorjoachimschmidt557 <joachim.schmidt557@outlook.com>2021-01-17 11:04:25 +0100
committerAndrew Kelley <andrew@ziglang.org>2021-02-01 12:17:24 -0800
commit446ebddb937ccc8bea7060b74268e90702656fde (patch)
treec72023040b9f179de969847b435b424bce4a3365 /src
parent16905d96f70045fd9d630219c85a2eb508db38b4 (diff)
downloadzig-446ebddb937ccc8bea7060b74268e90702656fde.tar.gz
zig-446ebddb937ccc8bea7060b74268e90702656fde.zip
stage2 ARM: save function arguments to stack for debugging
This changes genArg to copy registers to the stack for better debugging. Thus, it requires genSetStack to be implemented in order for genArg to work.
Diffstat (limited to 'src')
-rw-r--r--src/codegen.zig91
1 files changed, 62 insertions, 29 deletions
diff --git a/src/codegen.zig b/src/codegen.zig
index 362b04ab26..904fda0deb 100644
--- a/src/codegen.zig
+++ b/src/codegen.zig
@@ -1567,6 +1567,59 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type {
}
}
+ fn genArgDbgInfo(self: *Self, inst: *ir.Inst.Arg, mcv: MCValue) !void {
+ const name_with_null = inst.name[0 .. mem.lenZ(inst.name) + 1];
+
+ switch (mcv) {
+ .register => |reg| {
+ // Copy arg to stack for better debugging
+ const ty = inst.base.ty;
+ const abi_size = math.cast(u32, ty.abiSize(self.target.*)) catch {
+ return self.fail(inst.base.src, "type '{}' too big to fit into stack frame", .{ty});
+ };
+ const abi_align = ty.abiAlignment(self.target.*);
+ const stack_offset = try self.allocMem(&inst.base, abi_size, abi_align);
+ try self.genSetStack(inst.base.src, ty, stack_offset, MCValue{ .register = reg });
+ const adjusted_stack_offset = math.negateCast(stack_offset + abi_size) catch {
+ return self.fail(inst.base.src, "Stack offset too large for arguments", .{});
+ };
+
+ switch (self.debug_output) {
+ .dwarf => |dbg_out| {
+ switch (arch) {
+ .arm, .armeb => {
+ try dbg_out.dbg_info.append(link.File.Elf.abbrev_parameter);
+
+ // Get length of the LEB128 stack offset
+ var counting_writer = std.io.countingWriter(std.io.null_writer);
+ leb128.writeILEB128(counting_writer.writer(), adjusted_stack_offset) catch unreachable;
+
+ // DW.AT_location, DW.FORM_exprloc
+ // ULEB128 dwarf expression length
+ try leb128.writeULEB128(dbg_out.dbg_info.writer(), counting_writer.bytes_written + 1);
+ try dbg_out.dbg_info.append(DW.OP_breg11);
+ try leb128.writeILEB128(dbg_out.dbg_info.writer(), adjusted_stack_offset);
+ },
+ else => {
+ try dbg_out.dbg_info.ensureCapacity(dbg_out.dbg_info.items.len + 3);
+ dbg_out.dbg_info.appendAssumeCapacity(link.File.Elf.abbrev_parameter);
+ dbg_out.dbg_info.appendSliceAssumeCapacity(&[2]u8{ // DW.AT_location, DW.FORM_exprloc
+ 1, // ULEB128 dwarf expression length
+ reg.dwarfLocOp(),
+ });
+ },
+ }
+ try dbg_out.dbg_info.ensureCapacity(dbg_out.dbg_info.items.len + 5 + name_with_null.len);
+ try self.addDbgInfoTypeReloc(inst.base.ty); // DW.AT_type, DW.FORM_ref4
+ dbg_out.dbg_info.appendSliceAssumeCapacity(name_with_null); // DW.AT_name, DW.FORM_string
+ },
+ .none => {},
+ }
+ },
+ else => {},
+ }
+ }
+
fn genArg(self: *Self, inst: *ir.Inst.Arg) !MCValue {
const arg_index = self.arg_index;
self.arg_index += 1;
@@ -1574,32 +1627,17 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type {
if (FreeRegInt == u0) {
return self.fail(inst.base.src, "TODO implement Register enum for {}", .{self.target.cpu.arch});
}
- if (inst.base.isUnused())
- return MCValue.dead;
-
- try self.registers.ensureCapacity(self.gpa, self.registers.count() + 1);
const result = self.args[arg_index];
+ try self.genArgDbgInfo(inst, result);
+
+ if (inst.base.isUnused())
+ return MCValue.dead;
- const name_with_null = inst.name[0 .. mem.lenZ(inst.name) + 1];
switch (result) {
.register => |reg| {
- self.registers.putAssumeCapacityNoClobber(toCanonicalReg(reg), &inst.base);
+ try self.registers.putNoClobber(self.gpa, toCanonicalReg(reg), &inst.base);
self.markRegUsed(reg);
-
- switch (self.debug_output) {
- .dwarf => |dbg_out| {
- try dbg_out.dbg_info.ensureCapacity(dbg_out.dbg_info.items.len + 8 + name_with_null.len);
- dbg_out.dbg_info.appendAssumeCapacity(link.File.Elf.abbrev_parameter);
- dbg_out.dbg_info.appendSliceAssumeCapacity(&[2]u8{ // DW.AT_location, DW.FORM_exprloc
- 1, // ULEB128 dwarf expression length
- reg.dwarfLocOp(),
- });
- try self.addDbgInfoTypeReloc(inst.base.ty); // DW.AT_type, DW.FORM_ref4
- dbg_out.dbg_info.appendSliceAssumeCapacity(name_with_null); // DW.AT_name, DW.FORM_string
- },
- .none => {},
- }
},
else => {},
}
@@ -3705,10 +3743,8 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type {
var nsaa: u32 = 0; // Next stacked argument address
for (param_types) |ty, i| {
- if (ty.abiAlignment(self.target.*) == 8) {
- // Round up NCRN to the next even number
- ncrn += ncrn % 2;
- }
+ if (ty.abiAlignment(self.target.*) == 8)
+ ncrn = std.mem.alignForwardGeneric(usize, ncrn, 2);
const param_size = @intCast(u32, ty.abiSize(self.target.*));
if (std.math.divCeil(u32, param_size, 4) catch unreachable <= 4 - ncrn) {
@@ -3722,11 +3758,8 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type {
return self.fail(src, "TODO MCValues split between registers and stack", .{});
} else {
ncrn = 4;
- if (ty.abiAlignment(self.target.*) == 8) {
- if (nsaa % 8 != 0) {
- nsaa += 8 - (nsaa % 8);
- }
- }
+ if (ty.abiAlignment(self.target.*) == 8)
+ nsaa = std.mem.alignForwardGeneric(u32, nsaa, 8);
result.args[i] = .{ .stack_offset = nsaa };
nsaa += param_size;