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/ADT/SmallVector.h"
14 #include "llvm/CodeGen/AsmPrinter.h"
15 #include "llvm/CodeGen/DIE.h"
16 #include "llvm/IR/DebugInfoMetadata.h"
17 #include "llvm/MC/MCStreamer.h"
23 DwarfFile::DwarfFile(AsmPrinter
*AP
, StringRef Pref
, BumpPtrAllocator
&DA
)
24 : Asm(AP
), Abbrevs(AbbrevAllocator
), StrPool(DA
, *Asm
, Pref
) {}
26 void DwarfFile::addUnit(std::unique_ptr
<DwarfCompileUnit
> U
) {
27 CUs
.push_back(std::move(U
));
30 // Emit the various dwarf units to the unit section USection with
31 // the abbreviations going into ASection.
32 void DwarfFile::emitUnits(bool UseOffsets
) {
33 for (const auto &TheU
: CUs
)
34 emitUnit(TheU
.get(), UseOffsets
);
37 void DwarfFile::emitUnit(DwarfUnit
*TheU
, bool UseOffsets
) {
38 if (TheU
->getCUNode()->isDebugDirectivesOnly())
41 MCSection
*S
= TheU
->getSection();
46 // Skip CUs that ended up not being needed (split CUs that were abandoned
47 // because they added no information beyond the non-split CU)
48 if (llvm::empty(TheU
->getUnitDie().values()))
51 Asm
->OutStreamer
->SwitchSection(S
);
52 TheU
->emitHeader(UseOffsets
);
53 Asm
->emitDwarfDIE(TheU
->getUnitDie());
55 if (MCSymbol
*EndLabel
= TheU
->getEndLabel())
56 Asm
->OutStreamer
->EmitLabel(EndLabel
);
59 // Compute the size and offset for each DIE.
60 void DwarfFile::computeSizeAndOffsets() {
61 // Offset from the first CU in the debug info section is 0 initially.
62 unsigned SecOffset
= 0;
64 // Iterate over each compile unit and set the size and offsets for each
65 // DIE within each compile unit. All offsets are CU relative.
66 for (const auto &TheU
: CUs
) {
67 if (TheU
->getCUNode()->isDebugDirectivesOnly())
70 // Skip CUs that ended up not being needed (split CUs that were abandoned
71 // because they added no information beyond the non-split CU)
72 if (llvm::empty(TheU
->getUnitDie().values()))
75 TheU
->setDebugSectionOffset(SecOffset
);
76 SecOffset
+= computeSizeAndOffsetsForUnit(TheU
.get());
80 unsigned DwarfFile::computeSizeAndOffsetsForUnit(DwarfUnit
*TheU
) {
81 // CU-relative offset is reset to 0 here.
82 unsigned Offset
= sizeof(int32_t) + // 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
, Abbrevs
, Offset
);
96 void DwarfFile::emitAbbrevs(MCSection
*Section
) { Abbrevs
.Emit(Asm
, Section
); }
98 // Emit strings into a string section.
99 void DwarfFile::emitStrings(MCSection
*StrSection
, MCSection
*OffsetSection
,
100 bool UseRelativeOffsets
) {
101 StrPool
.emit(*Asm
, StrSection
, OffsetSection
, UseRelativeOffsets
);
104 bool DwarfFile::addScopeVariable(LexicalScope
*LS
, DbgVariable
*Var
) {
105 auto &ScopeVars
= ScopeVariables
[LS
];
106 const DILocalVariable
*DV
= Var
->getVariable();
107 if (unsigned ArgNum
= DV
->getArg()) {
108 auto Cached
= ScopeVars
.Args
.find(ArgNum
);
109 if (Cached
== ScopeVars
.Args
.end())
110 ScopeVars
.Args
[ArgNum
] = Var
;
112 Cached
->second
->addMMIEntry(*Var
);
116 ScopeVars
.Locals
.push_back(Var
);
121 void DwarfFile::addScopeLabel(LexicalScope
*LS
, DbgLabel
*Label
) {
122 SmallVectorImpl
<DbgLabel
*> &Labels
= ScopeLabels
[LS
];
123 Labels
.push_back(Label
);
126 std::pair
<uint32_t, RangeSpanList
*>
127 DwarfFile::addRange(const DwarfCompileUnit
&CU
, SmallVector
<RangeSpan
, 2> R
) {
128 CURangeLists
.push_back(
129 RangeSpanList(Asm
->createTempSymbol("debug_ranges"), CU
, std::move(R
)));
130 return std::make_pair(CURangeLists
.size() - 1, &CURangeLists
.back());