| ... | @@ -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 | } |
| 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 | 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); | | |
| 1581 | | 1630 | |
| 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; |
| 1583 | | 1636 | |
| 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 address | 3743 | var nsaa: u32 = 0; // Next stacked argument address |
| 3706 | | 3744 | |
| 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 number | 3747 | ncrn = std.mem.alignForwardGeneric(usize, ncrn, 2); |
| 3710 | ncrn += ncrn % 2; | | |
| 3711 | } | | |
| 3712 | | 3748 | |
| 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 | } | | |
| 3730 | | 3763 | |
| 3731 | result.args[i] = .{ .stack_offset = nsaa }; | 3764 | result.args[i] = .{ .stack_offset = nsaa }; |
| 3732 | nsaa += param_size; | 3765 | nsaa += param_size; |