[llvm] Dwarfdump hack to display qualified name for any variable with a DW_AT_location for instr-ref purposes (PR #164954)

Shubham Sandeep Rastogi via llvm-commits llvm-commits at lists.llvm.org
Fri Oct 24 03:44:25 PDT 2025


https://github.com/rastogishubham created https://github.com/llvm/llvm-project/pull/164954

None

>From 97871f6b1bc22ce7f02b84c28766b9ce24b4a942 Mon Sep 17 00:00:00 2001
From: Shubham Sandeep Rastogi <srastogi22 at apple.com>
Date: Mon, 25 Aug 2025 10:06:18 -0700
Subject: [PATCH 1/2] Return nullopt if Reg is undef.

In describeORRLoadedValue in AArch64InstrInfo.cpp, we try to check if an
instruction is a copy like instruction, the isCopyLikeInstr function
returns a pair of destination and source registers. If any of them are
undef, we should just return a nullopt to avoid any crashes later in the
code when trying to get the SubReg for one of those registers.

rdar://158581204
---
 llvm/lib/Target/AArch64/AArch64InstrInfo.cpp |  3 +
 llvm/test/DebugInfo/AArch64/callsite.mir     | 68 ++++++++++++++++++++
 2 files changed, 71 insertions(+)
 create mode 100644 llvm/test/DebugInfo/AArch64/callsite.mir

diff --git a/llvm/lib/Target/AArch64/AArch64InstrInfo.cpp b/llvm/lib/Target/AArch64/AArch64InstrInfo.cpp
index 3ce7829207cb6..1d55b86a7ba45 100644
--- a/llvm/lib/Target/AArch64/AArch64InstrInfo.cpp
+++ b/llvm/lib/Target/AArch64/AArch64InstrInfo.cpp
@@ -10590,6 +10590,9 @@ describeORRLoadedValue(const MachineInstr &MI, Register DescribedReg,
   Register DestReg = DestSrc->Destination->getReg();
   Register SrcReg = DestSrc->Source->getReg();
 
+  if (!DestReg.isValid() || !SrcReg.isValid())
+    return std::nullopt;
+
   auto Expr = DIExpression::get(MI.getMF()->getFunction().getContext(), {});
 
   // If the described register is the destination, just return the source.
diff --git a/llvm/test/DebugInfo/AArch64/callsite.mir b/llvm/test/DebugInfo/AArch64/callsite.mir
new file mode 100644
index 0000000000000..e3bd764db430b
--- /dev/null
+++ b/llvm/test/DebugInfo/AArch64/callsite.mir
@@ -0,0 +1,68 @@
+# This test should not crash when generating call-site information. 
+# It was created to make sure that if isCopyLikeInstr in TargetInstrInfo.h 
+# returns an undef Dest Reg or Src Reg, we don't try to get a SubReg for it.
+
+# RUN: llc --mtriple=arm64e-apple-ios -start-before=aarch64-asm-printer %s -filetype=obj -o /dev/null --emit-call-site-info 
+--- |
+  %struct.rtyuio = type { i8 }
+  define noundef i32 @aserty(ptr noundef %0, ptr noundef %1) local_unnamed_addr #0 !dbg !23 {
+    ret i32 0
+  }
+  define void @asdfgh(ptr noundef %0, ptr noundef %1, i8 noundef zeroext %2) local_unnamed_addr #0 !dbg !53 {
+    %4 = alloca ptr
+    %5 = call ptr @llvm.stackguard()
+    %6 = alloca %struct.rtyuio
+    %7 = icmp eq ptr %1, null
+    br i1 %7, label %10, label %8
+    %9 = tail call i8 @polkiokl(ptr noundef %0) #6
+    br label %10
+    ret void
+  }
+  declare i8 @polkiokl(ptr noundef) local_unnamed_addr #2
+  !llvm.module.flags = !{!2, !8}
+  !llvm.dbg.cu = !{!9}
+  !2 = !{i32 2, !"Debug Info Version", i32 3}
+  !8 = !{i32 7, !"frame-pointer", i32 1}
+  !9 = distinct !DICompileUnit(language: DW_LANG_C_plus_plus_11, file: !10, emissionKind: FullDebug, sysroot: "/")
+  !10 = !DIFile(filename: "a.cpp", directory: "/")
+  !23 = distinct !DISubprogram(type: !27, flags: DIFlagPrototyped | DIFlagAllCallsDescribed, unit: !9, retainedNodes: !46)
+  !24 = distinct !DICompositeType(tag: DW_TAG_class_type, identifier: "yshscbshhdvcm")
+  !27 = !DISubroutineType(types: !28)
+  !28 = !{}
+  !30 = !DIDerivedType(tag: DW_TAG_typedef, baseType: !33)
+  !33 = distinct !DICompositeType(tag: DW_TAG_structure_type, identifier: "tyruwyeuiwiybabd")
+  !36 = !DISubroutineType(types: !37)
+  !37 = !{}
+  !46 = !{}
+  !47 = !DILocalVariable(scope: !23, type: !48, flags: DIFlagArtificial | DIFlagObjectPointer)
+  !48 = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: !24, size: 64)
+  !49 = !DILocalVariable(scope: !23, type: !30)
+  !50 = !DILocation(scope: !23)
+  !51 = !DILocation(scope: !23)
+  !53 = distinct !DISubprogram(type: !36, unit: !9, retainedNodes: !54)
+  !54 = !{}
+name:            aserty
+stack:
+  - { id: 0, name: '', type: spill-slot, offset: -8, size: 8, alignment: 8, 
+      debug-info-variable: '', debug-info-expression: '', debug-info-location: '' }
+  - { id: 1, name: '', type: spill-slot, offset: -16, size: 8, alignment: 8, 
+      debug-info-variable: '', debug-info-expression: '', debug-info-location: '' }
+callSites:
+  - { bb: 0, offset: 9, fwdArgRegs: 
+      - { arg: 2, reg: '$w2' } }
+body:             |
+  bb.0 (%ir-block.2):
+    DBG_VALUE $x0, $noreg, !47, !DIExpression(),  debug-location !50
+    DBG_VALUE $x1, $noreg, !49, !DIExpression(),  debug-location !50
+    frame-setup PACIBSP implicit-def $lr, implicit killed $lr, implicit $sp
+    early-clobber $sp = frame-setup STPXpre $fp, killed $lr, $sp, -2 :: (store (s64) into %stack.1), (store (s64) into %stack.0)
+    $fp = frame-setup ADDXri $sp, 0, 0
+    frame-setup CFI_INSTRUCTION def_cfa $w29, 16
+    frame-setup CFI_INSTRUCTION offset $w30, -8
+    frame-setup CFI_INSTRUCTION offset $w29, -16
+    $x2 = ORRXrs $xzr, undef $noreg, 0, implicit $wzr,  debug-location !51
+    BL @asdfgh, csr_darwin_aarch64_aapcs, implicit-def dead $lr, implicit $sp, implicit killed $x0, implicit killed $x1, implicit killed $w2, implicit-def $sp,  debug-location !51
+...
+name:            asdfgh
+body:             |
+  bb.2 (%ir-block.10):

