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 {...@@ -1567,6 +1567,59 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type {
1567 }1567 }
1568 }1568 }
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
1570 fn genArg(self: *Self, inst: *ir.Inst.Arg) !MCValue {1623 fn genArg(self: *Self, inst: *ir.Inst.Arg) !MCValue {
1571 const arg_index = self.arg_index;1624 const arg_index = self.arg_index;
1572 self.arg_index += 1;1625 self.arg_index += 1;
...@@ -1574,32 +1627,17 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type {...@@ -1574,32 +1627,17 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type {
1574 if (FreeRegInt == u0) {1627 if (FreeRegInt == u0) {
1575 return self.fail(inst.base.src, "TODO implement Register enum for {}", .{self.target.cpu.arch});1628 return self.fail(inst.base.src, "TODO implement Register enum for {}", .{self.target.cpu.arch});
1576 }1629 }
1577 if (inst.base.isUnused())
1578 return MCValue.dead;
1579
1580 try self.registers.ensureCapacity(self.gpa, self.registers.count() + 1);
15811630
1582 const result = self.args[arg_index];1631 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];
1585 switch (result) {1637 switch (result) {
1586 .register => |reg| {1638 .register => |reg| {
1587 self.registers.putAssumeCapacityNoClobber(toCanonicalReg(reg), &inst.base);1639 try self.registers.putNoClobber(self.gpa, toCanonicalReg(reg), &inst.base);
1588 self.markRegUsed(reg);1640 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 }
1603 },1641 },
1604 else => {},1642 else => {},
1605 }1643 }
...@@ -3705,10 +3743,8 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type {...@@ -3705,10 +3743,8 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type {
3705 var nsaa: u32 = 0; // Next stacked argument address3743 var nsaa: u32 = 0; // Next stacked argument address
37063744
3707 for (param_types) |ty, i| {3745 for (param_types) |ty, i| {
3708 if (ty.abiAlignment(self.target.*) == 8) {3746 if (ty.abiAlignment(self.target.*) == 8)
3709 // Round up NCRN to the next even number3747 ncrn = std.mem.alignForwardGeneric(usize, ncrn, 2);
3710 ncrn += ncrn % 2;
3711 }
37123748
3713 const param_size = @intCast(u32, ty.abiSize(self.target.*));3749 const param_size = @intCast(u32, ty.abiSize(self.target.*));
3714 if (std.math.divCeil(u32, param_size, 4) catch unreachable <= 4 - ncrn) {3750 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 {...@@ -3722,11 +3758,8 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type {
3722 return self.fail(src, "TODO MCValues split between registers and stack", .{});3758 return self.fail(src, "TODO MCValues split between registers and stack", .{});
3723 } else {3759 } else {
3724 ncrn = 4;3760 ncrn = 4;
3725 if (ty.abiAlignment(self.target.*) == 8) {3761 if (ty.abiAlignment(self.target.*) == 8)
3726 if (nsaa % 8 != 0) {3762 nsaa = std.mem.alignForwardGeneric(u32, nsaa, 8);
3727 nsaa += 8 - (nsaa % 8);
3728 }
3729 }
37303763
3731 result.args[i] = .{ .stack_offset = nsaa };3764 result.args[i] = .{ .stack_offset = nsaa };
3732 nsaa += param_size;3765 nsaa += param_size;