https://github.com/OCHyams created https://github.com/llvm/llvm-project/pull/164372
DW_TAG_base_type DIEs are permitted to have both byte_size and bit_size attributes "If the value of an object of the given type does not fully occupy the storage described by a byte size attribute" Change Clang to emit the actual bit-size of _BitInt in debug metadata, and change LLVM to add DW_AT_bit_size to base_type DIEs when the condition above is true. Fixes [#61952](https://github.com/llvm/llvm-project/issues/61952) >From 83f7c7c070f1b3912b09974944c9e6783efe1983 Mon Sep 17 00:00:00 2001 From: Orlando Cazalet-Hyams <[email protected]> Date: Mon, 20 Oct 2025 17:00:06 +0100 Subject: [PATCH] [DebugInfo] Emit DW_AT_bit_size for _BitSize types and others DW_TAG_base_type DIEs are permitted to have both byte_size and bit_size attributes "If the value of an object of the given type does not fully occupy the storage described by a byte size attribute" Change Clang to emit the actual bit-size of _BitInt in debug metadata, and change LLVM to add DW_AT_bit_size to base_type DIEs when the condition above is true. --- clang/lib/CodeGen/CGDebugInfo.cpp | 4 +- clang/test/DebugInfo/Generic/bit-int.c | 8 ++++ .../CodeGen/AsmPrinter/DwarfCompileUnit.cpp | 5 +++ llvm/lib/CodeGen/AsmPrinter/DwarfUnit.cpp | 13 ++++++- llvm/test/DebugInfo/bit-int-size.ll | 38 +++++++++++++++++++ 5 files changed, 63 insertions(+), 5 deletions(-) create mode 100644 clang/test/DebugInfo/Generic/bit-int.c create mode 100644 llvm/test/DebugInfo/bit-int-size.ll diff --git a/clang/lib/CodeGen/CGDebugInfo.cpp b/clang/lib/CodeGen/CGDebugInfo.cpp index 12e2813ef2ec7..2ad187de16acc 100644 --- a/clang/lib/CodeGen/CGDebugInfo.cpp +++ b/clang/lib/CodeGen/CGDebugInfo.cpp @@ -1152,9 +1152,7 @@ llvm::DIType *CGDebugInfo::CreateType(const BitIntType *Ty) { llvm::dwarf::TypeKind Encoding = Ty->isUnsigned() ? llvm::dwarf::DW_ATE_unsigned : llvm::dwarf::DW_ATE_signed; - - return DBuilder.createBasicType(Name, CGM.getContext().getTypeSize(Ty), - Encoding); + return DBuilder.createBasicType(Name, Ty->getNumBits(), Encoding); } llvm::DIType *CGDebugInfo::CreateType(const ComplexType *Ty) { diff --git a/clang/test/DebugInfo/Generic/bit-int.c b/clang/test/DebugInfo/Generic/bit-int.c new file mode 100644 index 0000000000000..16b3d7a2582c9 --- /dev/null +++ b/clang/test/DebugInfo/Generic/bit-int.c @@ -0,0 +1,8 @@ +// RUN: %clang_cc1 -x c++ %s -debug-info-kind=standalone -gno-column-info -emit-llvm -o - | FileCheck %s +// RUN: %clang_cc1 -x c %s -debug-info-kind=standalone -gno-column-info -emit-llvm -o - | FileCheck %s + +unsigned _BitInt(2) a; +_BitInt(2) b; + +// CHECK: !DIBasicType(name: "_BitInt", size: 2, encoding: DW_ATE_signed) +// CHECK: !DIBasicType(name: "unsigned _BitInt", size: 2, encoding: DW_ATE_unsigned) diff --git a/llvm/lib/CodeGen/AsmPrinter/DwarfCompileUnit.cpp b/llvm/lib/CodeGen/AsmPrinter/DwarfCompileUnit.cpp index 518121e200190..6f68548aa25f4 100644 --- a/llvm/lib/CodeGen/AsmPrinter/DwarfCompileUnit.cpp +++ b/llvm/lib/CodeGen/AsmPrinter/DwarfCompileUnit.cpp @@ -1795,6 +1795,11 @@ 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 value of an object of the given type does not fully occupy the + // storage described by a byte size attribute, the base type entry may also + // have a DW_AT_bit_size [...] attribute. + if (Btr.BitSize && (Btr.BitSize % 8)) + addUInt(Die, dwarf::DW_AT_bit_size, std::nullopt, Btr.BitSize); Btr.Die = &Die; } diff --git a/llvm/lib/CodeGen/AsmPrinter/DwarfUnit.cpp b/llvm/lib/CodeGen/AsmPrinter/DwarfUnit.cpp index e40fb768027b8..1253d9a463cbb 100644 --- a/llvm/lib/CodeGen/AsmPrinter/DwarfUnit.cpp +++ b/llvm/lib/CodeGen/AsmPrinter/DwarfUnit.cpp @@ -766,8 +766,17 @@ void DwarfUnit::constructTypeDIE(DIE &Buffer, const DIBasicType *BTy) { addUInt(Buffer, dwarf::DW_AT_encoding, dwarf::DW_FORM_data1, BTy->getEncoding()); - uint64_t Size = BTy->getSizeInBits() >> 3; - addUInt(Buffer, dwarf::DW_AT_byte_size, std::nullopt, Size); + uint64_t SizeInBytes = divideCeil(BTy->getSizeInBits(), 8); + addUInt(Buffer, dwarf::DW_AT_byte_size, std::nullopt, SizeInBytes); + if (BTy->getTag() == dwarf::Tag::DW_TAG_base_type) { + // DW_TAG_base_type: + // If the value of an object of the given type does not fully occupy the + // storage described by a byte size attribute, the base type entry may also + // have a DW_AT_bit_size [...] attribute. + if (uint64_t SizeInBits = BTy->getSizeInBits(); + SizeInBits && SizeInBits % 8) + addUInt(Buffer, dwarf::DW_AT_bit_size, std::nullopt, SizeInBits); + } if (BTy->isBigEndian()) addUInt(Buffer, dwarf::DW_AT_endianity, std::nullopt, dwarf::DW_END_big); diff --git a/llvm/test/DebugInfo/bit-int-size.ll b/llvm/test/DebugInfo/bit-int-size.ll new file mode 100644 index 0000000000000..69ab756f4e288 --- /dev/null +++ b/llvm/test/DebugInfo/bit-int-size.ll @@ -0,0 +1,38 @@ +; RUN: %llc_dwarf %s -filetype=obj -o - | llvm-dwarfdump - | FileCheck %s +; REQUIRES: object-emission + +;; Check base types with bit-sizes that don't fit fully fit within a byte +;; multiple get both a a byte_size and bit_size attribute. + +; CHECK: DW_TAG_base_type +; CHECK-NEXT: DW_AT_name ("unsigned _BitInt") +; CHECK-NEXT: DW_AT_encoding (DW_ATE_unsigned) +; CHECK-NEXT: DW_AT_byte_size (0x02) +; CHECK-NEXT: DW_AT_bit_size (0x09) + +; CHECK: DW_TAG_base_type +; CHECK-NEXT: DW_AT_name ("unsigned _BitInt") +; CHECK-NEXT: DW_AT_encoding (DW_ATE_signed) +; CHECK-NEXT: DW_AT_byte_size (0x01) +; CHECK-NEXT: DW_AT_bit_size (0x02) + +@a = global i8 0, align 1, !dbg !0 +@b = global i8 0, align 1, !dbg !5 + +!llvm.dbg.cu = !{!2} +!llvm.module.flags = !{!10, !11} +!llvm.ident = !{!12} + +!0 = !DIGlobalVariableExpression(var: !1, expr: !DIExpression()) +!1 = distinct !DIGlobalVariable(name: "a", scope: !2, file: !7, line: 4, 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: false, runtimeVersion: 0, emissionKind: FullDebug, globals: !4, splitDebugInlining: false, nameTableKind: None) +!3 = !DIFile(filename: "bit-int.c", directory: "/") +!4 = !{!0, !5} +!5 = !DIGlobalVariableExpression(var: !6, expr: !DIExpression()) +!6 = distinct !DIGlobalVariable(name: "b", scope: !2, file: !7, line: 5, type: !8, isLocal: false, isDefinition: true) +!7 = !DIFile(filename: "bit-int.c", directory: "/") +!8 = !DIBasicType(name: "_BitInt", size: 2, encoding: DW_ATE_signed) +!9 = !DIBasicType(name: "unsigned _BitInt", size: 2, encoding: DW_ATE_unsigned) +!10 = !{i32 2, !"Debug Info Version", i32 3} +!11 = !{i32 1, !"wchar_size", i32 4} +!12 = !{!"clang version 22.0.0git"} _______________________________________________ cfe-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
