-
Notifications
You must be signed in to change notification settings - Fork 15.2k
[DWARF] Ignore DW_ATE_lo_user to hi_user in DebugHandlerBase assertion #161695
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
Fixes llvm#140362 Clang's `CGDebugInfo::CreateType(const ComplexType *Ty)` already emits this ATE encoding (0x80) without giving it an explicit name. I chose the name because it sounded right rather than because I know that's what GNU uses as I couldn't find that info (but I can see that the 0x80 encoding is what GCC emits for this example).
@llvm/pr-subscribers-debuginfo @llvm/pr-subscribers-clang Author: Orlando Cazalet-Hyams (OCHyams) ChangesFixes #140362 Clang's Full diff: https://github.com/llvm/llvm-project/pull/161695.diff 4 Files Affected:
diff --git a/clang/lib/CodeGen/CGDebugInfo.cpp b/clang/lib/CodeGen/CGDebugInfo.cpp
index 12c7d48e20d67..c1e21c6c2e0aa 100644
--- a/clang/lib/CodeGen/CGDebugInfo.cpp
+++ b/clang/lib/CodeGen/CGDebugInfo.cpp
@@ -1119,7 +1119,7 @@ llvm::DIType *CGDebugInfo::CreateType(const ComplexType *Ty) {
// Bit size and offset of the type.
llvm::dwarf::TypeKind Encoding = llvm::dwarf::DW_ATE_complex_float;
if (Ty->isComplexIntegerType())
- Encoding = llvm::dwarf::DW_ATE_lo_user;
+ Encoding = llvm::dwarf::DW_ATE_GNU_complex_signed;
uint64_t Size = CGM.getContext().getTypeSize(Ty);
return DBuilder.createBasicType("complex", Size, Encoding);
diff --git a/llvm/include/llvm/BinaryFormat/Dwarf.def b/llvm/include/llvm/BinaryFormat/Dwarf.def
index 2c9a3c0f6fb04..29199b2659f0e 100644
--- a/llvm/include/llvm/BinaryFormat/Dwarf.def
+++ b/llvm/include/llvm/BinaryFormat/Dwarf.def
@@ -1111,6 +1111,8 @@ HANDLE_DW_ATE(0x12, ASCII, 5, DWARF)
// HANDLE_DW_ATE(0x80, ALTIUM_fract, 2, ALTIUM) = DW_ATE_low_user
// HANDLE_DW_ATE(0x81, ALTIUM_accum, 2, ALTIUM)
+HANDLE_DW_ATE(0x80, GNU_complex_signed, 4, GNU)
+
HANDLE_DW_ATE(0x81, HP_complex_float, 2, HP)
HANDLE_DW_ATE(0x82, HP_float128, 2, HP)
HANDLE_DW_ATE(0x83, HP_complex_float128, 2, HP)
diff --git a/llvm/lib/CodeGen/AsmPrinter/DebugHandlerBase.cpp b/llvm/lib/CodeGen/AsmPrinter/DebugHandlerBase.cpp
index 0f3ff985974ce..983fd7594157b 100644
--- a/llvm/lib/CodeGen/AsmPrinter/DebugHandlerBase.cpp
+++ b/llvm/lib/CodeGen/AsmPrinter/DebugHandlerBase.cpp
@@ -236,6 +236,7 @@ bool DebugHandlerBase::isUnsignedDIType(const DIType *Ty) {
Encoding == dwarf::DW_ATE_float || Encoding == dwarf::DW_ATE_UTF ||
Encoding == dwarf::DW_ATE_boolean ||
Encoding == dwarf::DW_ATE_complex_float ||
+ Encoding == dwarf::DW_ATE_GNU_complex_signed ||
Encoding == dwarf::DW_ATE_signed_fixed ||
Encoding == dwarf::DW_ATE_unsigned_fixed ||
(Ty->getTag() == dwarf::DW_TAG_unspecified_type &&
diff --git a/llvm/test/DebugInfo/dwarf-complex-int.ll b/llvm/test/DebugInfo/dwarf-complex-int.ll
new file mode 100644
index 0000000000000..ad8a1fa78f083
--- /dev/null
+++ b/llvm/test/DebugInfo/dwarf-complex-int.ll
@@ -0,0 +1,59 @@
+; REQUIRES: object-emission
+; RUN: %llc_dwarf %s -filetype=obj -o - | llvm-dwarfdump - | FileCheck %s
+
+;; https://github.com/llvm/llvm-project/issues/140362
+;; Don't assert when emitting a complex integer type in DWARF.
+
+;; C source:
+;; int g;
+;;
+;; void foo(_Complex short c) { __builtin_memmove(&g, (char *)&c, 2); }
+;;
+;; void bar() { foo(0); }
+
+; CHECK: DW_AT_type ([[complex:0x[0-9a-f]+]] "complex")
+
+; CHECK: [[complex]]: DW_TAG_base_type
+; CHECK-NEXT: DW_AT_name ("complex")
+; CHECK-NEXT: DW_AT_encoding (DW_ATE_GNU_complex_signed)
+; CHECK-NEXT: DW_AT_byte_size (0x04)
+
+@g = dso_local local_unnamed_addr global i32 0, align 4, !dbg !0
+
+define dso_local void @bar() local_unnamed_addr !dbg !18 {
+entry:
+ #dbg_value(i32 0, !21, !DIExpression(), !27)
+ store i16 0, ptr @g, align 4, !dbg !29
+ ret void, !dbg !30
+}
+
+!llvm.dbg.cu = !{!2}
+!llvm.module.flags = !{!10, !11}
+!llvm.ident = !{!17}
+
+!0 = !DIGlobalVariableExpression(var: !1, expr: !DIExpression())
+!1 = distinct !DIGlobalVariable(name: "g", scope: !2, file: !8, line: 1, type: !9, isLocal: false, isDefinition: true)
+!2 = distinct !DICompileUnit(language: DW_LANG_C_plus_plus_14, file: !3, producer: "clang version 22.0.0git", isOptimized: true, runtimeVersion: 0, emissionKind: FullDebug, retainedTypes: !4, globals: !7, splitDebugInlining: false, nameTableKind: None)
+!3 = !DIFile(filename: "/app/example.cpp", directory: "/app")
+!4 = !{!5}
+!5 = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: !6, size: 64)
+!6 = !DIBasicType(name: "char", size: 8, encoding: DW_ATE_signed_char)
+!7 = !{!0}
+!8 = !DIFile(filename: "example.cpp", directory: "/app")
+!9 = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed)
+!10 = !{i32 7, !"Dwarf Version", i32 5}
+!11 = !{i32 2, !"Debug Info Version", i32 3}
+!17 = !{!"clang version 22.0.0git"}
+!18 = distinct !DISubprogram(name: "bar", linkageName: "bar()", scope: !8, file: !8, line: 5, type: !19, scopeLine: 5, flags: DIFlagPrototyped | DIFlagAllCallsDescribed, spFlags: DISPFlagDefinition | DISPFlagOptimized, unit: !2, keyInstructions: true)
+!19 = !DISubroutineType(types: !20)
+!20 = !{null}
+!21 = !DILocalVariable(name: "c", arg: 1, scope: !22, file: !8, line: 3, type: !25)
+!22 = distinct !DISubprogram(name: "foo", linkageName: "_ZL3fooCs", scope: !8, file: !8, line: 3, type: !23, scopeLine: 3, flags: DIFlagPrototyped | DIFlagAllCallsDescribed, spFlags: DISPFlagLocalToUnit | DISPFlagDefinition | DISPFlagOptimized, unit: !2, retainedNodes: !26, keyInstructions: true)
+!23 = !DISubroutineType(types: !24)
+!24 = !{null, !25}
+!25 = !DIBasicType(name: "complex", size: 32, encoding: 128)
+!26 = !{!21}
+!27 = !DILocation(line: 0, scope: !22, inlinedAt: !28)
+!28 = distinct !DILocation(line: 5, column: 14, scope: !18)
+!29 = !DILocation(line: 3, column: 37, scope: !22, inlinedAt: !28, atomGroup: 1, atomRank: 1)
+!30 = !DILocation(line: 5, column: 22, scope: !18, atomGroup: 1, atomRank: 1)
|
@llvm/pr-subscribers-llvm-binary-utilities Author: Orlando Cazalet-Hyams (OCHyams) ChangesFixes #140362 Clang's Full diff: https://github.com/llvm/llvm-project/pull/161695.diff 4 Files Affected:
diff --git a/clang/lib/CodeGen/CGDebugInfo.cpp b/clang/lib/CodeGen/CGDebugInfo.cpp
index 12c7d48e20d67..c1e21c6c2e0aa 100644
--- a/clang/lib/CodeGen/CGDebugInfo.cpp
+++ b/clang/lib/CodeGen/CGDebugInfo.cpp
@@ -1119,7 +1119,7 @@ llvm::DIType *CGDebugInfo::CreateType(const ComplexType *Ty) {
// Bit size and offset of the type.
llvm::dwarf::TypeKind Encoding = llvm::dwarf::DW_ATE_complex_float;
if (Ty->isComplexIntegerType())
- Encoding = llvm::dwarf::DW_ATE_lo_user;
+ Encoding = llvm::dwarf::DW_ATE_GNU_complex_signed;
uint64_t Size = CGM.getContext().getTypeSize(Ty);
return DBuilder.createBasicType("complex", Size, Encoding);
diff --git a/llvm/include/llvm/BinaryFormat/Dwarf.def b/llvm/include/llvm/BinaryFormat/Dwarf.def
index 2c9a3c0f6fb04..29199b2659f0e 100644
--- a/llvm/include/llvm/BinaryFormat/Dwarf.def
+++ b/llvm/include/llvm/BinaryFormat/Dwarf.def
@@ -1111,6 +1111,8 @@ HANDLE_DW_ATE(0x12, ASCII, 5, DWARF)
// HANDLE_DW_ATE(0x80, ALTIUM_fract, 2, ALTIUM) = DW_ATE_low_user
// HANDLE_DW_ATE(0x81, ALTIUM_accum, 2, ALTIUM)
+HANDLE_DW_ATE(0x80, GNU_complex_signed, 4, GNU)
+
HANDLE_DW_ATE(0x81, HP_complex_float, 2, HP)
HANDLE_DW_ATE(0x82, HP_float128, 2, HP)
HANDLE_DW_ATE(0x83, HP_complex_float128, 2, HP)
diff --git a/llvm/lib/CodeGen/AsmPrinter/DebugHandlerBase.cpp b/llvm/lib/CodeGen/AsmPrinter/DebugHandlerBase.cpp
index 0f3ff985974ce..983fd7594157b 100644
--- a/llvm/lib/CodeGen/AsmPrinter/DebugHandlerBase.cpp
+++ b/llvm/lib/CodeGen/AsmPrinter/DebugHandlerBase.cpp
@@ -236,6 +236,7 @@ bool DebugHandlerBase::isUnsignedDIType(const DIType *Ty) {
Encoding == dwarf::DW_ATE_float || Encoding == dwarf::DW_ATE_UTF ||
Encoding == dwarf::DW_ATE_boolean ||
Encoding == dwarf::DW_ATE_complex_float ||
+ Encoding == dwarf::DW_ATE_GNU_complex_signed ||
Encoding == dwarf::DW_ATE_signed_fixed ||
Encoding == dwarf::DW_ATE_unsigned_fixed ||
(Ty->getTag() == dwarf::DW_TAG_unspecified_type &&
diff --git a/llvm/test/DebugInfo/dwarf-complex-int.ll b/llvm/test/DebugInfo/dwarf-complex-int.ll
new file mode 100644
index 0000000000000..ad8a1fa78f083
--- /dev/null
+++ b/llvm/test/DebugInfo/dwarf-complex-int.ll
@@ -0,0 +1,59 @@
+; REQUIRES: object-emission
+; RUN: %llc_dwarf %s -filetype=obj -o - | llvm-dwarfdump - | FileCheck %s
+
+;; https://github.com/llvm/llvm-project/issues/140362
+;; Don't assert when emitting a complex integer type in DWARF.
+
+;; C source:
+;; int g;
+;;
+;; void foo(_Complex short c) { __builtin_memmove(&g, (char *)&c, 2); }
+;;
+;; void bar() { foo(0); }
+
+; CHECK: DW_AT_type ([[complex:0x[0-9a-f]+]] "complex")
+
+; CHECK: [[complex]]: DW_TAG_base_type
+; CHECK-NEXT: DW_AT_name ("complex")
+; CHECK-NEXT: DW_AT_encoding (DW_ATE_GNU_complex_signed)
+; CHECK-NEXT: DW_AT_byte_size (0x04)
+
+@g = dso_local local_unnamed_addr global i32 0, align 4, !dbg !0
+
+define dso_local void @bar() local_unnamed_addr !dbg !18 {
+entry:
+ #dbg_value(i32 0, !21, !DIExpression(), !27)
+ store i16 0, ptr @g, align 4, !dbg !29
+ ret void, !dbg !30
+}
+
+!llvm.dbg.cu = !{!2}
+!llvm.module.flags = !{!10, !11}
+!llvm.ident = !{!17}
+
+!0 = !DIGlobalVariableExpression(var: !1, expr: !DIExpression())
+!1 = distinct !DIGlobalVariable(name: "g", scope: !2, file: !8, line: 1, type: !9, isLocal: false, isDefinition: true)
+!2 = distinct !DICompileUnit(language: DW_LANG_C_plus_plus_14, file: !3, producer: "clang version 22.0.0git", isOptimized: true, runtimeVersion: 0, emissionKind: FullDebug, retainedTypes: !4, globals: !7, splitDebugInlining: false, nameTableKind: None)
+!3 = !DIFile(filename: "/app/example.cpp", directory: "/app")
+!4 = !{!5}
+!5 = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: !6, size: 64)
+!6 = !DIBasicType(name: "char", size: 8, encoding: DW_ATE_signed_char)
+!7 = !{!0}
+!8 = !DIFile(filename: "example.cpp", directory: "/app")
+!9 = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed)
+!10 = !{i32 7, !"Dwarf Version", i32 5}
+!11 = !{i32 2, !"Debug Info Version", i32 3}
+!17 = !{!"clang version 22.0.0git"}
+!18 = distinct !DISubprogram(name: "bar", linkageName: "bar()", scope: !8, file: !8, line: 5, type: !19, scopeLine: 5, flags: DIFlagPrototyped | DIFlagAllCallsDescribed, spFlags: DISPFlagDefinition | DISPFlagOptimized, unit: !2, keyInstructions: true)
+!19 = !DISubroutineType(types: !20)
+!20 = !{null}
+!21 = !DILocalVariable(name: "c", arg: 1, scope: !22, file: !8, line: 3, type: !25)
+!22 = distinct !DISubprogram(name: "foo", linkageName: "_ZL3fooCs", scope: !8, file: !8, line: 3, type: !23, scopeLine: 3, flags: DIFlagPrototyped | DIFlagAllCallsDescribed, spFlags: DISPFlagLocalToUnit | DISPFlagDefinition | DISPFlagOptimized, unit: !2, retainedNodes: !26, keyInstructions: true)
+!23 = !DISubroutineType(types: !24)
+!24 = !{null, !25}
+!25 = !DIBasicType(name: "complex", size: 32, encoding: 128)
+!26 = !{!21}
+!27 = !DILocation(line: 0, scope: !22, inlinedAt: !28)
+!28 = distinct !DILocation(line: 5, column: 14, scope: !18)
+!29 = !DILocation(line: 3, column: 37, scope: !22, inlinedAt: !28, atomGroup: 1, atomRank: 1)
+!30 = !DILocation(line: 5, column: 22, scope: !18, atomGroup: 1, atomRank: 1)
|
Not sure how useful it is, but apparently binutils dwarfdump dumps this as:
(using gcc to compile an example with Be nice to know how GCC emits this, whether it uses the ATE_ATIUM_fract name, or some other name for the same constant. |
Ah looking in gcc source from whatever version I have lying around that I last built I can see this -
I have no context or history as to why both GCC and Clang are using "raw" (I have no stake in this really, I was just doing some cleaning up / scanning of my inbox as I've been neglecting it a bit, and this looked like an easy fix) |
I mean... I /guess/ some extension has to start at (apparently we did get standardized ATEs for these uses approved for DWARFv6 ( https://dwarfstd.org/issues/210218.2.html ) and seems GCC's might've already tentatively added them ( https://inbox.sourceware.org/gcc-bugs/[email protected]%2Fbugzilla%2F/T/ )) And the LLVM implementation dates back to even before I was working on LLVM... 7b0344f
Oh, llvm-dwarfdump/libDebugInfoDWARF asserts if it doesn't recognize an enumerator in a DWARF enumeration (or specifically in the DW_ATE enumeration)? Yeah, that seems wrong in general - we'll always be behind some other implementations extension usage, etc - and being able to dump unknown stuff is important when investigating bugs, cross-toolchain behavior, etc. Ideally, I'd guess - we'd dump what we think the extension name is for an enumerator, and failing that (or perhaps in addition) we might print the absolute number, and something like Given that it looks like this use of lo_user wasn't "here's the first extension, and this value has a specific meaning between GCC and Clang" but maybe more "if you see this value, give up on DW_ATE_* and use the name instead" (judging by GCC's use of it for a variety of fallback cases in nearby code, if I'm reading it correctly) - maybe best to not add an explicit name for it, at least not on this basis.
nod appreciate the looking, for sure |
Thanks for helping dig into the background.
It's just LLVM CodeGen that asserts, from my little testing I don't think llvm-dwarfdump runs into this issue. Dwarfdump prints the
Sounds good. I've changed the assert to ignore the range [lo_user, hi_user], which probably makes sense as LLVM can't discern user-space ATE encoding clashes without extra help? (llvm-dwarfdump prints the encoding "raw" as 0x80 - see the test) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It's just LLVM CodeGen that asserts
Oh, fascinating - so this has been a totally untested codepath? I guess release builds did just fine/didn't assert (because no assertions enabled) so it's probably been working fine for people for years in practice...
Fixes #140362
Clang's
CGDebugInfo::CreateType(const ComplexType *Ty)
already emits this ATE encoding (0x80) without giving it an explicit name. I chose the name because it sounded right rather than because I know that's what GNU uses as I couldn't find that info (but I can see that the 0x80 encoding is what GCC emits for this example).