16e07bfd0SEugene Zelenko //===- llvm/CodeGen/DwarfFile.cpp - Dwarf Debug Framework -----------------===//
285f80d71SDavid Blaikie //
32946cd70SChandler Carruth // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
42946cd70SChandler Carruth // See https://llvm.org/LICENSE.txt for license information.
52946cd70SChandler Carruth // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
685f80d71SDavid Blaikie //
785f80d71SDavid Blaikie //===----------------------------------------------------------------------===//
885f80d71SDavid Blaikie 
985f80d71SDavid Blaikie #include "DwarfFile.h"
107c384cceSPeter Collingbourne #include "DwarfCompileUnit.h"
1185f80d71SDavid Blaikie #include "DwarfDebug.h"
1285f80d71SDavid Blaikie #include "DwarfUnit.h"
136e07bfd0SEugene Zelenko #include "llvm/CodeGen/AsmPrinter.h"
146e07bfd0SEugene Zelenko #include "llvm/IR/DebugInfoMetadata.h"
1585f80d71SDavid Blaikie #include "llvm/MC/MCStreamer.h"
166e07bfd0SEugene Zelenko #include <cstdint>
1785f80d71SDavid Blaikie 
186e07bfd0SEugene Zelenko using namespace llvm;
196e07bfd0SEugene Zelenko 
DwarfFile(AsmPrinter * AP,StringRef Pref,BumpPtrAllocator & DA)209412d63fSFrederic Riss DwarfFile::DwarfFile(AsmPrinter *AP, StringRef Pref, BumpPtrAllocator &DA)
213462a420SGreg Clayton     : Asm(AP), Abbrevs(AbbrevAllocator), StrPool(DA, *Asm, Pref) {}
2285f80d71SDavid Blaikie 
addUnit(std::unique_ptr<DwarfCompileUnit> U)237c384cceSPeter Collingbourne void DwarfFile::addUnit(std::unique_ptr<DwarfCompileUnit> U) {
2485f80d71SDavid Blaikie   CUs.push_back(std::move(U));
2585f80d71SDavid Blaikie }
2685f80d71SDavid Blaikie 
2785f80d71SDavid Blaikie // Emit the various dwarf units to the unit section USection with
2885f80d71SDavid Blaikie // the abbreviations going into ASection.
emitUnits(bool UseOffsets)29063d725fSRafael Espindola void DwarfFile::emitUnits(bool UseOffsets) {
307c384cceSPeter Collingbourne   for (const auto &TheU : CUs)
317c384cceSPeter Collingbourne     emitUnit(TheU.get(), UseOffsets);
327c384cceSPeter Collingbourne }
337c384cceSPeter Collingbourne 
emitUnit(DwarfUnit * TheU,bool UseOffsets)347c384cceSPeter Collingbourne void DwarfFile::emitUnit(DwarfUnit *TheU, bool UseOffsets) {
35d4dd7215SAlexey Bataev   if (TheU->getCUNode()->isDebugDirectivesOnly())
36d4dd7215SAlexey Bataev     return;
37d4dd7215SAlexey Bataev 
38560ff355SDavid Blaikie   MCSection *S = TheU->getSection();
3985f80d71SDavid Blaikie 
40560ff355SDavid Blaikie   if (!S)
41560ff355SDavid Blaikie     return;
42560ff355SDavid Blaikie 
43104dcb34SDavid Blaikie   // Skip CUs that ended up not being needed (split CUs that were abandoned
44104dcb34SDavid Blaikie   // because they added no information beyond the non-split CU)
45104dcb34SDavid Blaikie   if (llvm::empty(TheU->getUnitDie().values()))
46104dcb34SDavid Blaikie     return;
47104dcb34SDavid Blaikie 
48*adf4142fSFangrui Song   Asm->OutStreamer->switchSection(S);
49063d725fSRafael Espindola   TheU->emitHeader(UseOffsets);
50560ff355SDavid Blaikie   Asm->emitDwarfDIE(TheU->getUnitDie());
51c4e08febSDavid Blaikie 
52c4e08febSDavid Blaikie   if (MCSymbol *EndLabel = TheU->getEndLabel())
536d2d589bSFangrui Song     Asm->OutStreamer->emitLabel(EndLabel);
5485f80d71SDavid Blaikie }
55f299947bSDavid Blaikie 
5685f80d71SDavid Blaikie // Compute the size and offset for each DIE.
computeSizeAndOffsets()5785f80d71SDavid Blaikie void DwarfFile::computeSizeAndOffsets() {
5885f80d71SDavid Blaikie   // Offset from the first CU in the debug info section is 0 initially.
59a845ebd6SIgor Kudrin   uint64_t SecOffset = 0;
6085f80d71SDavid Blaikie 
6185f80d71SDavid Blaikie   // Iterate over each compile unit and set the size and offsets for each
6285f80d71SDavid Blaikie   // DIE within each compile unit. All offsets are CU relative.
6385f80d71SDavid Blaikie   for (const auto &TheU : CUs) {
64d4dd7215SAlexey Bataev     if (TheU->getCUNode()->isDebugDirectivesOnly())
65d4dd7215SAlexey Bataev       continue;
66d4dd7215SAlexey Bataev 
67104dcb34SDavid Blaikie     // Skip CUs that ended up not being needed (split CUs that were abandoned
68104dcb34SDavid Blaikie     // because they added no information beyond the non-split CU)
69104dcb34SDavid Blaikie     if (llvm::empty(TheU->getUnitDie().values()))
70104dcb34SDavid Blaikie       return;
71104dcb34SDavid Blaikie 
7235630c33SGreg Clayton     TheU->setDebugSectionOffset(SecOffset);
737c384cceSPeter Collingbourne     SecOffset += computeSizeAndOffsetsForUnit(TheU.get());
747c384cceSPeter Collingbourne   }
75a845ebd6SIgor Kudrin   if (SecOffset > UINT32_MAX && !Asm->isDwarf64())
76a845ebd6SIgor Kudrin     report_fatal_error("The generated debug information is too large "
77a845ebd6SIgor Kudrin                        "for the 32-bit DWARF format.");
787c384cceSPeter Collingbourne }
7985f80d71SDavid Blaikie 
computeSizeAndOffsetsForUnit(DwarfUnit * TheU)807c384cceSPeter Collingbourne unsigned DwarfFile::computeSizeAndOffsetsForUnit(DwarfUnit *TheU) {
8185f80d71SDavid Blaikie   // CU-relative offset is reset to 0 here.
825dd1c591SIgor Kudrin   unsigned Offset = Asm->getUnitLengthFieldByteSize() + // Length of Unit Info
8385f80d71SDavid Blaikie                     TheU->getHeaderSize();              // Unit-specific headers
8485f80d71SDavid Blaikie 
857c384cceSPeter Collingbourne   // The return value here is CU-relative, after laying out
8685f80d71SDavid Blaikie   // all of the CU DIE.
877c384cceSPeter Collingbourne   return computeSizeAndOffset(TheU->getUnitDie(), Offset);
8885f80d71SDavid Blaikie }
897c384cceSPeter Collingbourne 
9085f80d71SDavid Blaikie // Compute the size and offset of a DIE. The offset is relative to start of the
9185f80d71SDavid Blaikie // CU. It returns the offset after laying out the DIE.
computeSizeAndOffset(DIE & Die,unsigned Offset)9285f80d71SDavid Blaikie unsigned DwarfFile::computeSizeAndOffset(DIE &Die, unsigned Offset) {
9339385d4cSAlexey Lapshin   return Die.computeOffsetsAndAbbrevs(Asm->getDwarfFormParams(), Abbrevs,
9439385d4cSAlexey Lapshin                                       Offset);
9585f80d71SDavid Blaikie }
9685f80d71SDavid Blaikie 
emitAbbrevs(MCSection * Section)973462a420SGreg Clayton void DwarfFile::emitAbbrevs(MCSection *Section) { Abbrevs.Emit(Asm, Section); }
9885f80d71SDavid Blaikie 
9985f80d71SDavid Blaikie // Emit strings into a string section.
emitStrings(MCSection * StrSection,MCSection * OffsetSection,bool UseRelativeOffsets)100456b555fSWolfgang Pieb void DwarfFile::emitStrings(MCSection *StrSection, MCSection *OffsetSection,
101456b555fSWolfgang Pieb                             bool UseRelativeOffsets) {
102456b555fSWolfgang Pieb   StrPool.emit(*Asm, StrSection, OffsetSection, UseRelativeOffsets);
10385f80d71SDavid Blaikie }
104f299947bSDavid Blaikie 
addScopeVariable(LexicalScope * LS,DbgVariable * Var)105ca7e4702SAdrian Prantl bool DwarfFile::addScopeVariable(LexicalScope *LS, DbgVariable *Var) {
106c929f7adSAdrian Prantl   auto &ScopeVars = ScopeVariables[LS];
107a9308c49SDuncan P. N. Exon Smith   const DILocalVariable *DV = Var->getVariable();
1087348ddaaSDuncan P. N. Exon Smith   if (unsigned ArgNum = DV->getArg()) {
109c929f7adSAdrian Prantl     auto Cached = ScopeVars.Args.find(ArgNum);
110c929f7adSAdrian Prantl     if (Cached == ScopeVars.Args.end())
111c929f7adSAdrian Prantl       ScopeVars.Args[ArgNum] = Var;
112c929f7adSAdrian Prantl     else {
113c929f7adSAdrian Prantl       Cached->second->addMMIEntry(*Var);
114ca7e4702SAdrian Prantl       return false;
115ca7e4702SAdrian Prantl     }
116c929f7adSAdrian Prantl   } else {
117c929f7adSAdrian Prantl     ScopeVars.Locals.push_back(Var);
1183b5c8400SDavid Blaikie   }
119ca7e4702SAdrian Prantl   return true;
1203b5c8400SDavid Blaikie }
1212532ac88SHsiangkai Wang 
addScopeLabel(LexicalScope * LS,DbgLabel * Label)1222532ac88SHsiangkai Wang void DwarfFile::addScopeLabel(LexicalScope *LS, DbgLabel *Label) {
1232532ac88SHsiangkai Wang   SmallVectorImpl<DbgLabel *> &Labels = ScopeLabels[LS];
1242532ac88SHsiangkai Wang   Labels.push_back(Label);
1252532ac88SHsiangkai Wang }
126c4af8bf2SDavid Blaikie 
127c4af8bf2SDavid Blaikie std::pair<uint32_t, RangeSpanList *>
addRange(const DwarfCompileUnit & CU,SmallVector<RangeSpan,2> R)128c8f7e6c1SDavid Blaikie DwarfFile::addRange(const DwarfCompileUnit &CU, SmallVector<RangeSpan, 2> R) {
129c8f7e6c1SDavid Blaikie   CURangeLists.push_back(
13064fa76efSDavid Blaikie       RangeSpanList{Asm->createTempSymbol("debug_ranges"), &CU, std::move(R)});
131c4af8bf2SDavid Blaikie   return std::make_pair(CURangeLists.size() - 1, &CURangeLists.back());
132c4af8bf2SDavid Blaikie }
133