[llvm] [llvm][dwarfdump] Pretty-print DW_AT_language_version (PR #164222)
    Michael Buch via llvm-commits 
    llvm-commits at lists.llvm.org
       
    Tue Oct 21 02:44:34 PDT 2025
    
    
  
https://github.com/Michael137 updated https://github.com/llvm/llvm-project/pull/164222
>From eaeeeaca5f5d28ace4545a963866cd4e8f8a3666 Mon Sep 17 00:00:00 2001
From: Michael Buch <michaelbuch12 at gmail.com>
Date: Mon, 20 Oct 2025 09:49:13 +0100
Subject: [PATCH 1/5] [llvm][dwarfdump] Pretty-print DW_AT_language_version in
 non-verbose dwarfdump
---
 llvm/lib/DebugInfo/DWARF/DWARFDie.cpp         | 25 ++++++++++++++-
 .../X86/DW_AT_language_version-pretty.s       | 32 +++++++++++++++++++
 .../X86/DW_AT_language_version.s              | 21 +++++++-----
 3 files changed, 69 insertions(+), 9 deletions(-)
 create mode 100644 llvm/test/tools/llvm-dwarfdump/X86/DW_AT_language_version-pretty.s
diff --git a/llvm/lib/DebugInfo/DWARF/DWARFDie.cpp b/llvm/lib/DebugInfo/DWARF/DWARFDie.cpp
index 212a0c039298b..5c4fbfad4e8d5 100644
--- a/llvm/lib/DebugInfo/DWARF/DWARFDie.cpp
+++ b/llvm/lib/DebugInfo/DWARF/DWARFDie.cpp
@@ -107,6 +107,27 @@ static DWARFDie resolveReferencedType(DWARFDie D, DWARFFormValue F) {
   return D.getAttributeValueAsReferencedDie(F).resolveTypeUnitReference();
 }
 
+static llvm::StringRef
+prettyLanguageVersionString(const DWARFAttribute &AttrValue,
+                            const DWARFDie &Die) {
+  assert(AttrValue.Attr == DW_AT_language_version);
+
+  auto NameForm = Die.find(DW_AT_language_name);
+  if (!NameForm)
+    return {};
+
+  auto LName = NameForm->getAsUnsignedConstant();
+  if (!LName)
+    return {};
+
+  auto LVersion = AttrValue.Value.getAsUnsignedConstant();
+  if (!LVersion)
+    return {};
+
+  return llvm::dwarf::LanguageDescription(
+      static_cast<SourceLanguageName>(*LName), *LVersion);
+}
+
 static void dumpAttribute(raw_ostream &OS, const DWARFDie &Die,
                           const DWARFAttribute &AttrValue, unsigned Indent,
                           DIDumpOptions DumpOpts) {
@@ -143,7 +164,9 @@ static void dumpAttribute(raw_ostream &OS, const DWARFDie &Die,
         }
       }
     }
-  } else if (std::optional<uint64_t> Val = FormValue.getAsUnsignedConstant())
+  } else if (Attr == llvm::dwarf::DW_AT_language_version && !DumpOpts.Verbose)
+    Name = prettyLanguageVersionString(AttrValue, Die);
+  else if (std::optional<uint64_t> Val = FormValue.getAsUnsignedConstant())
     Name = AttributeValueString(Attr, *Val);
 
   if (!Name.empty())
