Skip to content

Commit

Permalink
[lldb][DWARFASTParserClang][NFC] Factor out unnamed bitfield creation…
Browse files Browse the repository at this point in the history
… into helper (llvm#108196)

This logic will need adjusting soon for
llvm#108155

This patch pulls out the logic for detecting/creating unnamed bitfields
out of `ParseSingleMember` to make the latter (in my opinion) more
readable. Otherwise we have a large number of similarly named variables
in scope.
  • Loading branch information
Michael137 authored and VitaNuo committed Sep 12, 2024
1 parent 654be01 commit 895431e
Show file tree
Hide file tree
Showing 2 changed files with 70 additions and 36 deletions.
75 changes: 40 additions & 35 deletions lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2858,7 +2858,6 @@ void DWARFASTParserClang::ParseSingleMember(
}

const uint64_t character_width = 8;
const uint64_t word_width = 32;
CompilerType member_clang_type = member_type->GetLayoutCompilerType();

const auto accessibility = attrs.accessibility == eAccessNone
Expand Down Expand Up @@ -2926,40 +2925,9 @@ void DWARFASTParserClang::ParseSingleMember(
detect_unnamed_bitfields =
die.GetCU()->Supports_unnamed_objc_bitfields();

if (detect_unnamed_bitfields) {
std::optional<FieldInfo> unnamed_field_info;
uint64_t last_field_end =
last_field_info.bit_offset + last_field_info.bit_size;

if (!last_field_info.IsBitfield()) {
// The last field was not a bit-field...
// but if it did take up the entire word then we need to extend
// last_field_end so the bit-field does not step into the last
// fields padding.
if (last_field_end != 0 && ((last_field_end % word_width) != 0))
last_field_end += word_width - (last_field_end % word_width);
}

if (ShouldCreateUnnamedBitfield(last_field_info, last_field_end,
this_field_info, layout_info)) {
unnamed_field_info = FieldInfo{};
unnamed_field_info->bit_size =
this_field_info.bit_offset - last_field_end;
unnamed_field_info->bit_offset = last_field_end;
}

if (unnamed_field_info) {
clang::FieldDecl *unnamed_bitfield_decl =
TypeSystemClang::AddFieldToRecordType(
class_clang_type, llvm::StringRef(),
m_ast.GetBuiltinTypeForEncodingAndBitSize(eEncodingSint,
word_width),
accessibility, unnamed_field_info->bit_size);

layout_info.field_offsets.insert(std::make_pair(
unnamed_bitfield_decl, unnamed_field_info->bit_offset));
}
}
if (detect_unnamed_bitfields)
AddUnnamedBitfieldToRecordTypeIfNeeded(layout_info, class_clang_type,
last_field_info, this_field_info);

last_field_info = this_field_info;
last_field_info.SetIsBitfield(true);
Expand Down Expand Up @@ -3764,6 +3732,43 @@ bool DWARFASTParserClang::ShouldCreateUnnamedBitfield(
return true;
}

void DWARFASTParserClang::AddUnnamedBitfieldToRecordTypeIfNeeded(
ClangASTImporter::LayoutInfo &class_layout_info,
const CompilerType &class_clang_type, const FieldInfo &previous_field,
const FieldInfo &current_field) {
// TODO: get this value from target
const uint64_t word_width = 32;
uint64_t last_field_end = previous_field.bit_offset + previous_field.bit_size;

if (!previous_field.IsBitfield()) {
// The last field was not a bit-field...
// but if it did take up the entire word then we need to extend
// last_field_end so the bit-field does not step into the last
// fields padding.
if (last_field_end != 0 && ((last_field_end % word_width) != 0))
last_field_end += word_width - (last_field_end % word_width);
}

// Nothing to be done.
if (!ShouldCreateUnnamedBitfield(previous_field, last_field_end,
current_field, class_layout_info))
return;

// Place the unnamed bitfield into the gap between the previous field's end
// and the current field's start.
const uint64_t unnamed_bit_size = current_field.bit_offset - last_field_end;
const uint64_t unnamed_bit_offset = last_field_end;

clang::FieldDecl *unnamed_bitfield_decl =
TypeSystemClang::AddFieldToRecordType(
class_clang_type, llvm::StringRef(),
m_ast.GetBuiltinTypeForEncodingAndBitSize(eEncodingSint, word_width),
lldb::AccessType::eAccessPublic, unnamed_bit_size);

class_layout_info.field_offsets.insert(
std::make_pair(unnamed_bitfield_decl, unnamed_bit_offset));
}

void DWARFASTParserClang::ParseRustVariantPart(
DWARFDIE &die, const DWARFDIE &parent_die,
const CompilerType &class_clang_type,
Expand Down
31 changes: 30 additions & 1 deletion lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.h
Original file line number Diff line number Diff line change
Expand Up @@ -266,7 +266,7 @@ class DWARFASTParserClang : public lldb_private::plugin::dwarf::DWARFASTParser {
FieldInfo() = default;

void SetIsBitfield(bool flag) { is_bitfield = flag; }
bool IsBitfield() { return is_bitfield; }
bool IsBitfield() const { return is_bitfield; }

void SetIsArtificial(bool flag) { is_artificial = flag; }
bool IsArtificial() const { return is_artificial; }
Expand Down Expand Up @@ -318,6 +318,35 @@ class DWARFASTParserClang : public lldb_private::plugin::dwarf::DWARFASTParser {
FieldInfo const &this_field_info,
lldb_private::ClangASTImporter::LayoutInfo const &layout_info) const;

/// Tries to detect whether \ref class_clang_type contained an unnamed
/// bit-field between \ref previous_field and \ref current_field, and if
/// so, adds a clang::FieldDecl representing that bit-field to
/// \ref class_clang_type.
///
/// This is necessary because Clang (and GCC) doesn't emit a DW_TAG_member
/// entry for unnamed bit-fields. So we derive it (with some exceptions),
/// by checking whether there is a gap between where the storage of a
/// DW_TAG_member ended and the subsequent DW_TAG_member began.
///
/// \param[in,out] layout_info Layout information of all decls parsed by the
/// current parser. Will contain an entry for
/// the unnamed bit-field if this function created
/// one.
///
/// \param[in] class_clang_type The RecordType to which the unnamed bit-field
/// will be added (if any).
///
/// \param[in] previous_field FieldInfo of the previous DW_TAG_member
/// we parsed.
///
/// \param[in] current_field FieldInfo of the current DW_TAG_member
/// being parsed.
///
void AddUnnamedBitfieldToRecordTypeIfNeeded(
lldb_private::ClangASTImporter::LayoutInfo &class_layout_info,
const lldb_private::CompilerType &class_clang_type,
const FieldInfo &previous_field, const FieldInfo &current_field);

/// Parses a DW_TAG_APPLE_property DIE and appends the parsed data to the
/// list of delayed Objective-C properties.
///
Expand Down

0 comments on commit 895431e

Please sign in to comment.