[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