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 
1285f80d71SDavid Blaikie #include "DwarfDebug.h"
1385f80d71SDavid Blaikie #include "DwarfUnit.h"
1485f80d71SDavid Blaikie #include "llvm/MC/MCStreamer.h"
1585f80d71SDavid Blaikie #include "llvm/Support/LEB128.h"
1685f80d71SDavid Blaikie #include "llvm/IR/DataLayout.h"
1785f80d71SDavid Blaikie #include "llvm/ADT/STLExtras.h"
1885f80d71SDavid Blaikie #include "llvm/Target/TargetLoweringObjectFile.h"
1985f80d71SDavid Blaikie 
2085f80d71SDavid Blaikie namespace llvm {
212b22b1e9SDavid Blaikie DwarfFile::DwarfFile(AsmPrinter *AP, DwarfDebug &DD, StringRef Pref,
222b22b1e9SDavid Blaikie                      BumpPtrAllocator &DA)
23*bcfa8a56SDavid Blaikie     : Asm(AP), DD(DD), StrPool(DA, *Asm, Pref) {}
2485f80d71SDavid Blaikie 
2505e736fbSDavid Blaikie DwarfFile::~DwarfFile() {}
2685f80d71SDavid Blaikie 
2785f80d71SDavid Blaikie // Define a unique number for the abbreviation.
2885f80d71SDavid Blaikie //
2985f80d71SDavid Blaikie void DwarfFile::assignAbbrevNumber(DIEAbbrev &Abbrev) {
3085f80d71SDavid Blaikie   // Check the set for priors.
3185f80d71SDavid Blaikie   DIEAbbrev *InSet = AbbreviationsSet.GetOrInsertNode(&Abbrev);
3285f80d71SDavid Blaikie 
3385f80d71SDavid Blaikie   // If it's newly added.
3485f80d71SDavid Blaikie   if (InSet == &Abbrev) {
3585f80d71SDavid Blaikie     // Add to abbreviation list.
3685f80d71SDavid Blaikie     Abbreviations.push_back(&Abbrev);
3785f80d71SDavid Blaikie 
3885f80d71SDavid Blaikie     // Assign the vector position + 1 as its number.
3985f80d71SDavid Blaikie     Abbrev.setNumber(Abbreviations.size());
4085f80d71SDavid Blaikie   } else {
4185f80d71SDavid Blaikie     // Assign existing abbreviation number.
4285f80d71SDavid Blaikie     Abbrev.setNumber(InSet->getNumber());
4385f80d71SDavid Blaikie   }
4485f80d71SDavid Blaikie }
4585f80d71SDavid Blaikie 
4685f80d71SDavid Blaikie void DwarfFile::addUnit(std::unique_ptr<DwarfUnit> U) {
4785f80d71SDavid Blaikie   CUs.push_back(std::move(U));
4885f80d71SDavid Blaikie }
4985f80d71SDavid Blaikie 
5085f80d71SDavid Blaikie // Emit the various dwarf units to the unit section USection with
5185f80d71SDavid Blaikie // the abbreviations going into ASection.
522b22b1e9SDavid Blaikie void DwarfFile::emitUnits(const MCSymbol *ASectionSym) {
5385f80d71SDavid Blaikie   for (const auto &TheU : CUs) {
54adcde36cSDavid Blaikie     DIE &Die = TheU->getUnitDie();
5585f80d71SDavid Blaikie     const MCSection *USection = TheU->getSection();
5685f80d71SDavid Blaikie     Asm->OutStreamer.SwitchSection(USection);
5785f80d71SDavid Blaikie 
5885f80d71SDavid Blaikie     // Emit the compile units header.
5985f80d71SDavid Blaikie     Asm->OutStreamer.EmitLabel(TheU->getLabelBegin());
6085f80d71SDavid Blaikie 
6185f80d71SDavid Blaikie     // Emit size of content not including length itself
6285f80d71SDavid Blaikie     Asm->OutStreamer.AddComment("Length of Unit");
63adcde36cSDavid Blaikie     Asm->EmitInt32(TheU->getHeaderSize() + Die.getSize());
6485f80d71SDavid Blaikie 
6585f80d71SDavid Blaikie     TheU->emitHeader(ASectionSym);
6685f80d71SDavid Blaikie 
672b22b1e9SDavid Blaikie     DD.emitDIE(Die);
6885f80d71SDavid Blaikie     Asm->OutStreamer.EmitLabel(TheU->getLabelEnd());
6985f80d71SDavid Blaikie   }
7085f80d71SDavid Blaikie }
71f299947bSDavid Blaikie 
7285f80d71SDavid Blaikie // Compute the size and offset for each DIE.
7385f80d71SDavid Blaikie void DwarfFile::computeSizeAndOffsets() {
7485f80d71SDavid Blaikie   // Offset from the first CU in the debug info section is 0 initially.
7585f80d71SDavid Blaikie   unsigned SecOffset = 0;
7685f80d71SDavid Blaikie 
7785f80d71SDavid Blaikie   // Iterate over each compile unit and set the size and offsets for each
7885f80d71SDavid Blaikie   // DIE within each compile unit. All offsets are CU relative.
7985f80d71SDavid Blaikie   for (const auto &TheU : CUs) {
8085f80d71SDavid Blaikie     TheU->setDebugInfoOffset(SecOffset);
8185f80d71SDavid Blaikie 
8285f80d71SDavid Blaikie     // CU-relative offset is reset to 0 here.
8385f80d71SDavid Blaikie     unsigned Offset = sizeof(int32_t) +      // Length of Unit Info
8485f80d71SDavid Blaikie                       TheU->getHeaderSize(); // Unit-specific headers
8585f80d71SDavid Blaikie 
8685f80d71SDavid Blaikie     // EndOffset here is CU-relative, after laying out
8785f80d71SDavid Blaikie     // all of the CU DIE.
88adcde36cSDavid Blaikie     unsigned EndOffset = computeSizeAndOffset(TheU->getUnitDie(), Offset);
8985f80d71SDavid Blaikie     SecOffset += EndOffset;
9085f80d71SDavid Blaikie   }
9185f80d71SDavid Blaikie }
9285f80d71SDavid Blaikie // Compute the size and offset of a DIE. The offset is relative to start of the
9385f80d71SDavid Blaikie // CU. It returns the offset after laying out the DIE.
9485f80d71SDavid Blaikie unsigned DwarfFile::computeSizeAndOffset(DIE &Die, unsigned Offset) {
9585f80d71SDavid Blaikie   // Record the abbreviation.
9685f80d71SDavid Blaikie   assignAbbrevNumber(Die.getAbbrev());
9785f80d71SDavid Blaikie 
9885f80d71SDavid Blaikie   // Get the abbreviation for this DIE.
9985f80d71SDavid Blaikie   const DIEAbbrev &Abbrev = Die.getAbbrev();
10085f80d71SDavid Blaikie 
10185f80d71SDavid Blaikie   // Set DIE offset
10285f80d71SDavid Blaikie   Die.setOffset(Offset);
10385f80d71SDavid Blaikie 
10485f80d71SDavid Blaikie   // Start the size with the size of abbreviation code.
10585f80d71SDavid Blaikie   Offset += getULEB128Size(Die.getAbbrevNumber());
10685f80d71SDavid Blaikie 
10785f80d71SDavid Blaikie   const SmallVectorImpl<DIEValue *> &Values = Die.getValues();
10885f80d71SDavid Blaikie   const SmallVectorImpl<DIEAbbrevData> &AbbrevData = Abbrev.getData();
10985f80d71SDavid Blaikie 
11085f80d71SDavid Blaikie   // Size the DIE attribute values.
11185f80d71SDavid Blaikie   for (unsigned i = 0, N = Values.size(); i < N; ++i)
11285f80d71SDavid Blaikie     // Size attribute value.
11385f80d71SDavid Blaikie     Offset += Values[i]->SizeOf(Asm, AbbrevData[i].getForm());
11485f80d71SDavid Blaikie 
11585f80d71SDavid Blaikie   // Get the children.
11685f80d71SDavid Blaikie   const auto &Children = Die.getChildren();
11785f80d71SDavid Blaikie 
11885f80d71SDavid Blaikie   // Size the DIE children if any.
11985f80d71SDavid Blaikie   if (!Children.empty()) {
12085f80d71SDavid Blaikie     assert(Abbrev.hasChildren() && "Children flag not set");
12185f80d71SDavid Blaikie 
12285f80d71SDavid Blaikie     for (auto &Child : Children)
12385f80d71SDavid Blaikie       Offset = computeSizeAndOffset(*Child, Offset);
12485f80d71SDavid Blaikie 
12585f80d71SDavid Blaikie     // End of children marker.
12685f80d71SDavid Blaikie     Offset += sizeof(int8_t);
12785f80d71SDavid Blaikie   }
12885f80d71SDavid Blaikie 
12985f80d71SDavid Blaikie   Die.setSize(Offset - Die.getOffset());
13085f80d71SDavid Blaikie   return Offset;
13185f80d71SDavid Blaikie }
13285f80d71SDavid Blaikie void DwarfFile::emitAbbrevs(const MCSection *Section) {
13385f80d71SDavid Blaikie   // Check to see if it is worth the effort.
13485f80d71SDavid Blaikie   if (!Abbreviations.empty()) {
13585f80d71SDavid Blaikie     // Start the debug abbrev section.
13685f80d71SDavid Blaikie     Asm->OutStreamer.SwitchSection(Section);
13785f80d71SDavid Blaikie 
13885f80d71SDavid Blaikie     // For each abbrevation.
13985f80d71SDavid Blaikie     for (const DIEAbbrev *Abbrev : Abbreviations) {
14085f80d71SDavid Blaikie       // Emit the abbrevations code (base 1 index.)
14185f80d71SDavid Blaikie       Asm->EmitULEB128(Abbrev->getNumber(), "Abbreviation Code");
14285f80d71SDavid Blaikie 
14385f80d71SDavid Blaikie       // Emit the abbreviations data.
14485f80d71SDavid Blaikie       Abbrev->Emit(Asm);
14585f80d71SDavid Blaikie     }
14685f80d71SDavid Blaikie 
14785f80d71SDavid Blaikie     // Mark end of abbreviations.
14885f80d71SDavid Blaikie     Asm->EmitULEB128(0, "EOM(3)");
14985f80d71SDavid Blaikie   }
15085f80d71SDavid Blaikie }
15185f80d71SDavid Blaikie 
15285f80d71SDavid Blaikie // Emit strings into a string section.
15385f80d71SDavid Blaikie void DwarfFile::emitStrings(const MCSection *StrSection,
1546741bb09SDavid Blaikie                             const MCSection *OffsetSection) {
1556741bb09SDavid Blaikie   StrPool.emit(*Asm, StrSection, OffsetSection);
15685f80d71SDavid Blaikie }
157f299947bSDavid Blaikie 
158f299947bSDavid Blaikie // If Var is a current function argument then add it to CurrentFnArguments list.
159f299947bSDavid Blaikie bool DwarfFile::addCurrentFnArgument(DbgVariable *Var, LexicalScope *Scope) {
160f299947bSDavid Blaikie   if (Scope->getParent())
161f299947bSDavid Blaikie     return false;
162f299947bSDavid Blaikie   DIVariable DV = Var->getVariable();
163f299947bSDavid Blaikie   if (DV.getTag() != dwarf::DW_TAG_arg_variable)
164f299947bSDavid Blaikie     return false;
165f299947bSDavid Blaikie   unsigned ArgNo = DV.getArgNumber();
166f299947bSDavid Blaikie   if (ArgNo == 0)
167f299947bSDavid Blaikie     return false;
168f299947bSDavid Blaikie 
169f299947bSDavid Blaikie   auto &CurrentFnArguments = DD.getCurrentFnArguments();
170f299947bSDavid Blaikie 
171f299947bSDavid Blaikie   // llvm::Function argument size is not good indicator of how many
172f299947bSDavid Blaikie   // arguments does the function have at source level.
173f299947bSDavid Blaikie   if (ArgNo > CurrentFnArguments.size())
174f299947bSDavid Blaikie     CurrentFnArguments.resize(ArgNo * 2);
175f299947bSDavid Blaikie   assert(!CurrentFnArguments[ArgNo - 1]);
176f299947bSDavid Blaikie   CurrentFnArguments[ArgNo - 1] = Var;
177f299947bSDavid Blaikie   return true;
178f299947bSDavid Blaikie }
17985f80d71SDavid Blaikie }
180