| ... | @@ -1681,22 +1681,34 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type { | ... | @@ -1681,22 +1681,34 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type { |
| 1681 | | 1681 | |
| 1682 | switch (mcv) { | 1682 | switch (mcv) { |
| 1683 | .register => |reg| { | 1683 | .register => |reg| { |
| 1684 | // Copy arg to stack for better debugging | 1684 | switch (self.debug_output) { |
| 1685 | const ty = inst.base.ty; | 1685 | .dwarf => |dbg_out| { |
| 1686 | const abi_size = math.cast(u32, ty.abiSize(self.target.*)) catch { | 1686 | try dbg_out.dbg_info.ensureCapacity(dbg_out.dbg_info.items.len + 3); |
| 1687 | return self.fail(inst.base.src, "type '{}' too big to fit into stack frame", .{ty}); | 1687 | dbg_out.dbg_info.appendAssumeCapacity(link.File.Elf.abbrev_parameter); |
| 1688 | }; | 1688 | dbg_out.dbg_info.appendSliceAssumeCapacity(&[2]u8{ // DW.AT_location, DW.FORM_exprloc |
| 1689 | const abi_align = ty.abiAlignment(self.target.*); | 1689 | 1, // ULEB128 dwarf expression length |
| 1690 | const stack_offset = try self.allocMem(&inst.base, abi_size, abi_align); | 1690 | reg.dwarfLocOp(), |
| 1691 | try self.genSetStack(inst.base.src, ty, stack_offset, MCValue{ .register = reg }); | 1691 | }); |
| 1692 | const adjusted_stack_offset = math.negateCast(stack_offset + abi_size) catch { | 1692 | try dbg_out.dbg_info.ensureCapacity(dbg_out.dbg_info.items.len + 5 + name_with_null.len); |
| 1693 | return self.fail(inst.base.src, "Stack offset too large for arguments", .{}); | 1693 | try self.addDbgInfoTypeReloc(inst.base.ty); // DW.AT_type, DW.FORM_ref4 |
| 1694 | }; | 1694 | dbg_out.dbg_info.appendSliceAssumeCapacity(name_with_null); // DW.AT_name, DW.FORM_string |
| 1695 | | 1695 | }, |
| | 1696 | .none => {}, |
| | 1697 | } |
| | 1698 | }, |
| | 1699 | .stack_offset => |offset| { |
| 1696 | switch (self.debug_output) { | 1700 | switch (self.debug_output) { |
| 1697 | .dwarf => |dbg_out| { | 1701 | .dwarf => |dbg_out| { |
| 1698 | switch (arch) { | 1702 | switch (arch) { |
| 1699 | .arm, .armeb => { | 1703 | .arm, .armeb => { |
| | 1704 | const ty = inst.base.ty; |
| | 1705 | const abi_size = math.cast(u32, ty.abiSize(self.target.*)) catch { |
| | 1706 | return self.fail(inst.base.src, "type '{}' too big to fit into stack frame", .{ty}); |
| | 1707 | }; |
| | 1708 | const adjusted_stack_offset = math.negateCast(offset + abi_size) catch { |
| | 1709 | return self.fail(inst.base.src, "Stack offset too large for arguments", .{}); |
| | 1710 | }; |
| | 1711 | |
| 1700 | try dbg_out.dbg_info.append(link.File.Elf.abbrev_parameter); | 1712 | try dbg_out.dbg_info.append(link.File.Elf.abbrev_parameter); |
| 1701 | | 1713 | |
| 1702 | // Get length of the LEB128 stack offset | 1714 | // Get length of the LEB128 stack offset |
| ... | @@ -1708,19 +1720,13 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type { | ... | @@ -1708,19 +1720,13 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type { |
| 1708 | try leb128.writeULEB128(dbg_out.dbg_info.writer(), counting_writer.bytes_written + 1); | 1720 | try leb128.writeULEB128(dbg_out.dbg_info.writer(), counting_writer.bytes_written + 1); |
| 1709 | try dbg_out.dbg_info.append(DW.OP_breg11); | 1721 | try dbg_out.dbg_info.append(DW.OP_breg11); |
| 1710 | try leb128.writeILEB128(dbg_out.dbg_info.writer(), adjusted_stack_offset); | 1722 | try leb128.writeILEB128(dbg_out.dbg_info.writer(), adjusted_stack_offset); |
| | 1723 | |
| | 1724 | try dbg_out.dbg_info.ensureCapacity(dbg_out.dbg_info.items.len + 5 + name_with_null.len); |
| | 1725 | try self.addDbgInfoTypeReloc(inst.base.ty); // DW.AT_type, DW.FORM_ref4 |
| | 1726 | dbg_out.dbg_info.appendSliceAssumeCapacity(name_with_null); // DW.AT_name, DW.FORM_string |
| 1711 | }, | 1727 | }, |
| 1712 | else => { | 1728 | else => {}, |
| 1713 | try dbg_out.dbg_info.ensureCapacity(dbg_out.dbg_info.items.len + 3); | | |
| 1714 | dbg_out.dbg_info.appendAssumeCapacity(link.File.Elf.abbrev_parameter); | | |
| 1715 | dbg_out.dbg_info.appendSliceAssumeCapacity(&[2]u8{ // DW.AT_location, DW.FORM_exprloc | | |
| 1716 | 1, // ULEB128 dwarf expression length | | |
| 1717 | reg.dwarfLocOp(), | | |
| 1718 | }); | | |
| 1719 | }, | | |
| 1720 | } | 1729 | } |
| 1721 | try dbg_out.dbg_info.ensureCapacity(dbg_out.dbg_info.items.len + 5 + name_with_null.len); | | |
| 1722 | try self.addDbgInfoTypeReloc(inst.base.ty); // DW.AT_type, DW.FORM_ref4 | | |
| 1723 | dbg_out.dbg_info.appendSliceAssumeCapacity(name_with_null); // DW.AT_name, DW.FORM_string | | |
| 1724 | }, | 1730 | }, |
| 1725 | .none => {}, | 1731 | .none => {}, |
| 1726 | } | 1732 | } |
| ... | @@ -1738,19 +1744,39 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type { | ... | @@ -1738,19 +1744,39 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type { |
| 1738 | } | 1744 | } |
| 1739 | | 1745 | |
| 1740 | const result = self.args[arg_index]; | 1746 | const result = self.args[arg_index]; |
| 1741 | try self.genArgDbgInfo(inst, result); | 1747 | const mcv = switch (arch) { |
| | 1748 | // TODO support stack-only registers on all target architectures |
| | 1749 | .arm, .armeb, .aarch64, .aarch64_32, .aarch64_be => switch (result) { |
| | 1750 | // Copy registers to the stack |
| | 1751 | .register => |reg| blk: { |
| | 1752 | const ty = inst.base.ty; |
| | 1753 | const abi_size = math.cast(u32, ty.abiSize(self.target.*)) catch { |
| | 1754 | return self.fail(inst.base.src, "type '{}' too big to fit into stack frame", .{ty}); |
| | 1755 | }; |
| | 1756 | const abi_align = ty.abiAlignment(self.target.*); |
| | 1757 | const stack_offset = try self.allocMem(&inst.base, abi_size, abi_align); |
| | 1758 | try self.genSetStack(inst.base.src, ty, stack_offset, MCValue{ .register = reg }); |
| | 1759 | |
| | 1760 | break :blk MCValue{ .stack_offset = stack_offset }; |
| | 1761 | }, |
| | 1762 | else => result, |
| | 1763 | }, |
| | 1764 | else => result, |
| | 1765 | }; |
| | 1766 | try self.genArgDbgInfo(inst, mcv); |
| 1742 | | 1767 | |
| 1743 | if (inst.base.isUnused()) | 1768 | if (inst.base.isUnused()) |
| 1744 | return MCValue.dead; | 1769 | return MCValue.dead; |
| 1745 | | 1770 | |
| 1746 | switch (result) { | 1771 | switch (mcv) { |
| 1747 | .register => |reg| { | 1772 | .register => |reg| { |
| 1748 | try self.register_manager.registers.ensureCapacity(self.gpa, self.register_manager.registers.count() + 1); | 1773 | try self.register_manager.registers.ensureCapacity(self.gpa, self.register_manager.registers.count() + 1); |
| 1749 | self.register_manager.getRegAssumeFree(toCanonicalReg(reg), &inst.base); | 1774 | self.register_manager.getRegAssumeFree(toCanonicalReg(reg), &inst.base); |
| 1750 | }, | 1775 | }, |
| 1751 | else => {}, | 1776 | else => {}, |
| 1752 | } | 1777 | } |
| 1753 | return result; | 1778 | |
| | 1779 | return mcv; |
| 1754 | } | 1780 | } |
| 1755 | | 1781 | |
| 1756 | fn genBreakpoint(self: *Self, src: LazySrcLoc) !MCValue { | 1782 | fn genBreakpoint(self: *Self, src: LazySrcLoc) !MCValue { |
| ... | @@ -2257,7 +2283,7 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type { | ... | @@ -2257,7 +2283,7 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type { |
| 2257 | const rhs = try self.resolveInst(inst.rhs); | 2283 | const rhs = try self.resolveInst(inst.rhs); |
| 2258 | | 2284 | |
| 2259 | const src_mcv = rhs; | 2285 | const src_mcv = rhs; |
| 2260 | const dst_mcv = if (lhs != .register) try self.copyToNewRegister(&inst.base, lhs) else lhs; | 2286 | const dst_mcv = if (lhs != .register) try self.copyToNewRegister(inst.lhs, lhs) else lhs; |
| 2261 | | 2287 | |
| 2262 | try self.genArmBinOpCode(inst.base.src, dst_mcv.register, dst_mcv, src_mcv, .cmp_eq); | 2288 | try self.genArmBinOpCode(inst.base.src, dst_mcv.register, dst_mcv, src_mcv, .cmp_eq); |
| 2263 | const info = inst.lhs.ty.intInfo(self.target.*); | 2289 | const info = inst.lhs.ty.intInfo(self.target.*); |