From ec99905f7b39914ddb074c13ffbe05f0216784a1 Mon Sep 17 00:00:00 2001 From: Jakub Jelinek Date: Wed, 8 Jan 2025 10:57:50 +0100 Subject: [PATCH] dwarf2out: Emit DWARF 6 DW_AT_language_{name,version} DWARF has voted in recently https://dwarfstd.org/issues/241209.1.html , which is basically just a guarantee that the DWARF 6 draft DW_AT_language_{name,version} attribute codes and content of https://dwarfstd.org/languages-v6.html can be used as an extension in DWARF 5 and won't be changed. So, this patch is an alternative to the https://gcc.gnu.org/pipermail/gcc-patches/2024-November/669671.html patch, which had the major problem that it required changing all the DWARF consumers to be able to debug C17 or later or C++17 or later sources. This patch uses still DWARF 5 DW_LANG_C11 or DW_LANG_C_plus_plus_14, the latest code in DWARF 5 proper, so all DWARF 5 capable consumers should be able to deal with that, but additionally emits the DWARF 6 attributes so that newer DWARF consumers can see it isn't just C++14 but say C++23 or C11 but C23. Consumers which don't know those DWARF 6 attributes would just ignore them. This is like any other -gno-strict-dwarf extension, except that normally we emit say DWARF 5 codes where possible only after DWARF 5 is released, while in this case there is a guarantee it can be used before DWARF 6 is released. 2025-01-08 Jakub Jelinek include/ * dwarf2.h (enum dwarf_source_language): Fix comment pasto. (enum dwarf_source_language_name): New type. * dwarf2.def (DW_AT_language_name, DW_AT_language_version): New DWARF 6 codes. gcc/ * dwarf2out.cc (break_out_comdat_types): Copy over DW_AT_language_{name,version} if present. (output_skeleton_debug_sections): Remove also DW_AT_language_{name,version}. (gen_compile_unit_die): For C17, C23, C2Y, C++17, C++20, C++23 and C++26 emit for -gdwarf-5 -gno-strict-dwarf also DW_AT_language_{name,version} attributes. gcc/testsuite/ * g++.dg/debug/dwarf2/lang-cpp17.C: Add -gno-strict-dwarf to dg-options. Check also for DW_AT_language_{name,version} values. * g++.dg/debug/dwarf2/lang-cpp20.C: Likewise. * g++.dg/debug/dwarf2/lang-cpp23.C: New test. --- gcc/dwarf2out.cc | 76 ++++++++++++++++--- .../g++.dg/debug/dwarf2/lang-cpp17.C | 6 +- .../g++.dg/debug/dwarf2/lang-cpp20.C | 6 +- .../g++.dg/debug/dwarf2/lang-cpp23.C | 10 +++ include/dwarf2.def | 3 + include/dwarf2.h | 55 +++++++++++++- 6 files changed, 139 insertions(+), 17 deletions(-) create mode 100644 gcc/testsuite/g++.dg/debug/dwarf2/lang-cpp23.C diff --git a/gcc/dwarf2out.cc b/gcc/dwarf2out.cc index 1f6a6ce4182..8085b8d85d8 100644 --- a/gcc/dwarf2out.cc +++ b/gcc/dwarf2out.cc @@ -8755,6 +8755,14 @@ break_out_comdat_types (dw_die_ref die) unit = new_die (DW_TAG_type_unit, NULL, NULL); add_AT_unsigned (unit, DW_AT_language, get_AT_unsigned (comp_unit_die (), DW_AT_language)); + if (unsigned lname = get_AT_unsigned (comp_unit_die (), + DW_AT_language_name)) + { + add_AT_unsigned (unit, DW_AT_language_name, lname); + add_AT_unsigned (unit, DW_AT_language_version, + get_AT_unsigned (comp_unit_die (), + DW_AT_language_version)); + } /* Add the new unit's type DIE into the comdat type list. */ type_node = ggc_cleared_alloc (); @@ -11404,6 +11412,8 @@ output_skeleton_debug_sections (dw_die_ref comp_unit, /* These attributes will be found in the full debug_info section. */ remove_AT (comp_unit, DW_AT_producer); remove_AT (comp_unit, DW_AT_language); + remove_AT (comp_unit, DW_AT_language_name); + remove_AT (comp_unit, DW_AT_language_version); switch_to_section (debug_skeleton_info_section); ASM_OUTPUT_LABEL (asm_out_file, debug_skeleton_info_section_label); @@ -25318,7 +25328,7 @@ gen_compile_unit_die (const char *filename) { dw_die_ref die; const char *language_string = lang_hooks.name; - int language; + int language, lname, lversion; die = new_die (DW_TAG_compile_unit, NULL, NULL); @@ -25366,6 +25376,8 @@ gen_compile_unit_die (const char *filename) } language = DW_LANG_C; + lname = 0; + lversion = 0; if (startswith (language_string, "GNU C") && ISDIGIT (language_string[5])) { @@ -25376,11 +25388,28 @@ gen_compile_unit_die (const char *filename) language = DW_LANG_C99; if (dwarf_version >= 5 /* || !dwarf_strict */) - if (strcmp (language_string, "GNU C11") == 0 - || strcmp (language_string, "GNU C17") == 0 - || strcmp (language_string, "GNU C23") == 0 - || strcmp (language_string, "GNU C2Y") == 0) - language = DW_LANG_C11; + { + if (strcmp (language_string, "GNU C11") == 0) + language = DW_LANG_C11; + else if (strcmp (language_string, "GNU C17") == 0) + { + language = DW_LANG_C11; + lname = DW_LNAME_C; + lversion = 201710; + } + else if (strcmp (language_string, "GNU C23") == 0) + { + language = DW_LANG_C11; + lname = DW_LNAME_C; + lversion = 202311; + } + else if (strcmp (language_string, "GNU C2Y") == 0) + { + language = DW_LANG_C11; + lname = DW_LNAME_C; + lversion = 202500; + } + } } } else if (startswith (language_string, "GNU C++")) @@ -25392,12 +25421,30 @@ gen_compile_unit_die (const char *filename) language = DW_LANG_C_plus_plus_11; else if (strcmp (language_string, "GNU C++14") == 0) language = DW_LANG_C_plus_plus_14; - else if (strcmp (language_string, "GNU C++17") == 0 - || strcmp (language_string, "GNU C++20") == 0 - || strcmp (language_string, "GNU C++23") == 0 - || strcmp (language_string, "GNU C++26") == 0) - /* For now. */ - language = DW_LANG_C_plus_plus_14; + else if (strcmp (language_string, "GNU C++17") == 0) + { + language = DW_LANG_C_plus_plus_14; + lname = DW_LNAME_C_plus_plus; + lversion = 201703; + } + else if (strcmp (language_string, "GNU C++20") == 0) + { + language = DW_LANG_C_plus_plus_14; + lname = DW_LNAME_C_plus_plus; + lversion = 202002; + } + else if (strcmp (language_string, "GNU C++23") == 0) + { + language = DW_LANG_C_plus_plus_14; + lname = DW_LNAME_C_plus_plus; + lversion = 202302; + } + else if (strcmp (language_string, "GNU C++26") == 0) + { + language = DW_LANG_C_plus_plus_14; + lname = DW_LNAME_C_plus_plus; + lversion = 202400; + } } } else if (strcmp (language_string, "GNU F77") == 0) @@ -25441,6 +25488,11 @@ gen_compile_unit_die (const char *filename) language = DW_LANG_Ada83; add_AT_unsigned (die, DW_AT_language, language); + if (lname && dwarf_version >= 5 && !dwarf_strict) + { + add_AT_unsigned (die, DW_AT_language_name, lname); + add_AT_unsigned (die, DW_AT_language_version, lversion); + } switch (language) { diff --git a/gcc/testsuite/g++.dg/debug/dwarf2/lang-cpp17.C b/gcc/testsuite/g++.dg/debug/dwarf2/lang-cpp17.C index a1e3cccea26..18f73eed874 100644 --- a/gcc/testsuite/g++.dg/debug/dwarf2/lang-cpp17.C +++ b/gcc/testsuite/g++.dg/debug/dwarf2/lang-cpp17.C @@ -1,8 +1,10 @@ // { dg-do compile } -// { dg-options "-O -std=c++17 -gdwarf-5 -dA" } +// { dg-options "-O -std=c++17 -gdwarf-5 -dA -gno-strict-dwarf" } // { dg-skip-if "AIX DWARF5" { powerpc-ibm-aix* } } -// For -gdwarf-6 hopefully DW_LANG_C_plus_plus_17 // DW_LANG_C_plus_plus_14 = 0x0021 +// DW_LNAME_C_plus_plus = 0x0004 201703 // { dg-final { scan-assembler "0x21\[^\n\r]* DW_AT_language" } } */ +// { dg-final { scan-assembler "0x4\[^\n\r]* DW_AT_language_name" } } */ +// { dg-final { scan-assembler "0x313e7\[^\n\r]* DW_AT_language_version" } } */ int version; diff --git a/gcc/testsuite/g++.dg/debug/dwarf2/lang-cpp20.C b/gcc/testsuite/g++.dg/debug/dwarf2/lang-cpp20.C index 62abd618155..28eca154441 100644 --- a/gcc/testsuite/g++.dg/debug/dwarf2/lang-cpp20.C +++ b/gcc/testsuite/g++.dg/debug/dwarf2/lang-cpp20.C @@ -1,8 +1,10 @@ // { dg-do compile } -// { dg-options "-O -std=c++20 -gdwarf-5 -dA" } +// { dg-options "-O -std=c++20 -gdwarf-5 -dA -gno-strict-dwarf" } // { dg-skip-if "AIX DWARF5" { powerpc-ibm-aix* } } -// For -gdwarf-6 hopefully DW_LANG_C_plus_plus_20 // DW_LANG_C_plus_plus_14 = 0x0021 +// DW_LNAME_C_plus_plus = 0x0004 202002 // { dg-final { scan-assembler "0x21\[^\n\r]* DW_AT_language" } } */ +// { dg-final { scan-assembler "0x4\[^\n\r]* DW_AT_language_name" } } */ +// { dg-final { scan-assembler "0x31512\[^\n\r]* DW_AT_language_version" } } */ int version; diff --git a/gcc/testsuite/g++.dg/debug/dwarf2/lang-cpp23.C b/gcc/testsuite/g++.dg/debug/dwarf2/lang-cpp23.C new file mode 100644 index 00000000000..8bcc8f2d389 --- /dev/null +++ b/gcc/testsuite/g++.dg/debug/dwarf2/lang-cpp23.C @@ -0,0 +1,10 @@ +// { dg-do compile } +// { dg-options "-O -std=c++23 -gdwarf-5 -dA -gno-strict-dwarf" } +// { dg-skip-if "AIX DWARF5" { powerpc-ibm-aix* } } +// DW_LANG_C_plus_plus_14 = 0x0021 +// DW_LNAME_C_plus_plus = 0x0004 202302 +// { dg-final { scan-assembler "0x21\[^\n\r]* DW_AT_language" } } */ +// { dg-final { scan-assembler "0x4\[^\n\r]* DW_AT_language_name" } } */ +// { dg-final { scan-assembler "0x3163e\[^\n\r]* DW_AT_language_version" } } */ + +int version; diff --git a/include/dwarf2.def b/include/dwarf2.def index 63cb35560e7..e9acb79df9c 100644 --- a/include/dwarf2.def +++ b/include/dwarf2.def @@ -364,6 +364,9 @@ DW_AT (DW_AT_export_symbols, 0x89) DW_AT (DW_AT_deleted, 0x8a) DW_AT (DW_AT_defaulted, 0x8b) DW_AT (DW_AT_loclists_base, 0x8c) +/* DWARF 6. */ +DW_AT (DW_AT_language_name, 0x90) +DW_AT (DW_AT_language_version, 0x91) DW_AT_DUP (DW_AT_lo_user, 0x2000) /* Implementation-defined range start. */ DW_AT_DUP (DW_AT_hi_user, 0x3fff) /* Implementation-defined range end. */ diff --git a/include/dwarf2.h b/include/dwarf2.h index 0b193a250de..344447fbc36 100644 --- a/include/dwarf2.h +++ b/include/dwarf2.h @@ -411,7 +411,7 @@ enum dwarf_source_language DW_LANG_Hylo = 0x0042, DW_LANG_lo_user = 0x8000, /* Implementation-defined range start. */ - DW_LANG_hi_user = 0xffff, /* Implementation-defined range start. */ + DW_LANG_hi_user = 0xffff, /* Implementation-defined range end. */ /* MIPS. */ DW_LANG_Mips_Assembler = 0x8001, @@ -428,6 +428,59 @@ enum dwarf_source_language DW_LANG_Rust_old = 0x9000 }; +/* DWARF 6 source language names and codes. */ +enum dwarf_source_language_name + { + /* https://dwarfstd.org/languages-v6.html */ + DW_LNAME_Ada = 0x0001, + DW_LNAME_BLISS = 0x0002, + DW_LNAME_C = 0x0003, + DW_LNAME_C_plus_plus = 0x0004, + DW_LNAME_Cobol = 0x0005, + DW_LNAME_Crystal = 0x0006, + DW_LNAME_D = 0x0007, + DW_LNAME_Dylan = 0x0008, + DW_LNAME_Fortran = 0x0009, + DW_LNAME_Go = 0x000a, + DW_LNAME_Haskell = 0x000b, + DW_LNAME_Java = 0x000c, + DW_LNAME_Julia = 0x000d, + DW_LNAME_Kotlin = 0x000e, + DW_LNAME_Modula2 = 0x000f, + DW_LNAME_Modula3 = 0x0010, + DW_LNAME_ObjC = 0x0011, + DW_LNAME_ObjC_plus_plus = 0x0012, + DW_LNAME_OCaml = 0x0013, + DW_LNAME_OpenCL_C = 0x0014, + DW_LNAME_Pascal = 0x0015, + DW_LNAME_PLI = 0x0016, + DW_LNAME_Python = 0x0017, + DW_LNAME_RenderScript = 0x0018, + DW_LNAME_Rust = 0x0019, + DW_LNAME_Swift = 0x001a, + DW_LNAME_UPC = 0x001b, + DW_LNAME_Zig = 0x001c, + DW_LNAME_Assembly = 0x001d, + DW_LNAME_C_sharp = 0x001e, + DW_LNAME_Mojo = 0x001f, + DW_LNAME_GLSL = 0x0020, + DW_LNAME_GLSL_ES = 0x0021, + DW_LNAME_HLSL = 0x0022, + DW_LNAME_OpenCL_CPP = 0x0023, + DW_LNAME_CPP_for_OpenCL = 0x0024, + DW_LNAME_SYCL = 0x0025, + DW_LNAME_Ruby = 0x0026, + DW_LNAME_Move = 0x0027, + DW_LNAME_Hylo = 0x0028, + DW_LNAME_HIP = 0x0029, + DW_LNAME_Odin = 0x002a, + DW_LNAME_P4 = 0x002b, + DW_LNAME_Metal = 0x002c, + + DW_LNAME_lo_user = 0x8000, /* Implementation-defined range start. */ + DW_LNAME_hi_user = 0xffff /* Implementation-defined range end. */ + }; + /* Names and codes for macro information. */ enum dwarf_macinfo_record_type {