diff --git a/llvm/test/tools/llvm-dwarfdump/X86/DW_AT_language_version-pretty.s b/llvm/test/tools/llvm-dwarfdump/X86/DW_AT_language_version-pretty.s
new file mode 100644
index 0000000000000..f9986a9cf2fb0
--- /dev/null
+++ b/llvm/test/tools/llvm-dwarfdump/X86/DW_AT_language_version-pretty.s
@@ -0,0 +1,32 @@
+# Demonstrate dumping DW_AT_language_version in human-readable form.
+# RUN: llvm-mc -triple=x86_64--linux -filetype=obj < %s | \
+# RUN:     llvm-dwarfdump - | FileCheck %s --implicit-check-not "DW_AT_language_version"
+
+# CHECK: .debug_info contents:
+# CHECK: DW_AT_language_name (DW_LNAME_C)
+# CHECK: DW_AT_language_version (C11)
+
+        .section        .debug_abbrev,"", at progbits
+        .byte   1                       # Abbreviation Code
+        .byte   17                      # DW_TAG_compile_unit
+        .byte   1                       # DW_CHILDREN_no 
+        .ascii  "\220\001"              # DW_AT_language_name
+        .byte   5                       # DW_FORM_data2
+        .ascii  "\221\001"              # DW_AT_language_version
+        .byte   6                       # DW_FORM_data4
+        .byte   0                       # EOM(1)
+        .byte   0                       # EOM(2)
+        .byte   0                       # EOM(3)
+
+        .section        .debug_info,"", at progbits
+        .long   .Ldebug_info_end0-.Ldebug_info_start0 # Length of Unit
+.Ldebug_info_start0:
+        .short  5                       # DWARF version number
+        .byte   1                       # Unit type
+        .byte   8                       # Address Size (in bytes)
+        .long   .debug_abbrev           # Offset Into Abbrev. Section
+        .byte   1                       # Abbrev [1] DW_TAG_compile_unit
+        .short  3                       # DW_AT_language_name
+        .long   201112                  # DW_AT_language_version
+        .byte   0 
+.Ldebug_info_end0:
diff --git a/llvm/test/tools/llvm-dwarfdump/X86/DW_AT_language_version.s b/llvm/test/tools/llvm-dwarfdump/X86/DW_AT_language_version.s
index f1be8fdf6cd3e..e9bcfdedd346d 100644
--- a/llvm/test/tools/llvm-dwarfdump/X86/DW_AT_language_version.s
+++ b/llvm/test/tools/llvm-dwarfdump/X86/DW_AT_language_version.s
@@ -1,13 +1,18 @@
 # Demonstrate dumping DW_AT_language_version.
-# RUN: llvm-mc -triple=x86_64--linux -filetype=obj < %s | \
-# RUN:     llvm-dwarfdump -v - | FileCheck %s
+# RUN: llvm-mc -triple=x86_64--linux -filetype=obj -o %t.o < %s
+# RUN: llvm-dwarfdump -v %t.o | FileCheck %s --check-prefix=VERBOSE
+# RUN: llvm-dwarfdump %t.o | FileCheck %s --check-prefix=NO-VERBOSE
 
-# CHECK: .debug_abbrev contents:
-# CHECK: DW_AT_language_version DW_FORM_data4
-# CHECK: DW_AT_language_version DW_FORM_data2
-# CHECK: .debug_info contents:
-# CHECK: DW_AT_language_version [DW_FORM_data4] (201402)
-# CHECK: DW_AT_language_version [DW_FORM_data2] (0)
+# VERBOSE: .debug_abbrev contents:
+# VERBOSE: DW_AT_language_version DW_FORM_data4
+# VERBOSE: DW_AT_language_version DW_FORM_data2
+# VERBOSE: .debug_info contents:
+# VERBOSE: DW_AT_language_version [DW_FORM_data4] (201402)
+# VERBOSE: DW_AT_language_version [DW_FORM_data2] (0)
+
+# NO-VERBOSE: .debug_info contents:
+# NO-VERBOSE: DW_AT_language_version (201402)
+# NO-VERBOSE: DW_AT_language_version (0)
 
         .section        .debug_abbrev,"", at progbits
         .byte   1                       # Abbreviation Code
>From 662b7e6e417d0aec84fb1b84603d80cb5236e404 Mon Sep 17 00:00:00 2001
From: Michael Buch <michaelbuch12 at gmail.com>
Date: Mon, 20 Oct 2025 12:56:58 +0100
Subject: [PATCH 2/5] fixup! fix test
---
 .../Generic/compileunit-source-language-name.ll        | 10 +++++-----
 1 file changed, 5 insertions(+), 5 deletions(-)
diff --git a/llvm/test/DebugInfo/Generic/compileunit-source-language-name.ll b/llvm/test/DebugInfo/Generic/compileunit-source-language-name.ll
index f5dcf01c7e89f..90e0daf7648f3 100644
--- a/llvm/test/DebugInfo/Generic/compileunit-source-language-name.ll
+++ b/llvm/test/DebugInfo/Generic/compileunit-source-language-name.ll
@@ -1,11 +1,11 @@
 ; AIX doesn't have support for DWARF 6 DW_AT_language_name
 ; XFAIL: target={{.*}}-zos{{.*}}, target={{.*}}-aix{{.*}}
