| ... | ... | @@ -1567,6 +1567,59 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type { |
| 1567 | 1567 | } |
| 1568 | 1568 | } |
| 1569 | 1569 | |
| 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 | 1623 | fn genArg(self: *Self, inst: *ir.Inst.Arg) !MCValue { |
| 1571 | 1624 | const arg_index = self.arg_index; |
| 1572 | 1625 | self.arg_index += 1; |
| ... | ... | @@ -1574,32 +1627,17 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type { |
| 1574 | 1627 | if (FreeRegInt == u0) { |
| 1575 | 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); |
| 1581 | 1630 | |
| 1582 | 1631 | const result = self.args[arg_index]; |
| 1632 | try self.genArgDbgInfo(inst, result); |
| 1633 | |
| 1634 | if (inst.base.isUnused()) |
| 1635 | return MCValue.dead; |
| 1583 | 1636 | |
| 1584 | | const name_with_null = inst.name[0 .. mem.lenZ(inst.name) + 1]; |
| 1585 | 1637 | switch (result) { |
| 1586 | 1638 | .register => |reg| { |
| 1587 | | self.registers.putAssumeCapacityNoClobber(toCanonicalReg(reg), &inst.base); |
| 1639 | try self.registers.putNoClobber(self.gpa, toCanonicalReg(reg), &inst.base); |
| 1588 | 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 | 1642 | else => {}, |
| 1605 | 1643 | } |
| ... | ... | @@ -3705,10 +3743,8 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type { |
| 3705 | 3743 | var nsaa: u32 = 0; // Next stacked argument address |
| 3706 | 3744 | |
| 3707 | 3745 | 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); |
| 3712 | 3748 | |
| 3713 | 3749 | const param_size = @intCast(u32, ty.abiSize(self.target.*)); |
| 3714 | 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 | 3758 | return self.fail(src, "TODO MCValues split between registers and stack", .{}); |
| 3723 | 3759 | } else { |
| 3724 | 3760 | 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); |
| 3730 | 3763 | |
| 3731 | 3764 | result.args[i] = .{ .stack_offset = nsaa }; |
| 3732 | 3765 | nsaa += param_size; |