[llvm] [DwarfDebug] Track abstract entities in DwarfUnit separately (PR #152680)

David Blaikie via llvm-commits llvm-commits at lists.llvm.org
Fri Oct 10 22:08:00 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;
+
+public:
+  void insertDIE(const DINode *N, DIE *Die) {
+    assert((!isa<DILabel>(N) && !isa<DILocalVariable>(N)) &&
+           "Use getLabels().insertDIE() for labels or getLVs().insertDIE() for "
+           "local variables");
+    auto [_, Inserted] = MDNodeToDieMap.try_emplace(N, Die);
+    assert((Inserted || isa<DISubprogram>(N) || isa<DIType>(N)) &&
+           "DIE for this DINode has already been added");
+  }
+
+  void insertDIE(DIE *D) { MDNodeToDieMap.try_emplace(nullptr, D); }
+
+  DIE *getDIE(const DINode *N) const {
+    DIE *D = MDNodeToDieMap.lookup(N);
+    assert((!D || (!isa<DILabel>(N) && !isa<DILocalVariable>(N))) &&
+           "Use getLabels().getDIE() for labels or getLVs().getDIE() for "
+           "local variables");
+    return D;
+  }
+
+  auto &getLVs() { return LVHolder; }
+  auto &getLVs() const { return LVHolder; }
+
+  auto &getLabels() { return LabelHolder; }
+  auto &getLabels() const { return LabelHolder; }
----------------
dwblaikie wrote:

Probably worth spelling out the return types

https://github.com/llvm/llvm-project/pull/152680


More information about the llvm-commits mailing list