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 
42560ff355SDavid Blaikie   MCSection *S = TheU->getSection();
4385f80d71SDavid Blaikie 
44560ff355SDavid Blaikie   if (!S)
45560ff355SDavid Blaikie     return;
46560ff355SDavid Blaikie 
47560ff355SDavid Blaikie   Asm->OutStreamer->SwitchSection(S);
48063d725fSRafael Espindola   TheU->emitHeader(UseOffsets);
49560ff355SDavid Blaikie   Asm->emitDwarfDIE(TheU->getUnitDie());
50*c4e08febSDavid Blaikie 
51*c4e08febSDavid Blaikie   if (MCSymbol *EndLabel = TheU->getEndLabel())
52*c4e08febSDavid Blaikie     Asm->OutStreamer->EmitLabel(EndLabel);
5385f80d71SDavid Blaikie }
54f299947bSDavid Blaikie 
5585f80d71SDavid Blaikie // Compute the size and offset for each DIE.
5685f80d71SDavid Blaikie void DwarfFile::computeSizeAndOffsets() {
5785f80d71SDavid Blaikie   // Offset from the first CU in the debug info section is 0 initially.
5885f80d71SDavid Blaikie   unsigned SecOffset = 0;
5985f80d71SDavid Blaikie 
6085f80d71SDavid Blaikie   // Iterate over each compile unit and set the size and offsets for each
6185f80d71SDavid Blaikie   // DIE within each compile unit. All offsets are CU relative.
6285f80d71SDavid Blaikie   for (const auto &TheU : CUs) {
63d4dd7215SAlexey Bataev     if (TheU->getCUNode()->isDebugDirectivesOnly())
64d4dd7215SAlexey Bataev       continue;
65d4dd7215SAlexey Bataev 
6635630c33SGreg Clayton     TheU->setDebugSectionOffset(SecOffset);
677c384cceSPeter Collingbourne     SecOffset += computeSizeAndOffsetsForUnit(TheU.get());
687c384cceSPeter Collingbourne   }
697c384cceSPeter Collingbourne }
7085f80d71SDavid Blaikie 
717c384cceSPeter Collingbourne unsigned DwarfFile::computeSizeAndOffsetsForUnit(DwarfUnit *TheU) {
7285f80d71SDavid Blaikie   // CU-relative offset is reset to 0 here.
7385f80d71SDavid Blaikie   unsigned Offset = sizeof(int32_t) +      // Length of Unit Info
7485f80d71SDavid Blaikie                     TheU->getHeaderSize(); // Unit-specific headers
7585f80d71SDavid Blaikie 
767c384cceSPeter Collingbourne   // The return value here is CU-relative, after laying out
7785f80d71SDavid Blaikie   // all of the CU DIE.
787c384cceSPeter Collingbourne   return computeSizeAndOffset(TheU->getUnitDie(), Offset);
7985f80d71SDavid Blaikie }
807c384cceSPeter Collingbourne 
8185f80d71SDavid Blaikie // Compute the size and offset of a DIE. The offset is relative to start of the
8285f80d71SDavid Blaikie // CU. It returns the offset after laying out the DIE.
8385f80d71SDavid Blaikie unsigned DwarfFile::computeSizeAndOffset(DIE &Die, unsigned Offset) {
843462a420SGreg Clayton   return Die.computeOffsetsAndAbbrevs(Asm, Abbrevs, Offset);
8585f80d71SDavid Blaikie }
8685f80d71SDavid Blaikie 
873462a420SGreg Clayton void DwarfFile::emitAbbrevs(MCSection *Section) { Abbrevs.Emit(Asm, Section); }
8885f80d71SDavid Blaikie 
8985f80d71SDavid Blaikie // Emit strings into a string section.
90456b555fSWolfgang Pieb void DwarfFile::emitStrings(MCSection *StrSection, MCSection *OffsetSection,
91456b555fSWolfgang Pieb                             bool UseRelativeOffsets) {
92456b555fSWolfgang Pieb   StrPool.emit(*Asm, StrSection, OffsetSection, UseRelativeOffsets);
9385f80d71SDavid Blaikie }
94f299947bSDavid Blaikie 
95ca7e4702SAdrian Prantl bool DwarfFile::addScopeVariable(LexicalScope *LS, DbgVariable *Var) {
96c929f7adSAdrian Prantl   auto &ScopeVars = ScopeVariables[LS];
97a9308c49SDuncan P. N. Exon Smith   const DILocalVariable *DV = Var->getVariable();
987348ddaaSDuncan P. N. Exon Smith   if (unsigned ArgNum = DV->getArg()) {
99c929f7adSAdrian Prantl     auto Cached = ScopeVars.Args.find(ArgNum);
100c929f7adSAdrian Prantl     if (Cached == ScopeVars.Args.end())
101c929f7adSAdrian Prantl       ScopeVars.Args[ArgNum] = Var;
102c929f7adSAdrian Prantl     else {
103c929f7adSAdrian Prantl       Cached->second->addMMIEntry(*Var);
104ca7e4702SAdrian Prantl       return false;
105ca7e4702SAdrian Prantl     }
106c929f7adSAdrian Prantl   } else {
107c929f7adSAdrian Prantl     ScopeVars.Locals.push_back(Var);
1083b5c8400SDavid Blaikie   }
109ca7e4702SAdrian Prantl   return true;
1103b5c8400SDavid Blaikie }
1112532ac88SHsiangkai Wang 
1122532ac88SHsiangkai Wang void DwarfFile::addScopeLabel(LexicalScope *LS, DbgLabel *Label) {
1132532ac88SHsiangkai Wang   SmallVectorImpl<DbgLabel *> &Labels = ScopeLabels[LS];
1142532ac88SHsiangkai Wang   Labels.push_back(Label);
1152532ac88SHsiangkai Wang }
116c4af8bf2SDavid Blaikie 
117c4af8bf2SDavid Blaikie std::pair<uint32_t, RangeSpanList *>
118c8f7e6c1SDavid Blaikie DwarfFile::addRange(const DwarfCompileUnit &CU, SmallVector<RangeSpan, 2> R) {
119c8f7e6c1SDavid Blaikie   CURangeLists.push_back(
120c8f7e6c1SDavid Blaikie       RangeSpanList(Asm->createTempSymbol("debug_ranges"), CU, std::move(R)));
121c4af8bf2SDavid Blaikie   return std::make_pair(CURangeLists.size() - 1, &CURangeLists.back());
122c4af8bf2SDavid Blaikie }
123