[Lldb-commits] [llvm] [lldb] Fix size in bytes of type DIEs when size in bits is not a multiple of 8 (PR #69741)
Augusto Noronha via lldb-commits
lldb-commits at lists.llvm.org
Fri Nov 10 10:41:12 PST 2023
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 <augusto2112 at 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)
+
More information about the lldb-commits
mailing list