[llvm] ca715de - [llvm][DebugInfo] Add DW_AT_type to DW_TAG_enumeration_type in non-strict DWARF v2 mode (#98335)

via llvm-commits llvm-commits at lists.llvm.org
Fri Jul 12 01:42:33 PDT 2024


Author: David Spickett
Date: 2024-07-12T09:42:30+01:00
New Revision: ca715de4bcf31085ee7a35aaf60843e994801f10

URL: https://github.com/llvm/llvm-project/commit/ca715de4bcf31085ee7a35aaf60843e994801f10
DIFF: https://github.com/llvm/llvm-project/commit/ca715de4bcf31085ee7a35aaf60843e994801f10.diff

LOG: [llvm][DebugInfo] Add DW_AT_type to DW_TAG_enumeration_type in non-strict DWARF v2 mode (#98335)

During testing of https://github.com/llvm/llvm-project/pull/96202 we
found that when clang set to DWARF v2 was used to build the test file,
lldb could not tell that the unsigned enum type was in fact unsigned. So
it defaulted to signed and printed the wrong value.

The reason for this is that DWARFv2 does not include DW_AT_type in
DW_TAG_enumeration_type. This was added in DWARF v3:
"The enumeration type entry may also have a DW_AT_type attribute which
refers to the underlying data type used to implement the enumeration.

In C or C++, the underlying type will be the appropriate integral type
determined by the compiler from the properties of the enumeration
literal values."

I noticed that gcc does emit this attribute for DWARF v2 but not when
strict DWARF is requested (more details in
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=16063#c7).

This patch changes to clang to do the same. This will improve the
experience of anyone using tools that can understand the attribute but
for whatever reason are stuck building binaries containing v2 only.

You can see a current clang/gcc comparison here:
https://godbolt.org/z/eG9Kc9WGf

https://reviews.llvm.org/D42734 added the original code that emitted
this for >= v3 only.

Added: 
    

Modified: 
    llvm/docs/ReleaseNotes.rst
    llvm/lib/CodeGen/AsmPrinter/DwarfUnit.cpp
    llvm/test/DebugInfo/Generic/debug-info-enum.ll
    llvm/test/DebugInfo/X86/dbg-rust-valid-enum-as-scope.ll

Removed: 
    


################################################################################
diff  --git a/llvm/docs/ReleaseNotes.rst b/llvm/docs/ReleaseNotes.rst
index 4b8f7f20b5118..1dd7fce2334c9 100644
--- a/llvm/docs/ReleaseNotes.rst
+++ b/llvm/docs/ReleaseNotes.rst
@@ -319,6 +319,13 @@ Changes to the Debug Info
   supported on a best-effort basis from here onwards; for more information, see
   the `migration docs <https://llvm.org/docs/RemoveDIsDebugInfo.html>`_.
 
+* When emitting DWARF v2 and not in strict DWARF mode, LLVM will now add
+  a ``DW_AT_type`` to instances of ``DW_TAG_enumeration_type``. This is actually
+  a DWARF v3 feature which tells tools what the enum's underlying type is.
+  Emitting this for v2 as well will help users who have to build binaries with
+  DWARF v2 but are using tools that understand newer DWARF standards. Older
+  tools will ignore it. (`#98335 <https://github.com/llvm/llvm-project/pull/98335>`_)
+
 Changes to the LLVM tools
 ---------------------------------
 * llvm-nm and llvm-objdump can now print symbol information from linked

diff  --git a/llvm/lib/CodeGen/AsmPrinter/DwarfUnit.cpp b/llvm/lib/CodeGen/AsmPrinter/DwarfUnit.cpp
index 6c04fa1c67a95..e76b0fe2081c0 100644
--- a/llvm/lib/CodeGen/AsmPrinter/DwarfUnit.cpp
+++ b/llvm/lib/CodeGen/AsmPrinter/DwarfUnit.cpp
@@ -1585,7 +1585,7 @@ void DwarfUnit::constructEnumTypeDIE(DIE &Buffer, const DICompositeType *CTy) {
   const DIType *DTy = CTy->getBaseType();
   bool IsUnsigned = DTy && DD->isUnsignedDIType(DTy);
   if (DTy) {
-    if (DD->getDwarfVersion() >= 3)
+    if (!Asm->TM.Options.DebugStrictDwarf || DD->getDwarfVersion() >= 3)
       addType(Buffer, DTy);
     if (DD->getDwarfVersion() >= 4 && (CTy->getFlags() & DINode::FlagEnumClass))
       addFlag(Buffer, dwarf::DW_AT_enum_class);

diff  --git a/llvm/test/DebugInfo/Generic/debug-info-enum.ll b/llvm/test/DebugInfo/Generic/debug-info-enum.ll
index 85e22931a5fc1..9af465d59b7d9 100644
--- a/llvm/test/DebugInfo/Generic/debug-info-enum.ll
+++ b/llvm/test/DebugInfo/Generic/debug-info-enum.ll
@@ -2,11 +2,17 @@
 ; * test value representation for each possible underlying integer type
 ; * test the integer type is as expected
 ; * test the DW_AT_enum_class attribute is present (resp. absent) as expected.
+; * test that DW_AT_type is present for v3 and greater, and v2 when strict DWARF
+;   is not enabled.
 
 ; RUN: llc -debugger-tune=gdb -dwarf-version=4 -filetype=obj -o %t.o < %s
-; RUN: llvm-dwarfdump -debug-info %t.o | FileCheck %s --check-prefix=CHECK --check-prefix=CHECK-DW4
+; RUN: llvm-dwarfdump -debug-info %t.o | FileCheck %s --check-prefixes=CHECK,CHECK-DW4,CHECK-TYPE
+; RUN: llc -debugger-tune=gdb -dwarf-version=3 -filetype=obj -o %t.o < %s
+; RUN: llvm-dwarfdump -debug-info %t.o | FileCheck %s --check-prefixes=CHECK,CHECK-TYPE
 ; RUN: llc -debugger-tune=gdb -dwarf-version=2 -filetype=obj -o %t.o < %s
-; RUN: llvm-dwarfdump -debug-info %t.o | FileCheck %s --check-prefix=CHECK --check-prefix=CHECK-DW2
+; RUN: llvm-dwarfdump -debug-info %t.o | FileCheck %s --check-prefixes=CHECK,CHECK-TYPE
+; RUN: llc -debugger-tune=gdb -dwarf-version=2 -strict-dwarf=true -filetype=obj -o %t.o < %s
+; RUN: llvm-dwarfdump -debug-info %t.o | FileCheck %s --check-prefixes=CHECK,CHECK-DW2-STRICT
 
 @x0 = global i8 0, align 1, !dbg !0
 @x1 = global i8 0, align 1, !dbg !46
@@ -34,8 +40,8 @@
 !8 = !DIEnumerator(name: "A0", value: -128)
 !9 = !DIEnumerator(name: "B0", value: 127)
 ; CHECK:         DW_TAG_enumeration_type
-; CHECK-DW2-NOT:   DW_AT_type
-; CHECK-DW4:       DW_AT_type{{.*}}"signed char"
+; CHECK-DW2-STRICT-NOT: DW_AT_type
+; CHECK-TYPE:      DW_AT_type{{.*}}"signed char"
 ; CHECK-DW4:       DW_AT_enum_class        (true)
 ; CHECK:           DW_AT_name      ("E0")
 ; CHECK:         DW_TAG_enumerator
@@ -51,8 +57,8 @@
 !12 = !{!13}
 !13 = !DIEnumerator(name: "A1", value: 255, isUnsigned: true)
 ; CHECK:         DW_TAG_enumeration_type
-; CHECK-DW2-NOT:   DW_AT_type
-; CHECK-DW4:       DW_AT_type{{.*}}"unsigned char"
+; CHECK-DW2-STRICT-NOT: DW_AT_type
+; CHECK-TYPE:      DW_AT_type{{.*}}"unsigned char"
 ; CHECK-DW4:       DW_AT_enum_class        (true)
 ; CHECK:           DW_AT_name      ("E1")
 ; CHECK:         DW_TAG_enumerator
@@ -66,8 +72,8 @@
 !17 = !DIEnumerator(name: "A2", value: -32768)
 !18 = !DIEnumerator(name: "B2", value: 32767)
 ; CHECK:         DW_TAG_enumeration_type
-; CHECK-DW2-NOT:   DW_AT_type
-; CHECK-DW4:       DW_AT_type{{.*}} "short"
+; CHECK-DW2-STRICT-NOT:   DW_AT_type
+; CHECK-TYPE:      DW_AT_type{{.*}} "short"
 ; CHECK-DW4:       DW_AT_enum_class        (true)
 ; CHECK:           DW_AT_name      ("E2")
 ; CHECK:         DW_TAG_enumerator
@@ -83,8 +89,8 @@
 !21 = !{!22}
 !22 = !DIEnumerator(name: "A3", value: 65535, isUnsigned: true)
 ; CHECK:         DW_TAG_enumeration_type
-; CHECK-DW2-NOT:   DW_AT_type
-; CHECK-DW4:       DW_AT_type{{.*}}"unsigned short"
+; CHECK-DW2-STRICT-NOT: DW_AT_type
+; CHECK-TYPE       DW_AT_type{{.*}}"unsigned short"
 ; CHECK-DW4:       DW_AT_enum_class        (true)
 ; CHECK:           DW_AT_name      ("E3")
 ; CHECK:         DW_TAG_enumerator
@@ -98,8 +104,8 @@
 !26 = !DIEnumerator(name: "A4", value: -2147483648)
 !27 = !DIEnumerator(name: "B4", value: 2147483647)
 ; CHECK:         DW_TAG_enumeration_type
-; CHECK-DW2-NOT:   DW_AT_type
-; CHECK-DW4:       DW_AT_type{{.*}}"int"
+; CHECK-DW2-STRICT-NOT: DW_AT_type
+; CHECK-TYPE:      DW_AT_type{{.*}}"int"
 ; CHECK-DW4:       DW_AT_enum_class        (true)
 ; CHECK:           DW_AT_name      ("E4")
 ; CHECK:         DW_TAG_enumerator
@@ -115,8 +121,8 @@
 !30 = !{!31}
 !31 = !DIEnumerator(name: "A5", value: 4294967295, isUnsigned: true)
 ; CHECK:         DW_TAG_enumeration_type
-; CHECK-DW2-NOT:   DW_AT_type
-; CHECK-DW4:       DW_AT_type{{.*}}"unsigned int"
+; CHECK-DW2-STRICT-NOT: DW_AT_type
+; CHECK-TYPE:      DW_AT_type{{.*}}"unsigned int"
 ; CHECK-DW4:       DW_AT_enum_class        (true)
 ; CHECK:           DW_AT_name      ("E5")
 ; CHECK:         DW_TAG_enumerator
@@ -130,8 +136,8 @@
 !35 = !DIEnumerator(name: "A6", value: -9223372036854775808)
 !36 = !DIEnumerator(name: "B6", value: 9223372036854775807)
 ; CHECK:         DW_TAG_enumeration_type
-; CHECK-DW2-NOT:   DW_AT_type
-; CHECK-DW4:       DW_AT_type{{.*}}"long long int"
+; CHECK-DW2-STRICT-NOT:   DW_AT_type
+; CHECK-TYPE:      DW_AT_type{{.*}}"long long int"
 ; CHECK-DW4:       DW_AT_enum_class        (true)
 ; CHECK:           DW_AT_name      ("E6")
 ; CHECK:         DW_TAG_enumerator
@@ -147,8 +153,8 @@
 !39 = !{!40}
 !40 = !DIEnumerator(name: "A7", value: 18446744073709551615, isUnsigned: true)
 ; CHECK:         DW_TAG_enumeration_type
-; CHECK-DW2-NOT:   DW_AT_type
-; CHECK-DW4:       DW_AT_type{{.*}}"long long unsigned int"
+; CHECK-DW2-STRICT-NOT:   DW_AT_type
+; CHECK-TYPE:      DW_AT_type{{.*}}"long long unsigned int"
 ; CHECK-DW4:       DW_AT_enum_class        (true)
 ; CHECK:           DW_AT_name      ("E7")
 ; CHECK:         DW_TAG_enumerator
@@ -163,8 +169,8 @@
 !43 = !DIEnumerator(name: "A8", value: -128)
 !44 = !DIEnumerator(name: "B8", value: 127)
 ; CHECK:         DW_TAG_enumeration_type
-; CHECK-DW2-NOT:   DW_AT_type
-; CHECK-DW4:       DW_AT_type{{.*}}"int"
+; CHECK-DW2-STRICT-NOT:   DW_AT_type
+; CHECK-TYPE:      DW_AT_type{{.*}}"int"
 ; CHECK-NOT:       DW_AT_enum_class
 ; CHECK:           DW_AT_name      ("E8")
 

diff  --git a/llvm/test/DebugInfo/X86/dbg-rust-valid-enum-as-scope.ll b/llvm/test/DebugInfo/X86/dbg-rust-valid-enum-as-scope.ll
index f44ca04e0fd96..263cbeee2a01f 100644
--- a/llvm/test/DebugInfo/X86/dbg-rust-valid-enum-as-scope.ll
+++ b/llvm/test/DebugInfo/X86/dbg-rust-valid-enum-as-scope.ll
@@ -3,6 +3,7 @@
 ; CHECK:   DW_AT_language	(DW_LANG_Rust)
 ; CHECK:   DW_TAG_namespace
 ; CHECK:     DW_TAG_enumeration_type
+; CHECK:     DW_AT_type (0x{{[0-9A-Fa-f]+}} "u8")
 ; CHECK:     DW_AT_name	("E")
 ; CHECK:       DW_TAG_enumerator
 ; CHECK:       DW_TAG_enumerator
@@ -12,6 +13,8 @@
 ; CHECK:         NULL
 ; CHECK:       NULL
 ; CHECK:     NULL
+; CHECK:   DW_TAG_base_type
+; CHECK:     DW_AT_name ("u8")
 ; CHECK:   DW_TAG_pointer_type
 ; CHECK:   NULL
 


        


More information about the llvm-commits mailing list