https://github.com/augusto2112 updated https://github.com/llvm/llvm-project/pull/69741
>From b34b8f1786a6fb274710c5e4318bad83b04b0480 Mon Sep 17 00:00:00 2001 From: Augusto Noronha <augusto2...@me.com> Date: Fri, 20 Oct 2023 10:18:03 -0700 Subject: [PATCH] Fix size in bytes of type DIEs when size in bits is not a multiple of 8 The existing code will always round down the size in bits when calculating the size in bytes (for example, a types with 1-7 bits will be emitted as 0 bytes long). Fix this by emitting the size in bits if the size is not aligned to a byte. --- .../SymbolFile/DWARF/DWARFASTParserClang.cpp | 27 ++++++-- llvm/lib/CodeGen/AsmPrinter/DwarfUnit.cpp | 31 ++++++--- .../AArch64/non_standard_bit_sizes.ll | 69 +++++++++++++++++++ 3 files changed, 114 insertions(+), 13 deletions(-) create mode 100644 llvm/test/DebugInfo/AArch64/non_standard_bit_sizes.ll diff --git a/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp b/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp index 3174c18c97d888c..ddbec7292eb68d6 100644 --- a/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp +++ b/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp @@ -298,6 +298,12 @@ ParsedDWARFTypeAttributes::ParsedDWARFTypeAttributes(const DWARFDIE &die) { byte_size = form_value.Unsigned(); break; + case DW_AT_bit_size: + // Convert the bit size to byte size, and round it up to the minimum about + // of bytes that will fit the bits. + byte_size = (form_value.Unsigned() + 7) / 8; + break; + case DW_AT_byte_stride: byte_stride = form_value.Unsigned(); break; @@ -2210,9 +2216,16 @@ bool DWARFASTParserClang::CompleteRecordType(const DWARFDIE &die, !layout_info.vbase_offsets.empty()) { if (type) layout_info.bit_size = type->GetByteSize(nullptr).value_or(0) * 8; - if (layout_info.bit_size == 0) - layout_info.bit_size = - die.GetAttributeValueAsUnsigned(DW_AT_byte_size, 0) * 8; + if (layout_info.bit_size == 0) { + auto byte_size = + die.GetAttributeValueAsUnsigned(DW_AT_byte_size, UINT64_MAX); + + if (byte_size != UINT64_MAX) + layout_info.bit_size = byte_size; + else + layout_info.bit_size = + die.GetAttributeValueAsUnsigned(DW_AT_bit_size, 0); + } clang::CXXRecordDecl *record_decl = m_ast.GetAsCXXRecordDecl(clang_type.GetOpaqueQualType()); @@ -2866,8 +2879,12 @@ void DWARFASTParserClang::ParseSingleMember( // Get the parent byte size so we can verify any members will fit const uint64_t parent_byte_size = parent_die.GetAttributeValueAsUnsigned(DW_AT_byte_size, UINT64_MAX); - const uint64_t parent_bit_size = - parent_byte_size == UINT64_MAX ? UINT64_MAX : parent_byte_size * 8; + uint64_t parent_bit_size; + if (parent_byte_size != UINT64_MAX) + parent_bit_size = parent_byte_size * 8; + else + parent_bit_size = + parent_die.GetAttributeValueAsUnsigned(DW_AT_bit_size, UINT64_MAX); // FIXME: Remove the workarounds below and make this const. MemberAttributes attrs(die, parent_die, module_sp); diff --git a/llvm/lib/CodeGen/AsmPrinter/DwarfUnit.cpp b/llvm/lib/CodeGen/AsmPrinter/DwarfUnit.cpp index a5960a5d4a09a17..aab1dc218973365 100644 --- a/llvm/lib/CodeGen/AsmPrinter/DwarfUnit.cpp +++ b/llvm/lib/CodeGen/AsmPrinter/DwarfUnit.cpp @@ -687,6 +687,17 @@ std::string DwarfUnit::getParentContextString(const DIScope *Context) const { return CS; } +/// Returns the most appropriate dwarf size attribute (bits or bytes) and size +/// to be used with it, given the input size in bits. +static std::pair<dwarf::Attribute, uint64_t> +getMostAppropriateRepresentationAndSize(uint64_t SizeInBits) { + if (SizeInBits % 8 == 0) { + return {dwarf::DW_AT_byte_size, SizeInBits / 8}; + } + return {dwarf::DW_AT_bit_size, SizeInBits}; +} + + void DwarfUnit::constructTypeDIE(DIE &Buffer, const DIBasicType *BTy) { // Get core information. StringRef Name = BTy->getName(); @@ -702,8 +713,9 @@ 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); + auto [SizeAttribute, Size] = + getMostAppropriateRepresentationAndSize(BTy->getSizeInBits()); + addUInt(Buffer, SizeAttribute, std::nullopt, Size); if (BTy->isBigEndian()) addUInt(Buffer, dwarf::DW_AT_endianity, std::nullopt, dwarf::DW_END_big); @@ -731,8 +743,9 @@ void DwarfUnit::constructTypeDIE(DIE &Buffer, const DIStringType *STy) { DwarfExpr.addExpression(Expr); addBlock(Buffer, dwarf::DW_AT_string_length, DwarfExpr.finalize()); } else { - uint64_t Size = STy->getSizeInBits() >> 3; - addUInt(Buffer, dwarf::DW_AT_byte_size, std::nullopt, Size); + auto [SizeAttributte, Size] = + getMostAppropriateRepresentationAndSize(STy->getSizeInBits()); + addUInt(Buffer, SizeAttributte, std::nullopt, Size); } if (DIExpression *Expr = STy->getStringLocationExp()) { @@ -755,7 +768,8 @@ void DwarfUnit::constructTypeDIE(DIE &Buffer, const DIStringType *STy) { void DwarfUnit::constructTypeDIE(DIE &Buffer, const DIDerivedType *DTy) { // Get core information. StringRef Name = DTy->getName(); - uint64_t Size = DTy->getSizeInBits() >> 3; + auto [SizeAttribute, Size] = + getMostAppropriateRepresentationAndSize(DTy->getSizeInBits()); uint16_t Tag = Buffer.getTag(); // Map to main type, void will not have a type. @@ -783,7 +797,7 @@ void DwarfUnit::constructTypeDIE(DIE &Buffer, const DIDerivedType *DTy) { && Tag != dwarf::DW_TAG_ptr_to_member_type && Tag != dwarf::DW_TAG_reference_type && Tag != dwarf::DW_TAG_rvalue_reference_type) - addUInt(Buffer, dwarf::DW_AT_byte_size, std::nullopt, Size); + addUInt(Buffer, SizeAttribute, std::nullopt, Size); if (Tag == dwarf::DW_TAG_ptr_to_member_type) addDIEEntry(Buffer, dwarf::DW_AT_containing_type, @@ -873,7 +887,8 @@ void DwarfUnit::constructTypeDIE(DIE &Buffer, const DICompositeType *CTy) { // Add name if not anonymous or intermediate type. StringRef Name = CTy->getName(); - uint64_t Size = CTy->getSizeInBits() >> 3; + auto [SizeAttribute, Size] = + getMostAppropriateRepresentationAndSize(CTy->getSizeInBits()); uint16_t Tag = Buffer.getTag(); switch (Tag) { @@ -1017,7 +1032,7 @@ void DwarfUnit::constructTypeDIE(DIE &Buffer, const DICompositeType *CTy) { // TODO: Do we care about size for enum forward declarations? if (Size && (!CTy->isForwardDecl() || Tag == dwarf::DW_TAG_enumeration_type)) - addUInt(Buffer, dwarf::DW_AT_byte_size, std::nullopt, Size); + addUInt(Buffer, SizeAttribute, std::nullopt, Size); else if (!CTy->isForwardDecl()) // Add zero size if it is not a forward declaration. addUInt(Buffer, dwarf::DW_AT_byte_size, std::nullopt, 0); diff --git a/llvm/test/DebugInfo/AArch64/non_standard_bit_sizes.ll b/llvm/test/DebugInfo/AArch64/non_standard_bit_sizes.ll new file mode 100644 index 000000000000000..8b55033a01fcbfb --- /dev/null +++ b/llvm/test/DebugInfo/AArch64/non_standard_bit_sizes.ll @@ -0,0 +1,69 @@ +; RUN: llc -mtriple arm64-apple-darwin -filetype=obj %s -o %t +; RUN: llvm-dwarfdump -all %t | FileCheck %s + +; Checks that bit sizes that are not byte aligned are rounded up. + +; Check that a 1 bit sized type gets emitted as 1 byte long. +; CHECK: DW_AT_name ("one_bit_int") +; CHECK-NEXT: DW_AT_encoding (DW_ATE_signed) +; CHECK-NEXT: DW_AT_byte_size (0x01) + +; Check that a 9 bit sized type gets emitted as 2 bytes long. +; CHECK: DW_AT_name ("nine_bit_double") +; CHECK-NEXT: DW_AT_encoding (DW_ATE_float) +; CHECK-NEXT: DW_AT_byte_size (0x02) + +; Check that a 7 bit sized type gets emitted as 1 bytes long. +; CHECK: DW_AT_name ("seven_bit_float") +; CHECK-NEXT: DW_AT_encoding (DW_ATE_float) +; CHECK-NEXT: DW_AT_byte_size (0x01) + +; Check that a byte aligned bit size is emitted with the same byte size. +; CHECK: DW_AT_name ("four_byte_S") +; CHECK-NEXT: DW_AT_byte_size (0x04) + +%struct.S = type { i32 } + +; Function Attrs: noinline nounwind optnone ssp uwtable(sync) +define void @func(i32 noundef %a, double noundef %b, float noundef %c, i64 %s.coerce) !dbg !10 { +entry: + %s = alloca %struct.S, align 4 + %a.addr = alloca i32, align 4 + %b.addr = alloca double, align 8 + %c.addr = alloca float, align 4 + call void @llvm.dbg.declare(metadata ptr %a.addr, metadata !20, metadata !DIExpression()), !dbg !21 + call void @llvm.dbg.declare(metadata ptr %b.addr, metadata !22, metadata !DIExpression()), !dbg !23 + call void @llvm.dbg.declare(metadata ptr %c.addr, metadata !24, metadata !DIExpression()), !dbg !25 + call void @llvm.dbg.declare(metadata ptr %s, metadata !26, metadata !DIExpression()), !dbg !27 + ret void, !dbg !28 +} + +; Function Attrs: nocallback nofree nosync nounwind speculatable willreturn memory(none) +declare void @llvm.dbg.declare(metadata, metadata, metadata) + +!llvm.module.flags = !{!2} +!llvm.dbg.cu = !{!7} + +!2 = !{i32 2, !"Debug Info Version", i32 3} +!7 = distinct !DICompileUnit(language: DW_LANG_C11, file: !8, producer: "clang", isOptimized: false, runtimeVersion: 0, emissionKind: FullDebug) +!8 = !DIFile(filename: "t.c", directory: "") +!10 = distinct !DISubprogram(name: "func", scope: !8, file: !8, line: 6, type: !11, scopeLine: 6, flags: DIFlagPrototyped, spFlags: DISPFlagDefinition, unit: !7, retainedNodes: !19) +!11 = !DISubroutineType(types: !12) +!12 = !{null, !13, !14, !15, !16} +!13 = !DIBasicType(name: "one_bit_int", size: 1, encoding: DW_ATE_signed) +!14 = !DIBasicType(name: "nine_bit_double", size: 9, encoding: DW_ATE_float) +!15 = !DIBasicType(name: "seven_bit_float", size: 7, encoding: DW_ATE_float) +!16 = distinct !DICompositeType(tag: DW_TAG_structure_type, name: "four_byte_S", file: !8, line: 2, size: 32, elements: !17) +!17 = !{!18} +!18 = !DIDerivedType(tag: DW_TAG_member, name: "field", scope: !16, file: !8, line: 3, baseType: !13, size: 32) +!19 = !{} +!20 = !DILocalVariable(name: "a", arg: 1, scope: !10, file: !8, line: 6, type: !13) +!21 = !DILocation(line: 6, column: 15, scope: !10) +!22 = !DILocalVariable(name: "b", arg: 2, scope: !10, file: !8, line: 6, type: !14) +!23 = !DILocation(line: 6, column: 25, scope: !10) +!24 = !DILocalVariable(name: "c", arg: 3, scope: !10, file: !8, line: 6, type: !15) +!25 = !DILocation(line: 6, column: 34, scope: !10) +!26 = !DILocalVariable(name: "s", arg: 4, scope: !10, file: !8, line: 6, type: !16) +!27 = !DILocation(line: 6, column: 46, scope: !10) +!28 = !DILocation(line: 7, column: 1, scope: !10) + _______________________________________________ lldb-commits mailing list lldb-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits