Skip to content

Commit f0c6d30

Browse files
authored
[lldb][DWARFASTParserClang][NFC] Factor out unnamed bitfield creation into helper (#108196)
This logic will need adjusting soon for #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.
1 parent c22b68c commit f0c6d30

File tree

2 files changed

+70
-36
lines changed

2 files changed

+70
-36
lines changed

lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp

Lines changed: 40 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -2858,7 +2858,6 @@ void DWARFASTParserClang::ParseSingleMember(
28582858
}
28592859

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

28642863
const auto accessibility = attrs.accessibility == eAccessNone
@@ -2926,40 +2925,9 @@ void DWARFASTParserClang::ParseSingleMember(
29262925
detect_unnamed_bitfields =
29272926
die.GetCU()->Supports_unnamed_objc_bitfields();
29282927

2929-
if (detect_unnamed_bitfields) {
2930-
std::optional<FieldInfo> unnamed_field_info;
2931-
uint64_t last_field_end =
2932-
last_field_info.bit_offset + last_field_info.bit_size;
2933-
2934-
if (!last_field_info.IsBitfield()) {
2935-
// The last field was not a bit-field...
2936-
// but if it did take up the entire word then we need to extend
2937-
// last_field_end so the bit-field does not step into the last
2938-
// fields padding.
2939-
if (last_field_end != 0 && ((last_field_end % word_width) != 0))
2940-
last_field_end += word_width - (last_field_end % word_width);
2941-
}
2942-
2943-
if (ShouldCreateUnnamedBitfield(last_field_info, last_field_end,
2944-
this_field_info, layout_info)) {
2945-
unnamed_field_info = FieldInfo{};
2946-
unnamed_field_info->bit_size =
2947-
this_field_info.bit_offset - last_field_end;
2948-
unnamed_field_info->bit_offset = last_field_end;
2949-
}
2950-
2951-
if (unnamed_field_info) {
2952-
clang::FieldDecl *unnamed_bitfield_decl =
2953-
TypeSystemClang::AddFieldToRecordType(
2954-
class_clang_type, llvm::StringRef(),
2955-
m_ast.GetBuiltinTypeForEncodingAndBitSize(eEncodingSint,
2956-
word_width),
2957-
accessibility, unnamed_field_info->bit_size);
2958-
2959-
layout_info.field_offsets.insert(std::make_pair(
2960-
unnamed_bitfield_decl, unnamed_field_info->bit_offset));
2961-
}
2962-
}
2928+
if (detect_unnamed_bitfields)
2929+
AddUnnamedBitfieldToRecordTypeIfNeeded(layout_info, class_clang_type,
2930+
last_field_info, this_field_info);
29632931

29642932
last_field_info = this_field_info;
29652933
last_field_info.SetIsBitfield(true);
@@ -3764,6 +3732,43 @@ bool DWARFASTParserClang::ShouldCreateUnnamedBitfield(
37643732
return true;
37653733
}
37663734

3735+
void DWARFASTParserClang::AddUnnamedBitfieldToRecordTypeIfNeeded(
3736+
ClangASTImporter::LayoutInfo &class_layout_info,
3737+
const CompilerType &class_clang_type, const FieldInfo &previous_field,
3738+
const FieldInfo &current_field) {
3739+
// TODO: get this value from target
3740+
const uint64_t word_width = 32;
3741+
uint64_t last_field_end = previous_field.bit_offset + previous_field.bit_size;
3742+
3743+
if (!previous_field.IsBitfield()) {
3744+
// The last field was not a bit-field...
3745+
// but if it did take up the entire word then we need to extend
3746+
// last_field_end so the bit-field does not step into the last
3747+
// fields padding.
3748+
if (last_field_end != 0 && ((last_field_end % word_width) != 0))
3749+
last_field_end += word_width - (last_field_end % word_width);
3750+
}
3751+
3752+
// Nothing to be done.
3753+
if (!ShouldCreateUnnamedBitfield(previous_field, last_field_end,
3754+
current_field, class_layout_info))
3755+
return;
3756+
3757+
// Place the unnamed bitfield into the gap between the previous field's end
3758+
// and the current field's start.
3759+
const uint64_t unnamed_bit_size = current_field.bit_offset - last_field_end;
3760+
const uint64_t unnamed_bit_offset = last_field_end;
3761+
3762+
clang::FieldDecl *unnamed_bitfield_decl =
3763+
TypeSystemClang::AddFieldToRecordType(
3764+
class_clang_type, llvm::StringRef(),
3765+
m_ast.GetBuiltinTypeForEncodingAndBitSize(eEncodingSint, word_width),
3766+
lldb::AccessType::eAccessPublic, unnamed_bit_size);
3767+
3768+
class_layout_info.field_offsets.insert(
3769+
std::make_pair(unnamed_bitfield_decl, unnamed_bit_offset));
3770+
}
3771+
37673772
void DWARFASTParserClang::ParseRustVariantPart(
37683773
DWARFDIE &die, const DWARFDIE &parent_die,
37693774
const CompilerType &class_clang_type,

lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.h

Lines changed: 30 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -266,7 +266,7 @@ class DWARFASTParserClang : public lldb_private::plugin::dwarf::DWARFASTParser {
266266
FieldInfo() = default;
267267

268268
void SetIsBitfield(bool flag) { is_bitfield = flag; }
269-
bool IsBitfield() { return is_bitfield; }
269+
bool IsBitfield() const { return is_bitfield; }
270270

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

321+
/// Tries to detect whether \ref class_clang_type contained an unnamed
322+
/// bit-field between \ref previous_field and \ref current_field, and if
323+
/// so, adds a clang::FieldDecl representing that bit-field to
324+
/// \ref class_clang_type.
325+
///
326+
/// This is necessary because Clang (and GCC) doesn't emit a DW_TAG_member
327+
/// entry for unnamed bit-fields. So we derive it (with some exceptions),
328+
/// by checking whether there is a gap between where the storage of a
329+
/// DW_TAG_member ended and the subsequent DW_TAG_member began.
330+
///
331+
/// \param[in,out] layout_info Layout information of all decls parsed by the
332+
/// current parser. Will contain an entry for
333+
/// the unnamed bit-field if this function created
334+
/// one.
335+
///
336+
/// \param[in] class_clang_type The RecordType to which the unnamed bit-field
337+
/// will be added (if any).
338+
///
339+
/// \param[in] previous_field FieldInfo of the previous DW_TAG_member
340+
/// we parsed.
341+
///
342+
/// \param[in] current_field FieldInfo of the current DW_TAG_member
343+
/// being parsed.
344+
///
345+
void AddUnnamedBitfieldToRecordTypeIfNeeded(
346+
lldb_private::ClangASTImporter::LayoutInfo &class_layout_info,
347+
const lldb_private::CompilerType &class_clang_type,
348+
const FieldInfo &previous_field, const FieldInfo &current_field);
349+
321350
/// Parses a DW_TAG_APPLE_property DIE and appends the parsed data to the
322351
/// list of delayed Objective-C properties.
323352
///

0 commit comments

Comments
 (0)