[llvm] [DwarfDebug] Track abstract entities in DwarfUnit separately (PR #152680)
Vladislav Dzhidzhoev via llvm-commits
llvm-commits at lists.llvm.org
Sat Oct 11 01:53:45 PDT 2025
================
@@ -53,6 +53,137 @@ struct RangeSpanList {
SmallVector<RangeSpan, 2> Ranges;
};
+/// Tracks abstract and concrete DIEs for debug info entities of a certain type.
+template <typename DINodeT, typename DbgEntityT> class DINodeInfoHolder {
+public:
+ using AbstractMapT = DenseMap<const DINodeT *, DIE *>;
+ using ConcreteMapT =
+ DenseMap<const DINodeT *, SmallDenseMap<const DbgEntityT *, DIE *, 2>>;
+
+private:
+ AbstractMapT AbstractMap;
+ ConcreteMapT ConcreteMap;
+
+public:
+ void insertAbstractDIE(const DINodeT *N, DIE *D) {
+ auto [_, Inserted] = AbstractMap.try_emplace(N, D);
+ assert(Inserted && "Duplicate abstract DIE for debug info node");
+ }
+
+ void insertConcreteDIE(const DINodeT *N, const DbgEntityT *E, DIE *D) {
+ auto [_, Inserted] = ConcreteMap[N].try_emplace(E, D);
+ assert(Inserted && "Duplicate concrete DIE for debug info node");
+ }
+
+ void insertDIE(const DINodeT *N, const DbgEntityT *E, DIE *D, bool Abstract) {
+ if (Abstract)
+ insertAbstractDIE(N, D);
+ else
+ insertConcreteDIE(N, E, D);
+ }
+
+ DIE *getAbstractDIE(const DINodeT *N) const { return AbstractMap.lookup(N); }
+
+ std::optional<
+ std::reference_wrapper<const typename ConcreteMapT::mapped_type>>
+ getConcreteDIEs(const DINodeT *N) const {
+ if (auto I = ConcreteMap.find(N); I != ConcreteMap.end())
+ return std::make_optional(std::ref(I->second));
+ return std::nullopt;
+ }
+
+ DIE *getConcreteDIE(const DINodeT *N, const DbgEntityT *E) const {
+ if (auto I = getConcreteDIEs(N))
+ return I->get().lookup(E);
+ return nullptr;
+ }
+
+ DIE *getAnyConcreteDIE(const DINodeT *N) const {
+ if (auto I = getConcreteDIEs(N))
+ return I->get().empty() ? nullptr : I->get().begin()->second;
+ return nullptr;
+ }
+
+ /// Returns abstract DIE for the entity.
+ /// If no abstract DIE was created, returns any concrete DIE for the entity.
+ DIE *getDIE(const DINodeT *N) const {
+ if (DIE *D = getAbstractDIE(N))
+ return D;
+
+ return getAnyConcreteDIE(N);
+ }
+
+ AbstractMapT &getAbstractDIEs() { return AbstractMap; }
+};
+
+/// Tracks DIEs for debug info entites.
+/// These DIEs can be shared across CUs, that is why we keep the map here
+/// instead of in DwarfCompileUnit.
+class DwarfInfoHolder {
+ /// DIEs of local DbgVariables.
+ DINodeInfoHolder<DILocalVariable, DbgVariable> LVHolder;
+ /// DIEs of labels.
+ DINodeInfoHolder<DILabel, DbgLabel> LabelHolder;
+ DenseMap<const DINode *, std::unique_ptr<DbgEntity>> AbstractEntities;
+ // List of abstract local scopes (either DISubprogram or DILexicalBlock).
+ DenseMap<const DILocalScope *, DIE *> AbstractLocalScopeDIEs;
+ /// Keeps track of abstract subprograms to populate them only once.
+ // FIXME: merge creation and population of abstract scopes.
+ SmallPtrSet<const DISubprogram *, 8> FinalizedAbstractSubprograms;
+
+ /// Other DINodes with the corresponding DIEs.
+ DenseMap<const DINode *, DIE *> MDNodeToDieMap;
----------------
dzhidzhoev wrote:
Currently, we have fields, where the DINodes shared across CUs are stored:
* DwarfFile::DITypeNodeToDieMap (which can also serve as a container for DISubprograms, according to DwarfUnit::isShareableAcrossCUs logic)
* DwarfFile::AbstractLocalScopeDIEs
* DwarfFile::AbstractEntities
* DwarfFile::FinalizedAbstractSubprograms
And we have the corresponding fields in DwarfUnit/DwarfCompileUnit:
* DwarfUnit::MDNodeToDieMap
* DwarfCompileUnit::AbstractLocalScopeDIEs
* DwarfCompileUnit::AbstractEntities
* DwarfCompileUnit::FinalizedAbstractSubprograms
The first goal of DwarfInfoHolder is to put that fields inside one "container", and reuse that container when needed. DwarfUnit::InfoHolder will store CU-local (or type-unit-local) DIEs, DwarfFile::InfoHolder will store shareable DIEs.
> So this creates a union of the way we were tracking the node<>die map at the file level and the unit level - and then stores that union at both the file and the unit level?
So, an instance of DwarfInfoHolder holds either shareable or CU-local DIEs. It's not a union of them.
Second goal is to split the general DIE map into separate maps for DILocalVariables, DILabels, DILocalScopes (in the following two PRs), and for the rest of DINodes (mostly types), since, as I assume, we can get DILocalVariables/DILabels/DILocalScopes used in multiple llvm::Functions during LTO with DISubprogram uniquing, so DIEs for these nodes created in different Functions should be somehow distinguished. It's done with additional DbgEntityT pointer.
https://github.com/llvm/llvm-project/pull/152680
More information about the llvm-commits
mailing list