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/ADT/SmallVector.h"
146e07bfd0SEugene Zelenko #include "llvm/CodeGen/AsmPrinter.h"
156e07bfd0SEugene Zelenko #include "llvm/CodeGen/DIE.h"
166e07bfd0SEugene Zelenko #include "llvm/IR/DebugInfoMetadata.h"
1785f80d71SDavid Blaikie #include "llvm/MC/MCStreamer.h"
186e07bfd0SEugene Zelenko #include <algorithm>
196e07bfd0SEugene Zelenko #include <cstdint>
2085f80d71SDavid Blaikie 
216e07bfd0SEugene Zelenko using namespace llvm;
226e07bfd0SEugene Zelenko 
239412d63fSFrederic Riss DwarfFile::DwarfFile(AsmPrinter *AP, StringRef Pref, BumpPtrAllocator &DA)
243462a420SGreg Clayton     : Asm(AP), Abbrevs(AbbrevAllocator), StrPool(DA, *Asm, Pref) {}
2585f80d71SDavid Blaikie 
267c384cceSPeter Collingbourne void DwarfFile::addUnit(std::unique_ptr<DwarfCompileUnit> U) {
2785f80d71SDavid Blaikie   CUs.push_back(std::move(U));
2885f80d71SDavid Blaikie }
2985f80d71SDavid Blaikie 
3085f80d71SDavid Blaikie // Emit the various dwarf units to the unit section USection with
3185f80d71SDavid Blaikie // the abbreviations going into ASection.
32063d725fSRafael Espindola void DwarfFile::emitUnits(bool UseOffsets) {
337c384cceSPeter Collingbourne   for (const auto &TheU : CUs)
347c384cceSPeter Collingbourne     emitUnit(TheU.get(), UseOffsets);
357c384cceSPeter Collingbourne }
367c384cceSPeter Collingbourne 
377c384cceSPeter Collingbourne void DwarfFile::emitUnit(DwarfUnit *TheU, bool UseOffsets) {
38d4dd7215SAlexey Bataev   if (TheU->getCUNode()->isDebugDirectivesOnly())
39d4dd7215SAlexey Bataev     return;
40d4dd7215SAlexey Bataev 
41560ff355SDavid Blaikie   MCSection *S = TheU->getSection();
4285f80d71SDavid Blaikie 
43560ff355SDavid Blaikie   if (!S)
44560ff355SDavid Blaikie     return;
45560ff355SDavid Blaikie 
46104dcb34SDavid Blaikie   // Skip CUs that ended up not being needed (split CUs that were abandoned
47104dcb34SDavid Blaikie   // because they added no information beyond the non-split CU)
48104dcb34SDavid Blaikie   if (llvm::empty(TheU->getUnitDie().values()))
49104dcb34SDavid Blaikie     return;
50104dcb34SDavid Blaikie 
51560ff355SDavid Blaikie   Asm->OutStreamer->SwitchSection(S);
52063d725fSRafael Espindola   TheU->emitHeader(UseOffsets);
53560ff355SDavid Blaikie   Asm->emitDwarfDIE(TheU->getUnitDie());
54c4e08febSDavid Blaikie 
55c4e08febSDavid Blaikie   if (MCSymbol *EndLabel = TheU->getEndLabel())
56c4e08febSDavid Blaikie     Asm->OutStreamer->EmitLabel(EndLabel);
5785f80d71SDavid Blaikie }
58f299947bSDavid Blaikie 
5985f80d71SDavid Blaikie // Compute the size and offset for each DIE.
6085f80d71SDavid Blaikie void DwarfFile::computeSizeAndOffsets() {
6185f80d71SDavid Blaikie   // Offset from the first CU in the debug info section is 0 initially.
6285f80d71SDavid Blaikie   unsigned SecOffset = 0;
6385f80d71SDavid Blaikie 
6485f80d71SDavid Blaikie   // Iterate over each compile unit and set the size and offsets for each
6585f80d71SDavid Blaikie   // DIE within each compile unit. All offsets are CU relative.
6685f80d71SDavid Blaikie   for (const auto &TheU : CUs) {
67d4dd7215SAlexey Bataev     if (TheU->getCUNode()->isDebugDirectivesOnly())
68d4dd7215SAlexey Bataev       continue;
69d4dd7215SAlexey Bataev 
70104dcb34SDavid Blaikie     // Skip CUs that ended up not being needed (split CUs that were abandoned
71104dcb34SDavid Blaikie     // because they added no information beyond the non-split CU)
72104dcb34SDavid Blaikie     if (llvm::empty(TheU->getUnitDie().values()))
73104dcb34SDavid Blaikie       return;
74104dcb34SDavid Blaikie 
7535630c33SGreg Clayton     TheU->setDebugSectionOffset(SecOffset);
767c384cceSPeter Collingbourne     SecOffset += computeSizeAndOffsetsForUnit(TheU.get());
777c384cceSPeter Collingbourne   }
787c384cceSPeter Collingbourne }
7985f80d71SDavid Blaikie 
807c384cceSPeter Collingbourne unsigned DwarfFile::computeSizeAndOffsetsForUnit(DwarfUnit *TheU) {
8185f80d71SDavid Blaikie   // CU-relative offset is reset to 0 here.
8285f80d71SDavid Blaikie   unsigned Offset = sizeof(int32_t) +      // 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.
9285f80d71SDavid Blaikie unsigned DwarfFile::computeSizeAndOffset(DIE &Die, unsigned Offset) {
933462a420SGreg Clayton   return Die.computeOffsetsAndAbbrevs(Asm, Abbrevs, Offset);
9485f80d71SDavid Blaikie }
9585f80d71SDavid Blaikie 
963462a420SGreg Clayton void DwarfFile::emitAbbrevs(MCSection *Section) { Abbrevs.Emit(Asm, Section); }
9785f80d71SDavid Blaikie 
9885f80d71SDavid Blaikie // Emit strings into a string section.
99456b555fSWolfgang Pieb void DwarfFile::emitStrings(MCSection *StrSection, MCSection *OffsetSection,
100456b555fSWolfgang Pieb                             bool UseRelativeOffsets) {
101456b555fSWolfgang Pieb   StrPool.emit(*Asm, StrSection, OffsetSection, UseRelativeOffsets);
10285f80d71SDavid Blaikie }
103f299947bSDavid Blaikie 
104ca7e4702SAdrian Prantl bool DwarfFile::addScopeVariable(LexicalScope *LS, DbgVariable *Var) {
105c929f7adSAdrian Prantl   auto &ScopeVars = ScopeVariables[LS];
106a9308c49SDuncan P. N. Exon Smith   const DILocalVariable *DV = Var->getVariable();
1077348ddaaSDuncan P. N. Exon Smith   if (unsigned ArgNum = DV->getArg()) {
108c929f7adSAdrian Prantl     auto Cached = ScopeVars.Args.find(ArgNum);
109c929f7adSAdrian Prantl     if (Cached == ScopeVars.Args.end())
110c929f7adSAdrian Prantl       ScopeVars.Args[ArgNum] = Var;
111c929f7adSAdrian Prantl     else {
112c929f7adSAdrian Prantl       Cached->second->addMMIEntry(*Var);
113ca7e4702SAdrian Prantl       return false;
114ca7e4702SAdrian Prantl     }
115c929f7adSAdrian Prantl   } else {
116c929f7adSAdrian Prantl     ScopeVars.Locals.push_back(Var);
1173b5c8400SDavid Blaikie   }
118ca7e4702SAdrian Prantl   return true;
1193b5c8400SDavid Blaikie }
1202532ac88SHsiangkai Wang 
1212532ac88SHsiangkai Wang void DwarfFile::addScopeLabel(LexicalScope *LS, DbgLabel *Label) {
1222532ac88SHsiangkai Wang   SmallVectorImpl<DbgLabel *> &Labels = ScopeLabels[LS];
1232532ac88SHsiangkai Wang   Labels.push_back(Label);
1242532ac88SHsiangkai Wang }
125c4af8bf2SDavid Blaikie 
126c4af8bf2SDavid Blaikie std::pair<uint32_t, RangeSpanList *>
127c8f7e6c1SDavid Blaikie DwarfFile::addRange(const DwarfCompileUnit &CU, SmallVector<RangeSpan, 2> R) {
128c8f7e6c1SDavid Blaikie   CURangeLists.push_back(
129*64fa76efSDavid Blaikie       RangeSpanList{Asm->createTempSymbol("debug_ranges"), &CU, std::move(R)});
130c4af8bf2SDavid Blaikie   return std::make_pair(CURangeLists.size() - 1, &CURangeLists.back());
131c4af8bf2SDavid Blaikie }
132