-; RUN: %llc_dwarf -filetype=obj -O0 < %s | llvm-dwarfdump -debug-info - | FileCheck %s --implicit-check-not "DW_AT_language"
+; RUN: %llc_dwarf -filetype=obj -O0 < %s | llvm-dwarfdump -debug-info -v - | FileCheck %s --implicit-check-not "DW_AT_language"
 
-; CHECK:     DW_AT_language_name (DW_LNAME_ObjC_plus_plus)
-; CHECK:     DW_AT_language_name (DW_LNAME_C_plus_plus)
-; CHECK:     DW_AT_language_version (201100)
-; CHECK:     DW_AT_language_name (DW_LNAME_Rust)
+; CHECK:     DW_AT_language_name [DW_FORM_data2] (DW_LNAME_ObjC_plus_plus)
+; CHECK:     DW_AT_language_name [DW_FORM_data2] (DW_LNAME_C_plus_plus)
+; CHECK:     DW_AT_language_version [DW_FORM_data4] (201100)
+; CHECK:     DW_AT_language_name [DW_FORM_data2] (DW_LNAME_Rust)
 ; CHECK-NOT: DW_AT_language_version
 
 @x = global i32 0, align 4, !dbg !0
>From 9deb8f4a3eb1e6fb5e805ca81c3c77ca05e3e404 Mon Sep 17 00:00:00 2001
From: Michael Buch <michaelbuch12 at gmail.com>
Date: Mon, 20 Oct 2025 15:09:56 +0100
Subject: [PATCH 3/5] fixup! print prettfied name in verbose mode too
---
 llvm/lib/DebugInfo/DWARF/DWARFDie.cpp         | 34 ++++++++++++++-----
 .../compileunit-source-language-name.ll       |  2 +-
 .../X86/DW_AT_language_version-pretty.s       | 15 +++++---
 3 files changed, 36 insertions(+), 15 deletions(-)
diff --git a/llvm/lib/DebugInfo/DWARF/DWARFDie.cpp b/llvm/lib/DebugInfo/DWARF/DWARFDie.cpp
index 5c4fbfad4e8d5..73217511f1b34 100644
--- a/llvm/lib/DebugInfo/DWARF/DWARFDie.cpp
+++ b/llvm/lib/DebugInfo/DWARF/DWARFDie.cpp
@@ -110,7 +110,8 @@ static DWARFDie resolveReferencedType(DWARFDie D, DWARFFormValue F) {
 static llvm::StringRef
 prettyLanguageVersionString(const DWARFAttribute &AttrValue,
                             const DWARFDie &Die) {
-  assert(AttrValue.Attr == DW_AT_language_version);
+  if (AttrValue.Attr != DW_AT_language_version)
+    return {};
 
   auto NameForm = Die.find(DW_AT_language_name);
   if (!NameForm)
@@ -164,20 +165,31 @@ static void dumpAttribute(raw_ostream &OS, const DWARFDie &Die,
         }
       }
     }
-  } else if (Attr == llvm::dwarf::DW_AT_language_version && !DumpOpts.Verbose)
-    Name = prettyLanguageVersionString(AttrValue, Die);
-  else if (std::optional<uint64_t> Val = FormValue.getAsUnsignedConstant())
+  } else if (std::optional<uint64_t> Val = FormValue.getAsUnsignedConstant())
     Name = AttributeValueString(Attr, *Val);
 
