authorgravatar for joachim.schmidt557@outlook.comJoachim Schmidt <joachim.schmidt557@outlook.com> 2021-01-17 11:04:25+01:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2021-02-01 12:17:24-08:00
log446ebddb937ccc8bea7060b74268e90702656fde
treec72023040b9f179de969847b435b424bce4a3365
parent16905d96f70045fd9d630219c85a2eb508db38b4

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.

1 files changed, 62 insertions(+), 29 deletions(-)

src/codegen.zig+62-29
......@@ -1567,6 +1567,59 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type {
15671567 }
15681568 }
15691569
1570 fn genArgDbgInfo(self: *Self, inst: *ir.Inst.Arg, mcv: MCValue) !void {
1571 const name_with_null = inst.name[0 .. mem.lenZ(inst.name) + 1];
1572
1573 switch (mcv) {
1574 .register => |reg| {
1575 // Copy arg to stack for better debugging
1576 const ty = inst.base.ty;
1577 const abi_size = math.cast(u32, ty.abiSize(self.target.*)) catch {
1578 return self.fail(inst.base.src, "type '{}' too big to fit into stack frame", .{ty});
1579 };
1580 const abi_align = ty.abiAlignment(self.target.*);
1581 const stack_offset = try self.allocMem(&inst.base, abi_size, abi_align);
1582 try self.genSetStack(inst.base.src, ty, stack_offset, MCValue{ .register = reg });
1583 const adjusted_stack_offset = math.negateCast(stack_offset + abi_size) catch {
1584 return self.fail(inst.base.src, "Stack offset too large for arguments", .{});
1585 };
1586
1587 switch (self.debug_output) {
1588 .dwarf => |dbg_out| {
1589 switch (arch) {
1590 .arm, .armeb => {
1591 try dbg_out.dbg_info.append(link.File.Elf.abbrev_parameter);
1592
1593 // Get length of the LEB128 stack offset
1594 var counting_writer = std.io.countingWriter(std.io.null_writer);
1595 leb128.writeILEB128(counting_writer.writer(), adjusted_stack_offset) catch unreachable;
1596
1597 // DW.AT_location, DW.FORM_exprloc
1598 // ULEB128 dwarf expression length
1599 try leb128.writeULEB128(dbg_out.dbg_info.writer(), counting_writer.bytes_written + 1);
1600 try dbg_out.dbg_info.append(DW.OP_breg11);
1601 try leb128.writeILEB128(dbg_out.dbg_info.writer(), adjusted_stack_offset);
1602 },
1603 else => {
1604 try dbg_out.dbg_info.ensureCapacity(dbg_out.dbg_info.items.len + 3);
1605 dbg_out.dbg_info.appendAssumeCapacity(link.File.Elf.abbrev_parameter);
1606 dbg_out.dbg_info.appendSliceAssumeCapacity(&[2]u8{ // DW.AT_location, DW.FORM_exprloc
1607 1, // ULEB128 dwarf expression length
1608 reg.dwarfLocOp(),
1609 });
1610 },
1611 }
1612 try dbg_out.dbg_info.ensureCapacity(dbg_out.dbg_info.items.len + 5 + name_with_null.len);
1613 try self.addDbgInfoTypeReloc(inst.base.ty); // DW.AT_type, DW.FORM_ref4
1614 dbg_out.dbg_info.appendSliceAssumeCapacity(name_with_null); // DW.AT_name, DW.FORM_string
1615 },
1616 .none => {},
1617 }
1618 },
1619 else => {},
1620 }
1621 }
1622
15701623 fn genArg(self: *Self, inst: *ir.Inst.Arg) !MCValue {
15711624 const arg_index = self.arg_index;
15721625 self.arg_index += 1;
......@@ -1574,32 +1627,17 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type {
15741627 if (FreeRegInt == u0) {
15751628 return self.fail(inst.base.src, "TODO implement Register enum for {}", .{self.target.cpu.arch});
15761629 }
1577 if (inst.base.isUnused())
1578 return MCValue.dead;
1579
1580 try self.registers.ensureCapacity(self.gpa, self.registers.count() + 1);
15811630
15821631 const result = self.args[arg_index];
1632 try self.genArgDbgInfo(inst, result);
1633
1634 if (inst.base.isUnused())
1635 return MCValue.dead;
15831636
1584 const name_with_null = inst.name[0 .. mem.lenZ(inst.name) + 1];
15851637 switch (result) {
15861638 .register => |reg| {
1587 self.registers.putAssumeCapacityNoClobber(toCanonicalReg(reg), &inst.base);
1639 try self.registers.putNoClobber(self.gpa, toCanonicalReg(reg), &inst.base);
15881640 self.markRegUsed(reg);
1589
1590 switch (self.debug_output) {
1591 .dwarf => |dbg_out| {
1592 try dbg_out.dbg_info.ensureCapacity(dbg_out.dbg_info.items.len + 8 + name_with_null.len);
1593 dbg_out.dbg_info.appendAssumeCapacity(link.File.Elf.abbrev_parameter);
1594 dbg_out.dbg_info.appendSliceAssumeCapacity(&[2]u8{ // DW.AT_location, DW.FORM_exprloc
1595 1, // ULEB128 dwarf expression length
1596 reg.dwarfLocOp(),
1597 });
1598 try self.addDbgInfoTypeReloc(inst.base.ty); // DW.AT_type, DW.FORM_ref4
1599 dbg_out.dbg_info.appendSliceAssumeCapacity(name_with_null); // DW.AT_name, DW.FORM_string
1600 },
1601 .none => {},
1602 }
16031641 },
16041642 else => {},
16051643 }
......@@ -3705,10 +3743,8 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type {
37053743 var nsaa: u32 = 0; // Next stacked argument address
37063744
37073745 for (param_types) |ty, i| {
3708 if (ty.abiAlignment(self.target.*) == 8) {
3709 // Round up NCRN to the next even number
3710 ncrn += ncrn % 2;
3711 }
3746 if (ty.abiAlignment(self.target.*) == 8)
3747 ncrn = std.mem.alignForwardGeneric(usize, ncrn, 2);
37123748
37133749 const param_size = @intCast(u32, ty.abiSize(self.target.*));
37143750 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 {
37223758 return self.fail(src, "TODO MCValues split between registers and stack", .{});
37233759 } else {
37243760 ncrn = 4;
3725 if (ty.abiAlignment(self.target.*) == 8) {
3726 if (nsaa % 8 != 0) {
3727 nsaa += 8 - (nsaa % 8);
3728 }
3729 }
3761 if (ty.abiAlignment(self.target.*) == 8)
3762 nsaa = std.mem.alignForwardGeneric(u32, nsaa, 8);
37303763
37313764 result.args[i] = .{ .stack_offset = nsaa };
37323765 nsaa += param_size;