aboutsummaryrefslogtreecommitdiff
path: root/llvm/lib
diff options
context:
space:
mode:
Diffstat (limited to 'llvm/lib')
-rw-r--r--llvm/lib/Bitcode/Reader/MetadataLoader.cpp87
-rw-r--r--llvm/lib/CodeGen/AsmPrinter/DwarfCompileUnit.cpp60
-rw-r--r--llvm/lib/CodeGen/AsmPrinter/DwarfCompileUnit.h16
-rw-r--r--llvm/lib/CodeGen/AsmPrinter/DwarfDebug.cpp13
-rw-r--r--llvm/lib/IR/DIBuilder.cpp34
-rw-r--r--llvm/lib/IR/Verifier.cpp6
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);
}
}