[llvm] [DebugInfo] Update DebugInfoFinder to take retainedNodes into account (PR #140285)

Vladislav Dzhidzhoev via llvm-commits llvm-commits at lists.llvm.org
Mon May 19 08:53:36 PDT 2025


https://github.com/dzhidzhoev updated https://github.com/llvm/llvm-project/pull/140285

>From dadd5eb79bec077c7169ed3b4da2276a1e04fa26 Mon Sep 17 00:00:00 2001
From: Vladislav Dzhidzhoev <vdzhidzhoev at accesssoftek.com>
Date: Fri, 16 May 2025 18:46:56 +0200
Subject: [PATCH 1/2] [DebugInfo] Update DebugInfoFinder to take retainedNodes
 into account

Since https://reviews.llvm.org/D144004, DISubprogram's retainedNodes
field is used to track DIImportedEntities, in addition to local
variables and labels.

However, the corresponding update for DebugInfoFinder, to make it visit
DISubprogram's retainedNodes, was missing.

This is the fix for it.

This change is separated from
https://github.com/llvm/llvm-project/pull/119001 to simplify it.
---
 llvm/include/llvm/IR/DebugInfo.h              |  3 +-
 llvm/lib/IR/DebugInfo.cpp                     | 35 ++++++++++-------
 .../Generic/debuginfofinder-retained-nodes.ll | 38 +++++++++++++++++++
 3 files changed, 62 insertions(+), 14 deletions(-)
 create mode 100644 llvm/test/DebugInfo/Generic/debuginfofinder-retained-nodes.ll

diff --git a/llvm/include/llvm/IR/DebugInfo.h b/llvm/include/llvm/IR/DebugInfo.h
index 73f45c3769be4..c47738a6442e6 100644
--- a/llvm/include/llvm/IR/DebugInfo.h
+++ b/llvm/include/llvm/IR/DebugInfo.h
@@ -110,7 +110,7 @@ class DebugInfoFinder {
   void processInstruction(const Module &M, const Instruction &I);
 
   /// Process a DILocalVariable.
-  void processVariable(const Module &M, const DILocalVariable *DVI);
+  void processVariable(DILocalVariable *DVI);
   /// Process debug info location.
   void processLocation(const Module &M, const DILocation *Loc);
   /// Process a DbgRecord (e.g, treat a DbgVariableRecord like a
@@ -127,6 +127,7 @@ class DebugInfoFinder {
   void processCompileUnit(DICompileUnit *CU);
   void processScope(DIScope *Scope);
   void processType(DIType *DT);
+  void processImportedEntity(DIImportedEntity *Import);
   bool addCompileUnit(DICompileUnit *CU);
   bool addGlobalVariable(DIGlobalVariableExpression *DIG);
   bool addScope(DIScope *Scope);
diff --git a/llvm/lib/IR/DebugInfo.cpp b/llvm/lib/IR/DebugInfo.cpp
index dff9a08c2c8e0..9abde9023d057 100644
--- a/llvm/lib/IR/DebugInfo.cpp
+++ b/llvm/lib/IR/DebugInfo.cpp
@@ -242,22 +242,14 @@ void DebugInfoFinder::processCompileUnit(DICompileUnit *CU) {
     else
       processSubprogram(cast<DISubprogram>(RT));
   for (auto *Import : CU->getImportedEntities()) {
-    auto *Entity = Import->getEntity();
-    if (auto *T = dyn_cast<DIType>(Entity))
-      processType(T);
-    else if (auto *SP = dyn_cast<DISubprogram>(Entity))
-      processSubprogram(SP);
-    else if (auto *NS = dyn_cast<DINamespace>(Entity))
-      processScope(NS->getScope());
-    else if (auto *M = dyn_cast<DIModule>(Entity))
-      processScope(M->getScope());
+    processImportedEntity(Import);
   }
 }
 
 void DebugInfoFinder::processInstruction(const Module &M,
                                          const Instruction &I) {
   if (auto *DVI = dyn_cast<DbgVariableIntrinsic>(&I))
-    processVariable(M, DVI->getVariable());
+    processVariable(DVI->getVariable());
 
   if (auto DbgLoc = I.getDebugLoc())
     processLocation(M, DbgLoc.get());
@@ -275,7 +267,7 @@ void DebugInfoFinder::processLocation(const Module &M, const DILocation *Loc) {
 
 void DebugInfoFinder::processDbgRecord(const Module &M, const DbgRecord &DR) {
   if (const DbgVariableRecord *DVR = dyn_cast<const DbgVariableRecord>(&DR))
-    processVariable(M, DVR->getVariable());
+    processVariable(DVR->getVariable());
   processLocation(M, DR.getDebugLoc().get());
 }
 
@@ -303,6 +295,18 @@ void DebugInfoFinder::processType(DIType *DT) {
   }
 }
 
+void DebugInfoFinder::processImportedEntity(DIImportedEntity *Import) {
+  auto *Entity = Import->getEntity();
+  if (auto *T = dyn_cast<DIType>(Entity))
+    processType(T);
+  else if (auto *SP = dyn_cast<DISubprogram>(Entity))
+    processSubprogram(SP);
+  else if (auto *NS = dyn_cast<DINamespace>(Entity))
+    processScope(NS->getScope());
+  else if (auto *M = dyn_cast<DIModule>(Entity))
+    processScope(M->getScope());
+}
+
 void DebugInfoFinder::processScope(DIScope *Scope) {
   if (!Scope)
     return;
@@ -350,10 +354,15 @@ void DebugInfoFinder::processSubprogram(DISubprogram *SP) {
       processType(TVal->getType());
     }
   }
+
+  for (auto *N : SP->getRetainedNodes())
+    if (auto *Var = dyn_cast_or_null<DILocalVariable>(N))
+      processVariable(Var);
+    else if (auto *Import = dyn_cast_or_null<DIImportedEntity>(N))
+      processImportedEntity(Import);
 }
 
-void DebugInfoFinder::processVariable(const Module &M,
-                                      const DILocalVariable *DV) {
+void DebugInfoFinder::processVariable(DILocalVariable *DV) {
   if (!NodesSeen.insert(DV).second)
     return;
   processScope(DV->getScope());
diff --git a/llvm/test/DebugInfo/Generic/debuginfofinder-retained-nodes.ll b/llvm/test/DebugInfo/Generic/debuginfofinder-retained-nodes.ll
new file mode 100644
index 0000000000000..f8185c65639d6
--- /dev/null
+++ b/llvm/test/DebugInfo/Generic/debuginfofinder-retained-nodes.ll
@@ -0,0 +1,38 @@
+; RUN: opt -passes='print<module-debuginfo>' -disable-output 2>&1 < %s \
+; RUN:   | FileCheck %s
+
+; This is to track DebugInfoFinder's ability to find the debug info metadata,
+; in particular, properly visit DISubprogram's retainedNodes.
+
+; CHECK: Compile unit: DW_LANG_C_plus_plus from /somewhere/source.cpp
+; CHECK: Subprogram: foo from /somewhere/source.cpp:1 ('_Z3foov')
+; CHECK: Subprogram: bar from /somewhere/source.cpp:5
+; CHECK: Type: T from /somewhere/source.cpp:2 DW_TAG_structure_type
+
+%struct.T = type { i32 }
+
+; Function Attrs: mustprogress noinline nounwind optnone ssp uwtable(sync)
+define noundef i32 @_Z3foov() !dbg !7 {
+entry:
+  ret i32 0
+}
+
+!llvm.dbg.cu = !{!0}
+!llvm.module.flags = !{!2, !3, !4, !5}
+!llvm.ident = !{!6}
+
+!0 = distinct !DICompileUnit(language: DW_LANG_C_plus_plus, file: !1, producer: "clang version 21.0.0git", isOptimized: false, runtimeVersion: 0, emissionKind: FullDebug)
+!1 = !DIFile(filename: "source.cpp", directory: "/somewhere")
+!2 = !{i32 7, !"Dwarf Version", i32 5}
+!3 = !{i32 2, !"Debug Info Version", i32 3}
+!4 = !{i32 1, !"wchar_size", i32 4}
+!5 = !{i32 8, !"PIC Level", i32 2}
+!6 = !{!"clang version 21.0.0git"}
+!7 = distinct !DISubprogram(name: "foo", linkageName: "_Z3foov", scope: !1, file: !1, line: 1, scopeLine: 1, flags: DIFlagPrototyped, spFlags: DISPFlagDefinition, unit: !0, retainedNodes: !8)
+!8 = !{!9}
+!9 = !DILocalVariable(name: "v", scope: !7, file: !1, line: 8, type: !10)
+!10 = distinct !DICompositeType(tag: DW_TAG_structure_type, name: "T", scope: !7, file: !1, line: 2, size: 32, flags: DIFlagTypePassByValue, elements: !11)
+!11 = !{!12, !14}
+!12 = !DIDerivedType(tag: DW_TAG_member, name: "x", scope: !10, file: !1, line: 3, baseType: !13, size: 32)
+!13 = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed)
+!14 = !DISubprogram(name: "bar", scope: !10, file: !1, line: 5, scopeLine: 5, flags: DIFlagPrototyped | DIFlagStaticMember, spFlags: DISPFlagLocalToUnit)
\ No newline at end of file

>From 072b5c8eb82adbf769ae1c37d0384954c98ae98b Mon Sep 17 00:00:00 2001
From: Vladislav Dzhidzhoev <vdzhidzhoev at accesssoftek.com>
Date: Mon, 19 May 2025 17:50:55 +0200
Subject: [PATCH 2/2] Added a test case; Fixed braces

---
 llvm/lib/IR/DebugInfo.cpp                                 | 6 +++---
 .../DebugInfo/Generic/debuginfofinder-retained-nodes.ll   | 8 ++++++--
 2 files changed, 9 insertions(+), 5 deletions(-)

diff --git a/llvm/lib/IR/DebugInfo.cpp b/llvm/lib/IR/DebugInfo.cpp
index 9abde9023d057..7db9891fdbd75 100644
--- a/llvm/lib/IR/DebugInfo.cpp
+++ b/llvm/lib/IR/DebugInfo.cpp
@@ -241,9 +241,8 @@ void DebugInfoFinder::processCompileUnit(DICompileUnit *CU) {
       processType(T);
     else
       processSubprogram(cast<DISubprogram>(RT));
-  for (auto *Import : CU->getImportedEntities()) {
+  for (auto *Import : CU->getImportedEntities())
     processImportedEntity(Import);
-  }
 }
 
 void DebugInfoFinder::processInstruction(const Module &M,
@@ -355,11 +354,12 @@ void DebugInfoFinder::processSubprogram(DISubprogram *SP) {
     }
   }
 
-  for (auto *N : SP->getRetainedNodes())
+  for (auto *N : SP->getRetainedNodes()) {
     if (auto *Var = dyn_cast_or_null<DILocalVariable>(N))
       processVariable(Var);
     else if (auto *Import = dyn_cast_or_null<DIImportedEntity>(N))
       processImportedEntity(Import);
+  }
 }
 
 void DebugInfoFinder::processVariable(DILocalVariable *DV) {
diff --git a/llvm/test/DebugInfo/Generic/debuginfofinder-retained-nodes.ll b/llvm/test/DebugInfo/Generic/debuginfofinder-retained-nodes.ll
index f8185c65639d6..a2038c7a6a4bf 100644
--- a/llvm/test/DebugInfo/Generic/debuginfofinder-retained-nodes.ll
+++ b/llvm/test/DebugInfo/Generic/debuginfofinder-retained-nodes.ll
@@ -7,6 +7,7 @@
 ; CHECK: Compile unit: DW_LANG_C_plus_plus from /somewhere/source.cpp
 ; CHECK: Subprogram: foo from /somewhere/source.cpp:1 ('_Z3foov')
 ; CHECK: Subprogram: bar from /somewhere/source.cpp:5
+; CHECK: Subprogram: imported from /somewhere/source.cpp:3
 ; CHECK: Type: T from /somewhere/source.cpp:2 DW_TAG_structure_type
 
 %struct.T = type { i32 }
@@ -29,10 +30,13 @@ entry:
 !5 = !{i32 8, !"PIC Level", i32 2}
 !6 = !{!"clang version 21.0.0git"}
 !7 = distinct !DISubprogram(name: "foo", linkageName: "_Z3foov", scope: !1, file: !1, line: 1, scopeLine: 1, flags: DIFlagPrototyped, spFlags: DISPFlagDefinition, unit: !0, retainedNodes: !8)
-!8 = !{!9}
+!8 = !{!9, !15}
 !9 = !DILocalVariable(name: "v", scope: !7, file: !1, line: 8, type: !10)
 !10 = distinct !DICompositeType(tag: DW_TAG_structure_type, name: "T", scope: !7, file: !1, line: 2, size: 32, flags: DIFlagTypePassByValue, elements: !11)
 !11 = !{!12, !14}
 !12 = !DIDerivedType(tag: DW_TAG_member, name: "x", scope: !10, file: !1, line: 3, baseType: !13, size: 32)
 !13 = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed)
-!14 = !DISubprogram(name: "bar", scope: !10, file: !1, line: 5, scopeLine: 5, flags: DIFlagPrototyped | DIFlagStaticMember, spFlags: DISPFlagLocalToUnit)
\ No newline at end of file
+!14 = !DISubprogram(name: "bar", scope: !10, file: !1, line: 5, scopeLine: 5, flags: DIFlagPrototyped | DIFlagStaticMember, spFlags: DISPFlagLocalToUnit)
+!15 = !DIImportedEntity(tag: DW_TAG_imported_declaration, scope: !7, entity: !16, file: !1, line: 7)
+!16 = distinct !DISubprogram(name: "imported", scope: !17, file: !1, line: 3, scopeLine: 3, flags: DIFlagPrototyped, spFlags: DISPFlagDefinition, unit: !0)
+!17 = !DINamespace(name: "ns", scope: null)
\ No newline at end of file



More information about the llvm-commits mailing list