16e07bfd0SEugene Zelenko //===- llvm/CodeGen/DwarfFile.cpp - Dwarf Debug Framework -----------------===//
285f80d71SDavid Blaikie //
385f80d71SDavid Blaikie //                     The LLVM Compiler Infrastructure
485f80d71SDavid Blaikie //
585f80d71SDavid Blaikie // This file is distributed under the University of Illinois Open Source
685f80d71SDavid Blaikie // License. See LICENSE.TXT for details.
785f80d71SDavid Blaikie //
885f80d71SDavid Blaikie //===----------------------------------------------------------------------===//
985f80d71SDavid Blaikie 
1085f80d71SDavid Blaikie #include "DwarfFile.h"
117c384cceSPeter Collingbourne #include "DwarfCompileUnit.h"
1285f80d71SDavid Blaikie #include "DwarfDebug.h"
1385f80d71SDavid Blaikie #include "DwarfUnit.h"
146e07bfd0SEugene Zelenko #include "llvm/ADT/SmallVector.h"
156e07bfd0SEugene Zelenko #include "llvm/CodeGen/AsmPrinter.h"
166e07bfd0SEugene Zelenko #include "llvm/CodeGen/DIE.h"
176e07bfd0SEugene Zelenko #include "llvm/IR/DebugInfoMetadata.h"
1885f80d71SDavid Blaikie #include "llvm/MC/MCStreamer.h"
196e07bfd0SEugene Zelenko #include <algorithm>
206e07bfd0SEugene Zelenko #include <cstdint>
2185f80d71SDavid Blaikie 
226e07bfd0SEugene Zelenko using namespace llvm;
236e07bfd0SEugene Zelenko 
249412d63fSFrederic Riss DwarfFile::DwarfFile(AsmPrinter *AP, StringRef Pref, BumpPtrAllocator &DA)
253462a420SGreg Clayton     : Asm(AP), Abbrevs(AbbrevAllocator), StrPool(DA, *Asm, Pref) {}
2685f80d71SDavid Blaikie 
277c384cceSPeter Collingbourne void DwarfFile::addUnit(std::unique_ptr<DwarfCompileUnit> U) {
2885f80d71SDavid Blaikie   CUs.push_back(std::move(U));
2985f80d71SDavid Blaikie }
3085f80d71SDavid Blaikie 
3185f80d71SDavid Blaikie // Emit the various dwarf units to the unit section USection with
3285f80d71SDavid Blaikie // the abbreviations going into ASection.
33063d725fSRafael Espindola void DwarfFile::emitUnits(bool UseOffsets) {
347c384cceSPeter Collingbourne   for (const auto &TheU : CUs)
357c384cceSPeter Collingbourne     emitUnit(TheU.get(), UseOffsets);
367c384cceSPeter Collingbourne }
377c384cceSPeter Collingbourne 
387c384cceSPeter Collingbourne void DwarfFile::emitUnit(DwarfUnit *TheU, bool UseOffsets) {
39d4dd7215SAlexey Bataev   if (TheU->getCUNode()->isDebugDirectivesOnly())
40d4dd7215SAlexey Bataev     return;
41d4dd7215SAlexey Bataev 
42*560ff355SDavid Blaikie   MCSection *S = TheU->getSection();
4385f80d71SDavid Blaikie 
44*560ff355SDavid Blaikie   if (!S)
45*560ff355SDavid Blaikie     return;
46*560ff355SDavid Blaikie 
47*560ff355SDavid Blaikie   Asm->OutStreamer->SwitchSection(S);
48063d725fSRafael Espindola   TheU->emitHeader(UseOffsets);
49*560ff355SDavid Blaikie   Asm->emitDwarfDIE(TheU->getUnitDie());
5085f80d71SDavid Blaikie }
51f299947bSDavid Blaikie 
5285f80d71SDavid Blaikie // Compute the size and offset for each DIE.
5385f80d71SDavid Blaikie void DwarfFile::computeSizeAndOffsets() {
5485f80d71SDavid Blaikie   // Offset from the first CU in the debug info section is 0 initially.
5585f80d71SDavid Blaikie   unsigned SecOffset = 0;
5685f80d71SDavid Blaikie 
5785f80d71SDavid Blaikie   // Iterate over each compile unit and set the size and offsets for each
5885f80d71SDavid Blaikie   // DIE within each compile unit. All offsets are CU relative.
5985f80d71SDavid Blaikie   for (const auto &TheU : CUs) {
60d4dd7215SAlexey Bataev     if (TheU->getCUNode()->isDebugDirectivesOnly())
61d4dd7215SAlexey Bataev       continue;
62d4dd7215SAlexey Bataev 
6335630c33SGreg Clayton     TheU->setDebugSectionOffset(SecOffset);
647c384cceSPeter Collingbourne     SecOffset += computeSizeAndOffsetsForUnit(TheU.get());
657c384cceSPeter Collingbourne   }
667c384cceSPeter Collingbourne }
6785f80d71SDavid Blaikie 
687c384cceSPeter Collingbourne unsigned DwarfFile::computeSizeAndOffsetsForUnit(DwarfUnit *TheU) {
6985f80d71SDavid Blaikie   // CU-relative offset is reset to 0 here.
7085f80d71SDavid Blaikie   unsigned Offset = sizeof(int32_t) +      // Length of Unit Info
7185f80d71SDavid Blaikie                     TheU->getHeaderSize(); // Unit-specific headers
7285f80d71SDavid Blaikie 
737c384cceSPeter Collingbourne   // The return value here is CU-relative, after laying out
7485f80d71SDavid Blaikie   // all of the CU DIE.
757c384cceSPeter Collingbourne   return computeSizeAndOffset(TheU->getUnitDie(), Offset);
7685f80d71SDavid Blaikie }
777c384cceSPeter Collingbourne 
7885f80d71SDavid Blaikie // Compute the size and offset of a DIE. The offset is relative to start of the
7985f80d71SDavid Blaikie // CU. It returns the offset after laying out the DIE.
8085f80d71SDavid Blaikie unsigned DwarfFile::computeSizeAndOffset(DIE &Die, unsigned Offset) {
813462a420SGreg Clayton   return Die.computeOffsetsAndAbbrevs(Asm, Abbrevs, Offset);
8285f80d71SDavid Blaikie }
8385f80d71SDavid Blaikie 
843462a420SGreg Clayton void DwarfFile::emitAbbrevs(MCSection *Section) { Abbrevs.Emit(Asm, Section); }
8585f80d71SDavid Blaikie 
8685f80d71SDavid Blaikie // Emit strings into a string section.
87456b555fSWolfgang Pieb void DwarfFile::emitStrings(MCSection *StrSection, MCSection *OffsetSection,
88456b555fSWolfgang Pieb                             bool UseRelativeOffsets) {
89456b555fSWolfgang Pieb   StrPool.emit(*Asm, StrSection, OffsetSection, UseRelativeOffsets);
9085f80d71SDavid Blaikie }
91f299947bSDavid Blaikie 
92ca7e4702SAdrian Prantl bool DwarfFile::addScopeVariable(LexicalScope *LS, DbgVariable *Var) {
93c929f7adSAdrian Prantl   auto &ScopeVars = ScopeVariables[LS];
94a9308c49SDuncan P. N. Exon Smith   const DILocalVariable *DV = Var->getVariable();
957348ddaaSDuncan P. N. Exon Smith   if (unsigned ArgNum = DV->getArg()) {
96c929f7adSAdrian Prantl     auto Cached = ScopeVars.Args.find(ArgNum);
97c929f7adSAdrian Prantl     if (Cached == ScopeVars.Args.end())
98c929f7adSAdrian Prantl       ScopeVars.Args[ArgNum] = Var;
99c929f7adSAdrian Prantl     else {
100c929f7adSAdrian Prantl       Cached->second->addMMIEntry(*Var);
101ca7e4702SAdrian Prantl       return false;
102ca7e4702SAdrian Prantl     }
103c929f7adSAdrian Prantl   } else {
104c929f7adSAdrian Prantl     ScopeVars.Locals.push_back(Var);
1053b5c8400SDavid Blaikie   }
106ca7e4702SAdrian Prantl   return true;
1073b5c8400SDavid Blaikie }
1082532ac88SHsiangkai Wang 
1092532ac88SHsiangkai Wang void DwarfFile::addScopeLabel(LexicalScope *LS, DbgLabel *Label) {
1102532ac88SHsiangkai Wang   SmallVectorImpl<DbgLabel *> &Labels = ScopeLabels[LS];
1112532ac88SHsiangkai Wang   Labels.push_back(Label);
1122532ac88SHsiangkai Wang }
113c4af8bf2SDavid Blaikie 
114c4af8bf2SDavid Blaikie std::pair<uint32_t, RangeSpanList *>
115c8f7e6c1SDavid Blaikie DwarfFile::addRange(const DwarfCompileUnit &CU, SmallVector<RangeSpan, 2> R) {
116c8f7e6c1SDavid Blaikie   CURangeLists.push_back(
117c8f7e6c1SDavid Blaikie       RangeSpanList(Asm->createTempSymbol("debug_ranges"), CU, std::move(R)));
118c4af8bf2SDavid Blaikie   return std::make_pair(CURangeLists.size() - 1, &CURangeLists.back());
119c4af8bf2SDavid Blaikie }
120