[llvm] [llvm-dwarfdump] Support for DW_AT_language_name and DW_AT_language_version (PR #162449)
via llvm-commits
llvm-commits at lists.llvm.org
Wed Oct 8 03:01:54 PDT 2025
llvmbot wrote:
<!--LLVM PR SUMMARY COMMENT-->
@llvm/pr-subscribers-debuginfo
Author: Michael Buch (Michael137)
<details>
<summary>Changes</summary>
Depends on:
* https://github.com/llvm/llvm-project/pull/162434
* https://github.com/llvm/llvm-project/pull/162446
Makes sure we dump the attributes in a user-friendly way.
More info on the attributes here: https://dwarfstd.org/languages-v6.html
---
Full diff: https://github.com/llvm/llvm-project/pull/162449.diff
7 Files Affected:
- (modified) llvm/include/llvm/BinaryFormat/Dwarf.def (+3)
- (modified) llvm/include/llvm/BinaryFormat/Dwarf.h (+2)
- (modified) llvm/lib/BinaryFormat/Dwarf.cpp (+22)
- (modified) llvm/lib/DebugInfo/DWARF/DWARFDie.cpp (+2-1)
- (added) llvm/test/tools/llvm-dwarfdump/X86/DW_AT_language_name.s (+35)
- (added) llvm/test/tools/llvm-dwarfdump/X86/DW_AT_language_version.s (+35)
- (modified) llvm/unittests/BinaryFormat/DwarfTest.cpp (+35)
``````````diff
diff --git a/llvm/include/llvm/BinaryFormat/Dwarf.def b/llvm/include/llvm/BinaryFormat/Dwarf.def
index 2c9a3c0f6fb04..fbf22cc6f760b 100644
--- a/llvm/include/llvm/BinaryFormat/Dwarf.def
+++ b/llvm/include/llvm/BinaryFormat/Dwarf.def
@@ -424,6 +424,9 @@ HANDLE_DW_AT(0x89, export_symbols, 5, DWARF)
HANDLE_DW_AT(0x8a, deleted, 5, DWARF)
HANDLE_DW_AT(0x8b, defaulted, 5, DWARF)
HANDLE_DW_AT(0x8c, loclists_base, 5, DWARF)
+// New in Dwarf v6:
+HANDLE_DW_AT(0x90, language_name, 6, DWARF)
+HANDLE_DW_AT(0x91, language_version, 6, DWARF)
// Vendor extensions:
HANDLE_DW_AT(0x806, GHS_namespace_alias, 0, GHS)
diff --git a/llvm/include/llvm/BinaryFormat/Dwarf.h b/llvm/include/llvm/BinaryFormat/Dwarf.h
index 2c5012510a5c3..ba74ab9515a75 100644
--- a/llvm/include/llvm/BinaryFormat/Dwarf.h
+++ b/llvm/include/llvm/BinaryFormat/Dwarf.h
@@ -997,6 +997,7 @@ LLVM_ABI StringRef VisibilityString(unsigned Visibility);
LLVM_ABI StringRef VirtualityString(unsigned Virtuality);
LLVM_ABI StringRef EnumKindString(unsigned EnumKind);
LLVM_ABI StringRef LanguageString(unsigned Language);
+LLVM_ABI StringRef SourceLanguageNameString(SourceLanguageName Lang);
LLVM_ABI StringRef CaseString(unsigned Case);
LLVM_ABI StringRef ConventionString(unsigned Convention);
LLVM_ABI StringRef InlineCodeString(unsigned Code);
@@ -1038,6 +1039,7 @@ LLVM_ABI unsigned getSubOperationEncoding(unsigned OpEncoding,
LLVM_ABI unsigned getVirtuality(StringRef VirtualityString);
LLVM_ABI unsigned getEnumKind(StringRef EnumKindString);
LLVM_ABI unsigned getLanguage(StringRef LanguageString);
+LLVM_ABI unsigned getSourceLanguageName(StringRef SourceLanguageNameString);
LLVM_ABI unsigned getCallingConvention(StringRef LanguageString);
LLVM_ABI unsigned getAttributeEncoding(StringRef EncodingString);
LLVM_ABI unsigned getMacinfo(StringRef MacinfoString);
diff --git a/llvm/lib/BinaryFormat/Dwarf.cpp b/llvm/lib/BinaryFormat/Dwarf.cpp
index 8b24044e19e50..033c6a44be638 100644
--- a/llvm/lib/BinaryFormat/Dwarf.cpp
+++ b/llvm/lib/BinaryFormat/Dwarf.cpp
@@ -472,6 +472,26 @@ StringRef llvm::dwarf::LanguageDescription(dwarf::SourceLanguageName lname) {
return "Unknown";
}
+llvm::StringRef llvm::dwarf::SourceLanguageNameString(SourceLanguageName Lang) {
+ switch (Lang) {
+#define HANDLE_DW_LNAME(ID, NAME, DESC, LOWER_BOUND) \
+ case DW_LNAME_##NAME: \
+ return "DW_LNAME_" #NAME;
+#include "llvm/BinaryFormat/Dwarf.def"
+ }
+
+ return {};
+}
+
+unsigned
+llvm::dwarf::getSourceLanguageName(StringRef SourceLanguageNameString) {
+ return StringSwitch<unsigned>(SourceLanguageNameString)
+#define HANDLE_DW_LNAME(ID, NAME, DESC, LOWER_BOUND) \
+ .Case("DW_LNAME_" #NAME, DW_LNAME_##NAME)
+#include "llvm/BinaryFormat/Dwarf.def"
+ .Default(0);
+}
+
StringRef llvm::dwarf::CaseString(unsigned Case) {
switch (Case) {
case DW_ID_case_sensitive:
@@ -762,6 +782,8 @@ StringRef llvm::dwarf::AttributeValueString(uint16_t Attr, unsigned Val) {
return DefaultedMemberString(Val);
case DW_AT_APPLE_enum_kind:
return EnumKindString(Val);
+ case DW_AT_language_name:
+ return SourceLanguageNameString(static_cast<SourceLanguageName>(Val));
}
return StringRef();
diff --git a/llvm/lib/DebugInfo/DWARF/DWARFDie.cpp b/llvm/lib/DebugInfo/DWARF/DWARFDie.cpp
index edc69a36cdff2..212a0c039298b 100644
--- a/llvm/lib/DebugInfo/DWARF/DWARFDie.cpp
+++ b/llvm/lib/DebugInfo/DWARF/DWARFDie.cpp
@@ -149,7 +149,8 @@ static void dumpAttribute(raw_ostream &OS, const DWARFDie &Die,
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_call_line || Attr == DW_AT_call_column ||
+ Attr == DW_AT_language_version) {
if (std::optional<uint64_t> Val = FormValue.getAsUnsignedConstant())
OS << *Val;
else
diff --git a/llvm/test/tools/llvm-dwarfdump/X86/DW_AT_language_name.s b/llvm/test/tools/llvm-dwarfdump/X86/DW_AT_language_name.s
new file mode 100644
index 0000000000000..af581753be56a
--- /dev/null
+++ b/llvm/test/tools/llvm-dwarfdump/X86/DW_AT_language_name.s
@@ -0,0 +1,35 @@
+# Demonstrate dumping DW_AT_language_name.
+# RUN: llvm-mc -triple=x86_64--linux -filetype=obj < %s | \
+# RUN: llvm-dwarfdump -v - | FileCheck %s
+
+# CHECK: .debug_abbrev contents:
+# CHECK: DW_AT_language_name DW_FORM_data2
+# CHECK: DW_AT_language_name DW_FORM_data2
+# CHECK: .debug_info contents:
+# CHECK: DW_AT_language_name [DW_FORM_data2] (DW_LNAME_C)
+# CHECK: DW_AT_language_name [DW_FORM_data2] (0x0000)
+
+ .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 "\220\001" # DW_AT_language_name
+ .byte 5 # DW_FORM_data2
+ .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
+ .short 0 # DW_AT_language_name
+ .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
new file mode 100644
index 0000000000000..f1be8fdf6cd3e
--- /dev/null
+++ b/llvm/test/tools/llvm-dwarfdump/X86/DW_AT_language_version.s
@@ -0,0 +1,35 @@
+# Demonstrate dumping DW_AT_language_version.
+# RUN: llvm-mc -triple=x86_64--linux -filetype=obj < %s | \
+# RUN: llvm-dwarfdump -v - | FileCheck %s
+
+# 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)
+
+ .section .debug_abbrev,"", at progbits
+ .byte 1 # Abbreviation Code
+ .byte 17 # DW_TAG_compile_unit
+ .byte 1 # DW_CHILDREN_no
+ .ascii "\221\001" # DW_AT_language_version
+ .byte 6 # DW_FORM_data4
+ .ascii "\221\001" # DW_AT_language_version
+ .byte 5 # DW_FORM_data2
+ .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
+ .long 201402 # DW_AT_language_version
+ .short 0 # DW_AT_language_version
+ .byte 0
+.Ldebug_info_end0:
diff --git a/llvm/unittests/BinaryFormat/DwarfTest.cpp b/llvm/unittests/BinaryFormat/DwarfTest.cpp
index 684e59fa2785c..1162eb709aa83 100644
--- a/llvm/unittests/BinaryFormat/DwarfTest.cpp
+++ b/llvm/unittests/BinaryFormat/DwarfTest.cpp
@@ -219,4 +219,39 @@ TEST(DwarfTest, lname) {
EXPECT_EQ(roundtrip(DW_LANG_##NAME), DW_LANG_##NAME);
#include "llvm/BinaryFormat/Dwarf.def"
}
+
+TEST(DwarfTest, lname_getSourceLanguageName) {
+ // Some basics.
+ EXPECT_EQ(getSourceLanguageName("DW_LNAME_Ada"), DW_LNAME_Ada);
+ EXPECT_EQ(getSourceLanguageName("DW_LNAME_Metal"), DW_LNAME_Metal);
+
+ // Test invalid input.
+ EXPECT_EQ(getSourceLanguageName(""), 0U);
+ EXPECT_EQ(getSourceLanguageName("blah"), 0U);
+ EXPECT_EQ(getSourceLanguageName("DW_LNAME__something_unlikely"), 0U);
+ EXPECT_EQ(getSourceLanguageName("DW_LANG_C"), 0U);
+
+ // Test that we cover all DW_LNAME_ names.
+#define xstr(X) #X
+#define HANDLE_DW_LNAME(ID, NAME, DESC, LOWER_BOUND) \
+ EXPECT_EQ(getSourceLanguageName(xstr(DW_LNAME_##NAME)), DW_LNAME_##NAME);
+#include "llvm/BinaryFormat/Dwarf.def"
+}
+
+TEST(DwarfTest, lname_SourceLanguageNameString) {
+ // Some basics.
+ EXPECT_EQ(SourceLanguageNameString(DW_LNAME_C_plus_plus),
+ "DW_LNAME_C_plus_plus");
+ EXPECT_EQ(SourceLanguageNameString(DW_LNAME_CPP_for_OpenCL),
+ "DW_LNAME_CPP_for_OpenCL");
+
+ // Test invalid input.
+ EXPECT_EQ(SourceLanguageNameString(static_cast<SourceLanguageName>(0)), "");
+
+ // Test that we cover all DW_LNAME_ names.
+#define xstr(X) #X
+#define HANDLE_DW_LNAME(ID, NAME, DESC, LOWER_BOUND) \
+ EXPECT_EQ(SourceLanguageNameString(DW_LNAME_##NAME), xstr(DW_LNAME_##NAME));
+#include "llvm/BinaryFormat/Dwarf.def"
+}
} // end namespace
``````````
</details>
https://github.com/llvm/llvm-project/pull/162449
More information about the llvm-commits
mailing list