12cab237bSDimitry Andric //===- llvm/CodeGen/DwarfFile.cpp - Dwarf Debug Framework -----------------===//
291bc56edSDimitry Andric //
391bc56edSDimitry Andric //                     The LLVM Compiler Infrastructure
491bc56edSDimitry Andric //
591bc56edSDimitry Andric // This file is distributed under the University of Illinois Open Source
691bc56edSDimitry Andric // License. See LICENSE.TXT for details.
791bc56edSDimitry Andric //
891bc56edSDimitry Andric //===----------------------------------------------------------------------===//
991bc56edSDimitry Andric 
1091bc56edSDimitry Andric #include "DwarfFile.h"
113ca95b02SDimitry Andric #include "DwarfCompileUnit.h"
1291bc56edSDimitry Andric #include "DwarfDebug.h"
1391bc56edSDimitry Andric #include "DwarfUnit.h"
142cab237bSDimitry Andric #include "llvm/ADT/SmallVector.h"
152cab237bSDimitry Andric #include "llvm/CodeGen/AsmPrinter.h"
162cab237bSDimitry Andric #include "llvm/CodeGen/DIE.h"
172cab237bSDimitry Andric #include "llvm/IR/DebugInfoMetadata.h"
1891bc56edSDimitry Andric #include "llvm/MC/MCStreamer.h"
192cab237bSDimitry Andric #include <algorithm>
202cab237bSDimitry Andric #include <cstdint>
2191bc56edSDimitry Andric 
222cab237bSDimitry Andric using namespace llvm;
232cab237bSDimitry Andric 
DwarfFile(AsmPrinter * AP,StringRef Pref,BumpPtrAllocator & DA)24ff0cc061SDimitry Andric DwarfFile::DwarfFile(AsmPrinter *AP, StringRef Pref, BumpPtrAllocator &DA)
25d88c1a5aSDimitry Andric     : Asm(AP), Abbrevs(AbbrevAllocator), StrPool(DA, *Asm, Pref) {}
2691bc56edSDimitry Andric 
addUnit(std::unique_ptr<DwarfCompileUnit> U)273ca95b02SDimitry Andric void DwarfFile::addUnit(std::unique_ptr<DwarfCompileUnit> U) {
2891bc56edSDimitry Andric   CUs.push_back(std::move(U));
2991bc56edSDimitry Andric }
3091bc56edSDimitry Andric 
3191bc56edSDimitry Andric // Emit the various dwarf units to the unit section USection with
3291bc56edSDimitry Andric // the abbreviations going into ASection.
emitUnits(bool UseOffsets)33ff0cc061SDimitry Andric void DwarfFile::emitUnits(bool UseOffsets) {
343ca95b02SDimitry Andric   for (const auto &TheU : CUs)
353ca95b02SDimitry Andric     emitUnit(TheU.get(), UseOffsets);
363ca95b02SDimitry Andric }
373ca95b02SDimitry Andric 
emitUnit(DwarfUnit * TheU,bool UseOffsets)383ca95b02SDimitry Andric void DwarfFile::emitUnit(DwarfUnit *TheU, bool UseOffsets) {
39*b5893f02SDimitry Andric   if (TheU->getCUNode()->isDebugDirectivesOnly())
40*b5893f02SDimitry Andric     return;
4191bc56edSDimitry Andric 
42*b5893f02SDimitry Andric   MCSection *S = TheU->getSection();
43*b5893f02SDimitry Andric 
44*b5893f02SDimitry Andric   if (!S)
45*b5893f02SDimitry Andric     return;
46*b5893f02SDimitry Andric 
47*b5893f02SDimitry Andric   Asm->OutStreamer->SwitchSection(S);
48ff0cc061SDimitry Andric   TheU->emitHeader(UseOffsets);
49*b5893f02SDimitry Andric   Asm->emitDwarfDIE(TheU->getUnitDie());
5091bc56edSDimitry Andric 
51*b5893f02SDimitry Andric   if (MCSymbol *EndLabel = TheU->getEndLabel())
52*b5893f02SDimitry Andric     Asm->OutStreamer->EmitLabel(EndLabel);
5391bc56edSDimitry Andric }
5439d628a0SDimitry Andric 
5591bc56edSDimitry Andric // Compute the size and offset for each DIE.
computeSizeAndOffsets()5691bc56edSDimitry Andric void DwarfFile::computeSizeAndOffsets() {
5791bc56edSDimitry Andric   // Offset from the first CU in the debug info section is 0 initially.
5891bc56edSDimitry Andric   unsigned SecOffset = 0;
5991bc56edSDimitry Andric 
6091bc56edSDimitry Andric   // Iterate over each compile unit and set the size and offsets for each
6191bc56edSDimitry Andric   // DIE within each compile unit. All offsets are CU relative.
6291bc56edSDimitry Andric   for (const auto &TheU : CUs) {
63*b5893f02SDimitry Andric     if (TheU->getCUNode()->isDebugDirectivesOnly())
64*b5893f02SDimitry Andric       continue;
65*b5893f02SDimitry Andric 
66d88c1a5aSDimitry Andric     TheU->setDebugSectionOffset(SecOffset);
673ca95b02SDimitry Andric     SecOffset += computeSizeAndOffsetsForUnit(TheU.get());
683ca95b02SDimitry Andric   }
693ca95b02SDimitry Andric }
7091bc56edSDimitry Andric 
computeSizeAndOffsetsForUnit(DwarfUnit * TheU)713ca95b02SDimitry Andric unsigned DwarfFile::computeSizeAndOffsetsForUnit(DwarfUnit *TheU) {
7291bc56edSDimitry Andric   // CU-relative offset is reset to 0 here.
7391bc56edSDimitry Andric   unsigned Offset = sizeof(int32_t) +      // Length of Unit Info
7491bc56edSDimitry Andric                     TheU->getHeaderSize(); // Unit-specific headers
7591bc56edSDimitry Andric 
763ca95b02SDimitry Andric   // The return value here is CU-relative, after laying out
7791bc56edSDimitry Andric   // all of the CU DIE.
783ca95b02SDimitry Andric   return computeSizeAndOffset(TheU->getUnitDie(), Offset);
7991bc56edSDimitry Andric }
803ca95b02SDimitry Andric 
8191bc56edSDimitry Andric // Compute the size and offset of a DIE. The offset is relative to start of the
8291bc56edSDimitry Andric // CU. It returns the offset after laying out the DIE.
computeSizeAndOffset(DIE & Die,unsigned Offset)8391bc56edSDimitry Andric unsigned DwarfFile::computeSizeAndOffset(DIE &Die, unsigned Offset) {
84d88c1a5aSDimitry Andric   return Die.computeOffsetsAndAbbrevs(Asm, Abbrevs, Offset);
8591bc56edSDimitry Andric }
8691bc56edSDimitry Andric 
emitAbbrevs(MCSection * Section)87d88c1a5aSDimitry Andric void DwarfFile::emitAbbrevs(MCSection *Section) { Abbrevs.Emit(Asm, Section); }
8891bc56edSDimitry Andric 
8991bc56edSDimitry Andric // Emit strings into a string section.
emitStrings(MCSection * StrSection,MCSection * OffsetSection,bool UseRelativeOffsets)904ba319b5SDimitry Andric void DwarfFile::emitStrings(MCSection *StrSection, MCSection *OffsetSection,
914ba319b5SDimitry Andric                             bool UseRelativeOffsets) {
924ba319b5SDimitry Andric   StrPool.emit(*Asm, StrSection, OffsetSection, UseRelativeOffsets);
9339d628a0SDimitry Andric }
9439d628a0SDimitry Andric 
addScopeVariable(LexicalScope * LS,DbgVariable * Var)95ff0cc061SDimitry Andric bool DwarfFile::addScopeVariable(LexicalScope *LS, DbgVariable *Var) {
964ba319b5SDimitry Andric   auto &ScopeVars = ScopeVariables[LS];
97ff0cc061SDimitry Andric   const DILocalVariable *DV = Var->getVariable();
98ff0cc061SDimitry Andric   if (unsigned ArgNum = DV->getArg()) {
994ba319b5SDimitry Andric     auto Cached = ScopeVars.Args.find(ArgNum);
1004ba319b5SDimitry Andric     if (Cached == ScopeVars.Args.end())
1014ba319b5SDimitry Andric       ScopeVars.Args[ArgNum] = Var;
1024ba319b5SDimitry Andric     else {
1034ba319b5SDimitry Andric       Cached->second->addMMIEntry(*Var);
104ff0cc061SDimitry Andric       return false;
105ff0cc061SDimitry Andric     }
1064ba319b5SDimitry Andric   } else {
1074ba319b5SDimitry Andric     ScopeVars.Locals.push_back(Var);
10839d628a0SDimitry Andric   }
109ff0cc061SDimitry Andric   return true;
11091bc56edSDimitry Andric }
111*b5893f02SDimitry Andric 
addScopeLabel(LexicalScope * LS,DbgLabel * Label)112*b5893f02SDimitry Andric void DwarfFile::addScopeLabel(LexicalScope *LS, DbgLabel *Label) {
113*b5893f02SDimitry Andric   SmallVectorImpl<DbgLabel *> &Labels = ScopeLabels[LS];
114*b5893f02SDimitry Andric   Labels.push_back(Label);
115*b5893f02SDimitry Andric }
116*b5893f02SDimitry Andric 
117*b5893f02SDimitry Andric std::pair<uint32_t, RangeSpanList *>
addRange(const DwarfCompileUnit & CU,SmallVector<RangeSpan,2> R)118*b5893f02SDimitry Andric DwarfFile::addRange(const DwarfCompileUnit &CU, SmallVector<RangeSpan, 2> R) {
119*b5893f02SDimitry Andric   CURangeLists.push_back(
120*b5893f02SDimitry Andric       RangeSpanList(Asm->createTempSymbol("debug_ranges"), CU, std::move(R)));
121*b5893f02SDimitry Andric   return std::make_pair(CURangeLists.size() - 1, &CURangeLists.back());
122*b5893f02SDimitry Andric }
123