Home | History | Annotate | Download | only in AsmPrinter
      1 //===-- llvm/CodeGen/DwarfFile.cpp - Dwarf Debug Framework ----------------===//
      2 //
      3 //                     The LLVM Compiler Infrastructure
      4 //
      5 // This file is distributed under the University of Illinois Open Source
      6 // License. See LICENSE.TXT for details.
      7 //
      8 //===----------------------------------------------------------------------===//
      9 
     10 #include "DwarfFile.h"
     11 #include "DwarfDebug.h"
     12 #include "DwarfUnit.h"
     13 #include "llvm/ADT/STLExtras.h"
     14 #include "llvm/IR/DataLayout.h"
     15 #include "llvm/MC/MCStreamer.h"
     16 #include "llvm/Support/LEB128.h"
     17 #include "llvm/Target/TargetLoweringObjectFile.h"
     18 
     19 namespace llvm {
     20 DwarfFile::DwarfFile(AsmPrinter *AP, StringRef Pref, BumpPtrAllocator &DA)
     21     : Asm(AP), StrPool(DA, *Asm, Pref) {}
     22 
     23 DwarfFile::~DwarfFile() {
     24   for (DIEAbbrev *Abbrev : Abbreviations)
     25     Abbrev->~DIEAbbrev();
     26 }
     27 
     28 // Define a unique number for the abbreviation.
     29 //
     30 DIEAbbrev &DwarfFile::assignAbbrevNumber(DIE &Die) {
     31   FoldingSetNodeID ID;
     32   DIEAbbrev Abbrev = Die.generateAbbrev();
     33   Abbrev.Profile(ID);
     34 
     35   void *InsertPos;
     36   if (DIEAbbrev *Existing =
     37           AbbreviationsSet.FindNodeOrInsertPos(ID, InsertPos)) {
     38     Die.setAbbrevNumber(Existing->getNumber());
     39     return *Existing;
     40   }
     41 
     42   // Move the abbreviation to the heap and assign a number.
     43   DIEAbbrev *New = new (AbbrevAllocator) DIEAbbrev(std::move(Abbrev));
     44   Abbreviations.push_back(New);
     45   New->setNumber(Abbreviations.size());
     46   Die.setAbbrevNumber(Abbreviations.size());
     47 
     48   // Store it for lookup.
     49   AbbreviationsSet.InsertNode(New, InsertPos);
     50   return *New;
     51 }
     52 
     53 void DwarfFile::addUnit(std::unique_ptr<DwarfUnit> U) {
     54   CUs.push_back(std::move(U));
     55 }
     56 
     57 // Emit the various dwarf units to the unit section USection with
     58 // the abbreviations going into ASection.
     59 void DwarfFile::emitUnits(bool UseOffsets) {
     60   for (const auto &TheU : CUs) {
     61     DIE &Die = TheU->getUnitDie();
     62     MCSection *USection = TheU->getSection();
     63     Asm->OutStreamer->SwitchSection(USection);
     64 
     65     TheU->emitHeader(UseOffsets);
     66 
     67     Asm->emitDwarfDIE(Die);
     68   }
     69 }
     70 
     71 // Compute the size and offset for each DIE.
     72 void DwarfFile::computeSizeAndOffsets() {
     73   // Offset from the first CU in the debug info section is 0 initially.
     74   unsigned SecOffset = 0;
     75 
     76   // Iterate over each compile unit and set the size and offsets for each
     77   // DIE within each compile unit. All offsets are CU relative.
     78   for (const auto &TheU : CUs) {
     79     TheU->setDebugInfoOffset(SecOffset);
     80 
     81     // CU-relative offset is reset to 0 here.
     82     unsigned Offset = sizeof(int32_t) +      // Length of Unit Info
     83                       TheU->getHeaderSize(); // Unit-specific headers
     84 
     85     // EndOffset here is CU-relative, after laying out
     86     // all of the CU DIE.
     87     unsigned EndOffset = computeSizeAndOffset(TheU->getUnitDie(), Offset);
     88     SecOffset += EndOffset;
     89   }
     90 }
     91 // Compute the size and offset of a DIE. The offset is relative to start of the
     92 // CU. It returns the offset after laying out the DIE.
     93 unsigned DwarfFile::computeSizeAndOffset(DIE &Die, unsigned Offset) {
     94   // Record the abbreviation.
     95   const DIEAbbrev &Abbrev = assignAbbrevNumber(Die);
     96 
     97   // Set DIE offset
     98   Die.setOffset(Offset);
     99 
    100   // Start the size with the size of abbreviation code.
    101   Offset += getULEB128Size(Die.getAbbrevNumber());
    102 
    103   // Size the DIE attribute values.
    104   for (const auto &V : Die.values())
    105     // Size attribute value.
    106     Offset += V.SizeOf(Asm);
    107 
    108   // Size the DIE children if any.
    109   if (Die.hasChildren()) {
    110     (void)Abbrev;
    111     assert(Abbrev.hasChildren() && "Children flag not set");
    112 
    113     for (auto &Child : Die.children())
    114       Offset = computeSizeAndOffset(Child, Offset);
    115 
    116     // End of children marker.
    117     Offset += sizeof(int8_t);
    118   }
    119 
    120   Die.setSize(Offset - Die.getOffset());
    121   return Offset;
    122 }
    123 
    124 void DwarfFile::emitAbbrevs(MCSection *Section) {
    125   // Check to see if it is worth the effort.
    126   if (!Abbreviations.empty()) {
    127     // Start the debug abbrev section.
    128     Asm->OutStreamer->SwitchSection(Section);
    129     Asm->emitDwarfAbbrevs(Abbreviations);
    130   }
    131 }
    132 
    133 // Emit strings into a string section.
    134 void DwarfFile::emitStrings(MCSection *StrSection, MCSection *OffsetSection) {
    135   StrPool.emit(*Asm, StrSection, OffsetSection);
    136 }
    137 
    138 bool DwarfFile::addScopeVariable(LexicalScope *LS, DbgVariable *Var) {
    139   SmallVectorImpl<DbgVariable *> &Vars = ScopeVariables[LS];
    140   const DILocalVariable *DV = Var->getVariable();
    141   // Variables with positive arg numbers are parameters.
    142   if (unsigned ArgNum = DV->getArg()) {
    143     // Keep all parameters in order at the start of the variable list to ensure
    144     // function types are correct (no out-of-order parameters)
    145     //
    146     // This could be improved by only doing it for optimized builds (unoptimized
    147     // builds have the right order to begin with), searching from the back (this
    148     // would catch the unoptimized case quickly), or doing a binary search
    149     // rather than linear search.
    150     auto I = Vars.begin();
    151     while (I != Vars.end()) {
    152       unsigned CurNum = (*I)->getVariable()->getArg();
    153       // A local (non-parameter) variable has been found, insert immediately
    154       // before it.
    155       if (CurNum == 0)
    156         break;
    157       // A later indexed parameter has been found, insert immediately before it.
    158       if (CurNum > ArgNum)
    159         break;
    160       if (CurNum == ArgNum) {
    161         (*I)->addMMIEntry(*Var);
    162         return false;
    163       }
    164       ++I;
    165     }
    166     Vars.insert(I, Var);
    167     return true;
    168   }
    169 
    170   Vars.push_back(Var);
    171   return true;
    172 }
    173 }
    174