[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