From 3b449bd46a11a55a40cbc0016a99b202fa05248e Mon Sep 17 00:00:00 2001 From: Vladislav Dzhidzhoev Date: Tue, 18 Jul 2023 14:22:46 +0200 Subject: [DebugMetadata][DwarfDebug] Support function-local types in lexical block scopes (4/7) RFC https://discourse.llvm.org/t/rfc-dwarfdebug-fix-and-improve-handling-imported-entities-types-and-static-local-in-subprogram-and-lexical-block-scopes/68544 Similar to imported declarations, the patch tracks function-local types in DISubprogram's 'retainedNodes' field. DwarfDebug is adjusted in accordance with the aforementioned metadata change and provided a support of function-local types scoped within a lexical block. The patch assumes that DICompileUnit's 'enums field' no longer tracks local types and DwarfDebug would assert if any locally-scoped types get placed there. Reviewed By: jmmartinez Authored-by: Kristina Bessonova Differential Revision: https://reviews.llvm.org/D144006 --- llvm/lib/Bitcode/Reader/MetadataLoader.cpp | 111 ++++++++++++++++++++--------- 1 file changed, 78 insertions(+), 33 deletions(-) (limited to 'llvm/lib/Bitcode/Reader/MetadataLoader.cpp') diff --git a/llvm/lib/Bitcode/Reader/MetadataLoader.cpp b/llvm/lib/Bitcode/Reader/MetadataLoader.cpp index 1a4b55e..963bc6b 100644 --- a/llvm/lib/Bitcode/Reader/MetadataLoader.cpp +++ b/llvm/lib/Bitcode/Reader/MetadataLoader.cpp @@ -547,6 +547,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) { @@ -554,48 +556,66 @@ class MetadataLoader::MetadataLoaderImpl { if (!CU) continue; - if (CU->getRawImportedEntities()) { - // Collect a set of imported entities to be moved. - SetVector EntitiesToRemove; + SetVector MetadataToRemove; + // Collect imported entities to be moved. + if (CU->getRawImportedEntities()) for (Metadata *Op : CU->getImportedEntities()->operands()) { auto *IE = cast(Op); - if (dyn_cast_or_null(IE->getScope())) { - EntitiesToRemove.insert(IE); - } + if (dyn_cast_or_null(IE->getScope())) + MetadataToRemove.insert(IE); + } + // Collect enums to be moved. + if (CU->getRawEnumTypes()) + for (Metadata *Op : CU->getEnumTypes()->operands()) { + auto *Enum = cast(Op); + if (dyn_cast_or_null(Enum->getScope())) + MetadataToRemove.insert(Enum); } - if (!EntitiesToRemove.empty()) { - // Make a new list of CU's 'imports'. - SmallVector NewImports; - for (Metadata *Op : CU->getImportedEntities()->operands()) { - if (!EntitiesToRemove.contains(cast(Op))) { + if (!MetadataToRemove.empty()) { + // Make a new list of CU's 'imports'. + SmallVector 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> SPToEntities; - for (auto *I : EntitiesToRemove) { - auto *Entity = cast(I); - if (auto *SP = findEnclosingSubprogram( - cast(Entity->getScope()))) { - SPToEntities[SP].push_back(Entity); - } - } + // Make a new list of CU's 'enums'. + SmallVector 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> SPToEntities; + for (auto *I : MetadataToRemove) { + DILocalScope *Scope = nullptr; + if (auto *Entity = dyn_cast(I)) + Scope = cast(Entity->getScope()); + else if (auto *Enum = dyn_cast(I)) + Scope = cast(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 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 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)); } } } @@ -711,6 +731,29 @@ class MetadataLoader::MetadataLoaderImpl { upgradeCULocals(); } + void cloneLocalTypes() { + for (unsigned I = 0; I < MetadataList.size(); ++I) { + if (auto *SP = dyn_cast_or_null(MetadataList[I])) { + auto RetainedNodes = SP->getRetainedNodes(); + SmallVector MDs(RetainedNodes.begin(), RetainedNodes.end()); + bool HasChanged = false; + for (auto &N : MDs) + if (auto *T = dyn_cast(N)) + if (auto *LS = dyn_cast_or_null(T->getScope())) + if (auto *Parent = findEnclosingSubprogram(LS)) + if (Parent != SP) { + HasChanged = true; + auto NewT = T->clone(); + NewT->replaceOperandWith(1, SP); + N = MDNode::replaceWithUniqued(std::move(NewT)); + } + + if (HasChanged) + SP->replaceRetainedNodes(MDNode::get(Context, MDs)); + } + } + } + void callMDTypeCallback(Metadata **Val, unsigned TypeID); public: @@ -1086,6 +1129,7 @@ Error MetadataLoader::MetadataLoaderImpl::parseMetadata(bool ModuleLevel) { // placeholders, that we flush here. resolveForwardRefsAndPlaceholders(Placeholders); upgradeDebugInfo(ModuleLevel); + cloneLocalTypes(); // Return at the beginning of the block, since it is easy to skip it // entirely from there. Stream.ReadBlockEnd(); // Pop the abbrev block context. @@ -1117,6 +1161,7 @@ Error MetadataLoader::MetadataLoaderImpl::parseMetadata(bool ModuleLevel) { case BitstreamEntry::EndBlock: resolveForwardRefsAndPlaceholders(Placeholders); upgradeDebugInfo(ModuleLevel); + cloneLocalTypes(); return Error::success(); case BitstreamEntry::Record: // The interesting case. -- cgit v1.1