[llvm] [llvm-dwarfdump] Print symbolic names for DW_AT_LLVM_address_space (PR #220728)
Gheorghe-Teodor Bercea via llvm-commits
llvm-commits at lists.llvm.org
Thu Sep 10 12:57:56 PDT 2026
https://github.com/doru1004 updated https://github.com/llvm/llvm-project/pull/220728
>From 6d20ac1e074f6d062207954c1f3417df684e36df Mon Sep 17 00:00:00 2001
From: Gheorghe-Teodor Bercea <dobercea at amd.com>
Date: Wed, 2 Sep 2026 16:19:48 -0400
Subject: [PATCH 1/3] Print symbolic names for DW_AT_LLVM_address_space
---
llvm/include/llvm/DebugInfo/DIContext.h | 1 +
llvm/lib/DebugInfo/DWARF/DWARFDie.cpp | 16 +++++
.../AMDGPU/DW_AT_LLVM_address_space.yaml | 60 +++++++++++++++++++
llvm/tools/llvm-dwarfdump/llvm-dwarfdump.cpp | 31 +++++++---
4 files changed, 100 insertions(+), 8 deletions(-)
create mode 100644 llvm/test/tools/llvm-dwarfdump/AMDGPU/DW_AT_LLVM_address_space.yaml
diff --git a/llvm/include/llvm/DebugInfo/DIContext.h b/llvm/include/llvm/DebugInfo/DIContext.h
index b404c92e71836..b6373f648283d 100644
--- a/llvm/include/llvm/DebugInfo/DIContext.h
+++ b/llvm/include/llvm/DebugInfo/DIContext.h
@@ -215,6 +215,7 @@ struct DIDumpOptions {
llvm::SmallVector<unsigned, 0> FilterChildTag;
std::function<llvm::StringRef(uint64_t DwarfRegNum, bool IsEH)>
GetNameForDWARFReg;
+ std::function<llvm::StringRef(uint64_t AS)> GetNameForDWARFAddressSpace;
/// Return default option set for printing a single DIE without children.
static DIDumpOptions getForSingleDIE() {
diff --git a/llvm/lib/DebugInfo/DWARF/DWARFDie.cpp b/llvm/lib/DebugInfo/DWARF/DWARFDie.cpp
index edc1bc831be79..503ba173c96fd 100644
--- a/llvm/lib/DebugInfo/DWARF/DWARFDie.cpp
+++ b/llvm/lib/DebugInfo/DWARF/DWARFDie.cpp
@@ -86,6 +86,20 @@ static void dumpLocationList(raw_ostream &OS, const DWARFFormValue &FormValue,
&Offset, OS, U->getBaseAddress(), Ctx.getDWARFObj(), U, DumpOpts, Indent);
}
+static void dumpDWARFAddressSpace(raw_ostream &OS,
+ const DWARFFormValue &FormValue,
+ DIDumpOptions DumpOpts) {
+ FormValue.dump(OS, DumpOpts);
+
+ auto AddressSpaceAsUInt = FormValue.getAsUnsignedConstant();
+ auto GetNameForDWARFAddressSpace = DumpOpts.GetNameForDWARFAddressSpace;
+ if (GetNameForDWARFAddressSpace && AddressSpaceAsUInt) {
+ StringRef ASName = GetNameForDWARFAddressSpace(*AddressSpaceAsUInt);
+ if (!ASName.empty())
+ OS << " \"" << ASName << "\"";
+ }
+}
+
static void dumpLocationExpr(raw_ostream &OS, const DWARFFormValue &FormValue,
DWARFUnit *U, unsigned Indent,
DIDumpOptions DumpOpts) {
@@ -234,6 +248,8 @@ static void dumpAttribute(raw_ostream &OS, const DWARFDie &Die,
FormValue.isFormClass(DWARFFormValue::FC_Block)))
dumpLocationExpr(OS, FormValue, U, sizeof(BaseIndent) + Indent + 4,
DumpOpts);
+ else if (Attr == dwarf::DW_AT_LLVM_address_space)
+ dumpDWARFAddressSpace(OS, FormValue, DumpOpts);
else
FormValue.dump(OS, DumpOpts);
diff --git a/llvm/test/tools/llvm-dwarfdump/AMDGPU/DW_AT_LLVM_address_space.yaml b/llvm/test/tools/llvm-dwarfdump/AMDGPU/DW_AT_LLVM_address_space.yaml
new file mode 100644
index 0000000000000..bf8ed95798644
--- /dev/null
+++ b/llvm/test/tools/llvm-dwarfdump/AMDGPU/DW_AT_LLVM_address_space.yaml
@@ -0,0 +1,60 @@
+# Test that DW_AT_LLVM_address_space values are printed with their symbolic
+# names. The names are target-dependent, so they are resolved through the
+# triple of the object being dumped. Values with no name for the target are
+# printed as plain integers.
+
+# RUN: yaml2obj %s | llvm-dwarfdump - | FileCheck %s
+
+# CHECK: DW_TAG_pointer_type
+# CHECK-NEXT: DW_AT_LLVM_address_space (0x00000000 "DW_ASPACE_LLVM_none")
+# CHECK: DW_TAG_pointer_type
+# CHECK-NEXT: DW_AT_LLVM_address_space (0x00000001 "DW_ASPACE_LLVM_AMDGPU_generic")
+# CHECK: DW_TAG_pointer_type
+# CHECK-NEXT: DW_AT_LLVM_address_space (0x00000003 "DW_ASPACE_LLVM_AMDGPU_local")
+# CHECK: DW_TAG_pointer_type
+# CHECK-NEXT: DW_AT_LLVM_address_space (0x00000004)
+
+--- !ELF
+FileHeader:
+ Class: ELFCLASS64
+ Data: ELFDATA2LSB
+ OSABI: ELFOSABI_AMDGPU_HSA
+ ABIVersion: 0x02
+ Type: ET_REL
+ Machine: EM_AMDGPU
+ Flags: [ EF_AMDGPU_MACH_AMDGCN_GFX900 ]
+DWARF:
+ debug_abbrev:
+ - Table:
+ - Code: 0x00000001
+ Tag: DW_TAG_compile_unit
+ Children: DW_CHILDREN_yes
+ - Code: 0x00000002
+ Tag: DW_TAG_pointer_type
+ Children: DW_CHILDREN_no
+ Attributes:
+ - Attribute: DW_AT_LLVM_address_space
+ Form: DW_FORM_data4
+ debug_info:
+ - Version: 5
+ UnitType: DW_UT_compile
+ AbbrOffset: 0
+ AddrSize: 8
+ Entries:
+ - AbbrCode: 0x00000001
+ Values: []
+ - AbbrCode: 0x00000002
+ Values:
+ - Value: 0x0000000000000000
+ - AbbrCode: 0x00000002
+ Values:
+ - Value: 0x0000000000000001
+ - AbbrCode: 0x00000002
+ Values:
+ - Value: 0x0000000000000003
+ - AbbrCode: 0x00000002
+ Values:
+ - Value: 0x0000000000000004
+ - AbbrCode: 0x00000000
+ Values: []
+...
diff --git a/llvm/tools/llvm-dwarfdump/llvm-dwarfdump.cpp b/llvm/tools/llvm-dwarfdump/llvm-dwarfdump.cpp
index 41f9b1dc88284..0bff42cd611c6 100644
--- a/llvm/tools/llvm-dwarfdump/llvm-dwarfdump.cpp
+++ b/llvm/tools/llvm-dwarfdump/llvm-dwarfdump.cpp
@@ -16,6 +16,7 @@
#include "llvm/ADT/SmallSet.h"
#include "llvm/ADT/SmallVectorExtras.h"
#include "llvm/ADT/StringSet.h"
+#include "llvm/BinaryFormat/Dwarf.h"
#include "llvm/DebugInfo/DIContext.h"
#include "llvm/DebugInfo/DWARF/DWARFAcceleratorTable.h"
#include "llvm/DebugInfo/DWARF/DWARFCompileUnit.h"
@@ -446,9 +447,11 @@ using HandlerFn = std::function<bool(ObjectFile &, DWARFContext &DICtx,
/// Print only DIEs that have a certain name.
static bool filterByName(
const StringSet<> &Names, DWARFDie Die, StringRef NameRef, raw_ostream &OS,
- std::function<StringRef(uint64_t RegNum, bool IsEH)> GetNameForDWARFReg) {
+ std::function<StringRef(uint64_t RegNum, bool IsEH)> GetNameForDWARFReg,
+ std::function<StringRef(uint64_t AS)> GetNameForDWARFAddressSpace) {
DIDumpOptions DumpOpts = getDumpOpts(Die.getDwarfUnit()->getContext());
DumpOpts.GetNameForDWARFReg = GetNameForDWARFReg;
+ DumpOpts.GetNameForDWARFAddressSpace = GetNameForDWARFAddressSpace;
std::string Name =
(IgnoreCase && !UseRegex) ? NameRef.lower() : NameRef.str();
if (UseRegex) {
@@ -477,15 +480,18 @@ static bool filterByName(
static void filterByName(
const StringSet<> &Names, DWARFContext::unit_iterator_range CUs,
raw_ostream &OS,
- std::function<StringRef(uint64_t RegNum, bool IsEH)> GetNameForDWARFReg) {
+ std::function<StringRef(uint64_t RegNum, bool IsEH)> GetNameForDWARFReg,
+ std::function<StringRef(uint64_t AS)> GetNameForDWARFAddressSpace) {
auto filterDieNames = [&](DWARFUnit *Unit) {
for (const auto &Entry : Unit->dies()) {
DWARFDie Die = {Unit, &Entry};
if (const char *Name = Die.getName(DINameKind::ShortName))
- if (filterByName(Names, Die, Name, OS, GetNameForDWARFReg))
+ if (filterByName(Names, Die, Name, OS, GetNameForDWARFReg,
+ GetNameForDWARFAddressSpace))
continue;
if (const char *Name = Die.getName(DINameKind::LinkageName))
- filterByName(Names, Die, Name, OS, GetNameForDWARFReg);
+ filterByName(Names, Die, Name, OS, GetNameForDWARFReg,
+ GetNameForDWARFAddressSpace);
}
};
for (const auto &CU : CUs) {
@@ -552,7 +558,8 @@ static void getDies(DWARFContext &DICtx, const DWARFDebugNames &Accel,
/// Print only DIEs that have a certain name.
static void filterByAccelName(
ArrayRef<std::string> Names, DWARFContext &DICtx, raw_ostream &OS,
- std::function<StringRef(uint64_t RegNum, bool IsEH)> GetNameForDWARFReg) {
+ std::function<StringRef(uint64_t RegNum, bool IsEH)> GetNameForDWARFReg,
+ std::function<StringRef(uint64_t AS)> GetNameForDWARFAddressSpace) {
SmallVector<DWARFDie, 4> Dies;
for (const auto &Name : Names) {
getDies(DICtx, DICtx.getAppleNames(), Name, Dies);
@@ -565,6 +572,7 @@ static void filterByAccelName(
DIDumpOptions DumpOpts = getDumpOpts(DICtx);
DumpOpts.GetNameForDWARFReg = GetNameForDWARFReg;
+ DumpOpts.GetNameForDWARFAddressSpace = GetNameForDWARFAddressSpace;
for (DWARFDie Die : Dies)
Die.dump(OS, 0, DumpOpts);
}
@@ -750,6 +758,12 @@ static bool dumpObjectFile(ObjectFile &Obj, DWARFContext &DICtx,
return {};
};
+ // Address space names are target-dependent.
+ Triple TT = Obj.makeTriple();
+ auto GetASName = [TT](uint64_t AS) -> StringRef {
+ return dwarf::AddressSpaceString(AS, TT);
+ };
+
// The UUID dump already contains all the same information.
if (!(DumpType & DIDT_UUID) || DumpType == DIDT_All)
OS << Filename << ":\tfile format " << Obj.getFileFormatName() << '\n';
@@ -764,14 +778,14 @@ static bool dumpObjectFile(ObjectFile &Obj, DWARFContext &DICtx,
for (const auto &name : Name)
Names.insert((IgnoreCase && !UseRegex) ? StringRef(name).lower() : name);
- filterByName(Names, DICtx.normal_units(), OS, GetRegName);
- filterByName(Names, DICtx.dwo_units(), OS, GetRegName);
+ filterByName(Names, DICtx.normal_units(), OS, GetRegName, GetASName);
+ filterByName(Names, DICtx.dwo_units(), OS, GetRegName, GetASName);
return true;
}
// Handle the --find option and lower it to --debug-info=<offset>.
if (!Find.empty()) {
- filterByAccelName(Find, DICtx, OS, GetRegName);
+ filterByAccelName(Find, DICtx, OS, GetRegName, GetASName);
return true;
}
@@ -784,6 +798,7 @@ static bool dumpObjectFile(ObjectFile &Obj, DWARFContext &DICtx,
// Dump the complete DWARF structure.
auto DumpOpts = getDumpOpts(DICtx);
DumpOpts.GetNameForDWARFReg = GetRegName;
+ DumpOpts.GetNameForDWARFAddressSpace = GetASName;
DICtx.dump(OS, DumpOpts, DumpOffsets);
return true;
}
>From 789327c0faa82d19188e8d3e6b521b79723acd53 Mon Sep 17 00:00:00 2001
From: Gheorghe-Teodor Bercea <dobercea at amd.com>
Date: Tue, 8 Sep 2026 18:20:24 -0400
Subject: [PATCH 2/3] Address review comments: avoid needless copies
---
llvm/lib/DebugInfo/DWARF/DWARFDie.cpp | 11 ++++++-----
llvm/tools/llvm-dwarfdump/llvm-dwarfdump.cpp | 2 +-
2 files changed, 7 insertions(+), 6 deletions(-)
diff --git a/llvm/lib/DebugInfo/DWARF/DWARFDie.cpp b/llvm/lib/DebugInfo/DWARF/DWARFDie.cpp
index 503ba173c96fd..9eec3761441ea 100644
--- a/llvm/lib/DebugInfo/DWARF/DWARFDie.cpp
+++ b/llvm/lib/DebugInfo/DWARF/DWARFDie.cpp
@@ -88,13 +88,14 @@ static void dumpLocationList(raw_ostream &OS, const DWARFFormValue &FormValue,
static void dumpDWARFAddressSpace(raw_ostream &OS,
const DWARFFormValue &FormValue,
- DIDumpOptions DumpOpts) {
+ const DIDumpOptions &DumpOpts) {
FormValue.dump(OS, DumpOpts);
- auto AddressSpaceAsUInt = FormValue.getAsUnsignedConstant();
- auto GetNameForDWARFAddressSpace = DumpOpts.GetNameForDWARFAddressSpace;
- if (GetNameForDWARFAddressSpace && AddressSpaceAsUInt) {
- StringRef ASName = GetNameForDWARFAddressSpace(*AddressSpaceAsUInt);
+ std::optional<uint64_t> AddressSpaceAsUInt =
+ FormValue.getAsUnsignedConstant();
+ if (DumpOpts.GetNameForDWARFAddressSpace && AddressSpaceAsUInt) {
+ StringRef ASName =
+ DumpOpts.GetNameForDWARFAddressSpace(*AddressSpaceAsUInt);
if (!ASName.empty())
OS << " \"" << ASName << "\"";
}
diff --git a/llvm/tools/llvm-dwarfdump/llvm-dwarfdump.cpp b/llvm/tools/llvm-dwarfdump/llvm-dwarfdump.cpp
index 0bff42cd611c6..6462e00518ae6 100644
--- a/llvm/tools/llvm-dwarfdump/llvm-dwarfdump.cpp
+++ b/llvm/tools/llvm-dwarfdump/llvm-dwarfdump.cpp
@@ -760,7 +760,7 @@ static bool dumpObjectFile(ObjectFile &Obj, DWARFContext &DICtx,
// Address space names are target-dependent.
Triple TT = Obj.makeTriple();
- auto GetASName = [TT](uint64_t AS) -> StringRef {
+ auto GetASName = [&TT](uint64_t AS) -> StringRef {
return dwarf::AddressSpaceString(AS, TT);
};
>From 76b2c4fbaf3d06d914c6567b123303c81d849bda Mon Sep 17 00:00:00 2001
From: Gheorghe-Teodor Bercea <dobercea at amd.com>
Date: Thu, 10 Sep 2026 15:57:39 -0400
Subject: [PATCH 3/3] Address review comments: reuse the object triple, use
function_ref
---
llvm/lib/DebugInfo/DWARF/DWARFDie.cpp | 8 +++---
llvm/tools/llvm-dwarfdump/llvm-dwarfdump.cpp | 28 +++++++++-----------
2 files changed, 15 insertions(+), 21 deletions(-)
diff --git a/llvm/lib/DebugInfo/DWARF/DWARFDie.cpp b/llvm/lib/DebugInfo/DWARF/DWARFDie.cpp
index 9eec3761441ea..20f75e9c32dee 100644
--- a/llvm/lib/DebugInfo/DWARF/DWARFDie.cpp
+++ b/llvm/lib/DebugInfo/DWARF/DWARFDie.cpp
@@ -91,11 +91,9 @@ static void dumpDWARFAddressSpace(raw_ostream &OS,
const DIDumpOptions &DumpOpts) {
FormValue.dump(OS, DumpOpts);
- std::optional<uint64_t> AddressSpaceAsUInt =
- FormValue.getAsUnsignedConstant();
- if (DumpOpts.GetNameForDWARFAddressSpace && AddressSpaceAsUInt) {
- StringRef ASName =
- DumpOpts.GetNameForDWARFAddressSpace(*AddressSpaceAsUInt);
+ std::optional<uint64_t> AddressSpace = FormValue.getAsUnsignedConstant();
+ if (DumpOpts.GetNameForDWARFAddressSpace && AddressSpace) {
+ StringRef ASName = DumpOpts.GetNameForDWARFAddressSpace(*AddressSpace);
if (!ASName.empty())
OS << " \"" << ASName << "\"";
}
diff --git a/llvm/tools/llvm-dwarfdump/llvm-dwarfdump.cpp b/llvm/tools/llvm-dwarfdump/llvm-dwarfdump.cpp
index 6462e00518ae6..2fe63b4c0c88d 100644
--- a/llvm/tools/llvm-dwarfdump/llvm-dwarfdump.cpp
+++ b/llvm/tools/llvm-dwarfdump/llvm-dwarfdump.cpp
@@ -447,8 +447,8 @@ using HandlerFn = std::function<bool(ObjectFile &, DWARFContext &DICtx,
/// Print only DIEs that have a certain name.
static bool filterByName(
const StringSet<> &Names, DWARFDie Die, StringRef NameRef, raw_ostream &OS,
- std::function<StringRef(uint64_t RegNum, bool IsEH)> GetNameForDWARFReg,
- std::function<StringRef(uint64_t AS)> GetNameForDWARFAddressSpace) {
+ function_ref<StringRef(uint64_t RegNum, bool IsEH)> GetNameForDWARFReg,
+ function_ref<StringRef(uint64_t AS)> GetNameForDWARFAddressSpace) {
DIDumpOptions DumpOpts = getDumpOpts(Die.getDwarfUnit()->getContext());
DumpOpts.GetNameForDWARFReg = GetNameForDWARFReg;
DumpOpts.GetNameForDWARFAddressSpace = GetNameForDWARFAddressSpace;
@@ -480,8 +480,8 @@ static bool filterByName(
static void filterByName(
const StringSet<> &Names, DWARFContext::unit_iterator_range CUs,
raw_ostream &OS,
- std::function<StringRef(uint64_t RegNum, bool IsEH)> GetNameForDWARFReg,
- std::function<StringRef(uint64_t AS)> GetNameForDWARFAddressSpace) {
+ function_ref<StringRef(uint64_t RegNum, bool IsEH)> GetNameForDWARFReg,
+ function_ref<StringRef(uint64_t AS)> GetNameForDWARFAddressSpace) {
auto filterDieNames = [&](DWARFUnit *Unit) {
for (const auto &Entry : Unit->dies()) {
DWARFDie Die = {Unit, &Entry};
@@ -558,8 +558,8 @@ static void getDies(DWARFContext &DICtx, const DWARFDebugNames &Accel,
/// Print only DIEs that have a certain name.
static void filterByAccelName(
ArrayRef<std::string> Names, DWARFContext &DICtx, raw_ostream &OS,
- std::function<StringRef(uint64_t RegNum, bool IsEH)> GetNameForDWARFReg,
- std::function<StringRef(uint64_t AS)> GetNameForDWARFAddressSpace) {
+ function_ref<StringRef(uint64_t RegNum, bool IsEH)> GetNameForDWARFReg,
+ function_ref<StringRef(uint64_t AS)> GetNameForDWARFAddressSpace) {
SmallVector<DWARFDie, 4> Dies;
for (const auto &Name : Names) {
getDies(DICtx, DICtx.getAppleNames(), Name, Dies);
@@ -580,7 +580,7 @@ static void filterByAccelName(
/// Print all DIEs in apple accelerator tables
static void findAllApple(
DWARFContext &DICtx, raw_ostream &OS,
- std::function<StringRef(uint64_t RegNum, bool IsEH)> GetNameForDWARFReg) {
+ function_ref<StringRef(uint64_t RegNum, bool IsEH)> GetNameForDWARFReg) {
MapVector<StringRef, llvm::SmallSet<DWARFDie, 2>> NameToDies;
auto PushDIEs = [&](const AppleAcceleratorTable &Accel) {
@@ -724,13 +724,8 @@ static bool collectObjectSources(ObjectFile &Obj, DWARFContext &DICtx,
return Result;
}
-static std::unique_ptr<MCRegisterInfo>
-createRegInfo(const object::ObjectFile &Obj) {
+static std::unique_ptr<MCRegisterInfo> createRegInfo(const Triple &TT) {
std::unique_ptr<MCRegisterInfo> MCRegInfo;
- Triple TT;
- TT.setArch(Triple::ArchType(Obj.getArch()));
- TT.setVendor(Triple::UnknownVendor);
- TT.setOS(Triple::UnknownOS);
std::string TargetLookupError;
const Target *TheTarget = TargetRegistry::lookupTarget(TT, TargetLookupError);
if (!TargetLookupError.empty())
@@ -742,7 +737,10 @@ createRegInfo(const object::ObjectFile &Obj) {
static bool dumpObjectFile(ObjectFile &Obj, DWARFContext &DICtx,
const Twine &Filename, raw_ostream &OS) {
- auto MCRegInfo = createRegInfo(Obj);
+ // Register and address space names are target-dependent.
+ Triple TT = Obj.makeTriple();
+
+ auto MCRegInfo = createRegInfo(TT);
if (!MCRegInfo)
logAllUnhandledErrors(createStringError(inconvertibleErrorCode(),
"Error in creating MCRegInfo"),
@@ -758,8 +756,6 @@ static bool dumpObjectFile(ObjectFile &Obj, DWARFContext &DICtx,
return {};
};
- // Address space names are target-dependent.
- Triple TT = Obj.makeTriple();
auto GetASName = [&TT](uint64_t AS) -> StringRef {
return dwarf::AddressSpaceString(AS, TT);
};
More information about the llvm-commits
mailing list