Skip to content

Commit

Permalink
[llvm][DebugInfo] Add DW_AT_type to DW_TAG_enumeration_type in non-st…
Browse files Browse the repository at this point in the history
…rict DWARF v2 mode (llvm#98335)

During testing of llvm#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.
  • Loading branch information
DavidSpickett authored and aaryanshukla committed Jul 14, 2024
1 parent 60bf582 commit 9abb2fa
Show file tree
Hide file tree
Showing 4 changed files with 37 additions and 21 deletions.
7 changes: 7 additions & 0 deletions llvm/docs/ReleaseNotes.rst
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
2 changes: 1 addition & 1 deletion llvm/lib/CodeGen/AsmPrinter/DwarfUnit.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down
46 changes: 26 additions & 20 deletions llvm/test/DebugInfo/Generic/debug-info-enum.ll
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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
Expand All @@ -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
Expand All @@ -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
Expand All @@ -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
Expand All @@ -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
Expand All @@ -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
Expand All @@ -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
Expand All @@ -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
Expand All @@ -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")

Expand Down
3 changes: 3 additions & 0 deletions llvm/test/DebugInfo/X86/dbg-rust-valid-enum-as-scope.ll
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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

Expand Down

0 comments on commit 9abb2fa

Please sign in to comment.