185f80d71SDavid Blaikie //===-- 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"
1185f80d71SDavid Blaikie #include "DwarfDebug.h"
1285f80d71SDavid Blaikie #include "DwarfUnit.h"
13d9903888SChandler Carruth #include "llvm/ADT/STLExtras.h"
14d9903888SChandler Carruth #include "llvm/IR/DataLayout.h"
1585f80d71SDavid Blaikie #include "llvm/MC/MCStreamer.h"
1685f80d71SDavid Blaikie #include "llvm/Support/LEB128.h"
1785f80d71SDavid Blaikie #include "llvm/Target/TargetLoweringObjectFile.h"
1885f80d71SDavid Blaikie 
1985f80d71SDavid Blaikie namespace llvm {
202b22b1e9SDavid Blaikie DwarfFile::DwarfFile(AsmPrinter *AP, DwarfDebug &DD, StringRef Pref,
212b22b1e9SDavid Blaikie                      BumpPtrAllocator &DA)
22bcfa8a56SDavid Blaikie     : Asm(AP), DD(DD), StrPool(DA, *Asm, Pref) {}
2385f80d71SDavid Blaikie 
2405e736fbSDavid Blaikie DwarfFile::~DwarfFile() {}
2585f80d71SDavid Blaikie 
2685f80d71SDavid Blaikie // Define a unique number for the abbreviation.
2785f80d71SDavid Blaikie //
2885f80d71SDavid Blaikie void DwarfFile::assignAbbrevNumber(DIEAbbrev &Abbrev) {
2985f80d71SDavid Blaikie   // Check the set for priors.
3085f80d71SDavid Blaikie   DIEAbbrev *InSet = AbbreviationsSet.GetOrInsertNode(&Abbrev);
3185f80d71SDavid Blaikie 
3285f80d71SDavid Blaikie   // If it's newly added.
3385f80d71SDavid Blaikie   if (InSet == &Abbrev) {
3485f80d71SDavid Blaikie     // Add to abbreviation list.
3585f80d71SDavid Blaikie     Abbreviations.push_back(&Abbrev);
3685f80d71SDavid Blaikie 
3785f80d71SDavid Blaikie     // Assign the vector position + 1 as its number.
3885f80d71SDavid Blaikie     Abbrev.setNumber(Abbreviations.size());
3985f80d71SDavid Blaikie   } else {
4085f80d71SDavid Blaikie     // Assign existing abbreviation number.
4185f80d71SDavid Blaikie     Abbrev.setNumber(InSet->getNumber());
4285f80d71SDavid Blaikie   }
4385f80d71SDavid Blaikie }
4485f80d71SDavid Blaikie 
4585f80d71SDavid Blaikie void DwarfFile::addUnit(std::unique_ptr<DwarfUnit> U) {
4685f80d71SDavid Blaikie   CUs.push_back(std::move(U));
4785f80d71SDavid Blaikie }
4885f80d71SDavid Blaikie 
4985f80d71SDavid Blaikie // Emit the various dwarf units to the unit section USection with
5085f80d71SDavid Blaikie // the abbreviations going into ASection.
512b22b1e9SDavid Blaikie void DwarfFile::emitUnits(const MCSymbol *ASectionSym) {
5285f80d71SDavid Blaikie   for (const auto &TheU : CUs) {
53adcde36cSDavid Blaikie     DIE &Die = TheU->getUnitDie();
5485f80d71SDavid Blaikie     const MCSection *USection = TheU->getSection();
5585f80d71SDavid Blaikie     Asm->OutStreamer.SwitchSection(USection);
5685f80d71SDavid Blaikie 
5785f80d71SDavid Blaikie     TheU->emitHeader(ASectionSym);
5885f80d71SDavid Blaikie 
592b22b1e9SDavid Blaikie     DD.emitDIE(Die);
6085f80d71SDavid Blaikie   }
6185f80d71SDavid Blaikie }
62f299947bSDavid Blaikie 
6385f80d71SDavid Blaikie // Compute the size and offset for each DIE.
6485f80d71SDavid Blaikie void DwarfFile::computeSizeAndOffsets() {
6585f80d71SDavid Blaikie   // Offset from the first CU in the debug info section is 0 initially.
6685f80d71SDavid Blaikie   unsigned SecOffset = 0;
6785f80d71SDavid Blaikie 
6885f80d71SDavid Blaikie   // Iterate over each compile unit and set the size and offsets for each
6985f80d71SDavid Blaikie   // DIE within each compile unit. All offsets are CU relative.
7085f80d71SDavid Blaikie   for (const auto &TheU : CUs) {
7185f80d71SDavid Blaikie     TheU->setDebugInfoOffset(SecOffset);
7285f80d71SDavid Blaikie 
7385f80d71SDavid Blaikie     // CU-relative offset is reset to 0 here.
7485f80d71SDavid Blaikie     unsigned Offset = sizeof(int32_t) +      // Length of Unit Info
7585f80d71SDavid Blaikie                       TheU->getHeaderSize(); // Unit-specific headers
7685f80d71SDavid Blaikie 
7785f80d71SDavid Blaikie     // EndOffset here is CU-relative, after laying out
7885f80d71SDavid Blaikie     // all of the CU DIE.
79adcde36cSDavid Blaikie     unsigned EndOffset = computeSizeAndOffset(TheU->getUnitDie(), Offset);
8085f80d71SDavid Blaikie     SecOffset += EndOffset;
8185f80d71SDavid Blaikie   }
8285f80d71SDavid Blaikie }
8385f80d71SDavid Blaikie // Compute the size and offset of a DIE. The offset is relative to start of the
8485f80d71SDavid Blaikie // CU. It returns the offset after laying out the DIE.
8585f80d71SDavid Blaikie unsigned DwarfFile::computeSizeAndOffset(DIE &Die, unsigned Offset) {
8685f80d71SDavid Blaikie   // Record the abbreviation.
8785f80d71SDavid Blaikie   assignAbbrevNumber(Die.getAbbrev());
8885f80d71SDavid Blaikie 
8985f80d71SDavid Blaikie   // Get the abbreviation for this DIE.
9085f80d71SDavid Blaikie   const DIEAbbrev &Abbrev = Die.getAbbrev();
9185f80d71SDavid Blaikie 
9285f80d71SDavid Blaikie   // Set DIE offset
9385f80d71SDavid Blaikie   Die.setOffset(Offset);
9485f80d71SDavid Blaikie 
9585f80d71SDavid Blaikie   // Start the size with the size of abbreviation code.
9685f80d71SDavid Blaikie   Offset += getULEB128Size(Die.getAbbrevNumber());
9785f80d71SDavid Blaikie 
9885f80d71SDavid Blaikie   const SmallVectorImpl<DIEValue *> &Values = Die.getValues();
9985f80d71SDavid Blaikie   const SmallVectorImpl<DIEAbbrevData> &AbbrevData = Abbrev.getData();
10085f80d71SDavid Blaikie 
10185f80d71SDavid Blaikie   // Size the DIE attribute values.
10285f80d71SDavid Blaikie   for (unsigned i = 0, N = Values.size(); i < N; ++i)
10385f80d71SDavid Blaikie     // Size attribute value.
10485f80d71SDavid Blaikie     Offset += Values[i]->SizeOf(Asm, AbbrevData[i].getForm());
10585f80d71SDavid Blaikie 
10685f80d71SDavid Blaikie   // Get the children.
10785f80d71SDavid Blaikie   const auto &Children = Die.getChildren();
10885f80d71SDavid Blaikie 
10985f80d71SDavid Blaikie   // Size the DIE children if any.
11085f80d71SDavid Blaikie   if (!Children.empty()) {
11185f80d71SDavid Blaikie     assert(Abbrev.hasChildren() && "Children flag not set");
11285f80d71SDavid Blaikie 
11385f80d71SDavid Blaikie     for (auto &Child : Children)
11485f80d71SDavid Blaikie       Offset = computeSizeAndOffset(*Child, Offset);
11585f80d71SDavid Blaikie 
11685f80d71SDavid Blaikie     // End of children marker.
11785f80d71SDavid Blaikie     Offset += sizeof(int8_t);
11885f80d71SDavid Blaikie   }
11985f80d71SDavid Blaikie 
12085f80d71SDavid Blaikie   Die.setSize(Offset - Die.getOffset());
12185f80d71SDavid Blaikie   return Offset;
12285f80d71SDavid Blaikie }
12385f80d71SDavid Blaikie void DwarfFile::emitAbbrevs(const MCSection *Section) {
12485f80d71SDavid Blaikie   // Check to see if it is worth the effort.
12585f80d71SDavid Blaikie   if (!Abbreviations.empty()) {
12685f80d71SDavid Blaikie     // Start the debug abbrev section.
12785f80d71SDavid Blaikie     Asm->OutStreamer.SwitchSection(Section);
12885f80d71SDavid Blaikie 
12985f80d71SDavid Blaikie     // For each abbrevation.
13085f80d71SDavid Blaikie     for (const DIEAbbrev *Abbrev : Abbreviations) {
13185f80d71SDavid Blaikie       // Emit the abbrevations code (base 1 index.)
13285f80d71SDavid Blaikie       Asm->EmitULEB128(Abbrev->getNumber(), "Abbreviation Code");
13385f80d71SDavid Blaikie 
13485f80d71SDavid Blaikie       // Emit the abbreviations data.
13585f80d71SDavid Blaikie       Abbrev->Emit(Asm);
13685f80d71SDavid Blaikie     }
13785f80d71SDavid Blaikie 
13885f80d71SDavid Blaikie     // Mark end of abbreviations.
13985f80d71SDavid Blaikie     Asm->EmitULEB128(0, "EOM(3)");
14085f80d71SDavid Blaikie   }
14185f80d71SDavid Blaikie }
14285f80d71SDavid Blaikie 
14385f80d71SDavid Blaikie // Emit strings into a string section.
14485f80d71SDavid Blaikie void DwarfFile::emitStrings(const MCSection *StrSection,
1456741bb09SDavid Blaikie                             const MCSection *OffsetSection) {
1466741bb09SDavid Blaikie   StrPool.emit(*Asm, StrSection, OffsetSection);
14785f80d71SDavid Blaikie }
148f299947bSDavid Blaikie 
149*ca7e4702SAdrian Prantl bool DwarfFile::addScopeVariable(LexicalScope *LS, DbgVariable *Var) {
15080e5b1ebSDavid Blaikie   SmallVectorImpl<DbgVariable *> &Vars = ScopeVariables[LS];
1513b5c8400SDavid Blaikie   DIVariable DV = Var->getVariable();
1523b5c8400SDavid Blaikie   // Variables with positive arg numbers are parameters.
1533b5c8400SDavid Blaikie   if (unsigned ArgNum = DV.getArgNumber()) {
1543b5c8400SDavid Blaikie     // Keep all parameters in order at the start of the variable list to ensure
1553b5c8400SDavid Blaikie     // function types are correct (no out-of-order parameters)
1563b5c8400SDavid Blaikie     //
1573b5c8400SDavid Blaikie     // This could be improved by only doing it for optimized builds (unoptimized
1583b5c8400SDavid Blaikie     // builds have the right order to begin with), searching from the back (this
1593b5c8400SDavid Blaikie     // would catch the unoptimized case quickly), or doing a binary search
1603b5c8400SDavid Blaikie     // rather than linear search.
1613b5c8400SDavid Blaikie     auto I = Vars.begin();
1623b5c8400SDavid Blaikie     while (I != Vars.end()) {
1633b5c8400SDavid Blaikie       unsigned CurNum = (*I)->getVariable().getArgNumber();
1643b5c8400SDavid Blaikie       // A local (non-parameter) variable has been found, insert immediately
1653b5c8400SDavid Blaikie       // before it.
1663b5c8400SDavid Blaikie       if (CurNum == 0)
1673b5c8400SDavid Blaikie         break;
1683b5c8400SDavid Blaikie       // A later indexed parameter has been found, insert immediately before it.
1693b5c8400SDavid Blaikie       if (CurNum > ArgNum)
1703b5c8400SDavid Blaikie         break;
171*ca7e4702SAdrian Prantl       if (CurNum == ArgNum) {
172*ca7e4702SAdrian Prantl         (*I)->addMMIEntry(*Var);
173*ca7e4702SAdrian Prantl         return false;
174*ca7e4702SAdrian Prantl       }
1753b5c8400SDavid Blaikie       ++I;
1763b5c8400SDavid Blaikie     }
1773b5c8400SDavid Blaikie     Vars.insert(I, Var);
178*ca7e4702SAdrian Prantl     return true;
1793b5c8400SDavid Blaikie   }
1803b5c8400SDavid Blaikie 
1813b5c8400SDavid Blaikie   Vars.push_back(Var);
182*ca7e4702SAdrian Prantl   return true;
1833b5c8400SDavid Blaikie }
18485f80d71SDavid Blaikie }
185