https://github.com/augusto2112 updated https://github.com/llvm/llvm-project/pull/69741
>From 997da625fda1efebde43ec965c23c1a8ef9c0132 Mon Sep 17 00:00:00 2001 From: Augusto Noronha <augusto2...@me.com> Date: Fri, 10 Nov 2023 10:40:05 -0800 Subject: [PATCH] Emit DIE's size in bits when size 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 | 25 +++++-- llvm/lib/CodeGen/AsmPrinter/DwarfUnit.cpp | 30 +++++--- .../AArch64/non_standard_bit_sizes.ll | 69 +++++++++++++++++++ 3 files changed, 110 insertions(+), 14 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..928033ea48e890c 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 + // amount 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; @@ -2134,6 +2140,16 @@ bool DWARFASTParserClang::ParseTemplateParameterInfos( template_param_infos.hasParameterPack(); } +/// Reads the bit size from a die, by trying both the byte size and bit size +/// attributes. +static uint64_t GetSizeInBitsFromDie(const DWARFDIE &die) { + const uint64_t byte_size = + die.GetAttributeValueAsUnsigned(DW_AT_byte_size, UINT64_MAX); + if (byte_size != UINT64_MAX) + return byte_size * 8; + return die.GetAttributeValueAsUnsigned(DW_AT_bit_size, UINT64_MAX); +} + bool DWARFASTParserClang::CompleteRecordType(const DWARFDIE &die, lldb_private::Type *type, CompilerType &clang_type) { @@ -2211,8 +2227,7 @@ bool DWARFASTParserClang::CompleteRecordType(const DWARFDIE &die, 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; + layout_info.bit_size = GetSizeInBitsFromDie(die); clang::CXXRecordDecl *record_decl = m_ast.GetAsCXXRecordDecl(clang_type.GetOpaqueQualType()); @@ -2864,10 +2879,8 @@ void DWARFASTParserClang::ParseSingleMember( ModuleSP module_sp = parent_die.GetDWARF()->GetObjectFile()->GetModule(); const dw_tag_t tag = die.Tag(); // 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 = GetSizeInBitsFromDie(parent_die); + ; // 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..9633e3b19ec0d63 100644 --- a/llvm/lib/CodeGen/AsmPrinter/DwarfUnit.cpp +++ b/llvm/lib/CodeGen/AsmPrinter/DwarfUnit.cpp @@ -687,6 +687,16 @@ 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 +712,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 +742,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 +767,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 +796,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 +886,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 +1031,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..2e6afc9068151ff --- /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 bit long. +; CHECK: DW_AT_name ("one_bit_int") +; CHECK-NEXT: DW_AT_encoding (DW_ATE_signed) +; CHECK-NEXT: DW_AT_bit_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_bit_size (0x09) + +; 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_bit_size (0x07) + +; 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