diff options
Diffstat (limited to 'llvm/lib/CodeGen')
-rw-r--r-- | llvm/lib/CodeGen/AsmPrinter/DwarfCompileUnit.cpp | 144 | ||||
-rw-r--r-- | llvm/lib/CodeGen/AsmPrinter/DwarfCompileUnit.h | 44 | ||||
-rw-r--r-- | llvm/lib/CodeGen/AsmPrinter/DwarfDebug.cpp | 32 | ||||
-rw-r--r-- | llvm/lib/CodeGen/AsmPrinter/DwarfDebug.h | 17 | ||||
-rw-r--r-- | llvm/lib/CodeGen/AsmPrinter/DwarfUnit.cpp | 22 | ||||
-rw-r--r-- | llvm/lib/CodeGen/AsmPrinter/DwarfUnit.h | 3 |
6 files changed, 211 insertions, 51 deletions
diff --git a/llvm/lib/CodeGen/AsmPrinter/DwarfCompileUnit.cpp b/llvm/lib/CodeGen/AsmPrinter/DwarfCompileUnit.cpp index 56856c7ee3f..2638c25daa4 100644 --- a/llvm/lib/CodeGen/AsmPrinter/DwarfCompileUnit.cpp +++ b/llvm/lib/CodeGen/AsmPrinter/DwarfCompileUnit.cpp @@ -114,10 +114,16 @@ DIE *DwarfCompileUnit::getOrCreateGlobalVariableDIE( // Construct the context before querying for the existence of the DIE in // case such construction creates the DIE. - DIE *ContextDIE = getOrCreateContextDIE(GVContext); + // For Local Scope, do not construct context DIE. + bool IsLocalScope = GVContext && isa<DILocalScope>(GVContext); + DIE *ContextDIE = IsLocalScope ? nullptr : getOrCreateContextDIE(GVContext); + assert(ContextDIE || IsLocalScope); + + // Create new global variable and add to map. + DIE *VariableDIE = IsLocalScope + ? createDIE(GV->getTag(), GV) + : &createAndAddDIE(GV->getTag(), *ContextDIE, GV); - // Add to map. - DIE *VariableDIE = &createAndAddDIE(GV->getTag(), *ContextDIE, GV); DIScope *DeclContext; if (auto *SDMDecl = GV->getStaticDataMemberDeclaration()) { DeclContext = resolve(SDMDecl->getScope()); @@ -335,23 +341,15 @@ void DwarfCompileUnit::constructScopeDIE( if (DD->isLexicalScopeDIENull(Scope)) return; - unsigned ChildScopeCount; + bool HasNonScopeChildren; // 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. - createScopeChildrenDIE(Scope, Children, &ChildScopeCount); - - // Skip imported directives in gmlt-like data. - if (!includeMinimalInlineScopes()) { - // There is no need to emit empty lexical block DIE. - for (const auto *IE : ImportedEntities[DS]) - Children.push_back( - constructImportedEntityDIE(cast<DIImportedEntity>(IE))); - } + createScopeChildrenDIE(Scope, Children, &HasNonScopeChildren); // If there are only other scopes as children, put them directly in the // parent instead, as this scope would serve no purpose. - if (Children.size() == ChildScopeCount) { + if (!HasNonScopeChildren) { FinalChildren.insert(FinalChildren.end(), std::make_move_iterator(Children.begin()), std::make_move_iterator(Children.end())); @@ -366,6 +364,7 @@ void DwarfCompileUnit::constructScopeDIE( ScopeDIE->addChild(std::move(I)); FinalChildren.push_back(std::move(ScopeDIE)); + addLocalScopeDieToLexicalScope(Scope, ScopeDIE); } DIE::value_iterator @@ -558,20 +557,37 @@ DIE *DwarfCompileUnit::constructVariableDIE(DbgVariable &DV, DIE *DwarfCompileUnit::createScopeChildrenDIE(LexicalScope *Scope, SmallVectorImpl<DIE *> &Children, - unsigned *ChildScopeCount) { + bool *HasNonScopeChildren) { DIE *ObjectPointer = nullptr; + bool HasLocalDclDie = false; + auto *DS = Scope->getScopeNode(); for (DbgVariable *DV : DU->getScopeVariables().lookup(Scope)) Children.push_back(constructVariableDIE(*DV, *Scope, ObjectPointer)); - unsigned ChildCountWithoutScopes = Children.size(); + // Skip local declarations in gmlt-like data. + if (!includeMinimalInlineScopes()) { + for (const auto *DI : LocalDeclNodes[DS]) { + DIE *D = nullptr; + if (auto *IE = dyn_cast<DIImportedEntity>(DI)) + D = getOrCreateImportedEntityDIE(IE); + else if (auto *GV = dyn_cast<DIGlobalVariable>(DI)) + D = getOrCreateGlobalVariableDIE(GV); + else if (auto *RT = dyn_cast<DIType>(DI)) + D = getOrCreateTypeDIE(RT); + else + llvm_unreachable("Unexpected DI node!"); + addLocalDclDieToLexicalScope(Scope, D); + HasLocalDclDie = true; + } + } + + if (HasNonScopeChildren) + *HasNonScopeChildren = !Children.empty() || HasLocalDclDie; for (LexicalScope *LS : Scope->getChildren()) constructScopeDIE(LS, Children); - if (ChildScopeCount) - *ChildScopeCount = Children.size() - ChildCountWithoutScopes; - return ObjectPointer; } @@ -613,6 +629,8 @@ DIE *DwarfCompileUnit::createAndAddScopeChildren(LexicalScope *Scope, for (auto &I : Children) ScopeDIE.addChild(std::move(I)); + addLocalScopeDieToLexicalScope(Scope, &ScopeDIE); + return ObjectPointer; } @@ -649,10 +667,20 @@ void DwarfCompileUnit::constructAbstractSubprogramScopeDIE( addDIEEntry(*AbsDef, dwarf::DW_AT_object_pointer, *ObjectPointer); } +DIE *DwarfCompileUnit::getOrCreateImportedEntityDIE( + const DIImportedEntity *Module) { + if (DIE *Die = getDIE(Module)) + return Die; + + return constructImportedEntityDIE(Module); +} + DIE *DwarfCompileUnit::constructImportedEntityDIE( const DIImportedEntity *Module) { - DIE *IMDie = DIE::get(DIEValueAllocator, (dwarf::Tag)Module->getTag()); - insertDIE(Module, IMDie); + + assert(!getDIE(Module)); + + DIE *IMDie = createDIE(Module->getTag(), Module); DIE *EntityDie; auto *Entity = resolve(Module->getEntity()); if (auto *NS = dyn_cast<DINamespace>(Entity)) @@ -679,22 +707,46 @@ DIE *DwarfCompileUnit::constructImportedEntityDIE( } void DwarfCompileUnit::finishSubprogramDefinition(const DISubprogram *SP) { - DIE *D = getDIE(SP); - if (DIE *AbsSPDIE = DU->getAbstractSPDies().lookup(SP)) { - if (D) + if (DIE *D = getDIE(SP)) { + if (DIE *AbsSPDIE = DU->getAbstractSPDies().lookup(SP)) // If this subprogram has an abstract definition, reference that addDIEEntry(*D, dwarf::DW_AT_abstract_origin, *AbsSPDIE); - } else { - if (!D && !includeMinimalInlineScopes()) - // Lazily construct the subprogram if we didn't see either concrete or - // inlined versions during codegen. (except in -gmlt ^ where we want - // to omit these entirely) - D = getOrCreateSubprogramDIE(SP); - if (D) + else // And attach the attributes applySubprogramAttributesToDefinition(SP, *D); } } + +void DwarfCompileUnit::finishLocalScopeDefinitions() { + for (const auto &I : getLSDieInfoMap()) { + auto LSInfo = I.second; + // Attach all local dcl DIEs to abstract local scope if available, + // otherwise attach it to concrete local scope. + DIE *LBDie = + LSInfo.AbstractLSDie ? LSInfo.AbstractLSDie : LSInfo.ConcreteLSDie; + assert(LBDie || LSInfo.LocalDclDies.empty()); + for (auto &D : LSInfo.LocalDclDies) + LBDie->addChild(std::move(D)); + + if (isa<DISubprogram>(I.first)) + // For function scope there is nothing else to do. + // "abstract_origin" dwarf attribute was added somewhere else. + continue; + + if (LSInfo.AbstractLSDie) { + // Add "abstract_origin" dwarf attribute to concrete local scope pointing + // to the corresponding abstract local scope. + if (LSInfo.ConcreteLSDie) + addDIEEntry(*LSInfo.ConcreteLSDie, dwarf::DW_AT_abstract_origin, + *LSInfo.AbstractLSDie); + // Add "abstract_origin" dwarf attribute to inline local scope pointing + // to the corresponding abstract local scope. + for (auto &L : LSInfo.InlineLSDies) + addDIEEntry(*L, dwarf::DW_AT_abstract_origin, *LSInfo.AbstractLSDie); + } + } +} + void DwarfCompileUnit::collectDeadVariables(const DISubprogram *SP) { assert(SP && "CU's subprogram list contains a non-subprogram"); assert(SP->isDefinition() && @@ -705,7 +757,7 @@ void DwarfCompileUnit::collectDeadVariables(const DISubprogram *SP) { DIE *SPDIE = DU->getAbstractSPDies().lookup(SP); if (!SPDIE) - SPDIE = getDIE(SP); + return; assert(SPDIE); for (const DILocalVariable *DV : Variables) { DbgVariable NewVar(DV, /* IA */ nullptr, DD); @@ -830,6 +882,34 @@ void DwarfCompileUnit::applySubprogramAttributesToDefinition( addGlobalName(SP->getName(), SPDie, Context); } +void DwarfCompileUnit::addLocalScopeDieToLexicalScope(LexicalScope *LS, + DIE *D) { + const DILocalScope *Scope = LS->getScopeNode(); + assert(!isa<DILexicalBlockFile>(Scope) && "Don't expect Lexical Block File!"); + auto &LSInfo = getLSDieInfoMap()[Scope]; + if (LS->isAbstractScope()) { + assert(!LSInfo.AbstractLSDie && "Adding abstract LS DIE twice."); + LSInfo.AbstractLSDie = D; + return; + } + if (LS->getInlinedAt()) { + assert(!LSInfo.InlineLSDies.count(D) && "Adding inline LS DIE twice."); + LSInfo.InlineLSDies.insert(D); + return; + } + assert(!LSInfo.ConcreteLSDie && "Adding cocncrete LS DIE twice."); + LSInfo.ConcreteLSDie = D; + return; +} + +void DwarfCompileUnit::addLocalDclDieToLexicalScope(LexicalScope *LS, DIE *D) { + const DILocalScope *Scope = LS->getScopeNode(); + assert(!isa<DILexicalBlockFile>(Scope) && "Don't expect Lexical Block File!"); + auto &LSInfo = getLSDieInfoMap()[Scope]; + LSInfo.LocalDclDies.insert(D); + return; +} + bool DwarfCompileUnit::isDwoUnit() const { return DD->useSplitDwarf() && Skeleton; } diff --git a/llvm/lib/CodeGen/AsmPrinter/DwarfCompileUnit.h b/llvm/lib/CodeGen/AsmPrinter/DwarfCompileUnit.h index bacf87d95c4..b47cbae5b22 100644 --- a/llvm/lib/CodeGen/AsmPrinter/DwarfCompileUnit.h +++ b/llvm/lib/CodeGen/AsmPrinter/DwarfCompileUnit.h @@ -15,6 +15,7 @@ #define LLVM_LIB_CODEGEN_ASMPRINTER_DWARFCOMPILEUNIT_H #include "DwarfUnit.h" +#include "llvm/ADT/SetVector.h" #include "llvm/ADT/StringRef.h" #include "llvm/IR/DebugInfo.h" #include "llvm/Support/Dwarf.h" @@ -48,11 +49,10 @@ class DwarfCompileUnit : public DwarfUnit { /// The start of the unit macro info within macro section. MCSymbol *MacroLabelBegin; - typedef llvm::SmallVector<const MDNode *, 8> ImportedEntityList; - typedef llvm::DenseMap<const MDNode *, ImportedEntityList> - ImportedEntityMap; + typedef llvm::SmallVector<const MDNode *, 8> LocalDeclNodeList; + typedef llvm::DenseMap<const MDNode *, LocalDeclNodeList> LocalScopesMap; - ImportedEntityMap ImportedEntities; + LocalScopesMap LocalDeclNodes; /// GlobalNames - A map of globally visible named entities for this unit. StringMap<const DIE *> GlobalNames; @@ -71,6 +71,15 @@ class DwarfCompileUnit : public DwarfUnit { // ranges/locs. const MCSymbol *BaseAddress; + struct LocalScopeDieInfo { + DIE *ConcreteLSDie = nullptr; + DIE *AbstractLSDie = nullptr; + SetVector<DIE *> InlineLSDies; + SetVector<DIE *> LocalDclDies; + }; + // Collection of local scope DIE info. + DenseMap<const MDNode *, LocalScopeDieInfo> LocalScopeDieInfoMap; + /// \brief Construct a DIE for the given DbgVariable without initializing the /// DbgVariable's DIE reference. DIE *constructVariableDIEImpl(const DbgVariable &DV, bool Abstract); @@ -117,8 +126,16 @@ public: unsigned getOrCreateSourceID(StringRef FileName, StringRef DirName) override; - void addImportedEntity(const DIImportedEntity* IE) { - ImportedEntities[IE->getScope()].push_back(IE); + void addLocalDeclNode(const DINode *DI, DILocalScope *Scope) { + // LocalDeclNodes maps local declaration DIEs to their parent DILocalScope. + // These local declaration entities will be processed when processing the + // lexical scopes collected by LexicalScopes component. + // DILexicalBlockFile is skipped by LexicalScopes and it collect its parent, + // which is of a DILexicalBlock. Thus, LocalDeclNodes must not map to + // DILexicalBlockFile but to its parent DILexicalBlock. + if (auto *File = dyn_cast<DILexicalBlockFile>(Scope)) + Scope = File->getScope(); + LocalDeclNodes[Scope].push_back(DI); } /// addRange - Add an address range to the list of ranges for this unit. @@ -166,7 +183,7 @@ public: /// A helper function to create children of a Scope DIE. DIE *createScopeChildrenDIE(LexicalScope *Scope, SmallVectorImpl<DIE *> &Children, - unsigned *ChildScopeCount = nullptr); + bool *HasNonScopeChildren = nullptr); /// \brief Construct a DIE for this subprogram scope. void constructSubprogramScopeDIE(LexicalScope *Scope); @@ -175,11 +192,15 @@ public: void constructAbstractSubprogramScopeDIE(LexicalScope *Scope); + /// \brief Get or create import_module DIE. + DIE *getOrCreateImportedEntityDIE(const DIImportedEntity *Module); /// \brief Construct import_module DIE. DIE *constructImportedEntityDIE(const DIImportedEntity *Module); void finishSubprogramDefinition(const DISubprogram *SP); + void finishLocalScopeDefinitions(); + void collectDeadVariables(const DISubprogram *SP); /// Set the skeleton unit associated with this unit. @@ -253,6 +274,15 @@ public: void setBaseAddress(const MCSymbol *Base) { BaseAddress = Base; } const MCSymbol *getBaseAddress() const { return BaseAddress; } + + DenseMap<const MDNode *, LocalScopeDieInfo> &getLSDieInfoMap() { + return LocalScopeDieInfoMap; + } + + /// Add local scope DIE entry to lexical scope info. + void addLocalScopeDieToLexicalScope(LexicalScope *LS, DIE *D); + /// Add local declaration DIE entry to lexical scope info. + void addLocalDclDieToLexicalScope(LexicalScope *LS, DIE *D); }; } // end llvm namespace diff --git a/llvm/lib/CodeGen/AsmPrinter/DwarfDebug.cpp b/llvm/lib/CodeGen/AsmPrinter/DwarfDebug.cpp index d4d94cabe83..589f88d1de6 100644 --- a/llvm/lib/CodeGen/AsmPrinter/DwarfDebug.cpp +++ b/llvm/lib/CodeGen/AsmPrinter/DwarfDebug.cpp @@ -455,6 +455,16 @@ void DwarfDebug::constructAndAddImportedEntityDIE(DwarfCompileUnit &TheCU, D->addChild(TheCU.constructImportedEntityDIE(N)); } +bool DwarfDebug::collectLocalScopedNode(DIScope *S, const DINode *N, + DwarfCompileUnit &CU) { + if (auto LS = dyn_cast_or_null<DILocalScope>(S)) { + getLocalScopes(LS->getSubprogram()).insert(LS); + CU.addLocalDeclNode(N, LS); + return true; + } + return false; +} + // Emit all Dwarf sections that should come prior to the content. Create // global DIEs and emit initial debug info sections. This is invoked by // the target AsmPrinter. @@ -474,10 +484,9 @@ void DwarfDebug::beginModule() { for (MDNode *N : CU_Nodes->operands()) { auto *CUNode = cast<DICompileUnit>(N); DwarfCompileUnit &CU = constructDwarfCompileUnit(CUNode); - for (auto *IE : CUNode->getImportedEntities()) - CU.addImportedEntity(IE); for (auto *GV : CUNode->getGlobalVariables()) - CU.getOrCreateGlobalVariableDIE(GV); + if (!collectLocalScopedNode(GV->getScope(), GV, CU)) + CU.getOrCreateGlobalVariableDIE(GV); for (auto *SP : CUNode->getSubprograms()) SPMap.insert(std::make_pair(SP, &CU)); for (auto *Ty : CUNode->getEnumTypes()) { @@ -489,14 +498,17 @@ void DwarfDebug::beginModule() { // The retained types array by design contains pointers to // MDNodes rather than DIRefs. Unique them here. DIType *RT = cast<DIType>(resolve(Ty->getRef())); - if (!RT->isExternalTypeRef()) + if (RT->isExternalTypeRef()) // There is no point in force-emitting a forward declaration. + continue; + if (!collectLocalScopedNode(resolve(Ty->getScope()), RT, CU)) CU.getOrCreateTypeDIE(RT); } // Emit imported_modules last so that the relevant context is already // available. for (auto *IE : CUNode->getImportedEntities()) - constructAndAddImportedEntityDIE(CU, IE); + if (!collectLocalScopedNode(IE->getScope(), IE, CU)) + constructAndAddImportedEntityDIE(CU, IE); } // Tell MMI that we have debug info. @@ -529,6 +541,11 @@ void DwarfDebug::finishSubprogramDefinitions() { }); } +void DwarfDebug::finishLocalScopeDefinitions() { + for (const auto &I : CUMap) + I.second->finishLocalScopeDefinitions(); +} + // Collect info for variables that were optimized out. void DwarfDebug::collectDeadVariables() { const Module *M = MMI->getModule(); @@ -554,6 +571,8 @@ void DwarfDebug::finalizeModuleInfo() { finishSubprogramDefinitions(); + finishLocalScopeDefinitions(); + finishVariableDefinitions(); // Collect info for variables that were optimized out. @@ -1164,6 +1183,9 @@ void DwarfDebug::endFunction(const MachineFunction *MF) { assert(LScopes.getAbstractScopesList().size() == NumAbstractScopes && "ensureAbstractVariableIsCreated inserted abstract scopes"); } + // Assure abstract local scope created for each one contains local DIEs. + for (const DILocalScope *LS : getLocalScopes(SP)) + LScopes.getOrCreateAbstractScope(LS); constructAbstractSubprogramScopeDIE(AScope); } diff --git a/llvm/lib/CodeGen/AsmPrinter/DwarfDebug.h b/llvm/lib/CodeGen/AsmPrinter/DwarfDebug.h index f0859ec1a8f..253fa182cd0 100644 --- a/llvm/lib/CodeGen/AsmPrinter/DwarfDebug.h +++ b/llvm/lib/CodeGen/AsmPrinter/DwarfDebug.h @@ -211,6 +211,10 @@ class DwarfDebug : public DebugHandlerBase { /// Size of each symbol emitted (for those symbols that have a specific size). DenseMap<const MCSymbol *, uint64_t> SymSize; + /// Holder for scopes containing local declaration DI nodes per DI function. + DenseMap<const DISubprogram *, SmallPtrSet<const DILocalScope *, 16>> + LocalScopesMap; + /// Collection of abstract variables. DenseMap<const MDNode *, std::unique_ptr<DbgVariable>> AbstractVariables; SmallVector<std::unique_ptr<DbgVariable>, 64> ConcreteVariables; @@ -327,6 +331,8 @@ class DwarfDebug : public DebugHandlerBase { void finishSubprogramDefinitions(); + void finishLocalScopeDefinitions(); + /// Finish off debug information after all functions have been /// processed. void finalizeModuleInfo(); @@ -425,6 +431,11 @@ class DwarfDebug : public DebugHandlerBase { void constructAndAddImportedEntityDIE(DwarfCompileUnit &TheCU, const DIImportedEntity *N); + /// Collect MD Node located within local scope node. + /// Return true if node was collected, false otherwise. + bool collectLocalScopedNode(DIScope *S, const DINode *N, + DwarfCompileUnit &CU); + /// Register a source line with debug info. Returns the unique /// label that was emitted and which provides correspondence to the /// source line list. @@ -567,6 +578,12 @@ public: SmallPtrSet<const MDNode *, 16> &getProcessedSPNodes() { return ProcessedSPNodes; } + + /// Return collection of function scopes that contains local declararion DIEs. + SmallPtrSet<const DILocalScope *, 16> & + getLocalScopes(const DISubprogram *SP) { + return LocalScopesMap[SP]; + } }; } // End of namespace llvm diff --git a/llvm/lib/CodeGen/AsmPrinter/DwarfUnit.cpp b/llvm/lib/CodeGen/AsmPrinter/DwarfUnit.cpp index 387921cb46f..b2fe3c04a25 100644 --- a/llvm/lib/CodeGen/AsmPrinter/DwarfUnit.cpp +++ b/llvm/lib/CodeGen/AsmPrinter/DwarfUnit.cpp @@ -298,10 +298,15 @@ void DwarfUnit::addDIEEntry(DIE &Die, dwarf::Attribute Attribute, Entry); } -DIE &DwarfUnit::createAndAddDIE(unsigned Tag, DIE &Parent, const DINode *N) { - DIE &Die = Parent.addChild(DIE::get(DIEValueAllocator, (dwarf::Tag)Tag)); +DIE *DwarfUnit::createDIE(unsigned Tag, const DINode *N) { + DIE *Die = DIE::get(DIEValueAllocator, (dwarf::Tag)Tag); if (N) - insertDIE(N, &Die); + insertDIE(N, Die); + return Die; +} + +DIE &DwarfUnit::createAndAddDIE(unsigned Tag, DIE &Parent, const DINode *N) { + DIE &Die = Parent.addChild(createDIE(Tag, N)); return Die; } @@ -727,15 +732,18 @@ DIE *DwarfUnit::getOrCreateTypeDIE(const MDNode *TyNode) { // Construct the context before querying for the existence of the DIE in case // such construction creates the DIE. + // For Local Scope, do not construct context DIE. auto *Context = resolve(Ty->getScope()); - DIE *ContextDIE = getOrCreateContextDIE(Context); - assert(ContextDIE); + bool IsLocalScope = Context && isa<DILocalScope>(Context); + DIE *ContextDIE = IsLocalScope ? nullptr : getOrCreateContextDIE(Context); + assert(ContextDIE || IsLocalScope); if (DIE *TyDIE = getDIE(Ty)) return TyDIE; - // Create new type. - DIE &TyDIE = createAndAddDIE(Ty->getTag(), *ContextDIE, Ty); + // Create new type and add to map. + DIE &TyDIE = IsLocalScope ? *createDIE(Ty->getTag(), Ty) + : createAndAddDIE(Ty->getTag(), *ContextDIE, Ty); updateAcceleratorTables(Context, Ty, TyDIE); diff --git a/llvm/lib/CodeGen/AsmPrinter/DwarfUnit.h b/llvm/lib/CodeGen/AsmPrinter/DwarfUnit.h index a79add630b3..a72e5a3ef51 100644 --- a/llvm/lib/CodeGen/AsmPrinter/DwarfUnit.h +++ b/llvm/lib/CodeGen/AsmPrinter/DwarfUnit.h @@ -298,6 +298,9 @@ public: /// Construct function argument DIEs. void constructSubprogramArguments(DIE &Buffer, DITypeRefArray Args); + /// Create a DIE with the given Tag, and call insertDIE if MD is not null. + DIE *createDIE(unsigned Tag, const DINode *N = nullptr); + /// Create a DIE with the given Tag, add the DIE to its parent, and /// call insertDIE if MD is not null. DIE &createAndAddDIE(unsigned Tag, DIE &Parent, const DINode *N = nullptr); |