>From c55968a5f8f39539fca3896be941c065bb2a891a Mon Sep 17 00:00:00 2001
From: Shubham Sandeep Rastogi <srastogi22 at apple.com>
Date: Wed, 15 Jan 2025 12:05:08 -0800
Subject: [PATCH 2/2] Hack dwarfdump stats to print vars with DW_AT_location

---
 .../CodeGen/AsmPrinter/DwarfCompileUnit.cpp   | 28 +++++-
 llvm/tools/llvm-dwarfdump/Statistics.cpp      | 96 ++++++++++++++++++-
 2 files changed, 118 insertions(+), 6 deletions(-)

diff --git a/llvm/lib/CodeGen/AsmPrinter/DwarfCompileUnit.cpp b/llvm/lib/CodeGen/AsmPrinter/DwarfCompileUnit.cpp
index 67f526fe91464..676ab15c563b4 100644
--- a/llvm/lib/CodeGen/AsmPrinter/DwarfCompileUnit.cpp
+++ b/llvm/lib/CodeGen/AsmPrinter/DwarfCompileUnit.cpp
@@ -1680,8 +1680,34 @@ void DwarfCompileUnit::addLocationList(DIE &Die, dwarf::Attribute Attribute,
 void DwarfCompileUnit::applyCommonDbgVariableAttributes(const DbgVariable &Var,
                                                         DIE &VariableDie) {
   StringRef Name = Var.getName();
+  DIE *CurrentDie = &VariableDie;
+  std::string FullName = "";
+  unsigned lexicalBlockCount = 0;
+  //   while(true) {
+  //     DIE* ParentDIE = CurrentDie->getParent();
+  //     if (ParentDIE == nullptr)
+  //       break;
+  //     auto ParentName = ParentDIE->findAttribute(dwarf::DW_AT_linkage_name);
+  //     if (ParentName.getAttribute() == 0) {
+  //       auto PName = ParentDIE->findAttribute(dwarf::DW_AT_name);
+  //       if (PName.getAttribute() == 0) {
+  //         if (ParentDIE->getTag() == dwarf::DW_TAG_lexical_block)
+  //           FullName.insert(0, "_" +
+  //           std::string(std::to_string(++lexicalBlockCount)));
+  //         goto label;
+  //       }
+  //       FullName.insert(0, PName.getDIEString().getString());
+  //       goto label;
+  //     }
+  //     FullName.insert(0, ParentName.getDIEString().getString());
+  // label:
+  //     CurrentDie = ParentDIE;
+  //     if (ParentDIE->getTag() == dwarf::DW_TAG_compile_unit)
+  //       break;
+  //   }
+  std::string FinalName = FullName + Name.str();
   if (!Name.empty())
-    addString(VariableDie, dwarf::DW_AT_name, Name);
+    addString(VariableDie, dwarf::DW_AT_name, FinalName);
   const auto *DIVar = Var.getVariable();
   if (DIVar) {
     if (uint32_t AlignInBytes = DIVar->getAlignInBytes())
diff --git a/llvm/tools/llvm-dwarfdump/Statistics.cpp b/llvm/tools/llvm-dwarfdump/Statistics.cpp
index a705e7d51d874..b13d2790d52ef 100644
--- a/llvm/tools/llvm-dwarfdump/Statistics.cpp
+++ b/llvm/tools/llvm-dwarfdump/Statistics.cpp
@@ -275,7 +275,8 @@ static void collectStatsForDie(DWARFDie Die, const std::string &FnPrefix,
                                StringMap<PerFunctionStats> &FnStatMap,
                                GlobalStats &GlobalStats,
                                LocationStats &LocStats,
-                               AbstractOriginVarsTy *AbstractOriginVariables) {
+                               AbstractOriginVarsTy *AbstractOriginVariables,
+                               std::string Prefix) {
   const dwarf::Tag Tag = Die.getTag();
   // Skip CU node.
   if (Tag == dwarf::DW_TAG_compile_unit)
@@ -366,6 +367,23 @@ static void collectStatsForDie(DWARFDie Die, const std::string &FnPrefix,
       consumeError(Loc.takeError());
     } else {
       HasLoc = true;
+      auto Name = Die.find(dwarf::DW_AT_name);
+      auto StringName = Name->getAsCString();
+      if (!StringName) {
+        consumeError(StringName.takeError());
+        auto AbsOrigin = Die.find(dwarf::DW_AT_abstract_origin);
+        if (AbsOrigin != std::nullopt) {
+          if (const char *Name =
+                  Die.getAttributeValueAsReferencedDie(*AbsOrigin)
+                      .getName(DINameKind::LinkageName)) {
+            llvm::outs() << "\nvariable name: " << Prefix << " " << Name
+                         << "\n";
+          }
+        }
+      } else {
+        std::string S(*StringName);
+        llvm::outs() << "\nvariable name: " << Prefix << " " << S << "\n";
+      }
       // Get PC coverage.
       auto Default = find_if(
           *Loc, [](const DWARFLocationExpression &L) { return !L.Range; });
@@ -500,7 +518,7 @@ static void collectStatsRecursive(
     AbstractOriginVarsTyMap &GlobalAbstractOriginFnInfo,
     AbstractOriginVarsTyMap &LocalAbstractOriginFnInfo,
     FunctionsWithAbstractOriginTy &FnsWithAbstractOriginToBeProcessed,
-    AbstractOriginVarsTy *AbstractOriginVarsPtr = nullptr) {
+    std::string Prefix, AbstractOriginVarsTy *AbstractOriginVarsPtr = nullptr) {
   // Skip NULL nodes.
   if (Die.isNULL())
     return;
@@ -609,7 +627,8 @@ static void collectStatsRecursive(
   } else {
     // Not a scope, visit the Die itself. It could be a variable.
     collectStatsForDie(Die, FnPrefix, VarPrefix, BytesInScope, InlineDepth,
-                       FnStatMap, GlobalStats, LocStats, AbstractOriginVarsPtr);
+                       FnStatMap, GlobalStats, LocStats, AbstractOriginVarsPtr,
+                       Prefix);
   }
 
   // Set InlineDepth correctly for child recursion
@@ -623,6 +642,65 @@ static void collectStatsRecursive(
   unsigned FormalParameterIndex = 0;
   DWARFDie Child = Die.getFirstChild();
   while (Child) {
+    std::string PreName = "";
+    if (Child.getTag() != dwarf::DW_TAG_formal_parameter &&
+        Child.getTag() != dwarf::DW_TAG_variable) {
+      if (Child.getTag() == dwarf::DW_TAG_lexical_block) {
+        PreName = " LinkageName: _" + std::to_string(LexicalBlockIndex);
+      } else if (Child.getTag() == dwarf::DW_TAG_subprogram) {
+        if (auto AbsOrig = Child.find(dwarf::DW_AT_abstract_origin)) {
+          if (const char *Name =
+                  Child.getAttributeValueAsReferencedDie(*AbsOrig).getName(
+                      DINameKind::LinkageName)) {
+            PreName = " Subprogram: " + std::string(Name) + ", ";
+          }
+        }
+        if (auto LinkName = Child.find(dwarf::DW_AT_linkage_name)) {
+          if (auto CString = LinkName->getAsCString()) {
+            PreName = " Subprogram: " + std::string(*CString) + ", ";
+          }
+        }
+      } else if (auto AbsOrig = Child.find(dwarf::DW_AT_abstract_origin)) {
+        if (const char *Name =
+                Child.getAttributeValueAsReferencedDie(*AbsOrig).getName(
+                    DINameKind::LinkageName)) {
+          if (Child.getTag() == dwarf::DW_TAG_namespace)
+            PreName = " Namespace: " + std::to_string(Child.getTag()) + " " +
+                      std::string(Name) + ", ";
+          else if (Child.getTag() == dwarf::DW_TAG_inlined_subroutine)
+            PreName = " InlinedSubroutine: " + std::to_string(Child.getTag()) +
+                      " " + std::string(Name) + ", ";
+          else
+            PreName = " AnythingElse: " + std::to_string(Child.getTag()) + " " +
+                      std::string(Name) + ", ";
+        }
+      } else if (auto LinkName = Child.find(dwarf::DW_AT_linkage_name)) {
+        if (auto CString = LinkName->getAsCString()) {
+          if (Child.getTag() == dwarf::DW_TAG_namespace)
+            PreName = " Namespace: " + std::to_string(Child.getTag()) + " " +
+                      std::string(*CString) + ", ";
+          else if (Child.getTag() == dwarf::DW_TAG_inlined_subroutine)
+            PreName = " InlinedSubroutine: " + std::to_string(Child.getTag()) +
+                      " " + std::string(*CString) + ", ";
+          else
+            PreName = " AnythingElse: " + std::to_string(Child.getTag()) + " " +
+                      std::string(*CString) + ", ";
+        }
+      } else if (auto Name = Child.find(dwarf::DW_AT_name)) {
+        if (auto CString = Name->getAsCString()) {
+          if (Child.getTag() == dwarf::DW_TAG_namespace)
+            PreName = " Namespace: " + std::to_string(Child.getTag()) + " " +
+                      std::string(*CString) + ", ";
+          else if (Child.getTag() == dwarf::DW_TAG_inlined_subroutine)
+            PreName = " InlinedSubroutine: " + std::to_string(Child.getTag()) +
+                      " " + std::string(*CString) + ", ";
+          else
+            PreName = " AnythingElse: " + std::to_string(Child.getTag()) + " " +
+                      std::string(*CString) + ", ";
+        }
+      }
+    }
+
     std::string ChildVarPrefix = VarPrefix;
     if (Child.getTag() == dwarf::DW_TAG_lexical_block)
       ChildVarPrefix += toHex(LexicalBlockIndex++) + '.';
@@ -633,7 +711,7 @@ static void collectStatsRecursive(
         Child, FnPrefix, ChildVarPrefix, BytesInScope, InlineDepth, FnStatMap,
         GlobalStats, LocStats, AbstractOriginFnCUs, GlobalAbstractOriginFnInfo,
         LocalAbstractOriginFnInfo, FnsWithAbstractOriginToBeProcessed,
-        AbstractOriginVarsPtr);
+        Prefix + PreName, AbstractOriginVarsPtr);
     Child = Child.getSibling();
   }
 
@@ -885,10 +963,18 @@ bool dwarfdump::collectStatsForObjectFile(ObjectFile &Obj, DWARFContext &DICtx,
       AbstractOriginVarsTyMap LocalAbstractOriginFnInfo;
       FunctionsWithAbstractOriginTy FnsWithAbstractOriginToBeProcessed;
 
+      auto CUName = CUDie.find(dwarf::DW_AT_name);
+      std::string name = "";
+      if (CUName != std::nullopt) {
+        auto Sname = CUName->getAsCString();
+        if (!Sname)
+          name.insert(0, *Sname);
+      }
+
       collectStatsRecursive(
           CUDie, "/", "g", 0, 0, Statistics, GlobalStats, LocStats,
           AbstractOriginFnCUs, GlobalAbstractOriginFnInfo,
-          LocalAbstractOriginFnInfo, FnsWithAbstractOriginToBeProcessed);
+          LocalAbstractOriginFnInfo, FnsWithAbstractOriginToBeProcessed, name);
 
       // collectZeroLocCovForVarsWithAbstractOrigin will filter out all
       // out-of-order DWARF functions that have been processed within it,



More information about the llvm-commits mailing list