[llvm] [llvm][dwarfdump] Pretty-print DW_AT_language_version in non-verbose dwarfdump (PR #164222)
Michael Buch via llvm-commits
llvm-commits at lists.llvm.org
Mon Oct 20 07:20:32 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/3] [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/3] 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/3] 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
More information about the llvm-commits
mailing list