-  if (!Name.empty())
-    WithColor(OS, Color) << Name;
-  else if (Attr == DW_AT_decl_line || Attr == DW_AT_decl_column ||
-           Attr == DW_AT_call_line || Attr == DW_AT_call_column ||
-           Attr == DW_AT_language_version) {
+  auto DumpUnsignedConstant = [&OS,
+                               &DumpOpts](const DWARFFormValue &FormValue) {
     if (std::optional<uint64_t> Val = FormValue.getAsUnsignedConstant())
       OS << *Val;
     else
       FormValue.dump(OS, DumpOpts);
+  };
+
+  llvm::StringRef PrettyVersionName =
+      prettyLanguageVersionString(AttrValue, Die);
+  const bool ShouldDumpRawLanguageVersion =
+      Attr == DW_AT_language_version &&
+      (DumpOpts.Verbose || PrettyVersionName.empty());
+
+  if (!Name.empty())
+    WithColor(OS, Color) << Name;
+  else if (Attr == DW_AT_decl_line || Attr == DW_AT_decl_column ||
+           Attr == DW_AT_call_line || Attr == DW_AT_call_column) {
+    DumpUnsignedConstant(FormValue);
+  } else if (Attr == DW_AT_language_version) {
+    if (ShouldDumpRawLanguageVersion)
+      DumpUnsignedConstant(FormValue);
   } else if (Attr == DW_AT_low_pc &&
              (FormValue.getAsAddress() ==
               dwarf::computeTombstoneAddress(U->getAddressByteSize()))) {
@@ -249,6 +261,10 @@ static void dumpAttribute(raw_ostream &OS, const DWARFDie &Die,
       DumpOpts.RecoverableErrorHandler(createStringError(
           errc::invalid_argument, "decoding address ranges: %s",
           toString(RangesOrError.takeError()).c_str()));
+  } else if (Attr == DW_AT_language_version) {
+    if (!PrettyVersionName.empty())
+      WithColor(OS, Color) << (ShouldDumpRawLanguageVersion ? " " : "")
+                           << PrettyVersionName;
   }
 
   OS << ")\n";
diff --git a/llvm/test/DebugInfo/Generic/compileunit-source-language-name.ll b/llvm/test/DebugInfo/Generic/compileunit-source-language-name.ll
index 90e0daf7648f3..58b5104592931 100644
--- a/llvm/test/DebugInfo/Generic/compileunit-source-language-name.ll
+++ b/llvm/test/DebugInfo/Generic/compileunit-source-language-name.ll
@@ -4,7 +4,7 @@
 
 ; CHECK:     DW_AT_language_name [DW_FORM_data2] (DW_LNAME_ObjC_plus_plus)
 ; CHECK:     DW_AT_language_name [DW_FORM_data2] (DW_LNAME_C_plus_plus)
-; CHECK:     DW_AT_language_version [DW_FORM_data4] (201100)
+; CHECK:     DW_AT_language_version [DW_FORM_data4] (201100 C++11)
 ; CHECK:     DW_AT_language_name [DW_FORM_data2] (DW_LNAME_Rust)
 ; CHECK-NOT: DW_AT_language_version
 
diff --git a/llvm/test/tools/llvm-dwarfdump/X86/DW_AT_language_version-pretty.s b/llvm/test/tools/llvm-dwarfdump/X86/DW_AT_language_version-pretty.s
index f9986a9cf2fb0..3af6fa922ae99 100644
--- a/llvm/test/tools/llvm-dwarfdump/X86/DW_AT_language_version-pretty.s
+++ b/llvm/test/tools/llvm-dwarfdump/X86/DW_AT_language_version-pretty.s
@@ -1,10 +1,15 @@
 # Demonstrate dumping DW_AT_language_version in human-readable form.
-# RUN: llvm-mc -triple=x86_64--linux -filetype=obj < %s | \
-# RUN:     llvm-dwarfdump - | FileCheck %s --implicit-check-not "DW_AT_language_version"
+# RUN: llvm-mc -triple=x86_64--linux -filetype=obj -o %t.o < %s
+# RUN: llvm-dwarfdump %t.o -v | FileCheck %s --check-prefix=VERBOSE
+# RUN: llvm-dwarfdump %t.o | FileCheck %s --check-prefix=NO-VERBOSE
 
-# CHECK: .debug_info contents:
-# CHECK: DW_AT_language_name (DW_LNAME_C)
-# CHECK: DW_AT_language_version (C11)
+# VERBOSE: .debug_info contents:
+# VERBOSE: DW_AT_language_name [DW_FORM_data2] (DW_LNAME_C)
+# VERBOSE: DW_AT_language_version [DW_FORM_data4] (201112 C11)
+
+# NO-VERBOSE: .debug_info contents:
+# NO-VERBOSE: DW_AT_language_name (DW_LNAME_C)
+# NO-VERBOSE: DW_AT_language_version (C11)
 
         .section        .debug_abbrev,"", at progbits
         .byte   1                       # Abbreviation Code
>From 16ee162d5d8b090ae3fc10081837e8240d8715f5 Mon Sep 17 00:00:00 2001
From: Michael Buch <michaelbuch12 at gmail.com>
Date: Tue, 21 Oct 2025 08:19:39 +0100
Subject: [PATCH 4/5] fixup! no const local
---
 llvm/lib/DebugInfo/DWARF/DWARFDie.cpp | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/llvm/lib/DebugInfo/DWARF/DWARFDie.cpp b/llvm/lib/DebugInfo/DWARF/DWARFDie.cpp
index 73217511f1b34..db5cc37c93f90 100644
--- a/llvm/lib/DebugInfo/DWARF/DWARFDie.cpp
+++ b/llvm/lib/DebugInfo/DWARF/DWARFDie.cpp
@@ -178,7 +178,7 @@ static void dumpAttribute(raw_ostream &OS, const DWARFDie &Die,
 
   llvm::StringRef PrettyVersionName =
       prettyLanguageVersionString(AttrValue, Die);
-  const bool ShouldDumpRawLanguageVersion =
+  bool ShouldDumpRawLanguageVersion =
       Attr == DW_AT_language_version &&
       (DumpOpts.Verbose || PrettyVersionName.empty());
 
>From 20e041148f5008572f1197ee029545e680f57187 Mon Sep 17 00:00:00 2001
From: Michael Buch <michaelbuch12 at gmail.com>
Date: Tue, 21 Oct 2025 08:29:05 +0100
Subject: [PATCH 5/5] fixup! add test explanation; add test-case for invalid
 DW_AT_language_name
---
 .../llvm-dwarfdump/X86/DW_AT_language_version-pretty.s     | 7 +++++++
 .../test/tools/llvm-dwarfdump/X86/DW_AT_language_version.s | 3 ++-
 2 files changed, 9 insertions(+), 1 deletion(-)
diff --git a/llvm/test/tools/llvm-dwarfdump/X86/DW_AT_language_version-pretty.s b/llvm/test/tools/llvm-dwarfdump/X86/DW_AT_language_version-pretty.s
index 3af6fa922ae99..b889ce5cfdcc3 100644
--- a/llvm/test/tools/llvm-dwarfdump/X86/DW_AT_language_version-pretty.s
+++ b/llvm/test/tools/llvm-dwarfdump/X86/DW_AT_language_version-pretty.s
@@ -6,10 +6,14 @@
 # VERBOSE: .debug_info contents:
 # VERBOSE: DW_AT_language_name [DW_FORM_data2] (DW_LNAME_C)
 # VERBOSE: DW_AT_language_version [DW_FORM_data4] (201112 C11)
+# VERBOSE: DW_AT_language_name [DW_FORM_data2] (0x0000)
+# VERBOSE: DW_AT_language_version [DW_FORM_data4] (12 Unknown)
 
 # NO-VERBOSE: .debug_info contents:
 # NO-VERBOSE: DW_AT_language_name (DW_LNAME_C)
 # NO-VERBOSE: DW_AT_language_version (C11)
+# NO-VERBOSE: DW_AT_language_name (0x0000)
+# NO-VERBOSE: DW_AT_language_version (Unknown)
 
         .section        .debug_abbrev,"", at progbits
         .byte   1                       # Abbreviation Code
@@ -33,5 +37,8 @@
         .byte   1                       # Abbrev [1] DW_TAG_compile_unit
         .short  3                       # DW_AT_language_name
         .long   201112                  # DW_AT_language_version
+        .byte   1                       # Abbrev [1] DW_TAG_compile_unit
+        .short  0                       # DW_AT_language_name
+        .long   12                      # DW_AT_language_version
         .byte   0 
 .Ldebug_info_end0:
diff --git a/llvm/test/tools/llvm-dwarfdump/X86/DW_AT_language_version.s b/llvm/test/tools/llvm-dwarfdump/X86/DW_AT_language_version.s
index e9bcfdedd346d..985836fcd1ef5 100644
--- a/llvm/test/tools/llvm-dwarfdump/X86/DW_AT_language_version.s
+++ b/llvm/test/tools/llvm-dwarfdump/X86/DW_AT_language_version.s
@@ -1,4 +1,5 @@
-# Demonstrate dumping DW_AT_language_version.
+# Demonstrate dumping DW_AT_language_version without an
+# accompanying DW_AT_language_name.
 # RUN: llvm-mc -triple=x86_64--linux -filetype=obj -o %t.o < %s
 # RUN: llvm-dwarfdump -v %t.o | FileCheck %s --check-prefix=VERBOSE
 # RUN: llvm-dwarfdump %t.o | FileCheck %s --check-prefix=NO-VERBOSE
    
    
More information about the llvm-commits
mailing list