diff --git a/llvm/lib/DebugInfo/DWARF/DWARFDie.cpp b/llvm/lib/DebugInfo/DWARF/DWARFDie.cpp index 212a0c039298b..db5cc37c93f90 100644 --- a/llvm/lib/DebugInfo/DWARF/DWARFDie.cpp +++ b/llvm/lib/DebugInfo/DWARF/DWARFDie.cpp @@ -107,6 +107,28 @@ static DWARFDie resolveReferencedType(DWARFDie D, DWARFFormValue F) { return D.getAttributeValueAsReferencedDie(F).resolveTypeUnitReference(); } +static llvm::StringRef +prettyLanguageVersionString(const DWARFAttribute &AttrValue, + const DWARFDie &Die) { + if (AttrValue.Attr != DW_AT_language_version) + return {}; + + 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(*LName), *LVersion); +} + static void dumpAttribute(raw_ostream &OS, const DWARFDie &Die, const DWARFAttribute &AttrValue, unsigned Indent, DIDumpOptions DumpOpts) { @@ -146,15 +168,28 @@ static void dumpAttribute(raw_ostream &OS, const DWARFDie &Die, } else if (std::optional 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 Val = FormValue.getAsUnsignedConstant()) OS << *Val; else FormValue.dump(OS, DumpOpts); + }; + + llvm::StringRef PrettyVersionName = + prettyLanguageVersionString(AttrValue, Die); + 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()))) { @@ -226,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 f5dcf01c7e89f..58b5104592931 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 C++11) +; 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 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..b889ce5cfdcc3 --- /dev/null +++ b/llvm/test/tools/llvm-dwarfdump/X86/DW_AT_language_version-pretty.s @@ -0,0 +1,44 @@ +# Demonstrate dumping DW_AT_language_version in human-readable form. +# 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 + +# 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,"",@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,"",@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 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 f1be8fdf6cd3e..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,13 +1,19 @@ -# Demonstrate dumping DW_AT_language_version. -# RUN: llvm-mc -triple=x86_64--linux -filetype=obj < %s | \ -# RUN: llvm-dwarfdump -v - | FileCheck %s +# 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 -# 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,"",@progbits .byte 1 # Abbreviation Code