1 //===- llvm/CodeGen/DwarfFile.cpp - Dwarf Debug Framework -----------------===//
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
7 //===----------------------------------------------------------------------===//
10 #include "DwarfCompileUnit.h"
11 #include "DwarfDebug.h"
12 #include "DwarfUnit.h"
13 #include "llvm/CodeGen/AsmPrinter.h"
14 #include "llvm/IR/DebugInfoMetadata.h"
15 #include "llvm/MC/MCStreamer.h"
20 DwarfFile::DwarfFile(AsmPrinter
*AP
, StringRef Pref
, BumpPtrAllocator
&DA
)
21 : Asm(AP
), Abbrevs(AbbrevAllocator
), StrPool(DA
, *Asm
, Pref
) {}
23 void DwarfFile::addUnit(std::unique_ptr
<DwarfCompileUnit
> U
) {
24 CUs
.push_back(std::move(U
));
27 // Emit the various dwarf units to the unit section USection with
28 // the abbreviations going into ASection.
29 void DwarfFile::emitUnits(bool UseOffsets
) {
30 for (const auto &TheU
: CUs
)
31 emitUnit(TheU
.get(), UseOffsets
);
34 void DwarfFile::emitUnit(DwarfUnit
*TheU
, bool UseOffsets
) {
35 if (TheU
->getCUNode()->isDebugDirectivesOnly())
38 MCSection
*S
= TheU
->getSection();
43 // Skip CUs that ended up not being needed (split CUs that were abandoned
44 // because they added no information beyond the non-split CU)
45 if (TheU
->getUnitDie().values().empty())
48 Asm
->OutStreamer
->switchSection(S
);
49 TheU
->emitHeader(UseOffsets
);
50 Asm
->emitDwarfDIE(TheU
->getUnitDie());
52 if (MCSymbol
*EndLabel
= TheU
->getEndLabel())
53 Asm
->OutStreamer
->emitLabel(EndLabel
);
56 // Compute the size and offset for each DIE.
57 void DwarfFile::computeSizeAndOffsets() {
58 // Offset from the first CU in the debug info section is 0 initially.
59 uint64_t SecOffset
= 0;
61 // Iterate over each compile unit and set the size and offsets for each
62 // DIE within each compile unit. All offsets are CU relative.
63 for (const auto &TheU
: CUs
) {
64 if (TheU
->getCUNode()->isDebugDirectivesOnly())
67 // Skip CUs that ended up not being needed (split CUs that were abandoned
68 // because they added no information beyond the non-split CU)
69 if (TheU
->getUnitDie().values().empty())
72 TheU
->setDebugSectionOffset(SecOffset
);
73 SecOffset
+= computeSizeAndOffsetsForUnit(TheU
.get());
75 if (SecOffset
> UINT32_MAX
&& !Asm
->isDwarf64())
76 report_fatal_error("The generated debug information is too large "
77 "for the 32-bit DWARF format.");
80 unsigned DwarfFile::computeSizeAndOffsetsForUnit(DwarfUnit
*TheU
) {
81 // CU-relative offset is reset to 0 here.
82 unsigned Offset
= Asm
->getUnitLengthFieldByteSize() + // Length of Unit Info
83 TheU
->getHeaderSize(); // Unit-specific headers
85 // The return value here is CU-relative, after laying out
87 return computeSizeAndOffset(TheU
->getUnitDie(), Offset
);
90 // Compute the size and offset of a DIE. The offset is relative to start of the
91 // CU. It returns the offset after laying out the DIE.
92 unsigned DwarfFile::computeSizeAndOffset(DIE
&Die
, unsigned Offset
) {
93 return Die
.computeOffsetsAndAbbrevs(Asm
->getDwarfFormParams(), Abbrevs
,
97 void DwarfFile::emitAbbrevs(MCSection
*Section
) { Abbrevs
.Emit(Asm
, Section
); }
99 // Emit strings into a string section.
100 void DwarfFile::emitStrings(MCSection
*StrSection
, MCSection
*OffsetSection
,
101 bool UseRelativeOffsets
) {
102 StrPool
.emit(*Asm
, StrSection
, OffsetSection
, UseRelativeOffsets
);
105 void DwarfFile::addScopeVariable(LexicalScope
*LS
, DbgVariable
*Var
) {
106 auto &ScopeVars
= ScopeVariables
[LS
];
107 const DILocalVariable
*DV
= Var
->getVariable();
108 if (unsigned ArgNum
= DV
->getArg()) {
109 auto Ret
= ScopeVars
.Args
.insert({ArgNum
, Var
});
113 ScopeVars
.Locals
.push_back(Var
);
117 void DwarfFile::addScopeLabel(LexicalScope
*LS
, DbgLabel
*Label
) {
118 SmallVectorImpl
<DbgLabel
*> &Labels
= ScopeLabels
[LS
];
119 Labels
.push_back(Label
);
122 std::pair
<uint32_t, RangeSpanList
*>
123 DwarfFile::addRange(const DwarfCompileUnit
&CU
, SmallVector
<RangeSpan
, 2> R
) {
124 CURangeLists
.push_back(
125 RangeSpanList
{Asm
->createTempSymbol("debug_ranges"), &CU
, std::move(R
)});
126 return std::make_pair(CURangeLists
.size() - 1, &CURangeLists
.back());