diff options
Diffstat (limited to 'llvm/lib')
-rw-r--r-- | llvm/lib/Bitcode/Reader/MetadataLoader.cpp | 87 | ||||
-rw-r--r-- | llvm/lib/CodeGen/AsmPrinter/DwarfCompileUnit.cpp | 60 | ||||
-rw-r--r-- | llvm/lib/CodeGen/AsmPrinter/DwarfCompileUnit.h | 16 | ||||
-rw-r--r-- | llvm/lib/CodeGen/AsmPrinter/DwarfDebug.cpp | 13 | ||||
-rw-r--r-- | llvm/lib/IR/DIBuilder.cpp | 34 | ||||
-rw-r--r-- | llvm/lib/IR/Verifier.cpp | 6 |
6 files changed, 142 insertions, 74 deletions
diff --git a/llvm/lib/Bitcode/Reader/MetadataLoader.cpp b/llvm/lib/Bitcode/Reader/MetadataLoader.cpp index 0a9a806..321eae6 100644 --- a/llvm/lib/Bitcode/Reader/MetadataLoader.cpp +++ b/llvm/lib/Bitcode/Reader/MetadataLoader.cpp @@ -548,6 +548,8 @@ class MetadataLoader::MetadataLoaderImpl { /// Move local imports from DICompileUnit's 'imports' field to /// DISubprogram's retainedNodes. + /// Move fucntion-local enums from DICompileUnit's enums + /// to DISubprogram's retainedNodes. void upgradeCULocals() { if (NamedMDNode *CUNodes = TheModule.getNamedMetadata("llvm.dbg.cu")) { for (unsigned I = 0, E = CUNodes->getNumOperands(); I != E; ++I) { @@ -555,48 +557,71 @@ class MetadataLoader::MetadataLoaderImpl { if (!CU) continue; - if (auto *RawImported = CU->getRawImportedEntities()) { - // Collect a set of imported entities to be moved. - SetVector<Metadata *> EntitiesToRemove; + SetVector<Metadata *> MetadataToRemove; + // Collect imported entities to be moved. + if (CU->getRawImportedEntities()) { for (Metadata *Op : CU->getImportedEntities()->operands()) { auto *IE = cast<DIImportedEntity>(Op); - if (auto *S = dyn_cast_or_null<DILocalScope>(IE->getScope())) { - EntitiesToRemove.insert(IE); + if (dyn_cast_or_null<DILocalScope>(IE->getScope())) { + MetadataToRemove.insert(IE); } } + } + // Collect enums to be moved. + if (CU->getRawEnumTypes()) { + for (Metadata *Op : CU->getEnumTypes()->operands()) { + auto *Enum = cast<DICompositeType>(Op); + if (dyn_cast_or_null<DILocalScope>(Enum->getScope())) { + MetadataToRemove.insert(Enum); + } + } + } - if (!EntitiesToRemove.empty()) { - // Make a new list of CU's 'imports'. - SmallVector<Metadata *> NewImports; - for (Metadata *Op : CU->getImportedEntities()->operands()) { - if (!EntitiesToRemove.contains(cast<DIImportedEntity>(Op))) { + if (!MetadataToRemove.empty()) { + // Make a new list of CU's 'imports'. + SmallVector<Metadata *> NewImports; + if (CU->getRawImportedEntities()) + for (Metadata *Op : CU->getImportedEntities()->operands()) + if (!MetadataToRemove.contains(Op)) NewImports.push_back(Op); - } - } - // Find DISubprogram corresponding to each entity. - std::map<DISubprogram *, SmallVector<Metadata *>> SPToEntities; - for (auto *I : EntitiesToRemove) { - auto *Entity = cast<DIImportedEntity>(I); - if (auto *SP = findEnclosingSubprogram( - cast<DILocalScope>(Entity->getScope()))) { - SPToEntities[SP].push_back(Entity); - } + // Make a new list of CU's 'enums'. + SmallVector<Metadata *> NewEnums; + if (CU->getRawEnumTypes()) + for (Metadata *Op : CU->getEnumTypes()->operands()) + if (!MetadataToRemove.contains(Op)) + NewEnums.push_back(Op); + + // Find DISubprogram corresponding to each entity. + std::map<DISubprogram *, SmallVector<Metadata *>> SPToEntities; + for (auto *I : MetadataToRemove) { + DILocalScope *Scope = nullptr; + if (auto *Entity = dyn_cast<DIImportedEntity>(I)) + Scope = cast<DILocalScope>(Entity->getScope()); + else if (auto *Enum = dyn_cast<DICompositeType>(I)) + Scope = cast<DILocalScope>(Enum->getScope()); + + if (auto *SP = findEnclosingSubprogram(Scope)) { + SPToEntities[SP].push_back(I); } + } - // Update DISubprograms' retainedNodes. - for (auto I = SPToEntities.begin(); I != SPToEntities.end(); ++I) { - auto *SP = I->first; - auto RetainedNodes = SP->getRetainedNodes(); - SmallVector<Metadata *> MDs(RetainedNodes.begin(), - RetainedNodes.end()); - MDs.append(I->second); - SP->replaceRetainedNodes(MDNode::get(Context, MDs)); - } + // Update DISubprograms' retainedNodes. + for (auto I = SPToEntities.begin(); I != SPToEntities.end(); ++I) { + auto *SP = I->first; + auto RetainedNodes = SP->getRetainedNodes(); + SmallVector<Metadata *> MDs(RetainedNodes.begin(), + RetainedNodes.end()); + MDs.append(I->second); + SP->replaceRetainedNodes(MDNode::get(Context, MDs)); + } - // Remove entities with local scope from CU. + // Remove entities with local scope from CU. + if (CU->getRawImportedEntities()) CU->replaceImportedEntities(MDTuple::get(Context, NewImports)); - } + // Remove enums with local scope from CU. + if (CU->getRawEnumTypes()) + CU->replaceEnumTypes(MDTuple::get(Context, NewEnums)); } } } diff --git a/llvm/lib/CodeGen/AsmPrinter/DwarfCompileUnit.cpp b/llvm/lib/CodeGen/AsmPrinter/DwarfCompileUnit.cpp index 58ed213..bf8bdbb 100644 --- a/llvm/lib/CodeGen/AsmPrinter/DwarfCompileUnit.cpp +++ b/llvm/lib/CodeGen/AsmPrinter/DwarfCompileUnit.cpp @@ -598,10 +598,9 @@ void DwarfCompileUnit::constructScopeDIE(LexicalScope *Scope, return; // Emit lexical blocks. - DIE *ScopeDIE = constructLexicalScopeDIE(Scope); + DIE *ScopeDIE = getOrCreateLexicalBlockDIE(Scope, ParentScopeDIE); assert(ScopeDIE && "Scope DIE should not be null."); - ParentScopeDIE.addChild(ScopeDIE); createAndAddScopeChildren(Scope, *ScopeDIE); } @@ -721,24 +720,39 @@ DIE *DwarfCompileUnit::constructInlinedScopeDIE(LexicalScope *Scope, return ScopeDIE; } -// Construct new DW_TAG_lexical_block for this scope and attach -// DW_AT_low_pc/DW_AT_high_pc labels. -DIE *DwarfCompileUnit::constructLexicalScopeDIE(LexicalScope *Scope) { +DIE *DwarfCompileUnit::getOrCreateLexicalBlockDIE(LexicalScope *Scope, + DIE &ParentScopeDIE) { if (DD->isLexicalScopeDIENull(Scope)) return nullptr; const auto *DS = Scope->getScopeNode(); - - auto ScopeDIE = DIE::get(DIEValueAllocator, dwarf::DW_TAG_lexical_block); - if (Scope->isAbstractScope()) { - assert(!getAbstractScopeDIEs().count(DS) && - "Abstract DIE for this scope exists!"); - getAbstractScopeDIEs()[DS] = ScopeDIE; - return ScopeDIE; + DIE *ScopeDIE = nullptr; + + // FIXME: We may have a concrete DIE for this scope already created. + // This may happen when we emit local variables for an abstract tree of + // an inlined function: if a local variable has a templated type with + // a function-local type as a template parameter. See PR55680 for details + // (see also llvm/test/DebugInfo/Generic/local-type-as-template-parameter.ll). + if (!Scope->isAbstractScope() && !Scope->getInlinedAt()) { + if (auto It = LexicalBlockDIEs.find(DS); It != LexicalBlockDIEs.end()) { + ScopeDIE = It->second; + assert(!ScopeDIE->findAttribute(dwarf::DW_AT_low_pc) && + !ScopeDIE->findAttribute(dwarf::DW_AT_ranges)); + assert(ScopeDIE->getParent() == &ParentScopeDIE); + } } - if (!Scope->getInlinedAt()) { - assert(!LexicalBlockDIEs.count(DS) && - "Concrete out-of-line DIE for this scope exists!"); - LexicalBlockDIEs[DS] = ScopeDIE; + if (!ScopeDIE) { + ScopeDIE = DIE::get(DIEValueAllocator, dwarf::DW_TAG_lexical_block); + ParentScopeDIE.addChild(ScopeDIE); + + if (Scope->isAbstractScope()) { + assert(!getAbstractScopeDIEs().count(DS) && + "Abstract DIE for this scope exists!"); + getAbstractScopeDIEs()[DS] = ScopeDIE; + return ScopeDIE; + } + + if (!Scope->getInlinedAt()) + LexicalBlockDIEs[DS] = ScopeDIE; } attachRangesOrLowHighPC(*ScopeDIE, Scope->getRanges()); @@ -1681,15 +1695,21 @@ void DwarfCompileUnit::createBaseTypeDIEs() { } } -DIE *DwarfCompileUnit::getLexicalBlockDIE(const DILexicalBlock *LB) { +DIE *DwarfCompileUnit::getLocalContextDIE(const DILexicalBlock *LB) { // Assume if there is an abstract tree all the DIEs are already emitted. bool isAbstract = getAbstractScopeDIEs().count(LB->getSubprogram()); if (isAbstract && getAbstractScopeDIEs().count(LB)) return getAbstractScopeDIEs()[LB]; assert(!isAbstract && "Missed lexical block DIE in abstract tree!"); - // Return a concrete DIE if it exists or nullptr otherwise. - return LexicalBlockDIEs.lookup(LB); + // Check if we have a concrete DIE. + if (auto It = LexicalBlockDIEs.find(LB); It != LexicalBlockDIEs.end()) + return It->second; + + // If nothing available found, we cannot just create a new lexical block, + // because it isn't known where to put it into the DIE tree. + // So, we may only try to find the most close avaiable parent DIE. + return getOrCreateContextDIE(LB->getScope()->getNonLexicalBlockFileScope()); } DIE *DwarfCompileUnit::getOrCreateContextDIE(const DIScope *Context) { @@ -1697,7 +1717,7 @@ DIE *DwarfCompileUnit::getOrCreateContextDIE(const DIScope *Context) { if (auto *LFScope = dyn_cast<DILexicalBlockFile>(Context)) Context = LFScope->getNonLexicalBlockFileScope(); if (auto *LScope = dyn_cast<DILexicalBlock>(Context)) - return getLexicalBlockDIE(LScope); + return getLocalContextDIE(LScope); // Otherwise the context must be a DISubprogram. auto *SPScope = cast<DISubprogram>(Context); diff --git a/llvm/lib/CodeGen/AsmPrinter/DwarfCompileUnit.h b/llvm/lib/CodeGen/AsmPrinter/DwarfCompileUnit.h index 6ef73eb..5662087 100644 --- a/llvm/lib/CodeGen/AsmPrinter/DwarfCompileUnit.h +++ b/llvm/lib/CodeGen/AsmPrinter/DwarfCompileUnit.h @@ -210,14 +210,9 @@ public: /// DIE to represent this concrete inlined copy of the function. DIE *constructInlinedScopeDIE(LexicalScope *Scope, DIE &ParentScopeDIE); - /// Construct new DW_TAG_lexical_block for this scope and - /// attach DW_AT_low_pc/DW_AT_high_pc labels. - DIE *constructLexicalScopeDIE(LexicalScope *Scope); - - /// Get a DIE for the given DILexicalBlock. - /// Note that this function assumes that the DIE has been already created - /// and it's an error, if it hasn't. - DIE *getLexicalBlockDIE(const DILexicalBlock *LB); + /// Get if available or create a new DW_TAG_lexical_block for the given + /// LexicalScope and attach DW_AT_low_pc/DW_AT_high_pc labels. + DIE *getOrCreateLexicalBlockDIE(LexicalScope *Scope, DIE &ParentDIE); /// constructVariableDIE - Construct a DIE for the given DbgVariable. DIE *constructVariableDIE(DbgVariable &DV, bool Abstract = false); @@ -234,6 +229,11 @@ public: /// This instance of 'getOrCreateContextDIE()' can handle DILocalScope. DIE *getOrCreateContextDIE(const DIScope *Ty) override; + /// Get DW_TAG_lexical_block for the given DILexicalBlock if available, + /// or the most close parent DIE, if no correspoding DW_TAG_lexical_block + /// exists. + DIE *getLocalContextDIE(const DILexicalBlock *LB); + /// Construct a DIE for this subprogram scope. DIE &constructSubprogramScopeDIE(const DISubprogram *Sub, LexicalScope *Scope); diff --git a/llvm/lib/CodeGen/AsmPrinter/DwarfDebug.cpp b/llvm/lib/CodeGen/AsmPrinter/DwarfDebug.cpp index b8502b4..557291c 100644 --- a/llvm/lib/CodeGen/AsmPrinter/DwarfDebug.cpp +++ b/llvm/lib/CodeGen/AsmPrinter/DwarfDebug.cpp @@ -1229,12 +1229,13 @@ void DwarfDebug::beginModule(Module *M) { CU.getOrCreateGlobalVariableDIE(GV, sortGlobalExprs(GVMap[GV])); } - for (auto *Ty : CUNode->getEnumTypes()) + for (auto *Ty : CUNode->getEnumTypes()) { + assert(!isa_and_nonnull<DILocalScope>(Ty->getScope()) && + "Unexpected function-local entity in 'enums' CU field."); CU.getOrCreateTypeDIE(cast<DIType>(Ty)); + } for (auto *Ty : CUNode->getRetainedTypes()) { - // The retained types array by design contains pointers to - // MDNodes rather than DIRefs. Unique them here. if (DIType *RT = dyn_cast<DIType>(Ty)) // There is no point in force-emitting a forward declaration. CU.getOrCreateTypeDIE(RT); @@ -1428,9 +1429,13 @@ void DwarfDebug::endModule() { "Unexpected function-local entity in 'imports' CU field."); CU->getOrCreateImportedEntityDIE(IE); } + + // Emit function-local entities. for (const auto *D : CU->getDeferredLocalDecls()) { if (auto *IE = dyn_cast<DIImportedEntity>(D)) CU->getOrCreateImportedEntityDIE(IE); + else if (auto *Ty = dyn_cast<DIType>(D)) + CU->getOrCreateTypeDIE(Ty); else llvm_unreachable("Unexpected local retained node!"); } @@ -1528,6 +1533,8 @@ static const DILocalScope *getRetainedNodeScope(const MDNode *N) { S = L->getScope(); else if (const auto *IE = dyn_cast<DIImportedEntity>(N)) S = IE->getScope(); + else if (const auto *T = dyn_cast<DIType>(N)) + S = T->getScope(); else llvm_unreachable("Unexpected retained node!"); diff --git a/llvm/lib/IR/DIBuilder.cpp b/llvm/lib/IR/DIBuilder.cpp index ae1a1a3..242ca44 100644 --- a/llvm/lib/IR/DIBuilder.cpp +++ b/llvm/lib/IR/DIBuilder.cpp @@ -29,7 +29,7 @@ DIBuilder::DIBuilder(Module &m, bool AllowUnresolvedNodes, DICompileUnit *CU) AllowUnresolvedNodes(AllowUnresolvedNodes) { if (CUNode) { if (const auto &ETs = CUNode->getEnumTypes()) - AllEnumTypes.assign(ETs.begin(), ETs.end()); + EnumTypes.assign(ETs.begin(), ETs.end()); if (const auto &RTs = CUNode->getRetainedTypes()) AllRetainTypes.assign(RTs.begin(), RTs.end()); if (const auto &GVs = CUNode->getGlobalVariables()) @@ -66,10 +66,10 @@ void DIBuilder::finalize() { return; } - if (!AllEnumTypes.empty()) + if (!EnumTypes.empty()) CUNode->replaceEnumTypes(MDTuple::get( - VMContext, SmallVector<Metadata *, 16>(AllEnumTypes.begin(), - AllEnumTypes.end()))); + VMContext, SmallVector<Metadata *, 16>(EnumTypes.begin(), + EnumTypes.end()))); SmallVector<Metadata *, 16> RetainValues; // Declarations and definitions of the same type may be retained. Some @@ -334,10 +334,13 @@ DIDerivedType *DIBuilder::createTypedef(DIType *Ty, StringRef Name, DIScope *Context, uint32_t AlignInBits, DINode::DIFlags Flags, DINodeArray Annotations) { - return DIDerivedType::get(VMContext, dwarf::DW_TAG_typedef, Name, File, - LineNo, getNonCompileUnitScope(Context), Ty, 0, - AlignInBits, 0, std::nullopt, Flags, nullptr, - Annotations); + auto *T = + DIDerivedType::get(VMContext, dwarf::DW_TAG_typedef, Name, File, LineNo, + getNonCompileUnitScope(Context), Ty, 0, AlignInBits, 0, + std::nullopt, Flags, nullptr, Annotations); + if (isa_and_nonnull<DILocalScope>(Context)) + getSubprogramNodesTrackingVector(Context).emplace_back(T); + return T; } DIDerivedType *DIBuilder::createFriend(DIType *Ty, DIType *FriendTy) { @@ -485,6 +488,8 @@ DICompositeType *DIBuilder::createClassType( OffsetInBits, Flags, Elements, 0, VTableHolder, cast_or_null<MDTuple>(TemplateParams), UniqueIdentifier); trackIfUnresolved(R); + if (isa_and_nonnull<DILocalScope>(Context)) + getSubprogramNodesTrackingVector(Context).emplace_back(R); return R; } @@ -498,6 +503,8 @@ DICompositeType *DIBuilder::createStructType( getNonCompileUnitScope(Context), DerivedFrom, SizeInBits, AlignInBits, 0, Flags, Elements, RunTimeLang, VTableHolder, nullptr, UniqueIdentifier); trackIfUnresolved(R); + if (isa_and_nonnull<DILocalScope>(Context)) + getSubprogramNodesTrackingVector(Context).emplace_back(R); return R; } @@ -510,6 +517,8 @@ DICompositeType *DIBuilder::createUnionType( getNonCompileUnitScope(Scope), nullptr, SizeInBits, AlignInBits, 0, Flags, Elements, RunTimeLang, nullptr, nullptr, UniqueIdentifier); trackIfUnresolved(R); + if (isa_and_nonnull<DILocalScope>(Scope)) + getSubprogramNodesTrackingVector(Scope).emplace_back(R); return R; } @@ -542,7 +551,10 @@ DICompositeType *DIBuilder::createEnumerationType( getNonCompileUnitScope(Scope), UnderlyingType, SizeInBits, AlignInBits, 0, IsScoped ? DINode::FlagEnumClass : DINode::FlagZero, Elements, 0, nullptr, nullptr, UniqueIdentifier); - AllEnumTypes.emplace_back(CTy); + if (isa_and_nonnull<DILocalScope>(Scope)) + getSubprogramNodesTrackingVector(Scope).emplace_back(CTy); + else + EnumTypes.emplace_back(CTy); trackIfUnresolved(CTy); return CTy; } @@ -640,6 +652,8 @@ DIBuilder::createForwardDecl(unsigned Tag, StringRef Name, DIScope *Scope, SizeInBits, AlignInBits, 0, DINode::FlagFwdDecl, nullptr, RuntimeLang, nullptr, nullptr, UniqueIdentifier); trackIfUnresolved(RetTy); + if (isa_and_nonnull<DILocalScope>(Scope)) + getSubprogramNodesTrackingVector(Scope).emplace_back(RetTy); return RetTy; } @@ -656,6 +670,8 @@ DICompositeType *DIBuilder::createReplaceableCompositeType( nullptr, Annotations) .release(); trackIfUnresolved(RetTy); + if (isa_and_nonnull<DILocalScope>(Scope)) + getSubprogramNodesTrackingVector(Scope).emplace_back(RetTy); return RetTy; } diff --git a/llvm/lib/IR/Verifier.cpp b/llvm/lib/IR/Verifier.cpp index 293d443..8f929dc 100644 --- a/llvm/lib/IR/Verifier.cpp +++ b/llvm/lib/IR/Verifier.cpp @@ -1384,9 +1384,9 @@ void Verifier::visitDISubprogram(const DISubprogram &N) { CheckDI(Node, "invalid retained nodes list", &N, RawNode); for (Metadata *Op : Node->operands()) { CheckDI(Op && (isa<DILocalVariable>(Op) || isa<DILabel>(Op) || - isa<DIImportedEntity>(Op)), - "invalid retained nodes, expected DILocalVariable, DILabel or " - "DIImportedEntity", + isa<DIImportedEntity>(Op) || isa<DIType>(Op)), + "invalid retained nodes, expected DILocalVariable, DILabel, " + "DIImportedEntity or DIType", &N, Node, Op); } } |