-
Notifications
You must be signed in to change notification settings - Fork 13.4k
[lldb] Prefer DW_AT_bit_size
over DW_AT_byte_size
in GetDIEBitSizeAndSign
#137123
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
base: main
Are you sure you want to change the base?
Conversation
@llvm/pr-subscribers-debuginfo @llvm/pr-subscribers-lldb Author: Yingwei Zheng (dtcxzyw) Changes
Stacked on #137118 and #137013. Full diff: https://github.com/llvm/llvm-project/pull/137123.diff 6 Files Affected:
diff --git a/lldb/source/Plugins/SymbolFile/DWARF/DWARFUnit.cpp b/lldb/source/Plugins/SymbolFile/DWARF/DWARFUnit.cpp
index 7d0afc04ac3b6..c6aab01fb4a59 100644
--- a/lldb/source/Plugins/SymbolFile/DWARF/DWARFUnit.cpp
+++ b/lldb/source/Plugins/SymbolFile/DWARF/DWARFUnit.cpp
@@ -707,9 +707,9 @@ DWARFUnit::GetDIEBitSizeAndSign(uint64_t relative_die_offset) const {
return llvm::createStringError("cannot resolve DW_OP_convert type DIE");
uint64_t encoding =
die.GetAttributeValueAsUnsigned(DW_AT_encoding, DW_ATE_hi_user);
- uint64_t bit_size = die.GetAttributeValueAsUnsigned(DW_AT_byte_size, 0) * 8;
+ uint64_t bit_size = die.GetAttributeValueAsUnsigned(DW_AT_bit_size, 0);
if (!bit_size)
- bit_size = die.GetAttributeValueAsUnsigned(DW_AT_bit_size, 0);
+ bit_size = die.GetAttributeValueAsUnsigned(DW_AT_byte_size, 0) * 8;
if (!bit_size)
return llvm::createStringError("unsupported type size");
bool sign;
diff --git a/lldb/test/Shell/SymbolFile/DWARF/print-boolean.c b/lldb/test/Shell/SymbolFile/DWARF/print-boolean.c
new file mode 100644
index 0000000000000..27778d89140ac
--- /dev/null
+++ b/lldb/test/Shell/SymbolFile/DWARF/print-boolean.c
@@ -0,0 +1,19 @@
+// RUN: %clang_host -O3 -ggdb -o %t %s
+// RUN: %lldb %t \
+// RUN: -o "b 17" \
+// RUN: -o r \
+// RUN: -o "p t" \
+// RUN: -o exit | FileCheck %s
+
+// CHECK: (lldb) p t
+// CHECK-NEXT: (int) 1
+
+int a, b, c;
+int d(int e) { return e; }
+int main() {
+ int t;
+ c = d(1);
+ t = 1 && c;
+ b = t & a;
+ return 0;
+}
diff --git a/llvm/lib/CodeGen/AsmPrinter/DwarfCompileUnit.cpp b/llvm/lib/CodeGen/AsmPrinter/DwarfCompileUnit.cpp
index 3939dae81841f..e73028d2e28d9 100644
--- a/llvm/lib/CodeGen/AsmPrinter/DwarfCompileUnit.cpp
+++ b/llvm/lib/CodeGen/AsmPrinter/DwarfCompileUnit.cpp
@@ -1749,6 +1749,10 @@ void DwarfCompileUnit::createBaseTypeDIEs() {
// Round up to smallest number of bytes that contains this number of bits.
addUInt(Die, dwarf::DW_AT_byte_size, std::nullopt,
divideCeil(Btr.BitSize, 8));
+ // If the size is not a multiple of 8 (e.g., boolean), add the bit size
+ // field.
+ if (Btr.BitSize % 8 != 0)
+ addUInt(Die, dwarf::DW_AT_bit_size, std::nullopt, Btr.BitSize);
Btr.Die = &Die;
}
diff --git a/llvm/lib/Transforms/InstCombine/InstructionCombining.cpp b/llvm/lib/Transforms/InstCombine/InstructionCombining.cpp
index f807f5f4519fc..c47d32dc01cd3 100644
--- a/llvm/lib/Transforms/InstCombine/InstructionCombining.cpp
+++ b/llvm/lib/Transforms/InstCombine/InstructionCombining.cpp
@@ -1396,6 +1396,24 @@ void InstCombinerImpl::freelyInvertAllUsersOf(Value *I, Value *IgnoredUser) {
"canFreelyInvertAllUsersOf() ?");
}
}
+
+ // Update pre-existing debug value uses.
+ SmallVector<DbgValueInst *, 4> DbgValues;
+ SmallVector<DbgVariableRecord *, 4> DbgVariableRecords;
+ llvm::findDbgValues(DbgValues, I, &DbgVariableRecords);
+ auto ApplyNot = [](DIExpression *Src) {
+ SmallVector<uint64_t> Elements;
+ Elements.reserve(Src->getElements().size() + 1);
+ Elements.push_back(dwarf::DW_OP_not);
+ Elements.append(Src->getElements().begin(), Src->getElements().end());
+ return DIExpression::get(Src->getContext(), Elements);
+ };
+
+ for (auto *DVI : DbgValues)
+ DVI->setExpression(ApplyNot(DVI->getExpression()));
+
+ for (DbgVariableRecord *DVR : DbgVariableRecords)
+ DVR->setExpression(ApplyNot(DVR->getExpression()));
}
/// Given a 'sub' instruction, return the RHS of the instruction if the LHS is a
diff --git a/llvm/test/DebugInfo/X86/convert-bool.ll b/llvm/test/DebugInfo/X86/convert-bool.ll
new file mode 100644
index 0000000000000..3b131579dfe74
--- /dev/null
+++ b/llvm/test/DebugInfo/X86/convert-bool.ll
@@ -0,0 +1,43 @@
+; RUN: llc -mtriple=x86_64 -dwarf-version=5 -filetype=obj -O0 < %s | llvm-dwarfdump - | FileCheck %s
+
+; CHECK: DW_TAG_base_type
+; CHECK-NEXT: DW_AT_name ("DW_ATE_unsigned_1")
+; CHECK-NEXT: DW_AT_encoding (DW_ATE_unsigned)
+; CHECK-NEXT: DW_AT_byte_size (0x01)
+; CHECK-NEXT: DW_AT_bit_size (0x01)
+
+define void @main() !dbg !18 {
+entry:
+ #dbg_value(i1 false, !22, !DIExpression(DW_OP_not, DW_OP_LLVM_convert, 1, DW_ATE_unsigned, DW_OP_LLVM_convert, 32, DW_ATE_unsigned, DW_OP_stack_value), !23)
+ ret void, !dbg !24
+}
+
+!llvm.dbg.cu = !{!0}
+!llvm.module.flags = !{!10, !11, !12, !13, !14, !15, !16}
+!llvm.ident = !{!17}
+
+!0 = distinct !DICompileUnit(language: DW_LANG_C11, file: !1, producer: "clang version 21.0.0git", isOptimized: true, runtimeVersion: 0, emissionKind: FullDebug, globals: !2, splitDebugInlining: false, nameTableKind: None)
+!1 = !DIFile(filename: "test.c", directory: "/", checksumkind: CSK_MD5, checksum: "100bdbce655d729c24c7c0e8523a58ae")
+!2 = !{!3, !6, !8}
+!3 = !DIGlobalVariableExpression(var: !4, expr: !DIExpression())
+!4 = distinct !DIGlobalVariable(name: "a", scope: !0, file: !1, line: 1, type: !5, isLocal: false, isDefinition: true)
+!5 = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed)
+!6 = !DIGlobalVariableExpression(var: !7, expr: !DIExpression())
+!7 = distinct !DIGlobalVariable(name: "b", scope: !0, file: !1, line: 1, type: !5, isLocal: false, isDefinition: true)
+!8 = !DIGlobalVariableExpression(var: !9, expr: !DIExpression())
+!9 = distinct !DIGlobalVariable(name: "c", scope: !0, file: !1, line: 1, type: !5, isLocal: false, isDefinition: true)
+!10 = !{i32 7, !"Dwarf Version", i32 5}
+!11 = !{i32 2, !"Debug Info Version", i32 3}
+!12 = !{i32 1, !"wchar_size", i32 4}
+!13 = !{i32 8, !"PIC Level", i32 2}
+!14 = !{i32 7, !"PIE Level", i32 2}
+!15 = !{i32 7, !"uwtable", i32 2}
+!16 = !{i32 7, !"debug-info-assignment-tracking", i1 true}
+!17 = !{!"clang version 21.0.0git"}
+!18 = distinct !DISubprogram(name: "main", scope: !1, file: !1, line: 3, type: !19, scopeLine: 3, flags: DIFlagAllCallsDescribed, spFlags: DISPFlagDefinition | DISPFlagOptimized, unit: !0, retainedNodes: !21)
+!19 = !DISubroutineType(types: !20)
+!20 = !{null}
+!21 = !{!22}
+!22 = !DILocalVariable(name: "l_4516", scope: !18, file: !1, line: 4, type: !5)
+!23 = !DILocation(line: 0, scope: !18)
+!24 = !DILocation(line: 9, column: 1, scope: !18)
diff --git a/llvm/test/Transforms/InstCombine/debuginfo-invert.ll b/llvm/test/Transforms/InstCombine/debuginfo-invert.ll
new file mode 100644
index 0000000000000..8c673e319f7f7
--- /dev/null
+++ b/llvm/test/Transforms/InstCombine/debuginfo-invert.ll
@@ -0,0 +1,70 @@
+; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 5
+; RUN: opt -passes=instcombine -S %s -o - | FileCheck %s
+
+target datalayout = "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-i128:128-f80:128-n8:16:32:64-S128"
+target triple = "x86_64-unknown-linux-gnu"
+
+define i32 @test(i32 noundef %x, i32 noundef %y) !dbg !10 {
+; CHECK-LABEL: define i32 @test(
+; CHECK-SAME: i32 noundef [[X:%.*]], i32 noundef [[Y:%.*]]) !dbg [[DBG10:![0-9]+]] {
+; CHECK-NEXT: [[ENTRY:.*:]]
+; CHECK-NEXT: #dbg_value(i32 [[X]], [[META15:![0-9]+]], !DIExpression(), [[META18:![0-9]+]])
+; CHECK-NEXT: #dbg_value(i32 [[Y]], [[META16:![0-9]+]], !DIExpression(), [[META18]])
+; CHECK-NEXT: [[CMP_NOT:%.*]] = icmp eq i32 [[X]], 0, !dbg [[DBG19:![0-9]+]]
+; CHECK-NEXT: #dbg_value(i1 [[CMP_NOT]], [[META17:![0-9]+]], !DIExpression(DW_OP_not, DW_OP_LLVM_convert, 1, DW_ATE_unsigned, DW_OP_LLVM_convert, 32, DW_ATE_unsigned, DW_OP_stack_value), [[META18]])
+; CHECK-NEXT: [[TMP0:%.*]] = and i32 [[Y]], 1, !dbg [[DBG20:![0-9]+]]
+; CHECK-NEXT: [[AND:%.*]] = select i1 [[CMP_NOT]], i32 0, i32 [[TMP0]], !dbg [[DBG20]]
+; CHECK-NEXT: ret i32 [[AND]], !dbg [[DBG21:![0-9]+]]
+;
+entry:
+ #dbg_value(i32 %x, !15, !DIExpression(), !18)
+ #dbg_value(i32 %y, !16, !DIExpression(), !18)
+ %cmp = icmp ne i32 %x, 0, !dbg !19
+ %conv = zext i1 %cmp to i32, !dbg !19
+ #dbg_value(i32 %conv, !17, !DIExpression(), !18)
+ %and = and i32 %conv, %y, !dbg !20
+ ret i32 %and, !dbg !21
+}
+
+!llvm.dbg.cu = !{!0}
+!llvm.module.flags = !{!2, !3, !4, !5, !6, !7, !8}
+!llvm.ident = !{!9}
+
+!0 = distinct !DICompileUnit(language: DW_LANG_C11, file: !1, producer: "clang version 21.0.0git", isOptimized: true, runtimeVersion: 0, emissionKind: FullDebug, splitDebugInlining: false, nameTableKind: None)
+!1 = !DIFile(filename: "test.c", directory: "/", checksumkind: CSK_MD5, checksum: "b2d9ffc7905684d8b7c3b52a3136e57c")
+!2 = !{i32 7, !"Dwarf Version", i32 5}
+!3 = !{i32 2, !"Debug Info Version", i32 3}
+!4 = !{i32 1, !"wchar_size", i32 4}
+!5 = !{i32 8, !"PIC Level", i32 2}
+!6 = !{i32 7, !"PIE Level", i32 2}
+!7 = !{i32 7, !"uwtable", i32 2}
+!8 = !{i32 7, !"debug-info-assignment-tracking", i1 true}
+!9 = !{!"clang version 21.0.0git"}
+!10 = distinct !DISubprogram(name: "test", scope: !1, file: !1, line: 1, type: !11, scopeLine: 1, flags: DIFlagPrototyped | DIFlagAllCallsDescribed, spFlags: DISPFlagDefinition | DISPFlagOptimized, unit: !0, retainedNodes: !14)
+!11 = !DISubroutineType(types: !12)
+!12 = !{!13, !13, !13}
+!13 = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed)
+!14 = !{!15, !16, !17}
+!15 = !DILocalVariable(name: "x", arg: 1, scope: !10, file: !1, line: 1, type: !13)
+!16 = !DILocalVariable(name: "y", arg: 2, scope: !10, file: !1, line: 1, type: !13)
+!17 = !DILocalVariable(name: "z", scope: !10, file: !1, line: 2, type: !13)
+!18 = !DILocation(line: 0, scope: !10)
+!19 = !DILocation(line: 2, column: 13, scope: !10)
+!20 = !DILocation(line: 3, column: 12, scope: !10)
+!21 = !DILocation(line: 3, column: 3, scope: !10)
+;.
+; CHECK: [[META0:![0-9]+]] = distinct !DICompileUnit(language: DW_LANG_C11, file: [[META1:![0-9]+]], producer: "{{.*}}clang version {{.*}}", isOptimized: true, runtimeVersion: 0, emissionKind: FullDebug, splitDebugInlining: false, nameTableKind: None)
+; CHECK: [[META1]] = !DIFile(filename: "test.c", directory: {{.*}})
+; CHECK: [[DBG10]] = distinct !DISubprogram(name: "test", scope: [[META1]], file: [[META1]], line: 1, type: [[META11:![0-9]+]], scopeLine: 1, flags: DIFlagPrototyped | DIFlagAllCallsDescribed, spFlags: DISPFlagDefinition | DISPFlagOptimized, unit: [[META0]], retainedNodes: [[META14:![0-9]+]])
+; CHECK: [[META11]] = !DISubroutineType(types: [[META12:![0-9]+]])
+; CHECK: [[META12]] = !{[[META13:![0-9]+]], [[META13]], [[META13]]}
+; CHECK: [[META13]] = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed)
+; CHECK: [[META14]] = !{[[META15]], [[META16]], [[META17]]}
+; CHECK: [[META15]] = !DILocalVariable(name: "x", arg: 1, scope: [[DBG10]], file: [[META1]], line: 1, type: [[META13]])
+; CHECK: [[META16]] = !DILocalVariable(name: "y", arg: 2, scope: [[DBG10]], file: [[META1]], line: 1, type: [[META13]])
+; CHECK: [[META17]] = !DILocalVariable(name: "z", scope: [[DBG10]], file: [[META1]], line: 2, type: [[META13]])
+; CHECK: [[META18]] = !DILocation(line: 0, scope: [[DBG10]])
+; CHECK: [[DBG19]] = !DILocation(line: 2, column: 13, scope: [[DBG10]])
+; CHECK: [[DBG20]] = !DILocation(line: 3, column: 12, scope: [[DBG10]])
+; CHECK: [[DBG21]] = !DILocation(line: 3, column: 3, scope: [[DBG10]])
+;.
|
@llvm/pr-subscribers-llvm-transforms Author: Yingwei Zheng (dtcxzyw) Changes
Stacked on #137118 and #137013. Full diff: https://github.com/llvm/llvm-project/pull/137123.diff 6 Files Affected:
diff --git a/lldb/source/Plugins/SymbolFile/DWARF/DWARFUnit.cpp b/lldb/source/Plugins/SymbolFile/DWARF/DWARFUnit.cpp
index 7d0afc04ac3b6..c6aab01fb4a59 100644
--- a/lldb/source/Plugins/SymbolFile/DWARF/DWARFUnit.cpp
+++ b/lldb/source/Plugins/SymbolFile/DWARF/DWARFUnit.cpp
@@ -707,9 +707,9 @@ DWARFUnit::GetDIEBitSizeAndSign(uint64_t relative_die_offset) const {
return llvm::createStringError("cannot resolve DW_OP_convert type DIE");
uint64_t encoding =
die.GetAttributeValueAsUnsigned(DW_AT_encoding, DW_ATE_hi_user);
- uint64_t bit_size = die.GetAttributeValueAsUnsigned(DW_AT_byte_size, 0) * 8;
+ uint64_t bit_size = die.GetAttributeValueAsUnsigned(DW_AT_bit_size, 0);
if (!bit_size)
- bit_size = die.GetAttributeValueAsUnsigned(DW_AT_bit_size, 0);
+ bit_size = die.GetAttributeValueAsUnsigned(DW_AT_byte_size, 0) * 8;
if (!bit_size)
return llvm::createStringError("unsupported type size");
bool sign;
diff --git a/lldb/test/Shell/SymbolFile/DWARF/print-boolean.c b/lldb/test/Shell/SymbolFile/DWARF/print-boolean.c
new file mode 100644
index 0000000000000..27778d89140ac
--- /dev/null
+++ b/lldb/test/Shell/SymbolFile/DWARF/print-boolean.c
@@ -0,0 +1,19 @@
+// RUN: %clang_host -O3 -ggdb -o %t %s
+// RUN: %lldb %t \
+// RUN: -o "b 17" \
+// RUN: -o r \
+// RUN: -o "p t" \
+// RUN: -o exit | FileCheck %s
+
+// CHECK: (lldb) p t
+// CHECK-NEXT: (int) 1
+
+int a, b, c;
+int d(int e) { return e; }
+int main() {
+ int t;
+ c = d(1);
+ t = 1 && c;
+ b = t & a;
+ return 0;
+}
diff --git a/llvm/lib/CodeGen/AsmPrinter/DwarfCompileUnit.cpp b/llvm/lib/CodeGen/AsmPrinter/DwarfCompileUnit.cpp
index 3939dae81841f..e73028d2e28d9 100644
--- a/llvm/lib/CodeGen/AsmPrinter/DwarfCompileUnit.cpp
+++ b/llvm/lib/CodeGen/AsmPrinter/DwarfCompileUnit.cpp
@@ -1749,6 +1749,10 @@ void DwarfCompileUnit::createBaseTypeDIEs() {
// Round up to smallest number of bytes that contains this number of bits.
addUInt(Die, dwarf::DW_AT_byte_size, std::nullopt,
divideCeil(Btr.BitSize, 8));
+ // If the size is not a multiple of 8 (e.g., boolean), add the bit size
+ // field.
+ if (Btr.BitSize % 8 != 0)
+ addUInt(Die, dwarf::DW_AT_bit_size, std::nullopt, Btr.BitSize);
Btr.Die = &Die;
}
diff --git a/llvm/lib/Transforms/InstCombine/InstructionCombining.cpp b/llvm/lib/Transforms/InstCombine/InstructionCombining.cpp
index f807f5f4519fc..c47d32dc01cd3 100644
--- a/llvm/lib/Transforms/InstCombine/InstructionCombining.cpp
+++ b/llvm/lib/Transforms/InstCombine/InstructionCombining.cpp
@@ -1396,6 +1396,24 @@ void InstCombinerImpl::freelyInvertAllUsersOf(Value *I, Value *IgnoredUser) {
"canFreelyInvertAllUsersOf() ?");
}
}
+
+ // Update pre-existing debug value uses.
+ SmallVector<DbgValueInst *, 4> DbgValues;
+ SmallVector<DbgVariableRecord *, 4> DbgVariableRecords;
+ llvm::findDbgValues(DbgValues, I, &DbgVariableRecords);
+ auto ApplyNot = [](DIExpression *Src) {
+ SmallVector<uint64_t> Elements;
+ Elements.reserve(Src->getElements().size() + 1);
+ Elements.push_back(dwarf::DW_OP_not);
+ Elements.append(Src->getElements().begin(), Src->getElements().end());
+ return DIExpression::get(Src->getContext(), Elements);
+ };
+
+ for (auto *DVI : DbgValues)
+ DVI->setExpression(ApplyNot(DVI->getExpression()));
+
+ for (DbgVariableRecord *DVR : DbgVariableRecords)
+ DVR->setExpression(ApplyNot(DVR->getExpression()));
}
/// Given a 'sub' instruction, return the RHS of the instruction if the LHS is a
diff --git a/llvm/test/DebugInfo/X86/convert-bool.ll b/llvm/test/DebugInfo/X86/convert-bool.ll
new file mode 100644
index 0000000000000..3b131579dfe74
--- /dev/null
+++ b/llvm/test/DebugInfo/X86/convert-bool.ll
@@ -0,0 +1,43 @@
+; RUN: llc -mtriple=x86_64 -dwarf-version=5 -filetype=obj -O0 < %s | llvm-dwarfdump - | FileCheck %s
+
+; CHECK: DW_TAG_base_type
+; CHECK-NEXT: DW_AT_name ("DW_ATE_unsigned_1")
+; CHECK-NEXT: DW_AT_encoding (DW_ATE_unsigned)
+; CHECK-NEXT: DW_AT_byte_size (0x01)
+; CHECK-NEXT: DW_AT_bit_size (0x01)
+
+define void @main() !dbg !18 {
+entry:
+ #dbg_value(i1 false, !22, !DIExpression(DW_OP_not, DW_OP_LLVM_convert, 1, DW_ATE_unsigned, DW_OP_LLVM_convert, 32, DW_ATE_unsigned, DW_OP_stack_value), !23)
+ ret void, !dbg !24
+}
+
+!llvm.dbg.cu = !{!0}
+!llvm.module.flags = !{!10, !11, !12, !13, !14, !15, !16}
+!llvm.ident = !{!17}
+
+!0 = distinct !DICompileUnit(language: DW_LANG_C11, file: !1, producer: "clang version 21.0.0git", isOptimized: true, runtimeVersion: 0, emissionKind: FullDebug, globals: !2, splitDebugInlining: false, nameTableKind: None)
+!1 = !DIFile(filename: "test.c", directory: "/", checksumkind: CSK_MD5, checksum: "100bdbce655d729c24c7c0e8523a58ae")
+!2 = !{!3, !6, !8}
+!3 = !DIGlobalVariableExpression(var: !4, expr: !DIExpression())
+!4 = distinct !DIGlobalVariable(name: "a", scope: !0, file: !1, line: 1, type: !5, isLocal: false, isDefinition: true)
+!5 = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed)
+!6 = !DIGlobalVariableExpression(var: !7, expr: !DIExpression())
+!7 = distinct !DIGlobalVariable(name: "b", scope: !0, file: !1, line: 1, type: !5, isLocal: false, isDefinition: true)
+!8 = !DIGlobalVariableExpression(var: !9, expr: !DIExpression())
+!9 = distinct !DIGlobalVariable(name: "c", scope: !0, file: !1, line: 1, type: !5, isLocal: false, isDefinition: true)
+!10 = !{i32 7, !"Dwarf Version", i32 5}
+!11 = !{i32 2, !"Debug Info Version", i32 3}
+!12 = !{i32 1, !"wchar_size", i32 4}
+!13 = !{i32 8, !"PIC Level", i32 2}
+!14 = !{i32 7, !"PIE Level", i32 2}
+!15 = !{i32 7, !"uwtable", i32 2}
+!16 = !{i32 7, !"debug-info-assignment-tracking", i1 true}
+!17 = !{!"clang version 21.0.0git"}
+!18 = distinct !DISubprogram(name: "main", scope: !1, file: !1, line: 3, type: !19, scopeLine: 3, flags: DIFlagAllCallsDescribed, spFlags: DISPFlagDefinition | DISPFlagOptimized, unit: !0, retainedNodes: !21)
+!19 = !DISubroutineType(types: !20)
+!20 = !{null}
+!21 = !{!22}
+!22 = !DILocalVariable(name: "l_4516", scope: !18, file: !1, line: 4, type: !5)
+!23 = !DILocation(line: 0, scope: !18)
+!24 = !DILocation(line: 9, column: 1, scope: !18)
diff --git a/llvm/test/Transforms/InstCombine/debuginfo-invert.ll b/llvm/test/Transforms/InstCombine/debuginfo-invert.ll
new file mode 100644
index 0000000000000..8c673e319f7f7
--- /dev/null
+++ b/llvm/test/Transforms/InstCombine/debuginfo-invert.ll
@@ -0,0 +1,70 @@
+; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 5
+; RUN: opt -passes=instcombine -S %s -o - | FileCheck %s
+
+target datalayout = "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-i128:128-f80:128-n8:16:32:64-S128"
+target triple = "x86_64-unknown-linux-gnu"
+
+define i32 @test(i32 noundef %x, i32 noundef %y) !dbg !10 {
+; CHECK-LABEL: define i32 @test(
+; CHECK-SAME: i32 noundef [[X:%.*]], i32 noundef [[Y:%.*]]) !dbg [[DBG10:![0-9]+]] {
+; CHECK-NEXT: [[ENTRY:.*:]]
+; CHECK-NEXT: #dbg_value(i32 [[X]], [[META15:![0-9]+]], !DIExpression(), [[META18:![0-9]+]])
+; CHECK-NEXT: #dbg_value(i32 [[Y]], [[META16:![0-9]+]], !DIExpression(), [[META18]])
+; CHECK-NEXT: [[CMP_NOT:%.*]] = icmp eq i32 [[X]], 0, !dbg [[DBG19:![0-9]+]]
+; CHECK-NEXT: #dbg_value(i1 [[CMP_NOT]], [[META17:![0-9]+]], !DIExpression(DW_OP_not, DW_OP_LLVM_convert, 1, DW_ATE_unsigned, DW_OP_LLVM_convert, 32, DW_ATE_unsigned, DW_OP_stack_value), [[META18]])
+; CHECK-NEXT: [[TMP0:%.*]] = and i32 [[Y]], 1, !dbg [[DBG20:![0-9]+]]
+; CHECK-NEXT: [[AND:%.*]] = select i1 [[CMP_NOT]], i32 0, i32 [[TMP0]], !dbg [[DBG20]]
+; CHECK-NEXT: ret i32 [[AND]], !dbg [[DBG21:![0-9]+]]
+;
+entry:
+ #dbg_value(i32 %x, !15, !DIExpression(), !18)
+ #dbg_value(i32 %y, !16, !DIExpression(), !18)
+ %cmp = icmp ne i32 %x, 0, !dbg !19
+ %conv = zext i1 %cmp to i32, !dbg !19
+ #dbg_value(i32 %conv, !17, !DIExpression(), !18)
+ %and = and i32 %conv, %y, !dbg !20
+ ret i32 %and, !dbg !21
+}
+
+!llvm.dbg.cu = !{!0}
+!llvm.module.flags = !{!2, !3, !4, !5, !6, !7, !8}
+!llvm.ident = !{!9}
+
+!0 = distinct !DICompileUnit(language: DW_LANG_C11, file: !1, producer: "clang version 21.0.0git", isOptimized: true, runtimeVersion: 0, emissionKind: FullDebug, splitDebugInlining: false, nameTableKind: None)
+!1 = !DIFile(filename: "test.c", directory: "/", checksumkind: CSK_MD5, checksum: "b2d9ffc7905684d8b7c3b52a3136e57c")
+!2 = !{i32 7, !"Dwarf Version", i32 5}
+!3 = !{i32 2, !"Debug Info Version", i32 3}
+!4 = !{i32 1, !"wchar_size", i32 4}
+!5 = !{i32 8, !"PIC Level", i32 2}
+!6 = !{i32 7, !"PIE Level", i32 2}
+!7 = !{i32 7, !"uwtable", i32 2}
+!8 = !{i32 7, !"debug-info-assignment-tracking", i1 true}
+!9 = !{!"clang version 21.0.0git"}
+!10 = distinct !DISubprogram(name: "test", scope: !1, file: !1, line: 1, type: !11, scopeLine: 1, flags: DIFlagPrototyped | DIFlagAllCallsDescribed, spFlags: DISPFlagDefinition | DISPFlagOptimized, unit: !0, retainedNodes: !14)
+!11 = !DISubroutineType(types: !12)
+!12 = !{!13, !13, !13}
+!13 = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed)
+!14 = !{!15, !16, !17}
+!15 = !DILocalVariable(name: "x", arg: 1, scope: !10, file: !1, line: 1, type: !13)
+!16 = !DILocalVariable(name: "y", arg: 2, scope: !10, file: !1, line: 1, type: !13)
+!17 = !DILocalVariable(name: "z", scope: !10, file: !1, line: 2, type: !13)
+!18 = !DILocation(line: 0, scope: !10)
+!19 = !DILocation(line: 2, column: 13, scope: !10)
+!20 = !DILocation(line: 3, column: 12, scope: !10)
+!21 = !DILocation(line: 3, column: 3, scope: !10)
+;.
+; CHECK: [[META0:![0-9]+]] = distinct !DICompileUnit(language: DW_LANG_C11, file: [[META1:![0-9]+]], producer: "{{.*}}clang version {{.*}}", isOptimized: true, runtimeVersion: 0, emissionKind: FullDebug, splitDebugInlining: false, nameTableKind: None)
+; CHECK: [[META1]] = !DIFile(filename: "test.c", directory: {{.*}})
+; CHECK: [[DBG10]] = distinct !DISubprogram(name: "test", scope: [[META1]], file: [[META1]], line: 1, type: [[META11:![0-9]+]], scopeLine: 1, flags: DIFlagPrototyped | DIFlagAllCallsDescribed, spFlags: DISPFlagDefinition | DISPFlagOptimized, unit: [[META0]], retainedNodes: [[META14:![0-9]+]])
+; CHECK: [[META11]] = !DISubroutineType(types: [[META12:![0-9]+]])
+; CHECK: [[META12]] = !{[[META13:![0-9]+]], [[META13]], [[META13]]}
+; CHECK: [[META13]] = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed)
+; CHECK: [[META14]] = !{[[META15]], [[META16]], [[META17]]}
+; CHECK: [[META15]] = !DILocalVariable(name: "x", arg: 1, scope: [[DBG10]], file: [[META1]], line: 1, type: [[META13]])
+; CHECK: [[META16]] = !DILocalVariable(name: "y", arg: 2, scope: [[DBG10]], file: [[META1]], line: 1, type: [[META13]])
+; CHECK: [[META17]] = !DILocalVariable(name: "z", scope: [[DBG10]], file: [[META1]], line: 2, type: [[META13]])
+; CHECK: [[META18]] = !DILocation(line: 0, scope: [[DBG10]])
+; CHECK: [[DBG19]] = !DILocation(line: 2, column: 13, scope: [[DBG10]])
+; CHECK: [[DBG20]] = !DILocation(line: 3, column: 12, scope: [[DBG10]])
+; CHECK: [[DBG21]] = !DILocation(line: 3, column: 3, scope: [[DBG10]])
+;.
|
Can you file a gdb bug report with an executable showing this behavior? Or even just email it to me? |
Reproducer:
test.s: https://gist.github.com/dtcxzyw/a3fa3d33dbbea9717dfe7a1579df0d01
gcc version: gcc (Ubuntu 13.3.0-6ubuntu2~24.04) 13.3.0 |
DWARF says that a base type can have DW_AT_bit_size, without DW_AT_byte_size. However, gdb does not correctly handle this; in fact, it crashes, as pointed out in this LLVM merge request: llvm/llvm-project#137123 This patch reworks the base type size logic a bit to handle this situation.
Thank you for the test case. I sent a gdb fix: https://sourceware.org/pipermail/gdb-patches/2025-April/217513.html |
DWARF says that a base type can have DW_AT_bit_size, without DW_AT_byte_size. However, gdb does not correctly handle this; in fact, it crashes, as pointed out in this LLVM merge request: llvm/llvm-project#137123 This patch reworks the base type size logic a bit to handle this situation.
DWARF says that a base type can have DW_AT_bit_size, without DW_AT_byte_size. However, gdb does not correctly handle this; in fact, it crashes, as pointed out in this LLVM merge request: llvm/llvm-project#137123 This patch reworks the base type size logic a bit to handle this situation. Tested-by: Kevin Buettner <kevinb@redhat.com> Approved-by: Kevin Buettner <kevinb@redhat.com>
DW_AT_bit_size
will be ignored by lldb ifDW_AT_byte_size
is available and non-zero. Unfortunately, gdb crashes whenDW_AT_byte_size
does not exist or is set to zero. So I decided to change lldb to match gdb's behavior :(Stacked on #137118 and #137013.
Closes #71065