X-Git-Url: http://plrg.eecs.uci.edu/git/?a=blobdiff_plain;f=lib%2FCodeGen%2FAsmPrinter%2FDwarfDebug.cpp;h=f584c2a036fd49e08e8c58f6e8878af04f987e2c;hb=76f193825c63e7b93b943890a2ed22086fe3bc2d;hp=3f794ad8ff5442977d4ad2b03f37d6a3ea5e84f5;hpb=7385c3207c5fa893abe91cf75e95ed36f64caf40;p=oota-llvm.git diff --git a/lib/CodeGen/AsmPrinter/DwarfDebug.cpp b/lib/CodeGen/AsmPrinter/DwarfDebug.cpp index 3f794ad8ff5..f584c2a036f 100644 --- a/lib/CodeGen/AsmPrinter/DwarfDebug.cpp +++ b/lib/CodeGen/AsmPrinter/DwarfDebug.cpp @@ -11,12 +11,10 @@ // //===----------------------------------------------------------------------===// -#define DEBUG_TYPE "dwarfdebug" #include "ByteStreamer.h" #include "DwarfDebug.h" #include "DIE.h" #include "DIEHash.h" -#include "DwarfAccelTable.h" #include "DwarfUnit.h" #include "llvm/ADT/STLExtras.h" #include "llvm/ADT/Statistic.h" @@ -51,6 +49,8 @@ #include "llvm/Target/TargetRegisterInfo.h" using namespace llvm; +#define DEBUG_TYPE "dwarfdebug" + static cl::opt DisableDebugInfoPrinting("disable-debug-info-print", cl::Hidden, cl::desc("Disable debug info printing")); @@ -107,8 +107,6 @@ static const char *const DbgTimerName = "DWARF Debug Writer"; //===----------------------------------------------------------------------===// -namespace llvm { - /// resolve - Look in the DwarfDebug map for the MDNode that /// corresponds to the reference. template T DbgVariable::resolve(DIRef Ref) const { @@ -120,7 +118,6 @@ bool DbgVariable::isBlockByrefVariable() const { return Var.isBlockByrefVariable(DD->getTypeIdentifierMap()); } - DIType DbgVariable::getType() const { DIType Ty = Var.getType().resolve(DD->getTypeIdentifierMap()); // FIXME: isBlockByrefVariable should be reformulated in terms of complex @@ -166,29 +163,32 @@ DIType DbgVariable::getType() const { return Ty; } -} // end llvm namespace - -/// Return Dwarf Version by checking module flags. -static unsigned getDwarfVersionFromModule(const Module *M) { - Value *Val = M->getModuleFlag("Dwarf Version"); - if (!Val) - return dwarf::DWARF_VERSION; - return cast(Val)->getZExtValue(); -} +static LLVM_CONSTEXPR DwarfAccelTable::Atom TypeAtoms[] = { + DwarfAccelTable::Atom(dwarf::DW_ATOM_die_offset, dwarf::DW_FORM_data4), + DwarfAccelTable::Atom(dwarf::DW_ATOM_die_tag, dwarf::DW_FORM_data2), + DwarfAccelTable::Atom(dwarf::DW_ATOM_type_flags, dwarf::DW_FORM_data1)}; DwarfDebug::DwarfDebug(AsmPrinter *A, Module *M) - : Asm(A), MMI(Asm->MMI), FirstCU(0), PrevLabel(NULL), GlobalRangeCount(0), - InfoHolder(A, "info_string", DIEValueAllocator), + : Asm(A), MMI(Asm->MMI), FirstCU(nullptr), PrevLabel(nullptr), + GlobalRangeCount(0), InfoHolder(A, "info_string", DIEValueAllocator), UsedNonDefaultText(false), - SkeletonHolder(A, "skel_string", DIEValueAllocator) { - - DwarfInfoSectionSym = DwarfAbbrevSectionSym = DwarfStrSectionSym = 0; - DwarfDebugRangeSectionSym = DwarfDebugLocSectionSym = DwarfLineSectionSym = 0; - DwarfAddrSectionSym = 0; - DwarfAbbrevDWOSectionSym = DwarfStrDWOSectionSym = 0; - FunctionBeginSym = FunctionEndSym = 0; - CurFn = 0; - CurMI = 0; + SkeletonHolder(A, "skel_string", DIEValueAllocator), + AccelNames(DwarfAccelTable::Atom(dwarf::DW_ATOM_die_offset, + dwarf::DW_FORM_data4)), + AccelObjC(DwarfAccelTable::Atom(dwarf::DW_ATOM_die_offset, + dwarf::DW_FORM_data4)), + AccelNamespace(DwarfAccelTable::Atom(dwarf::DW_ATOM_die_offset, + dwarf::DW_FORM_data4)), + AccelTypes(TypeAtoms) { + + DwarfInfoSectionSym = DwarfAbbrevSectionSym = DwarfStrSectionSym = nullptr; + DwarfDebugRangeSectionSym = DwarfDebugLocSectionSym = nullptr; + DwarfLineSectionSym = nullptr; + DwarfAddrSectionSym = nullptr; + DwarfAbbrevDWOSectionSym = DwarfStrDWOSectionSym = nullptr; + FunctionBeginSym = FunctionEndSym = nullptr; + CurFn = nullptr; + CurMI = nullptr; // Turn on accelerator tables for Darwin by default, pubnames by // default for non-Darwin, and handle split dwarf. @@ -209,9 +209,8 @@ DwarfDebug::DwarfDebug(AsmPrinter *A, Module *M) else HasDwarfPubSections = DwarfPubSections == Enable; - DwarfVersion = DwarfVersionNumber - ? DwarfVersionNumber - : getDwarfVersionFromModule(MMI->getModule()); + DwarfVersion = DwarfVersionNumber ? DwarfVersionNumber + : MMI->getModule()->getDwarfVersion(); { NamedRegionTimer T(DbgTimerName, DWARFGroupName, TimePassesIsEnabled); @@ -219,76 +218,22 @@ DwarfDebug::DwarfDebug(AsmPrinter *A, Module *M) } } +// Define out of line so we don't have to include DwarfUnit.h in DwarfDebug.h. +DwarfDebug::~DwarfDebug() { } + // Switch to the specified MCSection and emit an assembler // temporary label to it if SymbolStem is specified. static MCSymbol *emitSectionSym(AsmPrinter *Asm, const MCSection *Section, - const char *SymbolStem = 0) { + const char *SymbolStem = nullptr) { Asm->OutStreamer.SwitchSection(Section); if (!SymbolStem) - return 0; + return nullptr; MCSymbol *TmpSym = Asm->GetTempSymbol(SymbolStem); Asm->OutStreamer.EmitLabel(TmpSym); return TmpSym; } -DwarfFile::~DwarfFile() { - for (DwarfUnit *DU : CUs) - delete DU; -} - -MCSymbol *DwarfFile::getStringPoolSym() { - return Asm->GetTempSymbol(StringPref); -} - -MCSymbol *DwarfFile::getStringPoolEntry(StringRef Str) { - std::pair &Entry = - StringPool.GetOrCreateValue(Str).getValue(); - if (Entry.first) - return Entry.first; - - Entry.second = NextStringPoolNumber++; - return Entry.first = Asm->GetTempSymbol(StringPref, Entry.second); -} - -unsigned DwarfFile::getStringPoolIndex(StringRef Str) { - std::pair &Entry = - StringPool.GetOrCreateValue(Str).getValue(); - if (Entry.first) - return Entry.second; - - Entry.second = NextStringPoolNumber++; - Entry.first = Asm->GetTempSymbol(StringPref, Entry.second); - return Entry.second; -} - -unsigned DwarfFile::getAddrPoolIndex(const MCSymbol *Sym, bool TLS) { - std::pair P = AddressPool.insert( - std::make_pair(Sym, AddressPoolEntry(NextAddrPoolNumber, TLS))); - if (P.second) - ++NextAddrPoolNumber; - return P.first->second.Number; -} - -// Define a unique number for the abbreviation. -// -void DwarfFile::assignAbbrevNumber(DIEAbbrev &Abbrev) { - // Check the set for priors. - DIEAbbrev *InSet = AbbreviationsSet.GetOrInsertNode(&Abbrev); - - // If it's newly added. - if (InSet == &Abbrev) { - // Add to abbreviation list. - Abbreviations.push_back(&Abbrev); - - // Assign the vector position + 1 as its number. - Abbrev.setNumber(Abbreviations.size()); - } else { - // Assign existing abbreviation number. - Abbrev.setNumber(InSet->getNumber()); - } -} - static bool isObjCClass(StringRef Name) { return Name.startswith("+") || Name.startswith("-"); } @@ -328,26 +273,26 @@ static bool SectionSort(const MCSection *A, const MCSection *B) { // TODO: Determine whether or not we should add names for programs // that do not have a DW_AT_name or DW_AT_linkage_name field - this // is only slightly different than the lookup of non-standard ObjC names. -static void addSubprogramNames(DwarfUnit *TheU, DISubprogram SP, DIE *Die) { +void DwarfDebug::addSubprogramNames(DISubprogram SP, DIE &Die) { if (!SP.isDefinition()) return; - TheU->addAccelName(SP.getName(), Die); + addAccelName(SP.getName(), Die); // If the linkage name is different than the name, go ahead and output // that as well into the name table. if (SP.getLinkageName() != "" && SP.getName() != SP.getLinkageName()) - TheU->addAccelName(SP.getLinkageName(), Die); + addAccelName(SP.getLinkageName(), Die); // If this is an Objective-C selector name add it to the ObjC accelerator // too. if (isObjCClass(SP.getName())) { StringRef Class, Category; getObjCClassCategory(SP.getName(), Class, Category); - TheU->addAccelObjC(Class, Die); + addAccelObjC(Class, Die); if (Category != "") - TheU->addAccelObjC(Category, Die); + addAccelObjC(Category, Die); // Also add the base method name to the name table. - TheU->addAccelName(getObjCMethodName(SP.getName()), Die); + addAccelName(getObjCMethodName(SP.getName()), Die); } } @@ -367,9 +312,9 @@ bool DwarfDebug::isSubprogramContext(const MDNode *Context) { // Find DIE for the given subprogram and attach appropriate DW_AT_low_pc // and DW_AT_high_pc attributes. If there are global variables in this // scope then create and insert DIEs for these variables. -DIE *DwarfDebug::updateSubprogramScopeDIE(DwarfCompileUnit *SPCU, +DIE &DwarfDebug::updateSubprogramScopeDIE(DwarfCompileUnit &SPCU, DISubprogram SP) { - DIE *SPDie = SPCU->getDIE(SP); + DIE *SPDie = SPCU.getDIE(SP); assert(SPDie && "Unable to find subprogram DIE!"); @@ -377,48 +322,45 @@ DIE *DwarfDebug::updateSubprogramScopeDIE(DwarfCompileUnit *SPCU, // object pointer later on. But what we don't want to do is process the // concrete DIE twice. if (DIE *AbsSPDIE = AbstractSPDies.lookup(SP)) { + assert(SPDie == AbsSPDIE); // Pick up abstract subprogram DIE. - SPDie = - SPCU->createAndAddDIE(dwarf::DW_TAG_subprogram, *SPCU->getUnitDie()); - SPCU->addDIEEntry(SPDie, dwarf::DW_AT_abstract_origin, AbsSPDIE); - } else { - DISubprogram SPDecl = SP.getFunctionDeclaration(); - if (!SPDecl.isSubprogram()) { - // There is not any need to generate specification DIE for a function - // defined at compile unit level. If a function is defined inside another - // function then gdb prefers the definition at top level and but does not - // expect specification DIE in parent function. So avoid creating - // specification DIE for a function defined inside a function. - DIScope SPContext = resolve(SP.getContext()); - if (SP.isDefinition() && !SPContext.isCompileUnit() && - !SPContext.isFile() && !isSubprogramContext(SPContext)) { - SPCU->addFlag(SPDie, dwarf::DW_AT_declaration); - - // Add arguments. - DICompositeType SPTy = SP.getType(); - DIArray Args = SPTy.getTypeArray(); - uint16_t SPTag = SPTy.getTag(); - if (SPTag == dwarf::DW_TAG_subroutine_type) - SPCU->constructSubprogramArguments(*SPDie, Args); - DIE *SPDeclDie = SPDie; - SPDie = SPCU->createAndAddDIE(dwarf::DW_TAG_subprogram, - *SPCU->getUnitDie()); - SPCU->addDIEEntry(SPDie, dwarf::DW_AT_specification, SPDeclDie); - } + SPDie = &SPCU.createAndAddDIE(dwarf::DW_TAG_subprogram, SPCU.getUnitDie()); + SPCU.addDIEEntry(*SPDie, dwarf::DW_AT_abstract_origin, *AbsSPDIE); + } else if (!SP.getFunctionDeclaration()) { + // There is not any need to generate specification DIE for a function + // defined at compile unit level. If a function is defined inside another + // function then gdb prefers the definition at top level and but does not + // expect specification DIE in parent function. So avoid creating + // specification DIE for a function defined inside a function. + DIScope SPContext = resolve(SP.getContext()); + if (SP.isDefinition() && !SPContext.isCompileUnit() && + !SPContext.isFile() && !isSubprogramContext(SPContext)) { + SPCU.addFlag(*SPDie, dwarf::DW_AT_declaration); + + // Add arguments. + DICompositeType SPTy = SP.getType(); + DIArray Args = SPTy.getTypeArray(); + uint16_t SPTag = SPTy.getTag(); + if (SPTag == dwarf::DW_TAG_subroutine_type) + SPCU.constructSubprogramArguments(*SPDie, Args); + DIE *SPDeclDie = SPDie; + SPDie = + &SPCU.createAndAddDIE(dwarf::DW_TAG_subprogram, SPCU.getUnitDie()); + SPCU.addDIEEntry(*SPDie, dwarf::DW_AT_specification, *SPDeclDie); } } - attachLowHighPC(SPCU, SPDie, FunctionBeginSym, FunctionEndSym); + attachLowHighPC(SPCU, *SPDie, FunctionBeginSym, FunctionEndSym); const TargetRegisterInfo *RI = Asm->TM.getRegisterInfo(); MachineLocation Location(RI->getFrameRegister(*Asm->MF)); - SPCU->addAddress(SPDie, dwarf::DW_AT_frame_base, Location); + SPCU.addAddress(*SPDie, dwarf::DW_AT_frame_base, Location); // Add name to the name table, we do this here because we're guaranteed // to have concrete versions of our DW_TAG_subprogram nodes. - addSubprogramNames(SPCU, SP, SPDie); + addSubprogramNames(SP, *SPDie); - return SPDie; + return *SPDie; } /// Check whether we should create a DIE for the given Scope, return true @@ -442,16 +384,16 @@ bool DwarfDebug::isLexicalScopeDIENull(LexicalScope *Scope) { return !End; } -static void addSectionLabel(AsmPrinter *Asm, DwarfUnit *U, DIE *D, +static void addSectionLabel(AsmPrinter &Asm, DwarfUnit &U, DIE &D, dwarf::Attribute A, const MCSymbol *L, const MCSymbol *Sec) { - if (Asm->MAI->doesDwarfUseRelocationsAcrossSections()) - U->addSectionLabel(D, A, L); + if (Asm.MAI->doesDwarfUseRelocationsAcrossSections()) + U.addSectionLabel(D, A, L); else - U->addSectionDelta(D, A, L, Sec); + U.addSectionDelta(D, A, L, Sec); } -void DwarfDebug::addScopeRangeList(DwarfCompileUnit *TheCU, DIE *ScopeDIE, +void DwarfDebug::addScopeRangeList(DwarfCompileUnit &TheCU, DIE &ScopeDIE, const SmallVectorImpl &Range) { // Emit offset in .debug_range as a relocatable label. emitDIE will handle // emitting it appropriately. @@ -460,10 +402,10 @@ void DwarfDebug::addScopeRangeList(DwarfCompileUnit *TheCU, DIE *ScopeDIE, // Under fission, ranges are specified by constant offsets relative to the // CU's DW_AT_GNU_ranges_base. if (useSplitDwarf()) - TheCU->addSectionDelta(ScopeDIE, dwarf::DW_AT_ranges, RangeSym, - DwarfDebugRangeSectionSym); + TheCU.addSectionDelta(ScopeDIE, dwarf::DW_AT_ranges, RangeSym, + DwarfDebugRangeSectionSym); else - addSectionLabel(Asm, TheCU, ScopeDIE, dwarf::DW_AT_ranges, RangeSym, + addSectionLabel(*Asm, TheCU, ScopeDIE, dwarf::DW_AT_ranges, RangeSym, DwarfDebugRangeSectionSym); RangeSpanList List(RangeSym); @@ -473,227 +415,243 @@ void DwarfDebug::addScopeRangeList(DwarfCompileUnit *TheCU, DIE *ScopeDIE, } // Add the range list to the set of ranges to be emitted. - TheCU->addRangeList(std::move(List)); + TheCU.addRangeList(std::move(List)); +} + +void DwarfDebug::attachRangesOrLowHighPC(DwarfCompileUnit &TheCU, DIE &Die, + const SmallVectorImpl &Ranges) { + assert(!Ranges.empty()); + if (Ranges.size() == 1) + attachLowHighPC(TheCU, Die, getLabelBeforeInsn(Ranges.front().first), + getLabelAfterInsn(Ranges.front().second)); + else + addScopeRangeList(TheCU, Die, Ranges); } // Construct new DW_TAG_lexical_block for this scope and attach // DW_AT_low_pc/DW_AT_high_pc labels. -DIE *DwarfDebug::constructLexicalScopeDIE(DwarfCompileUnit *TheCU, - LexicalScope *Scope) { +std::unique_ptr +DwarfDebug::constructLexicalScopeDIE(DwarfCompileUnit &TheCU, + LexicalScope *Scope) { if (isLexicalScopeDIENull(Scope)) - return 0; + return nullptr; - DIE *ScopeDIE = new DIE(dwarf::DW_TAG_lexical_block); + auto ScopeDIE = make_unique(dwarf::DW_TAG_lexical_block); if (Scope->isAbstractScope()) return ScopeDIE; - const SmallVectorImpl &ScopeRanges = Scope->getRanges(); - - // If we have multiple ranges, emit them into the range section. - if (ScopeRanges.size() > 1) { - addScopeRangeList(TheCU, ScopeDIE, ScopeRanges); - return ScopeDIE; - } - - // Construct the address range for this DIE. - SmallVectorImpl::const_iterator RI = ScopeRanges.begin(); - MCSymbol *Start = getLabelBeforeInsn(RI->first); - MCSymbol *End = getLabelAfterInsn(RI->second); - assert(End && "End label should not be null!"); - - assert(Start->isDefined() && "Invalid starting label for an inlined scope!"); - assert(End->isDefined() && "Invalid end label for an inlined scope!"); - - attachLowHighPC(TheCU, ScopeDIE, Start, End); + attachRangesOrLowHighPC(TheCU, *ScopeDIE, Scope->getRanges()); return ScopeDIE; } // This scope represents inlined body of a function. Construct DIE to // represent this concrete inlined copy of the function. -DIE *DwarfDebug::constructInlinedScopeDIE(DwarfCompileUnit *TheCU, - LexicalScope *Scope) { - const SmallVectorImpl &ScopeRanges = Scope->getRanges(); - assert(!ScopeRanges.empty() && - "LexicalScope does not have instruction markers!"); - - if (!Scope->getScopeNode()) - return NULL; +std::unique_ptr +DwarfDebug::constructInlinedScopeDIE(DwarfCompileUnit &TheCU, + LexicalScope *Scope) { + assert(Scope->getScopeNode()); DIScope DS(Scope->getScopeNode()); DISubprogram InlinedSP = getDISubprogram(DS); - DIE *OriginDIE = TheCU->getDIE(InlinedSP); + DIE *OriginDIE = TheCU.getDIE(InlinedSP); + // FIXME: This should be an assert (or possibly a + // getOrCreateSubprogram(InlinedSP)) otherwise we're just failing to emit + // inlining information. if (!OriginDIE) { DEBUG(dbgs() << "Unable to find original DIE for an inlined subprogram."); - return NULL; + return nullptr; } - DIE *ScopeDIE = new DIE(dwarf::DW_TAG_inlined_subroutine); - TheCU->addDIEEntry(ScopeDIE, dwarf::DW_AT_abstract_origin, OriginDIE); - - // If we have multiple ranges, emit them into the range section. - if (ScopeRanges.size() > 1) - addScopeRangeList(TheCU, ScopeDIE, ScopeRanges); - else { - SmallVectorImpl::const_iterator RI = ScopeRanges.begin(); - MCSymbol *StartLabel = getLabelBeforeInsn(RI->first); - MCSymbol *EndLabel = getLabelAfterInsn(RI->second); - - if (StartLabel == 0 || EndLabel == 0) - llvm_unreachable("Unexpected Start and End labels for an inlined scope!"); + auto ScopeDIE = make_unique(dwarf::DW_TAG_inlined_subroutine); + TheCU.addDIEEntry(*ScopeDIE, dwarf::DW_AT_abstract_origin, *OriginDIE); - assert(StartLabel->isDefined() && - "Invalid starting label for an inlined scope!"); - assert(EndLabel->isDefined() && "Invalid end label for an inlined scope!"); - - attachLowHighPC(TheCU, ScopeDIE, StartLabel, EndLabel); - } + attachRangesOrLowHighPC(TheCU, *ScopeDIE, Scope->getRanges()); InlinedSubprogramDIEs.insert(OriginDIE); // Add the call site information to the DIE. DILocation DL(Scope->getInlinedAt()); - TheCU->addUInt( - ScopeDIE, dwarf::DW_AT_call_file, None, - TheCU->getOrCreateSourceID(DL.getFilename(), DL.getDirectory())); - TheCU->addUInt(ScopeDIE, dwarf::DW_AT_call_line, None, DL.getLineNumber()); + TheCU.addUInt(*ScopeDIE, dwarf::DW_AT_call_file, None, + TheCU.getOrCreateSourceID(DL.getFilename(), DL.getDirectory())); + TheCU.addUInt(*ScopeDIE, dwarf::DW_AT_call_line, None, DL.getLineNumber()); // Add name to the name table, we do this here because we're guaranteed // to have concrete versions of our DW_TAG_inlined_subprogram nodes. - addSubprogramNames(TheCU, InlinedSP, ScopeDIE); + addSubprogramNames(InlinedSP, *ScopeDIE); return ScopeDIE; } -DIE *DwarfDebug::createScopeChildrenDIE(DwarfCompileUnit *TheCU, - LexicalScope *Scope, - SmallVectorImpl &Children) { - DIE *ObjectPointer = NULL; +static std::unique_ptr constructVariableDIE(DwarfCompileUnit &TheCU, + DbgVariable &DV, + const LexicalScope &Scope, + DIE *&ObjectPointer) { + AbstractOrInlined AOI = AOI_None; + if (Scope.isAbstractScope()) + AOI = AOI_Abstract; + else if (Scope.getInlinedAt()) + AOI = AOI_Inlined; + auto Var = TheCU.constructVariableDIE(DV, AOI); + if (DV.isObjectPointer()) + ObjectPointer = Var.get(); + return Var; +} + +DIE *DwarfDebug::createScopeChildrenDIE( + DwarfCompileUnit &TheCU, LexicalScope *Scope, + SmallVectorImpl> &Children) { + DIE *ObjectPointer = nullptr; // Collect arguments for current function. if (LScopes.isCurrentFunctionScope(Scope)) { for (DbgVariable *ArgDV : CurrentFnArguments) if (ArgDV) - if (DIE *Arg = - TheCU->constructVariableDIE(*ArgDV, Scope->isAbstractScope())) { - Children.push_back(Arg); - if (ArgDV->isObjectPointer()) - ObjectPointer = Arg; - } + Children.push_back( + constructVariableDIE(TheCU, *ArgDV, *Scope, ObjectPointer)); // If this is a variadic function, add an unspecified parameter. DISubprogram SP(Scope->getScopeNode()); DIArray FnArgs = SP.getType().getTypeArray(); if (FnArgs.getElement(FnArgs.getNumElements() - 1) .isUnspecifiedParameter()) { - DIE *Ellipsis = new DIE(dwarf::DW_TAG_unspecified_parameters); - Children.push_back(Ellipsis); + Children.push_back( + make_unique(dwarf::DW_TAG_unspecified_parameters)); } } // Collect lexical scope children first. for (DbgVariable *DV : ScopeVariables.lookup(Scope)) - if (DIE *Variable = TheCU->constructVariableDIE(*DV, - Scope->isAbstractScope())) { - Children.push_back(Variable); - if (DV->isObjectPointer()) - ObjectPointer = Variable; - } + Children.push_back(constructVariableDIE(TheCU, *DV, *Scope, ObjectPointer)); + for (LexicalScope *LS : Scope->getChildren()) - if (DIE *Nested = constructScopeDIE(TheCU, LS)) - Children.push_back(Nested); + if (std::unique_ptr Nested = constructScopeDIE(TheCU, LS)) + Children.push_back(std::move(Nested)); return ObjectPointer; } +void DwarfDebug::createAndAddScopeChildren(DwarfCompileUnit &TheCU, + LexicalScope *Scope, DIE &ScopeDIE) { + // We create children when the scope DIE is not null. + SmallVector, 8> Children; + if (DIE *ObjectPointer = createScopeChildrenDIE(TheCU, Scope, Children)) + TheCU.addDIEEntry(ScopeDIE, dwarf::DW_AT_object_pointer, *ObjectPointer); + + // Add children + for (auto &I : Children) + ScopeDIE.addChild(std::move(I)); +} + +void DwarfDebug::constructAbstractSubprogramScopeDIE(DwarfCompileUnit &TheCU, + LexicalScope *Scope) { + assert(Scope && Scope->getScopeNode()); + assert(Scope->isAbstractScope()); + assert(!Scope->getInlinedAt()); + + DISubprogram Sub(Scope->getScopeNode()); + + if (!ProcessedSPNodes.insert(Sub)) + return; + + if (DIE *ScopeDIE = TheCU.getDIE(Sub)) { + AbstractSPDies.insert(std::make_pair(Sub, ScopeDIE)); + TheCU.addUInt(*ScopeDIE, dwarf::DW_AT_inline, None, dwarf::DW_INL_inlined); + createAndAddScopeChildren(TheCU, Scope, *ScopeDIE); + } +} + +DIE &DwarfDebug::constructSubprogramScopeDIE(DwarfCompileUnit &TheCU, + LexicalScope *Scope) { + assert(Scope && Scope->getScopeNode()); + assert(!Scope->getInlinedAt()); + assert(!Scope->isAbstractScope()); + DISubprogram Sub(Scope->getScopeNode()); + + assert(Sub.isSubprogram()); + + ProcessedSPNodes.insert(Sub); + + DIE &ScopeDIE = updateSubprogramScopeDIE(TheCU, Sub); + + createAndAddScopeChildren(TheCU, Scope, ScopeDIE); + + return ScopeDIE; +} + // Construct a DIE for this scope. -DIE *DwarfDebug::constructScopeDIE(DwarfCompileUnit *TheCU, - LexicalScope *Scope) { +std::unique_ptr DwarfDebug::constructScopeDIE(DwarfCompileUnit &TheCU, + LexicalScope *Scope) { if (!Scope || !Scope->getScopeNode()) - return NULL; + return nullptr; DIScope DS(Scope->getScopeNode()); - SmallVector Children; - DIE *ObjectPointer = NULL; - bool ChildrenCreated = false; + assert((Scope->getInlinedAt() || !DS.isSubprogram()) && + "Only handle inlined subprograms here, use " + "constructSubprogramScopeDIE for non-inlined " + "subprograms"); + + SmallVector, 8> Children; // We try to create the scope DIE first, then the children DIEs. This will // avoid creating un-used children then removing them later when we find out // the scope DIE is null. - DIE *ScopeDIE = NULL; - if (Scope->getInlinedAt()) + std::unique_ptr ScopeDIE; + if (Scope->getParent() && DS.isSubprogram()) { ScopeDIE = constructInlinedScopeDIE(TheCU, Scope); - else if (DS.isSubprogram()) { - ProcessedSPNodes.insert(DS); - if (Scope->isAbstractScope()) { - ScopeDIE = TheCU->getDIE(DS); - // Note down abstract DIE. - if (ScopeDIE) - AbstractSPDies.insert(std::make_pair(DS, ScopeDIE)); - } else - ScopeDIE = updateSubprogramScopeDIE(TheCU, DISubprogram(DS)); + if (!ScopeDIE) + return nullptr; + // We create children when the scope DIE is not null. + createScopeChildrenDIE(TheCU, Scope, Children); } else { // Early exit when we know the scope DIE is going to be null. if (isLexicalScopeDIENull(Scope)) - return NULL; + return nullptr; // We create children here when we know the scope DIE is not going to be // null and the children will be added to the scope DIE. - ObjectPointer = createScopeChildrenDIE(TheCU, Scope, Children); - ChildrenCreated = true; + createScopeChildrenDIE(TheCU, Scope, Children); // There is no need to emit empty lexical block DIE. std::pair Range = - std::equal_range( - ScopesWithImportedEntities.begin(), - ScopesWithImportedEntities.end(), - std::pair(DS, (const MDNode *)0), - less_first()); + std::equal_range(ScopesWithImportedEntities.begin(), + ScopesWithImportedEntities.end(), + std::pair(DS, nullptr), + less_first()); if (Children.empty() && Range.first == Range.second) - return NULL; + return nullptr; ScopeDIE = constructLexicalScopeDIE(TheCU, Scope); assert(ScopeDIE && "Scope DIE should not be null."); for (ImportedEntityMap::const_iterator i = Range.first; i != Range.second; ++i) - constructImportedEntityDIE(TheCU, i->second, ScopeDIE); - } - - if (!ScopeDIE) { - assert(Children.empty() && - "We create children only when the scope DIE is not null."); - return NULL; + constructImportedEntityDIE(TheCU, i->second, *ScopeDIE); } - if (!ChildrenCreated) - // We create children when the scope DIE is not null. - ObjectPointer = createScopeChildrenDIE(TheCU, Scope, Children); // Add children - for (DIE *I : Children) - ScopeDIE->addChild(I); - - if (DS.isSubprogram() && ObjectPointer != NULL) - TheCU->addDIEEntry(ScopeDIE, dwarf::DW_AT_object_pointer, ObjectPointer); + for (auto &I : Children) + ScopeDIE->addChild(std::move(I)); return ScopeDIE; } -void DwarfDebug::addGnuPubAttributes(DwarfUnit *U, DIE *D) const { +void DwarfDebug::addGnuPubAttributes(DwarfUnit &U, DIE &D) const { if (!GenerateGnuPubSections) return; - U->addFlag(D, dwarf::DW_AT_GNU_pubnames); + U.addFlag(D, dwarf::DW_AT_GNU_pubnames); } // Create new DwarfCompileUnit for the given metadata node with tag // DW_TAG_compile_unit. -DwarfCompileUnit *DwarfDebug::constructDwarfCompileUnit(DICompileUnit DIUnit) { +DwarfCompileUnit &DwarfDebug::constructDwarfCompileUnit(DICompileUnit DIUnit) { StringRef FN = DIUnit.getFilename(); CompilationDir = DIUnit.getDirectory(); - DIE *Die = new DIE(dwarf::DW_TAG_compile_unit); - DwarfCompileUnit *NewCU = new DwarfCompileUnit( - InfoHolder.getUnits().size(), Die, DIUnit, Asm, this, &InfoHolder); - InfoHolder.addUnit(NewCU); + auto OwnedUnit = make_unique( + InfoHolder.getUnits().size(), DIUnit, Asm, this, &InfoHolder); + DwarfCompileUnit &NewCU = *OwnedUnit; + DIE &Die = NewCU.getUnitDie(); + InfoHolder.addUnit(std::move(OwnedUnit)); // LTO with assembly output shares a single line table amongst multiple CUs. // To avoid the compilation directory being ambiguous, let the line table @@ -701,53 +659,53 @@ DwarfCompileUnit *DwarfDebug::constructDwarfCompileUnit(DICompileUnit DIUnit) { // compilation directory. if (!Asm->OutStreamer.hasRawTextSupport() || SingleCU) Asm->OutStreamer.getContext().setMCLineTableCompilationDir( - NewCU->getUniqueID(), CompilationDir); + NewCU.getUniqueID(), CompilationDir); - NewCU->addString(Die, dwarf::DW_AT_producer, DIUnit.getProducer()); - NewCU->addUInt(Die, dwarf::DW_AT_language, dwarf::DW_FORM_data2, - DIUnit.getLanguage()); - NewCU->addString(Die, dwarf::DW_AT_name, FN); + NewCU.addString(Die, dwarf::DW_AT_producer, DIUnit.getProducer()); + NewCU.addUInt(Die, dwarf::DW_AT_language, dwarf::DW_FORM_data2, + DIUnit.getLanguage()); + NewCU.addString(Die, dwarf::DW_AT_name, FN); if (!useSplitDwarf()) { - NewCU->initStmtList(DwarfLineSectionSym); + NewCU.initStmtList(DwarfLineSectionSym); // If we're using split dwarf the compilation dir is going to be in the // skeleton CU and so we don't need to duplicate it here. if (!CompilationDir.empty()) - NewCU->addString(Die, dwarf::DW_AT_comp_dir, CompilationDir); + NewCU.addString(Die, dwarf::DW_AT_comp_dir, CompilationDir); addGnuPubAttributes(NewCU, Die); } if (DIUnit.isOptimized()) - NewCU->addFlag(Die, dwarf::DW_AT_APPLE_optimized); + NewCU.addFlag(Die, dwarf::DW_AT_APPLE_optimized); StringRef Flags = DIUnit.getFlags(); if (!Flags.empty()) - NewCU->addString(Die, dwarf::DW_AT_APPLE_flags, Flags); + NewCU.addString(Die, dwarf::DW_AT_APPLE_flags, Flags); if (unsigned RVer = DIUnit.getRunTimeVersion()) - NewCU->addUInt(Die, dwarf::DW_AT_APPLE_major_runtime_vers, - dwarf::DW_FORM_data1, RVer); + NewCU.addUInt(Die, dwarf::DW_AT_APPLE_major_runtime_vers, + dwarf::DW_FORM_data1, RVer); if (!FirstCU) - FirstCU = NewCU; + FirstCU = &NewCU; if (useSplitDwarf()) { - NewCU->initSection(Asm->getObjFileLowering().getDwarfInfoDWOSection(), - DwarfInfoDWOSectionSym); - NewCU->setSkeleton(constructSkeletonCU(NewCU)); + NewCU.initSection(Asm->getObjFileLowering().getDwarfInfoDWOSection(), + DwarfInfoDWOSectionSym); + NewCU.setSkeleton(constructSkeletonCU(NewCU)); } else - NewCU->initSection(Asm->getObjFileLowering().getDwarfInfoSection(), - DwarfInfoSectionSym); + NewCU.initSection(Asm->getObjFileLowering().getDwarfInfoSection(), + DwarfInfoSectionSym); - CUMap.insert(std::make_pair(DIUnit, NewCU)); - CUDieMap.insert(std::make_pair(Die, NewCU)); + CUMap.insert(std::make_pair(DIUnit, &NewCU)); + CUDieMap.insert(std::make_pair(&Die, &NewCU)); return NewCU; } // Construct subprogram DIE. -void DwarfDebug::constructSubprogramDIE(DwarfCompileUnit *TheCU, +void DwarfDebug::constructSubprogramDIE(DwarfCompileUnit &TheCU, const MDNode *N) { // FIXME: We should only call this routine once, however, during LTO if a // program is defined in multiple CUs we could end up calling it out of @@ -756,61 +714,56 @@ void DwarfDebug::constructSubprogramDIE(DwarfCompileUnit *TheCU, DwarfCompileUnit *&CURef = SPMap[N]; if (CURef) return; - CURef = TheCU; + CURef = &TheCU; DISubprogram SP(N); - if (!SP.isDefinition()) - // This is a method declaration which will be handled while constructing - // class type. - return; + assert(SP.isSubprogram()); + assert(SP.isDefinition()); - DIE *SubprogramDie = TheCU->getOrCreateSubprogramDIE(SP); + DIE &SubprogramDie = *TheCU.getOrCreateSubprogramDIE(SP); // Expose as a global name. - TheCU->addGlobalName(SP.getName(), SubprogramDie, resolve(SP.getContext())); + TheCU.addGlobalName(SP.getName(), SubprogramDie, resolve(SP.getContext())); } -void DwarfDebug::constructImportedEntityDIE(DwarfCompileUnit *TheCU, +void DwarfDebug::constructImportedEntityDIE(DwarfCompileUnit &TheCU, const MDNode *N) { DIImportedEntity Module(N); assert(Module.Verify()); - if (DIE *D = TheCU->getOrCreateContextDIE(Module.getContext())) - constructImportedEntityDIE(TheCU, Module, D); + if (DIE *D = TheCU.getOrCreateContextDIE(Module.getContext())) + constructImportedEntityDIE(TheCU, Module, *D); } -void DwarfDebug::constructImportedEntityDIE(DwarfCompileUnit *TheCU, - const MDNode *N, DIE *Context) { +void DwarfDebug::constructImportedEntityDIE(DwarfCompileUnit &TheCU, + const MDNode *N, DIE &Context) { DIImportedEntity Module(N); assert(Module.Verify()); return constructImportedEntityDIE(TheCU, Module, Context); } -void DwarfDebug::constructImportedEntityDIE(DwarfCompileUnit *TheCU, +void DwarfDebug::constructImportedEntityDIE(DwarfCompileUnit &TheCU, const DIImportedEntity &Module, - DIE *Context) { + DIE &Context) { assert(Module.Verify() && "Use one of the MDNode * overloads to handle invalid metadata"); - assert(Context && "Should always have a context for an imported_module"); - DIE *IMDie = new DIE(Module.getTag()); - TheCU->insertDIE(Module, IMDie); + DIE &IMDie = TheCU.createAndAddDIE(Module.getTag(), Context, Module); DIE *EntityDie; - DIDescriptor Entity = Module.getEntity(); + DIDescriptor Entity = resolve(Module.getEntity()); if (Entity.isNameSpace()) - EntityDie = TheCU->getOrCreateNameSpace(DINameSpace(Entity)); + EntityDie = TheCU.getOrCreateNameSpace(DINameSpace(Entity)); else if (Entity.isSubprogram()) - EntityDie = TheCU->getOrCreateSubprogramDIE(DISubprogram(Entity)); + EntityDie = TheCU.getOrCreateSubprogramDIE(DISubprogram(Entity)); else if (Entity.isType()) - EntityDie = TheCU->getOrCreateTypeDIE(DIType(Entity)); + EntityDie = TheCU.getOrCreateTypeDIE(DIType(Entity)); else - EntityDie = TheCU->getDIE(Entity); - TheCU->addSourceLine(IMDie, Module.getLineNumber(), - Module.getContext().getFilename(), - Module.getContext().getDirectory()); - TheCU->addDIEEntry(IMDie, dwarf::DW_AT_import, EntityDie); + EntityDie = TheCU.getDIE(Entity); + TheCU.addSourceLine(IMDie, Module.getLineNumber(), + Module.getContext().getFilename(), + Module.getContext().getDirectory()); + TheCU.addDIEEntry(IMDie, dwarf::DW_AT_import, *EntityDie); StringRef Name = Module.getName(); if (!Name.empty()) - TheCU->addString(IMDie, dwarf::DW_AT_name, Name); - Context->addChild(IMDie); + TheCU.addString(IMDie, dwarf::DW_AT_name, Name); } // Emit all Dwarf sections that should come prior to the content. Create @@ -836,7 +789,7 @@ void DwarfDebug::beginModule() { for (MDNode *N : CU_Nodes->operands()) { DICompileUnit CUNode(N); - DwarfCompileUnit *CU = constructDwarfCompileUnit(CUNode); + DwarfCompileUnit &CU = constructDwarfCompileUnit(CUNode); DIArray ImportedEntities = CUNode.getImportedEntities(); for (unsigned i = 0, e = ImportedEntities.getNumElements(); i != e; ++i) ScopesWithImportedEntities.push_back(std::make_pair( @@ -846,20 +799,20 @@ void DwarfDebug::beginModule() { ScopesWithImportedEntities.end(), less_first()); DIArray GVs = CUNode.getGlobalVariables(); for (unsigned i = 0, e = GVs.getNumElements(); i != e; ++i) - CU->createGlobalVariableDIE(DIGlobalVariable(GVs.getElement(i))); + CU.createGlobalVariableDIE(DIGlobalVariable(GVs.getElement(i))); DIArray SPs = CUNode.getSubprograms(); for (unsigned i = 0, e = SPs.getNumElements(); i != e; ++i) constructSubprogramDIE(CU, SPs.getElement(i)); DIArray EnumTypes = CUNode.getEnumTypes(); for (unsigned i = 0, e = EnumTypes.getNumElements(); i != e; ++i) - CU->getOrCreateTypeDIE(EnumTypes.getElement(i)); + CU.getOrCreateTypeDIE(EnumTypes.getElement(i)); DIArray RetainedTypes = CUNode.getRetainedTypes(); for (unsigned i = 0, e = RetainedTypes.getNumElements(); i != e; ++i) { DIType Ty(RetainedTypes.getElement(i)); // The retained types array by design contains pointers to // MDNodes rather than DIRefs. Unique them here. DIType UniqueTy(resolve(Ty.getRef())); - CU->getOrCreateTypeDIE(UniqueTy); + CU.getOrCreateTypeDIE(UniqueTy); } // Emit imported_modules last so that the relevant context is already // available. @@ -874,20 +827,6 @@ void DwarfDebug::beginModule() { SectionMap[Asm->getObjFileLowering().getTextSection()]; } -// Attach DW_AT_inline attribute with inlined subprogram DIEs. -void DwarfDebug::computeInlinedDIEs() { - // Attach DW_AT_inline attribute with inlined subprogram DIEs. - for (DIE *ISP : InlinedSubprogramDIEs) - FirstCU->addUInt(ISP, dwarf::DW_AT_inline, None, dwarf::DW_INL_inlined); - - for (const auto &AI : AbstractSPDies) { - DIE *ISP = AI.second; - if (InlinedSubprogramDIEs.count(ISP)) - continue; - FirstCU->addUInt(ISP, dwarf::DW_AT_inline, None, dwarf::DW_INL_inlined); - } -} - // Collect info for variables that were optimized out. void DwarfDebug::collectDeadVariables() { const Module *M = MMI->getModule(); @@ -895,34 +834,32 @@ void DwarfDebug::collectDeadVariables() { if (NamedMDNode *CU_Nodes = M->getNamedMetadata("llvm.dbg.cu")) { for (MDNode *N : CU_Nodes->operands()) { DICompileUnit TheCU(N); + // Construct subprogram DIE and add variables DIEs. + DwarfCompileUnit *SPCU = + static_cast(CUMap.lookup(TheCU)); + assert(SPCU && "Unable to find Compile Unit!"); DIArray Subprograms = TheCU.getSubprograms(); for (unsigned i = 0, e = Subprograms.getNumElements(); i != e; ++i) { DISubprogram SP(Subprograms.getElement(i)); if (ProcessedSPNodes.count(SP) != 0) continue; - if (!SP.isSubprogram()) - continue; - if (!SP.isDefinition()) - continue; + assert(SP.isSubprogram() && + "CU's subprogram list contains a non-subprogram"); + assert(SP.isDefinition() && + "CU's subprogram list contains a subprogram declaration"); DIArray Variables = SP.getVariables(); if (Variables.getNumElements() == 0) continue; - // Construct subprogram DIE and add variables DIEs. - DwarfCompileUnit *SPCU = - static_cast(CUMap.lookup(TheCU)); - assert(SPCU && "Unable to find Compile Unit!"); // FIXME: See the comment in constructSubprogramDIE about duplicate // subprogram DIEs. - constructSubprogramDIE(SPCU, SP); + constructSubprogramDIE(*SPCU, SP); DIE *SPDIE = SPCU->getDIE(SP); for (unsigned vi = 0, ve = Variables.getNumElements(); vi != ve; ++vi) { DIVariable DV(Variables.getElement(vi)); - if (!DV.isVariable()) - continue; - DbgVariable NewVar(DV, NULL, this); - if (DIE *VariableDIE = SPCU->constructVariableDIE(NewVar, false)) - SPDIE->addChild(VariableDIE); + assert(DV.isVariable()); + DbgVariable NewVar(DV, nullptr, this); + SPDIE->addChild(SPCU->constructVariableDIE(NewVar)); } } } @@ -933,29 +870,37 @@ void DwarfDebug::finalizeModuleInfo() { // Collect info for variables that were optimized out. collectDeadVariables(); - // Attach DW_AT_inline attribute with inlined subprogram DIEs. - computeInlinedDIEs(); - // Handle anything that needs to be done on a per-unit basis after // all other generation. - for (DwarfUnit *TheU : getUnits()) { + for (const auto &TheU : getUnits()) { // Emit DW_AT_containing_type attribute to connect types with their // vtable holding type. TheU->constructContainingTypeDIEs(); // Add CU specific attributes if we need to add any. - if (TheU->getUnitDie()->getTag() == dwarf::DW_TAG_compile_unit) { + if (TheU->getUnitDie().getTag() == dwarf::DW_TAG_compile_unit) { // If we're splitting the dwarf out now that we've got the entire // CU then add the dwo id to it. DwarfCompileUnit *SkCU = static_cast(TheU->getSkeleton()); if (useSplitDwarf()) { // Emit a unique identifier for this CU. - uint64_t ID = DIEHash(Asm).computeCUSignature(*TheU->getUnitDie()); + uint64_t ID = DIEHash(Asm).computeCUSignature(TheU->getUnitDie()); TheU->addUInt(TheU->getUnitDie(), dwarf::DW_AT_GNU_dwo_id, dwarf::DW_FORM_data8, ID); SkCU->addUInt(SkCU->getUnitDie(), dwarf::DW_AT_GNU_dwo_id, dwarf::DW_FORM_data8, ID); + + // We don't keep track of which addresses are used in which CU so this + // is a bit pessimistic under LTO. + if (!AddrPool.isEmpty()) + addSectionLabel(*Asm, *SkCU, SkCU->getUnitDie(), + dwarf::DW_AT_GNU_addr_base, DwarfAddrSectionSym, + DwarfAddrSectionSym); + if (!TheU->getRangeLists().empty()) + addSectionLabel(*Asm, *SkCU, SkCU->getUnitDie(), + dwarf::DW_AT_GNU_ranges_base, + DwarfDebugRangeSectionSym, DwarfDebugRangeSectionSym); } // If we have code split among multiple sections or non-contiguous @@ -964,26 +909,27 @@ void DwarfDebug::finalizeModuleInfo() { // FIXME: We should use ranges allow reordering of code ala // .subsections_via_symbols in mach-o. This would mean turning on // ranges for all subprogram DIEs for mach-o. - DwarfCompileUnit *U = SkCU ? SkCU : static_cast(TheU); + DwarfCompileUnit &U = + SkCU ? *SkCU : static_cast(*TheU); unsigned NumRanges = TheU->getRanges().size(); if (NumRanges) { if (NumRanges > 1) { - addSectionLabel(Asm, U, U->getUnitDie(), dwarf::DW_AT_ranges, - Asm->GetTempSymbol("cu_ranges", U->getUniqueID()), + addSectionLabel(*Asm, U, U.getUnitDie(), dwarf::DW_AT_ranges, + Asm->GetTempSymbol("cu_ranges", U.getUniqueID()), DwarfDebugRangeSectionSym); // A DW_AT_low_pc attribute may also be specified in combination with // DW_AT_ranges to specify the default base address for use in // location lists (see Section 2.6.2) and range lists (see Section // 2.17.3). - U->addUInt(U->getUnitDie(), dwarf::DW_AT_low_pc, dwarf::DW_FORM_addr, - 0); + U.addUInt(U.getUnitDie(), dwarf::DW_AT_low_pc, dwarf::DW_FORM_addr, + 0); } else { RangeSpan &Range = TheU->getRanges().back(); - U->addLocalLabelAddress(U->getUnitDie(), dwarf::DW_AT_low_pc, - Range.getStart()); - U->addLabelDelta(U->getUnitDie(), dwarf::DW_AT_high_pc, - Range.getEnd(), Range.getStart()); + U.addLocalLabelAddress(U.getUnitDie(), dwarf::DW_AT_low_pc, + Range.getStart()); + U.addLabelDelta(U.getUnitDie(), dwarf::DW_AT_high_pc, Range.getEnd(), + Range.getStart()); } } } @@ -1007,7 +953,7 @@ void DwarfDebug::endSections() { // Some symbols (e.g. common/bss on mach-o) can have no section but still // appear in the output. This sucks as we rely on sections to build // arange spans. We can do it without, but it's icky. - SectionMap[NULL].push_back(SCU); + SectionMap[nullptr].push_back(SCU); } } @@ -1025,7 +971,7 @@ void DwarfDebug::endSections() { // Add terminating symbols for each section. for (unsigned ID = 0, E = Sections.size(); ID != E; ID++) { const MCSection *Section = Sections[ID]; - MCSymbol *Sym = NULL; + MCSymbol *Sym = nullptr; if (Section) { // We can't call MCSection::getLabelEndName, as it's only safe to do so @@ -1038,14 +984,14 @@ void DwarfDebug::endSections() { } // Insert a final terminator. - SectionMap[Section].push_back(SymbolCU(NULL, Sym)); + SectionMap[Section].push_back(SymbolCU(nullptr, Sym)); } } // Emit all Dwarf sections that should come after the content. void DwarfDebug::endModule() { - assert(CurFn == 0); - assert(CurMI == 0); + assert(CurFn == nullptr); + assert(CurMI == nullptr); if (!FirstCU) return; @@ -1065,9 +1011,6 @@ void DwarfDebug::endModule() { // Corresponding abbreviations into a abbrev section. emitAbbreviations(); - // Emit info into a debug loc section. - emitDebugLoc(); - // Emit info into a debug aranges section. if (GenerateARangeSection) emitDebugARanges(); @@ -1081,8 +1024,11 @@ void DwarfDebug::endModule() { emitDebugAbbrevDWO(); emitDebugLineDWO(); // Emit DWO addresses. - InfoHolder.emitAddresses(Asm->getObjFileLowering().getDwarfAddrSection()); - } + AddrPool.emit(*Asm, Asm->getObjFileLowering().getDwarfAddrSection()); + emitDebugLocDWO(); + } else + // Emit info into a debug loc section. + emitDebugLoc(); // Emit info into the dwarf accelerator table sections. if (useDwarfAccelTables()) { @@ -1102,7 +1048,7 @@ void DwarfDebug::endModule() { SPMap.clear(); // Reset these for the next Module if we have one. - FirstCU = NULL; + FirstCU = nullptr; } // Find abstract variable, if any, associated with Var. @@ -1117,9 +1063,9 @@ DbgVariable *DwarfDebug::findAbstractVariable(DIVariable &DV, LexicalScope *Scope = LScopes.findAbstractScope(ScopeLoc.getScope(Ctx)); if (!Scope) - return NULL; + return nullptr; - AbsDbgVariable = new DbgVariable(Var, NULL, this); + AbsDbgVariable = new DbgVariable(Var, nullptr, this); addScopeVariable(Scope, AbsDbgVariable); AbstractVariables[Var] = AbsDbgVariable; return AbsDbgVariable; @@ -1158,7 +1104,7 @@ void DwarfDebug::collectVariableInfoFromMMITable( LexicalScope *Scope = LScopes.findLexicalScope(VI.Loc); // If variable scope is not found then skip this variable. - if (Scope == 0) + if (!Scope) continue; DbgVariable *AbsDbgVariable = findAbstractVariable(DV, VI.Loc); @@ -1166,28 +1112,12 @@ void DwarfDebug::collectVariableInfoFromMMITable( RegVar->setFrameIndex(VI.Slot); if (!addCurrentFnArgument(RegVar, Scope)) addScopeVariable(Scope, RegVar); - if (AbsDbgVariable) - AbsDbgVariable->setFrameIndex(VI.Slot); } } -// Return true if debug value, encoded by DBG_VALUE instruction, is in a -// defined reg. -static bool isDbgValueInDefinedReg(const MachineInstr *MI) { - assert(MI->isDebugValue() && "Invalid DBG_VALUE machine instruction!"); - return MI->getNumOperands() == 3 && MI->getOperand(0).isReg() && - MI->getOperand(0).getReg() && - (MI->getOperand(1).isImm() || - (MI->getOperand(1).isReg() && MI->getOperand(1).getReg() == 0U)); -} - // Get .debug_loc entry for the instruction range starting at MI. -static DebugLocEntry getDebugLocEntry(AsmPrinter *Asm, - const MCSymbol *FLabel, - const MCSymbol *SLabel, - const MachineInstr *MI, - DwarfCompileUnit *Unit) { - const MDNode *Var = MI->getOperand(MI->getNumOperands() - 1).getMetadata(); +static DebugLocEntry::Value getDebugLocValue(const MachineInstr *MI) { + const MDNode *Var = MI->getDebugVariable(); assert(MI->getNumOperands() == 3); if (MI->getOperand(0).isReg()) { @@ -1198,14 +1128,14 @@ static DebugLocEntry getDebugLocEntry(AsmPrinter *Asm, MLoc.set(MI->getOperand(0).getReg()); else MLoc.set(MI->getOperand(0).getReg(), MI->getOperand(1).getImm()); - return DebugLocEntry(FLabel, SLabel, MLoc, Var, Unit); + return DebugLocEntry::Value(Var, MLoc); } if (MI->getOperand(0).isImm()) - return DebugLocEntry(FLabel, SLabel, MI->getOperand(0).getImm(), Unit); + return DebugLocEntry::Value(Var, MI->getOperand(0).getImm()); if (MI->getOperand(0).isFPImm()) - return DebugLocEntry(FLabel, SLabel, MI->getOperand(0).getFPImm(), Unit); + return DebugLocEntry::Value(Var, MI->getOperand(0).getFPImm()); if (MI->getOperand(0).isCImm()) - return DebugLocEntry(FLabel, SLabel, MI->getOperand(0).getCImm(), Unit); + return DebugLocEntry::Value(Var, MI->getOperand(0).getCImm()); llvm_unreachable("Unexpected 3 operand DBG_VALUE instruction!"); } @@ -1213,30 +1143,34 @@ static DebugLocEntry getDebugLocEntry(AsmPrinter *Asm, // Find variables for each lexical scope. void DwarfDebug::collectVariableInfo(SmallPtrSet &Processed) { + LexicalScope *FnScope = LScopes.getCurrentFunctionScope(); + DwarfCompileUnit *TheCU = SPMap.lookup(FnScope->getScopeNode()); // Grab the variable info that was squirreled away in the MMI side-table. collectVariableInfoFromMMITable(Processed); - for (const MDNode *Var : UserVariables) { - if (Processed.count(Var)) + for (const auto &I : DbgValues) { + DIVariable DV(I.first); + if (Processed.count(DV)) continue; - // History contains relevant DBG_VALUE instructions for Var and instructions + // History contains relevant DBG_VALUE instructions for DV and instructions // clobbering it. - SmallVectorImpl &History = DbgValues[Var]; + const SmallVectorImpl &History = I.second; if (History.empty()) continue; const MachineInstr *MInsn = History.front(); - DIVariable DV(Var); - LexicalScope *Scope = NULL; + LexicalScope *Scope = nullptr; if (DV.getTag() == dwarf::DW_TAG_arg_variable && DISubprogram(DV.getContext()).describes(CurFn->getFunction())) Scope = LScopes.getCurrentFunctionScope(); - else if (MDNode *IA = DV.getInlinedAt()) - Scope = LScopes.findInlinedScope(DebugLoc::getFromDILocation(IA)); - else - Scope = LScopes.findLexicalScope(cast(DV->getOperand(1))); + else if (MDNode *IA = DV.getInlinedAt()) { + DebugLoc DL = DebugLoc::getFromDILocation(IA); + Scope = LScopes.findInlinedScope(DebugLoc::get( + DL.getLine(), DL.getCol(), DV.getContext(), IA)); + } else + Scope = LScopes.findLexicalScope(DV.getContext()); // If variable scope is not found then skip this variable. if (!Scope) continue; @@ -1260,6 +1194,11 @@ DwarfDebug::collectVariableInfo(SmallPtrSet &Processed) { // Handle multiple DBG_VALUE instructions describing one variable. RegVar->setDotDebugLocOffset(DotDebugLocEntries.size()); + DotDebugLocEntries.resize(DotDebugLocEntries.size() + 1); + DebugLocList &LocList = DotDebugLocEntries.back(); + LocList.Label = + Asm->GetTempSymbol("debug_loc", DotDebugLocEntries.size() - 1); + SmallVector &DebugLoc = LocList.List; for (SmallVectorImpl::const_iterator HI = History.begin(), HE = History.end(); @@ -1274,7 +1213,7 @@ DwarfDebug::collectVariableInfo(SmallPtrSet &Processed) { // Compute the range for a register location. const MCSymbol *FLabel = getLabelBeforeInsn(Begin); - const MCSymbol *SLabel = 0; + const MCSymbol *SLabel = nullptr; if (HI + 1 == HE) // If Begin is the last instruction in History then its value is valid @@ -1295,24 +1234,21 @@ DwarfDebug::collectVariableInfo(SmallPtrSet &Processed) { } // The value is valid until the next DBG_VALUE or clobber. - LexicalScope *FnScope = LScopes.getCurrentFunctionScope(); - DwarfCompileUnit *TheCU = SPMap.lookup(FnScope->getScopeNode()); - DebugLocEntry Loc = getDebugLocEntry(Asm, FLabel, SLabel, Begin, TheCU); - if (DotDebugLocEntries.empty() || !DotDebugLocEntries.back().Merge(Loc)) - DotDebugLocEntries.push_back(std::move(Loc)); + DebugLocEntry Loc(FLabel, SLabel, getDebugLocValue(Begin), TheCU); + if (DebugLoc.empty() || !DebugLoc.back().Merge(Loc)) + DebugLoc.push_back(std::move(Loc)); } - DotDebugLocEntries.push_back(DebugLocEntry()); } // Collect info for variables that were optimized out. - LexicalScope *FnScope = LScopes.getCurrentFunctionScope(); DIArray Variables = DISubprogram(FnScope->getScopeNode()).getVariables(); for (unsigned i = 0, e = Variables.getNumElements(); i != e; ++i) { DIVariable DV(Variables.getElement(i)); - if (!DV || !DV.isVariable() || !Processed.insert(DV)) + assert(DV.isVariable()); + if (!Processed.insert(DV)) continue; if (LexicalScope *Scope = LScopes.findLexicalScope(DV.getContext())) - addScopeVariable(Scope, new DbgVariable(DV, NULL, this)); + addScopeVariable(Scope, new DbgVariable(DV, nullptr, this)); } } @@ -1330,7 +1266,7 @@ MCSymbol *DwarfDebug::getLabelAfterInsn(const MachineInstr *MI) { // Process beginning of an instruction. void DwarfDebug::beginInstruction(const MachineInstr *MI) { - assert(CurMI == 0); + assert(CurMI == nullptr); CurMI = MI; // Check if source location changes, but ignore DBG_VALUE locations. if (!MI->isDebugValue()) { @@ -1349,7 +1285,7 @@ void DwarfDebug::beginInstruction(const MachineInstr *MI) { const MDNode *Scope = DL.getScope(Asm->MF->getFunction()->getContext()); recordSourceLine(DL.getLine(), DL.getCol(), Scope, Flags); } else - recordSourceLine(0, 0, 0, 0); + recordSourceLine(0, 0, nullptr, 0); } } @@ -1374,15 +1310,15 @@ void DwarfDebug::beginInstruction(const MachineInstr *MI) { // Process end of an instruction. void DwarfDebug::endInstruction() { - assert(CurMI != 0); + assert(CurMI != nullptr); // Don't create a new label after DBG_VALUE instructions. // They don't generate code. if (!CurMI->isDebugValue()) - PrevLabel = 0; + PrevLabel = nullptr; DenseMap::iterator I = LabelsAfterInsn.find(CurMI); - CurMI = 0; + CurMI = nullptr; // No label needed. if (I == LabelsAfterInsn.end()) @@ -1441,7 +1377,7 @@ void DwarfDebug::beginFunction(const MachineFunction *MF) { if (LScopes.empty()) return; - assert(UserVariables.empty() && DbgValues.empty() && "Maps weren't cleaned"); + assert(DbgValues.empty() && "DbgValues map wasn't cleaned!"); // Make sure that each lexical scope will have a begin/end label. identifyScopeMarkers(); @@ -1463,139 +1399,43 @@ void DwarfDebug::beginFunction(const MachineFunction *MF) { // Assumes in correct section after the entry point. Asm->OutStreamer.EmitLabel(FunctionBeginSym); - const TargetRegisterInfo *TRI = Asm->TM.getRegisterInfo(); - // LiveUserVar - Map physreg numbers to the MDNode they contain. - std::vector LiveUserVar(TRI->getNumRegs()); - - for (MachineFunction::const_iterator I = MF->begin(), E = MF->end(); I != E; - ++I) { - bool AtBlockEntry = true; - for (MachineBasicBlock::const_iterator II = I->begin(), IE = I->end(); - II != IE; ++II) { - const MachineInstr *MI = II; - - if (MI->isDebugValue()) { - assert(MI->getNumOperands() > 1 && "Invalid machine instruction!"); - - // Keep track of user variables. - const MDNode *Var = - MI->getOperand(MI->getNumOperands() - 1).getMetadata(); - - // Variable is in a register, we need to check for clobbers. - if (isDbgValueInDefinedReg(MI)) - LiveUserVar[MI->getOperand(0).getReg()] = Var; - - // Check the history of this variable. - SmallVectorImpl &History = DbgValues[Var]; - if (History.empty()) { - UserVariables.push_back(Var); - // The first mention of a function argument gets the FunctionBeginSym - // label, so arguments are visible when breaking at function entry. - DIVariable DV(Var); - if (DV.isVariable() && DV.getTag() == dwarf::DW_TAG_arg_variable && - getDISubprogram(DV.getContext()).describes(MF->getFunction())) - LabelsBeforeInsn[MI] = FunctionBeginSym; - } else { - // We have seen this variable before. Try to coalesce DBG_VALUEs. - const MachineInstr *Prev = History.back(); - if (Prev->isDebugValue()) { - // Coalesce identical entries at the end of History. - if (History.size() >= 2 && - Prev->isIdenticalTo(History[History.size() - 2])) { - DEBUG(dbgs() << "Coalescing identical DBG_VALUE entries:\n" - << "\t" << *Prev << "\t" - << *History[History.size() - 2] << "\n"); - History.pop_back(); - } - - // Terminate old register assignments that don't reach MI; - MachineFunction::const_iterator PrevMBB = Prev->getParent(); - if (PrevMBB != I && (!AtBlockEntry || std::next(PrevMBB) != I) && - isDbgValueInDefinedReg(Prev)) { - // Previous register assignment needs to terminate at the end of - // its basic block. - MachineBasicBlock::const_iterator LastMI = - PrevMBB->getLastNonDebugInstr(); - if (LastMI == PrevMBB->end()) { - // Drop DBG_VALUE for empty range. - DEBUG(dbgs() << "Dropping DBG_VALUE for empty range:\n" - << "\t" << *Prev << "\n"); - History.pop_back(); - } else if (std::next(PrevMBB) != PrevMBB->getParent()->end()) - // Terminate after LastMI. - History.push_back(LastMI); - } - } - } - History.push_back(MI); - } else { - // Not a DBG_VALUE instruction. - if (!MI->isPosition()) - AtBlockEntry = false; - + // Collect user variables, find the end of the prologue. + for (const auto &MBB : *MF) { + for (const auto &MI : MBB) { + if (MI.isDebugValue()) { + assert(MI.getNumOperands() > 1 && "Invalid machine instruction!"); + // Keep track of user variables in order of appearance. Create the + // empty history for each variable so that the order of keys in + // DbgValues is correct. Actual history will be populated in + // calculateDbgValueHistory() function. + const MDNode *Var = MI.getDebugVariable(); + DbgValues.insert( + std::make_pair(Var, SmallVector())); + } else if (!MI.getFlag(MachineInstr::FrameSetup) && + PrologEndLoc.isUnknown() && !MI.getDebugLoc().isUnknown()) { // First known non-DBG_VALUE and non-frame setup location marks // the beginning of the function body. - if (!MI->getFlag(MachineInstr::FrameSetup) && - (PrologEndLoc.isUnknown() && !MI->getDebugLoc().isUnknown())) - PrologEndLoc = MI->getDebugLoc(); - - // Check if the instruction clobbers any registers with debug vars. - for (const MachineOperand &MO : MI->operands()) { - if (!MO.isReg() || !MO.isDef() || !MO.getReg()) - continue; - for (MCRegAliasIterator AI(MO.getReg(), TRI, true); AI.isValid(); - ++AI) { - unsigned Reg = *AI; - const MDNode *Var = LiveUserVar[Reg]; - if (!Var) - continue; - // Reg is now clobbered. - LiveUserVar[Reg] = 0; - - // Was MD last defined by a DBG_VALUE referring to Reg? - DbgValueHistoryMap::iterator HistI = DbgValues.find(Var); - if (HistI == DbgValues.end()) - continue; - SmallVectorImpl &History = HistI->second; - if (History.empty()) - continue; - const MachineInstr *Prev = History.back(); - // Sanity-check: Register assignments are terminated at the end of - // their block. - if (!Prev->isDebugValue() || Prev->getParent() != MI->getParent()) - continue; - // Is the variable still in Reg? - if (!isDbgValueInDefinedReg(Prev) || - Prev->getOperand(0).getReg() != Reg) - continue; - // Var is clobbered. Make sure the next instruction gets a label. - History.push_back(MI); - } - } + PrologEndLoc = MI.getDebugLoc(); } } } + // Calculate history for local variables. + calculateDbgValueHistory(MF, Asm->TM.getRegisterInfo(), DbgValues); + + // Request labels for the full history. for (auto &I : DbgValues) { - SmallVectorImpl &History = I.second; + const SmallVectorImpl &History = I.second; if (History.empty()) continue; - // Make sure the final register assignments are terminated. - const MachineInstr *Prev = History.back(); - if (Prev->isDebugValue() && isDbgValueInDefinedReg(Prev)) { - const MachineBasicBlock *PrevMBB = Prev->getParent(); - MachineBasicBlock::const_iterator LastMI = - PrevMBB->getLastNonDebugInstr(); - if (LastMI == PrevMBB->end()) - // Drop DBG_VALUE for empty range. - History.pop_back(); - else if (PrevMBB != &PrevMBB->getParent()->back()) { - // Terminate after LastMI. - History.push_back(LastMI); - } - } - // Request labels for the full history. + // The first mention of a function argument gets the FunctionBeginSym + // label, so arguments are visible when breaking at function entry. + DIVariable DV(I.first); + if (DV.isVariable() && DV.getTag() == dwarf::DW_TAG_arg_variable && + getDISubprogram(DV.getContext()).describes(MF->getFunction())) + LabelsBeforeInsn[History.front()] = FunctionBeginSym; + for (const MachineInstr *MI : History) { if (MI->isDebugValue()) requestLabelBeforeInsn(MI); @@ -1656,11 +1496,11 @@ void DwarfDebug::endFunction(const MachineFunction *MF) { // Every beginFunction(MF) call should be followed by an endFunction(MF) call, // though the beginFunction may not be called at all. // We should handle both cases. - if (CurFn == 0) + if (!CurFn) CurFn = MF; else assert(CurFn == MF); - assert(CurFn != 0); + assert(CurFn != nullptr); if (!MMI->hasDebugInfo() || LScopes.empty()) { // If we don't have a lexical scope for this function then there will @@ -1668,7 +1508,7 @@ void DwarfDebug::endFunction(const MachineFunction *MF) { // previously used section to nullptr. PrevSection = nullptr; PrevCU = nullptr; - CurFn = 0; + CurFn = nullptr; return; } @@ -1684,55 +1524,53 @@ void DwarfDebug::endFunction(const MachineFunction *MF) { collectVariableInfo(ProcessedVars); LexicalScope *FnScope = LScopes.getCurrentFunctionScope(); - DwarfCompileUnit *TheCU = SPMap.lookup(FnScope->getScopeNode()); - assert(TheCU && "Unable to find compile unit!"); + DwarfCompileUnit &TheCU = *SPMap.lookup(FnScope->getScopeNode()); // Construct abstract scopes. for (LexicalScope *AScope : LScopes.getAbstractScopesList()) { DISubprogram SP(AScope->getScopeNode()); - if (SP.isSubprogram()) { - // Collect info for variables that were optimized out. - DIArray Variables = SP.getVariables(); - for (unsigned i = 0, e = Variables.getNumElements(); i != e; ++i) { - DIVariable DV(Variables.getElement(i)); - if (!DV || !DV.isVariable() || !ProcessedVars.insert(DV)) - continue; - // Check that DbgVariable for DV wasn't created earlier, when - // findAbstractVariable() was called for inlined instance of DV. - LLVMContext &Ctx = DV->getContext(); - DIVariable CleanDV = cleanseInlinedVariable(DV, Ctx); - if (AbstractVariables.lookup(CleanDV)) - continue; - if (LexicalScope *Scope = LScopes.findAbstractScope(DV.getContext())) - addScopeVariable(Scope, new DbgVariable(DV, NULL, this)); - } + if (!SP.isSubprogram()) + continue; + // Collect info for variables that were optimized out. + DIArray Variables = SP.getVariables(); + for (unsigned i = 0, e = Variables.getNumElements(); i != e; ++i) { + DIVariable DV(Variables.getElement(i)); + assert(DV && DV.isVariable()); + if (!ProcessedVars.insert(DV)) + continue; + // Check that DbgVariable for DV wasn't created earlier, when + // findAbstractVariable() was called for inlined instance of DV. + LLVMContext &Ctx = DV->getContext(); + DIVariable CleanDV = cleanseInlinedVariable(DV, Ctx); + if (AbstractVariables.lookup(CleanDV)) + continue; + if (LexicalScope *Scope = LScopes.findAbstractScope(DV.getContext())) + addScopeVariable(Scope, new DbgVariable(DV, nullptr, this)); } - if (ProcessedSPNodes.count(AScope->getScopeNode()) == 0) - constructScopeDIE(TheCU, AScope); + constructAbstractSubprogramScopeDIE(TheCU, AScope); } - DIE *CurFnDIE = constructScopeDIE(TheCU, FnScope); + DIE &CurFnDIE = constructSubprogramScopeDIE(TheCU, FnScope); if (!CurFn->getTarget().Options.DisableFramePointerElim(*CurFn)) - TheCU->addFlag(CurFnDIE, dwarf::DW_AT_APPLE_omit_frame_ptr); + TheCU.addFlag(CurFnDIE, dwarf::DW_AT_APPLE_omit_frame_ptr); // Add the range of this function to the list of ranges for the CU. RangeSpan Span(FunctionBeginSym, FunctionEndSym); - TheCU->addRange(std::move(Span)); + TheCU.addRange(std::move(Span)); PrevSection = Asm->getCurrentSection(); - PrevCU = TheCU; + PrevCU = &TheCU; // Clear debug info for (auto &I : ScopeVariables) DeleteContainerPointers(I.second); ScopeVariables.clear(); DeleteContainerPointers(CurrentFnArguments); - UserVariables.clear(); DbgValues.clear(); AbstractVariables.clear(); LabelsBeforeInsn.clear(); LabelsAfterInsn.clear(); - PrevLabel = NULL; - CurFn = 0; + PrevLabel = nullptr; + CurFn = nullptr; } // Register a source line with debug info. Returns the unique label that was @@ -1743,36 +1581,16 @@ void DwarfDebug::recordSourceLine(unsigned Line, unsigned Col, const MDNode *S, StringRef Dir; unsigned Src = 1; unsigned Discriminator = 0; - if (S) { - DIDescriptor Scope(S); - - if (Scope.isCompileUnit()) { - DICompileUnit CU(S); - Fn = CU.getFilename(); - Dir = CU.getDirectory(); - } else if (Scope.isFile()) { - DIFile F(S); - Fn = F.getFilename(); - Dir = F.getDirectory(); - } else if (Scope.isSubprogram()) { - DISubprogram SP(S); - Fn = SP.getFilename(); - Dir = SP.getDirectory(); - } else if (Scope.isLexicalBlockFile()) { - DILexicalBlockFile DBF(S); - Fn = DBF.getFilename(); - Dir = DBF.getDirectory(); - } else if (Scope.isLexicalBlock()) { - DILexicalBlock DB(S); - Fn = DB.getFilename(); - Dir = DB.getDirectory(); - Discriminator = DB.getDiscriminator(); - } else - llvm_unreachable("Unexpected scope info"); + if (DIScope Scope = DIScope(S)) { + assert(Scope.isScope()); + Fn = Scope.getFilename(); + Dir = Scope.getDirectory(); + if (Scope.isLexicalBlock()) + Discriminator = DILexicalBlock(S).getDiscriminator(); unsigned CUID = Asm->OutStreamer.getContext().getDwarfCompileUnitID(); - Src = static_cast(InfoHolder.getUnits()[CUID]) - ->getOrCreateSourceID(Fn, Dir); + Src = static_cast(*InfoHolder.getUnits()[CUID]) + .getOrCreateSourceID(Fn, Dir); } Asm->OutStreamer.EmitDwarfLocDirective(Src, Line, Col, Flags, 0, Discriminator, Fn); @@ -1782,68 +1600,6 @@ void DwarfDebug::recordSourceLine(unsigned Line, unsigned Col, const MDNode *S, // Emit Methods //===----------------------------------------------------------------------===// -// Compute the size and offset of a DIE. The offset is relative to start of the -// CU. It returns the offset after laying out the DIE. -unsigned DwarfFile::computeSizeAndOffset(DIE *Die, unsigned Offset) { - // Record the abbreviation. - assignAbbrevNumber(Die->getAbbrev()); - - // Get the abbreviation for this DIE. - const DIEAbbrev &Abbrev = Die->getAbbrev(); - - // Set DIE offset - Die->setOffset(Offset); - - // Start the size with the size of abbreviation code. - Offset += getULEB128Size(Die->getAbbrevNumber()); - - const SmallVectorImpl &Values = Die->getValues(); - const SmallVectorImpl &AbbrevData = Abbrev.getData(); - - // Size the DIE attribute values. - for (unsigned i = 0, N = Values.size(); i < N; ++i) - // Size attribute value. - Offset += Values[i]->SizeOf(Asm, AbbrevData[i].getForm()); - - // Get the children. - const std::vector &Children = Die->getChildren(); - - // Size the DIE children if any. - if (!Children.empty()) { - assert(Abbrev.hasChildren() && "Children flag not set"); - - for (DIE *Child : Children) - Offset = computeSizeAndOffset(Child, Offset); - - // End of children marker. - Offset += sizeof(int8_t); - } - - Die->setSize(Offset - Die->getOffset()); - return Offset; -} - -// Compute the size and offset for each DIE. -void DwarfFile::computeSizeAndOffsets() { - // Offset from the first CU in the debug info section is 0 initially. - unsigned SecOffset = 0; - - // Iterate over each compile unit and set the size and offsets for each - // DIE within each compile unit. All offsets are CU relative. - for (DwarfUnit *TheU : CUs) { - TheU->setDebugInfoOffset(SecOffset); - - // CU-relative offset is reset to 0 here. - unsigned Offset = sizeof(int32_t) + // Length of Unit Info - TheU->getHeaderSize(); // Unit-specific headers - - // EndOffset here is CU-relative, after laying out - // all of the CU DIE. - unsigned EndOffset = computeSizeAndOffset(TheU->getUnitDie(), Offset); - SecOffset += EndOffset; - } -} - // Emit initial Dwarf sections with a label at the start of each one. void DwarfDebug::emitSectionLabels() { const TargetLoweringObjectFile &TLOF = Asm->getObjFileLowering(); @@ -1851,9 +1607,12 @@ void DwarfDebug::emitSectionLabels() { // Dwarf sections base addresses. DwarfInfoSectionSym = emitSectionSym(Asm, TLOF.getDwarfInfoSection(), "section_info"); - if (useSplitDwarf()) + if (useSplitDwarf()) { DwarfInfoDWOSectionSym = emitSectionSym(Asm, TLOF.getDwarfInfoDWOSection(), "section_info_dwo"); + DwarfTypesDWOSectionSym = + emitSectionSym(Asm, TLOF.getDwarfTypesDWOSection(), "section_types_dwo"); + } DwarfAbbrevSectionSym = emitSectionSym(Asm, TLOF.getDwarfAbbrevSection(), "section_abbrev"); if (useSplitDwarf()) @@ -1864,7 +1623,6 @@ void DwarfDebug::emitSectionLabels() { DwarfLineSectionSym = emitSectionSym(Asm, TLOF.getDwarfLineSection(), "section_line"); - emitSectionSym(Asm, TLOF.getDwarfLocSection()); if (GenerateGnuPubSections) { DwarfGnuPubNamesSectionSym = emitSectionSym(Asm, TLOF.getDwarfGnuPubNamesSection()); @@ -1882,28 +1640,29 @@ void DwarfDebug::emitSectionLabels() { emitSectionSym(Asm, TLOF.getDwarfStrDWOSection(), "skel_string"); DwarfAddrSectionSym = emitSectionSym(Asm, TLOF.getDwarfAddrSection(), "addr_sec"); - } + DwarfDebugLocSectionSym = + emitSectionSym(Asm, TLOF.getDwarfLocDWOSection(), "skel_loc"); + } else + DwarfDebugLocSectionSym = + emitSectionSym(Asm, TLOF.getDwarfLocSection(), "section_debug_loc"); DwarfDebugRangeSectionSym = emitSectionSym(Asm, TLOF.getDwarfRangesSection(), "debug_range"); - - DwarfDebugLocSectionSym = - emitSectionSym(Asm, TLOF.getDwarfLocSection(), "section_debug_loc"); } // Recursively emits a debug information entry. -void DwarfDebug::emitDIE(DIE *Die) { +void DwarfDebug::emitDIE(DIE &Die) { // Get the abbreviation for this DIE. - const DIEAbbrev &Abbrev = Die->getAbbrev(); + const DIEAbbrev &Abbrev = Die.getAbbrev(); // Emit the code (index) for the abbreviation. if (Asm->isVerbose()) Asm->OutStreamer.AddComment("Abbrev [" + Twine(Abbrev.getNumber()) + - "] 0x" + Twine::utohexstr(Die->getOffset()) + - ":0x" + Twine::utohexstr(Die->getSize()) + " " + + "] 0x" + Twine::utohexstr(Die.getOffset()) + + ":0x" + Twine::utohexstr(Die.getSize()) + " " + dwarf::TagString(Abbrev.getTag())); Asm->EmitULEB128(Abbrev.getNumber()); - const SmallVectorImpl &Values = Die->getValues(); + const SmallVectorImpl &Values = Die.getValues(); const SmallVectorImpl &AbbrevData = Abbrev.getData(); // Emit the DIE attribute values. @@ -1925,38 +1684,14 @@ void DwarfDebug::emitDIE(DIE *Die) { // Emit the DIE children if any. if (Abbrev.hasChildren()) { - const std::vector &Children = Die->getChildren(); - - for (DIE *Child : Children) - emitDIE(Child); + for (auto &Child : Die.getChildren()) + emitDIE(*Child); Asm->OutStreamer.AddComment("End Of Children Mark"); Asm->EmitInt8(0); } } -// Emit the various dwarf units to the unit section USection with -// the abbreviations going into ASection. -void DwarfFile::emitUnits(DwarfDebug *DD, const MCSymbol *ASectionSym) { - for (DwarfUnit *TheU : CUs) { - DIE *Die = TheU->getUnitDie(); - const MCSection *USection = TheU->getSection(); - Asm->OutStreamer.SwitchSection(USection); - - // Emit the compile units header. - Asm->OutStreamer.EmitLabel(TheU->getLabelBegin()); - - // Emit size of content not including length itself - Asm->OutStreamer.AddComment("Length of Unit"); - Asm->EmitInt32(TheU->getHeaderSize() + Die->getSize()); - - TheU->emitHeader(ASectionSym); - - DD->emitDIE(Die); - Asm->OutStreamer.EmitLabel(TheU->getLabelEnd()); - } -} - // Emit the debug info section. void DwarfDebug::emitDebugInfo() { DwarfFile &Holder = useSplitDwarf() ? SkeletonHolder : InfoHolder; @@ -1971,26 +1706,6 @@ void DwarfDebug::emitAbbreviations() { Holder.emitAbbrevs(Asm->getObjFileLowering().getDwarfAbbrevSection()); } -void DwarfFile::emitAbbrevs(const MCSection *Section) { - // Check to see if it is worth the effort. - if (!Abbreviations.empty()) { - // Start the debug abbrev section. - Asm->OutStreamer.SwitchSection(Section); - - // For each abbrevation. - for (const DIEAbbrev *Abbrev : Abbreviations) { - // Emit the abbrevations code (base 1 index.) - Asm->EmitULEB128(Abbrev->getNumber(), "Abbreviation Code"); - - // Emit the abbreviations data. - Abbrev->Emit(Asm); - } - - // Mark end of abbreviations. - Asm->EmitULEB128(0, "EOM(3)"); - } -} - // Emit the last address of the section and the end of the line matrix. void DwarfDebug::emitEndOfLineMatrix(unsigned SectionEnd) { // Define last address of section. @@ -2017,97 +1732,52 @@ void DwarfDebug::emitEndOfLineMatrix(unsigned SectionEnd) { // Emit visible names into a hashed accelerator table section. void DwarfDebug::emitAccelNames() { - DwarfAccelTable AT( - DwarfAccelTable::Atom(dwarf::DW_ATOM_die_offset, dwarf::DW_FORM_data4)); - for (DwarfUnit *TheU : getUnits()) { - for (const auto &GI : TheU->getAccelNames()) { - StringRef Name = GI.getKey(); - for (const DIE *D : GI.second) - AT.AddName(Name, D); - } - } - - AT.FinalizeTable(Asm, "Names"); + AccelNames.FinalizeTable(Asm, "Names"); Asm->OutStreamer.SwitchSection( Asm->getObjFileLowering().getDwarfAccelNamesSection()); MCSymbol *SectionBegin = Asm->GetTempSymbol("names_begin"); Asm->OutStreamer.EmitLabel(SectionBegin); // Emit the full data. - AT.Emit(Asm, SectionBegin, &InfoHolder); + AccelNames.Emit(Asm, SectionBegin, &InfoHolder); } // Emit objective C classes and categories into a hashed accelerator table // section. void DwarfDebug::emitAccelObjC() { - DwarfAccelTable AT( - DwarfAccelTable::Atom(dwarf::DW_ATOM_die_offset, dwarf::DW_FORM_data4)); - for (DwarfUnit *TheU : getUnits()) { - for (const auto &GI : TheU->getAccelObjC()) { - StringRef Name = GI.getKey(); - for (const DIE *D : GI.second) - AT.AddName(Name, D); - } - } - - AT.FinalizeTable(Asm, "ObjC"); + AccelObjC.FinalizeTable(Asm, "ObjC"); Asm->OutStreamer.SwitchSection( Asm->getObjFileLowering().getDwarfAccelObjCSection()); MCSymbol *SectionBegin = Asm->GetTempSymbol("objc_begin"); Asm->OutStreamer.EmitLabel(SectionBegin); // Emit the full data. - AT.Emit(Asm, SectionBegin, &InfoHolder); + AccelObjC.Emit(Asm, SectionBegin, &InfoHolder); } // Emit namespace dies into a hashed accelerator table. void DwarfDebug::emitAccelNamespaces() { - DwarfAccelTable AT( - DwarfAccelTable::Atom(dwarf::DW_ATOM_die_offset, dwarf::DW_FORM_data4)); - for (DwarfUnit *TheU : getUnits()) { - for (const auto &GI : TheU->getAccelNamespace()) { - StringRef Name = GI.getKey(); - for (const DIE *D : GI.second) - AT.AddName(Name, D); - } - } - - AT.FinalizeTable(Asm, "namespac"); + AccelNamespace.FinalizeTable(Asm, "namespac"); Asm->OutStreamer.SwitchSection( Asm->getObjFileLowering().getDwarfAccelNamespaceSection()); MCSymbol *SectionBegin = Asm->GetTempSymbol("namespac_begin"); Asm->OutStreamer.EmitLabel(SectionBegin); // Emit the full data. - AT.Emit(Asm, SectionBegin, &InfoHolder); + AccelNamespace.Emit(Asm, SectionBegin, &InfoHolder); } // Emit type dies into a hashed accelerator table. void DwarfDebug::emitAccelTypes() { - std::vector Atoms; - Atoms.push_back( - DwarfAccelTable::Atom(dwarf::DW_ATOM_die_offset, dwarf::DW_FORM_data4)); - Atoms.push_back( - DwarfAccelTable::Atom(dwarf::DW_ATOM_die_tag, dwarf::DW_FORM_data2)); - Atoms.push_back( - DwarfAccelTable::Atom(dwarf::DW_ATOM_type_flags, dwarf::DW_FORM_data1)); - DwarfAccelTable AT(Atoms); - for (DwarfUnit *TheU : getUnits()) { - for (const auto &GI : TheU->getAccelTypes()) { - StringRef Name = GI.getKey(); - for (const auto &DI : GI.second) - AT.AddName(Name, DI.first, DI.second); - } - } - AT.FinalizeTable(Asm, "types"); + AccelTypes.FinalizeTable(Asm, "types"); Asm->OutStreamer.SwitchSection( Asm->getObjFileLowering().getDwarfAccelTypesSection()); MCSymbol *SectionBegin = Asm->GetTempSymbol("types_begin"); Asm->OutStreamer.EmitLabel(SectionBegin); // Emit the full data. - AT.Emit(Asm, SectionBegin, &InfoHolder); + AccelTypes.Emit(Asm, SectionBegin, &InfoHolder); } // Public name handling. @@ -2133,8 +1803,8 @@ static dwarf::PubIndexEntryDescriptor computeIndexValue(DwarfUnit *CU, // look for that now. DIEValue *SpecVal = Die->findAttribute(dwarf::DW_AT_specification); if (SpecVal) { - DIE *SpecDIE = cast(SpecVal)->getEntry(); - if (SpecDIE->findAttribute(dwarf::DW_AT_external)) + DIE &SpecDIE = cast(SpecVal)->getEntry(); + if (SpecDIE.findAttribute(dwarf::DW_AT_external)) Linkage = dwarf::GIEL_EXTERNAL; } else if (Die->findAttribute(dwarf::DW_AT_external)) Linkage = dwarf::GIEL_EXTERNAL; @@ -2246,69 +1916,6 @@ void DwarfDebug::emitDebugPubTypes(bool GnuStyle) { emitDebugPubSection(GnuStyle, PSec, "Types", &DwarfUnit::getGlobalTypes); } -// Emit strings into a string section. -void DwarfFile::emitStrings(const MCSection *StrSection, - const MCSection *OffsetSection = NULL, - const MCSymbol *StrSecSym = NULL) { - - if (StringPool.empty()) - return; - - // Start the dwarf str section. - Asm->OutStreamer.SwitchSection(StrSection); - - // Get all of the string pool entries and put them in an array by their ID so - // we can sort them. - SmallVector, 64 > Entries; - - for (const auto &I : StringPool) - Entries.push_back(std::make_pair(I.second.second, &I)); - - array_pod_sort(Entries.begin(), Entries.end()); - - for (const auto &Entry : Entries) { - // Emit a label for reference from debug information entries. - Asm->OutStreamer.EmitLabel(Entry.second->getValue().first); - - // Emit the string itself with a terminating null byte. - Asm->OutStreamer.EmitBytes(StringRef(Entry.second->getKeyData(), - Entry.second->getKeyLength() + 1)); - } - - // If we've got an offset section go ahead and emit that now as well. - if (OffsetSection) { - Asm->OutStreamer.SwitchSection(OffsetSection); - unsigned offset = 0; - unsigned size = 4; // FIXME: DWARF64 is 8. - for (const auto &Entry : Entries) { - Asm->OutStreamer.EmitIntValue(offset, size); - offset += Entry.second->getKeyLength() + 1; - } - } -} - -// Emit addresses into the section given. -void DwarfFile::emitAddresses(const MCSection *AddrSection) { - - if (AddressPool.empty()) - return; - - // Start the dwarf addr section. - Asm->OutStreamer.SwitchSection(AddrSection); - - // Order the address pool entries by ID - SmallVector Entries(AddressPool.size()); - - for (const auto &I : AddressPool) - Entries[I.second.Number] = - I.second.TLS - ? Asm->getObjFileLowering().getDebugThreadLocalSymbol(I.first) - : MCSymbolRefExpr::Create(I.first, Asm->OutContext); - - for (const MCExpr *Entry : Entries) - Asm->OutStreamer.EmitValue(Entry, Asm->getDataLayout().getPointerSize()); -} - // Emit visible names into a debug str section. void DwarfDebug::emitDebugStr() { DwarfFile &Holder = useSplitDwarf() ? SkeletonHolder : InfoHolder; @@ -2317,19 +1924,22 @@ void DwarfDebug::emitDebugStr() { void DwarfDebug::emitDebugLocEntry(ByteStreamer &Streamer, const DebugLocEntry &Entry) { - DIVariable DV(Entry.getVariable()); - if (Entry.isInt()) { + assert(Entry.getValues().size() == 1 && + "multi-value entries are not supported yet."); + const DebugLocEntry::Value Value = Entry.getValues()[0]; + DIVariable DV(Value.getVariable()); + if (Value.isInt()) { DIBasicType BTy(resolve(DV.getType())); if (BTy.Verify() && (BTy.getEncoding() == dwarf::DW_ATE_signed || BTy.getEncoding() == dwarf::DW_ATE_signed_char)) { Streamer.EmitInt8(dwarf::DW_OP_consts, "DW_OP_consts"); - Streamer.EmitSLEB128(Entry.getInt()); + Streamer.EmitSLEB128(Value.getInt()); } else { Streamer.EmitInt8(dwarf::DW_OP_constu, "DW_OP_constu"); - Streamer.EmitULEB128(Entry.getInt()); + Streamer.EmitULEB128(Value.getInt()); } - } else if (Entry.isLocation()) { - MachineLocation Loc = Entry.getLoc(); + } else if (Value.isLocation()) { + MachineLocation Loc = Value.getLoc(); if (!DV.hasComplexAddress()) // Regular entry. Asm->EmitDwarfRegOp(Streamer, Loc, DV.isIndirect()); @@ -2374,28 +1984,28 @@ void DwarfDebug::emitDebugLocEntry(ByteStreamer &Streamer, // FIXME: ^ } +void DwarfDebug::emitDebugLocEntryLocation(const DebugLocEntry &Entry) { + Asm->OutStreamer.AddComment("Loc expr size"); + MCSymbol *begin = Asm->OutStreamer.getContext().CreateTempSymbol(); + MCSymbol *end = Asm->OutStreamer.getContext().CreateTempSymbol(); + Asm->EmitLabelDifference(end, begin, 2); + Asm->OutStreamer.EmitLabel(begin); + // Emit the entry. + APByteStreamer Streamer(*Asm); + emitDebugLocEntry(Streamer, Entry); + // Close the range. + Asm->OutStreamer.EmitLabel(end); +} + // Emit locations into the debug loc section. void DwarfDebug::emitDebugLoc() { - if (DotDebugLocEntries.empty()) - return; - // Start the dwarf loc section. Asm->OutStreamer.SwitchSection( Asm->getObjFileLowering().getDwarfLocSection()); unsigned char Size = Asm->getDataLayout().getPointerSize(); - Asm->OutStreamer.EmitLabel(Asm->GetTempSymbol("debug_loc", 0)); - unsigned index = 1; - for (SmallVectorImpl::const_iterator - I = DotDebugLocEntries.begin(), - E = DotDebugLocEntries.end(); - I != E; ++I, ++index) { - const DebugLocEntry &Entry = *I; - - if (Entry.isEmpty()) { - Asm->OutStreamer.EmitIntValue(0, Size); - Asm->OutStreamer.EmitIntValue(0, Size); - Asm->OutStreamer.EmitLabel(Asm->GetTempSymbol("debug_loc", index)); - } else { + for (const auto &DebugLoc : DotDebugLocEntries) { + Asm->OutStreamer.EmitLabel(DebugLoc.Label); + for (const auto &Entry : DebugLoc.List) { // Set up the range. This range is relative to the entry point of the // compile unit. This is a hard coded 0 for low_pc when we're emitting // ranges, or the DW_AT_low_pc on the compile unit otherwise. @@ -2409,17 +2019,32 @@ void DwarfDebug::emitDebugLoc() { Asm->OutStreamer.EmitSymbolValue(Entry.getBeginSym(), Size); Asm->OutStreamer.EmitSymbolValue(Entry.getEndSym(), Size); } - Asm->OutStreamer.AddComment("Loc expr size"); - MCSymbol *begin = Asm->OutStreamer.getContext().CreateTempSymbol(); - MCSymbol *end = Asm->OutStreamer.getContext().CreateTempSymbol(); - Asm->EmitLabelDifference(end, begin, 2); - Asm->OutStreamer.EmitLabel(begin); - // Emit the entry. - APByteStreamer Streamer(*Asm); - emitDebugLocEntry(Streamer, Entry); - // Close the range. - Asm->OutStreamer.EmitLabel(end); + + emitDebugLocEntryLocation(Entry); } + Asm->OutStreamer.EmitIntValue(0, Size); + Asm->OutStreamer.EmitIntValue(0, Size); + } +} + +void DwarfDebug::emitDebugLocDWO() { + Asm->OutStreamer.SwitchSection( + Asm->getObjFileLowering().getDwarfLocDWOSection()); + for (const auto &DebugLoc : DotDebugLocEntries) { + Asm->OutStreamer.EmitLabel(DebugLoc.Label); + for (const auto &Entry : DebugLoc.List) { + // Just always use start_length for now - at least that's one address + // rather than two. We could get fancier and try to, say, reuse an + // address we know we've emitted elsewhere (the start of the function? + // The start of the CU or CU subrange that encloses this range?) + Asm->EmitInt8(dwarf::DW_LLE_start_length_entry); + unsigned idx = AddrPool.getIndex(Entry.getBeginSym()); + Asm->EmitULEB128(idx); + Asm->EmitLabelDifference(Entry.getEndSym(), Entry.getBeginSym(), 4); + + emitDebugLocEntryLocation(Entry); + } + Asm->EmitInt8(dwarf::DW_LLE_end_of_list_entry); } } @@ -2434,7 +2059,7 @@ void DwarfDebug::emitDebugARanges() { Asm->OutStreamer.SwitchSection( Asm->getObjFileLowering().getDwarfARangesSection()); - typedef DenseMap > SpansType; + typedef DenseMap> SpansType; SpansType Spans; @@ -2472,11 +2097,11 @@ void DwarfDebug::emitDebugARanges() { // If we have no section (e.g. common), just write out // individual spans for each symbol. - if (Section == NULL) { + if (!Section) { for (const SymbolCU &Cur : List) { ArangeSpan Span; Span.Start = Cur.Sym; - Span.End = NULL; + Span.End = nullptr; if (Cur.CU) Spans[Cur.CU].push_back(Span); } @@ -2583,9 +2208,6 @@ void DwarfDebug::emitDebugRanges() { for (const auto &I : CUMap) { DwarfCompileUnit *TheCU = I.second; - // Emit a symbol so we can find the beginning of our ranges. - Asm->OutStreamer.EmitLabel(TheCU->getLabelRange()); - // Iterate over the misc ranges for the compile units in the module. for (const RangeSpanList &List : TheCU->getRangeLists()) { // Emit our symbol so we can find the beginning of the range. @@ -2596,8 +2218,15 @@ void DwarfDebug::emitDebugRanges() { const MCSymbol *End = Range.getEnd(); assert(Begin && "Range without a begin symbol?"); assert(End && "Range without an end symbol?"); - Asm->OutStreamer.EmitSymbolValue(Begin, Size); - Asm->OutStreamer.EmitSymbolValue(End, Size); + if (TheCU->getRanges().size() == 1) { + // Grab the begin symbol from the first range as our base. + const MCSymbol *Base = TheCU->getRanges()[0].getStart(); + Asm->EmitLabelDifference(Begin, Base, Size); + Asm->EmitLabelDifference(End, Base, Size); + } else { + Asm->OutStreamer.EmitSymbolValue(Begin, Size); + Asm->OutStreamer.EmitSymbolValue(End, Size); + } } // And terminate the list with two 0 values. @@ -2626,65 +2255,52 @@ void DwarfDebug::emitDebugRanges() { // DWARF5 Experimental Separate Dwarf emitters. -void DwarfDebug::initSkeletonUnit(const DwarfUnit *U, DIE *Die, - DwarfUnit *NewU) { +void DwarfDebug::initSkeletonUnit(const DwarfUnit &U, DIE &Die, + std::unique_ptr NewU) { NewU->addLocalString(Die, dwarf::DW_AT_GNU_dwo_name, - U->getCUNode().getSplitDebugFilename()); + U.getCUNode().getSplitDebugFilename()); if (!CompilationDir.empty()) NewU->addLocalString(Die, dwarf::DW_AT_comp_dir, CompilationDir); - addGnuPubAttributes(NewU, Die); + addGnuPubAttributes(*NewU, Die); - SkeletonHolder.addUnit(NewU); + SkeletonHolder.addUnit(std::move(NewU)); } // This DIE has the following attributes: DW_AT_comp_dir, DW_AT_stmt_list, // DW_AT_low_pc, DW_AT_high_pc, DW_AT_ranges, DW_AT_dwo_name, DW_AT_dwo_id, // DW_AT_addr_base, DW_AT_ranges_base. -DwarfCompileUnit *DwarfDebug::constructSkeletonCU(const DwarfCompileUnit *CU) { - - DIE *Die = new DIE(dwarf::DW_TAG_compile_unit); - DwarfCompileUnit *NewCU = new DwarfCompileUnit( - CU->getUniqueID(), Die, CU->getCUNode(), Asm, this, &SkeletonHolder); - NewCU->initSection(Asm->getObjFileLowering().getDwarfInfoSection(), - DwarfInfoSectionSym); - - NewCU->initStmtList(DwarfLineSectionSym); - - initSkeletonUnit(CU, Die, NewCU); - - // Relocate to the beginning of the addr_base section, else 0 for the - // beginning of the one for this compile unit. - // We could shave off some space if we deferred adding these attributes until - // the end of the CU to see if we have a non-empty debug_addr and debug_ranges - // sections so we don't bother with extra attributes and relocations. - if (Asm->MAI->doesDwarfUseRelocationsAcrossSections()) { - NewCU->addSectionLabel(Die, dwarf::DW_AT_GNU_addr_base, DwarfAddrSectionSym); - NewCU->addSectionLabel(Die, dwarf::DW_AT_GNU_ranges_base, DwarfDebugRangeSectionSym); - } else { - NewCU->addSectionOffset(Die, dwarf::DW_AT_GNU_addr_base, 0); - NewCU->addSectionOffset(Die, dwarf::DW_AT_GNU_ranges_base, 0); - } +DwarfCompileUnit &DwarfDebug::constructSkeletonCU(const DwarfCompileUnit &CU) { + + auto OwnedUnit = make_unique( + CU.getUniqueID(), CU.getCUNode(), Asm, this, &SkeletonHolder); + DwarfCompileUnit &NewCU = *OwnedUnit; + NewCU.initSection(Asm->getObjFileLowering().getDwarfInfoSection(), + DwarfInfoSectionSym); + + NewCU.initStmtList(DwarfLineSectionSym); + + initSkeletonUnit(CU, NewCU.getUnitDie(), std::move(OwnedUnit)); return NewCU; } // This DIE has the following attributes: DW_AT_comp_dir, DW_AT_dwo_name, // DW_AT_addr_base. -DwarfTypeUnit *DwarfDebug::constructSkeletonTU(DwarfTypeUnit *TU) { +DwarfTypeUnit &DwarfDebug::constructSkeletonTU(DwarfTypeUnit &TU) { DwarfCompileUnit &CU = static_cast( - *SkeletonHolder.getUnits()[TU->getCU().getUniqueID()]); + *SkeletonHolder.getUnits()[TU.getCU().getUniqueID()]); - DIE *Die = new DIE(dwarf::DW_TAG_type_unit); - DwarfTypeUnit *NewTU = - new DwarfTypeUnit(TU->getUniqueID(), Die, CU, Asm, this, &SkeletonHolder); - NewTU->setTypeSignature(TU->getTypeSignature()); - NewTU->setType(NULL); - NewTU->initSection( - Asm->getObjFileLowering().getDwarfTypesSection(TU->getTypeSignature())); + auto OwnedUnit = make_unique(TU.getUniqueID(), CU, Asm, this, + &SkeletonHolder); + DwarfTypeUnit &NewTU = *OwnedUnit; + NewTU.setTypeSignature(TU.getTypeSignature()); + NewTU.setType(nullptr); + NewTU.initSection( + Asm->getObjFileLowering().getDwarfTypesSection(TU.getTypeSignature())); - initSkeletonUnit(TU, Die, NewTU); + initSkeletonUnit(TU, NewTU.getUnitDie(), std::move(OwnedUnit)); return NewTU; } @@ -2692,7 +2308,9 @@ DwarfTypeUnit *DwarfDebug::constructSkeletonTU(DwarfTypeUnit *TU) { // compile units that would normally be in debug_info. void DwarfDebug::emitDebugInfoDWO() { assert(useSplitDwarf() && "No split dwarf debug info?"); - InfoHolder.emitUnits(this, nullptr); + // Don't pass an abbrev symbol, using a constant zero instead so as not to + // emit relocations into the dwo file. + InfoHolder.emitUnits(this, /* AbbrevSymbol */ nullptr); } // Emit the .debug_abbrev.dwo section for separated dwarf. This contains the @@ -2729,14 +2347,25 @@ MCDwarfDwoLineTable *DwarfDebug::getDwoLineTable(const DwarfCompileUnit &CU) { return &SplitTypeUnitFileTable; } +static uint64_t makeTypeSignature(StringRef Identifier) { + MD5 Hash; + Hash.update(Identifier); + // ... take the least significant 8 bytes and return those. Our MD5 + // implementation always returns its results in little endian, swap bytes + // appropriately. + MD5::MD5Result Result; + Hash.final(Result); + return *reinterpret_cast(Result + 8); +} + void DwarfDebug::addDwarfTypeUnitType(DwarfCompileUnit &CU, - StringRef Identifier, DIE *RefDie, + StringRef Identifier, DIE &RefDie, DICompositeType CTy) { - // Flag the type unit reference as a declaration so that if it contains - // members (implicit special members, static data member definitions, member - // declarations for definitions in this CU, etc) consumers don't get confused - // and think this is a full definition. - CU.addFlag(RefDie, dwarf::DW_AT_declaration); + // Fast path if we're building some type units and one has already used the + // address pool we know we're going to throw away all this work anyway, so + // don't bother building dependent types. + if (!TypeUnitsUnderConstruction.empty() && AddrPool.hasBeenUsed()) + return; const DwarfTypeUnit *&TU = DwarfTypeUnits[CTy]; if (TU) { @@ -2744,45 +2373,110 @@ void DwarfDebug::addDwarfTypeUnitType(DwarfCompileUnit &CU, return; } - DIE *UnitDie = new DIE(dwarf::DW_TAG_type_unit); - DwarfTypeUnit *NewTU = - new DwarfTypeUnit(InfoHolder.getUnits().size(), UnitDie, CU, Asm, this, - &InfoHolder, getDwoLineTable(CU)); - TU = NewTU; - InfoHolder.addUnit(NewTU); + bool TopLevelType = TypeUnitsUnderConstruction.empty(); + AddrPool.resetUsedFlag(); - NewTU->addUInt(UnitDie, dwarf::DW_AT_language, dwarf::DW_FORM_data2, - CU.getLanguage()); + auto OwnedUnit = make_unique( + InfoHolder.getUnits().size() + TypeUnitsUnderConstruction.size(), CU, Asm, + this, &InfoHolder, getDwoLineTable(CU)); + DwarfTypeUnit &NewTU = *OwnedUnit; + DIE &UnitDie = NewTU.getUnitDie(); + TU = &NewTU; + TypeUnitsUnderConstruction.push_back( + std::make_pair(std::move(OwnedUnit), CTy)); + + NewTU.addUInt(UnitDie, dwarf::DW_AT_language, dwarf::DW_FORM_data2, + CU.getLanguage()); + + uint64_t Signature = makeTypeSignature(Identifier); + NewTU.setTypeSignature(Signature); - MD5 Hash; - Hash.update(Identifier); - // ... take the least significant 8 bytes and return those. Our MD5 - // implementation always returns its results in little endian, swap bytes - // appropriately. - MD5::MD5Result Result; - Hash.final(Result); - uint64_t Signature = *reinterpret_cast(Result + 8); - NewTU->setTypeSignature(Signature); if (useSplitDwarf()) - NewTU->setSkeleton(constructSkeletonTU(NewTU)); - else - CU.applyStmtList(*UnitDie); + NewTU.initSection(Asm->getObjFileLowering().getDwarfTypesDWOSection(), + DwarfTypesDWOSectionSym); + else { + CU.applyStmtList(UnitDie); + NewTU.initSection( + Asm->getObjFileLowering().getDwarfTypesSection(Signature)); + } - NewTU->setType(NewTU->createTypeDIE(CTy)); + NewTU.setType(NewTU.createTypeDIE(CTy)); - NewTU->initSection( - useSplitDwarf() - ? Asm->getObjFileLowering().getDwarfTypesDWOSection(Signature) - : Asm->getObjFileLowering().getDwarfTypesSection(Signature)); + if (TopLevelType) { + auto TypeUnitsToAdd = std::move(TypeUnitsUnderConstruction); + TypeUnitsUnderConstruction.clear(); + + // Types referencing entries in the address table cannot be placed in type + // units. + if (AddrPool.hasBeenUsed()) { + + // Remove all the types built while building this type. + // This is pessimistic as some of these types might not be dependent on + // the type that used an address. + for (const auto &TU : TypeUnitsToAdd) + DwarfTypeUnits.erase(TU.second); + + // Construct this type in the CU directly. + // This is inefficient because all the dependent types will be rebuilt + // from scratch, including building them in type units, discovering that + // they depend on addresses, throwing them out and rebuilding them. + CU.constructTypeDIE(RefDie, CTy); + return; + } - CU.addDIETypeSignature(RefDie, *NewTU); + // If the type wasn't dependent on fission addresses, finish adding the type + // and all its dependent types. + for (auto &TU : TypeUnitsToAdd) { + if (useSplitDwarf()) + TU.first->setSkeleton(constructSkeletonTU(*TU.first)); + InfoHolder.addUnit(std::move(TU.first)); + } + } + CU.addDIETypeSignature(RefDie, NewTU); } -void DwarfDebug::attachLowHighPC(DwarfCompileUnit *Unit, DIE *D, +void DwarfDebug::attachLowHighPC(DwarfCompileUnit &Unit, DIE &D, MCSymbol *Begin, MCSymbol *End) { - Unit->addLabelAddress(D, dwarf::DW_AT_low_pc, Begin); + assert(Begin && "Begin label should not be null!"); + assert(End && "End label should not be null!"); + assert(Begin->isDefined() && "Invalid starting label"); + assert(End->isDefined() && "Invalid end label"); + + Unit.addLabelAddress(D, dwarf::DW_AT_low_pc, Begin); if (DwarfVersion < 4) - Unit->addLabelAddress(D, dwarf::DW_AT_high_pc, End); + Unit.addLabelAddress(D, dwarf::DW_AT_high_pc, End); else - Unit->addLabelDelta(D, dwarf::DW_AT_high_pc, End, Begin); + Unit.addLabelDelta(D, dwarf::DW_AT_high_pc, End, Begin); +} + +// Accelerator table mutators - add each name along with its companion +// DIE to the proper table while ensuring that the name that we're going +// to reference is in the string table. We do this since the names we +// add may not only be identical to the names in the DIE. +void DwarfDebug::addAccelName(StringRef Name, const DIE &Die) { + if (!useDwarfAccelTables()) + return; + AccelNames.AddName(Name, InfoHolder.getStringPool().getSymbol(*Asm, Name), + &Die); +} + +void DwarfDebug::addAccelObjC(StringRef Name, const DIE &Die) { + if (!useDwarfAccelTables()) + return; + AccelObjC.AddName(Name, InfoHolder.getStringPool().getSymbol(*Asm, Name), + &Die); +} + +void DwarfDebug::addAccelNamespace(StringRef Name, const DIE &Die) { + if (!useDwarfAccelTables()) + return; + AccelNamespace.AddName(Name, InfoHolder.getStringPool().getSymbol(*Asm, Name), + &Die); +} + +void DwarfDebug::addAccelType(StringRef Name, const DIE &Die, char Flags) { + if (!useDwarfAccelTables()) + return; + AccelTypes.AddName(Name, InfoHolder.getStringPool().getSymbol(*Asm, Name), + &Die); }