Skip to content

Commit

Permalink
Use range-based for to iterate over fields in record layout, NFCI (ll…
Browse files Browse the repository at this point in the history
…vm#122029)

Move the common case of FieldDecl::getFieldIndex() inline to mitigate
the cost of removing the extra `FieldNo` induction variable.

Also rename isNoUniqueAddress parameter to isNonVirtualBaseType, which
appears to be more accurate. I think the current name is just a
consequence of autocomplete gone wrong.
  • Loading branch information
rnk authored Jan 9, 2025
1 parent 9ec9287 commit 26aa20a
Show file tree
Hide file tree
Showing 4 changed files with 52 additions and 59 deletions.
14 changes: 13 additions & 1 deletion clang/include/clang/AST/Decl.h
Original file line number Diff line number Diff line change
Expand Up @@ -3115,8 +3115,20 @@ class FieldDecl : public DeclaratorDecl, public Mergeable<FieldDecl> {

/// Returns the index of this field within its record,
/// as appropriate for passing to ASTRecordLayout::getFieldOffset.
unsigned getFieldIndex() const;
unsigned getFieldIndex() const {
const FieldDecl *Canonical = getCanonicalDecl();
if (Canonical->CachedFieldIndex == 0) {
Canonical->setCachedFieldIndex();
assert(Canonical->CachedFieldIndex != 0);
}
return Canonical->CachedFieldIndex - 1;
}

private:
/// Set CachedFieldIndex to the index of this field plus one.
void setCachedFieldIndex() const;

public:
/// Determines whether this field is mutable (C++ only).
bool isMutable() const { return Mutable; }

Expand Down
10 changes: 3 additions & 7 deletions clang/lib/AST/Decl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4651,12 +4651,9 @@ bool FieldDecl::isPotentiallyOverlapping() const {
return hasAttr<NoUniqueAddressAttr>() && getType()->getAsCXXRecordDecl();
}

unsigned FieldDecl::getFieldIndex() const {
const FieldDecl *Canonical = getCanonicalDecl();
if (Canonical != this)
return Canonical->getFieldIndex();

if (CachedFieldIndex) return CachedFieldIndex - 1;
void FieldDecl::setCachedFieldIndex() const {
assert(this == getCanonicalDecl() &&
"should be called on the canonical decl");

unsigned Index = 0;
const RecordDecl *RD = getParent()->getDefinition();
Expand All @@ -4670,7 +4667,6 @@ unsigned FieldDecl::getFieldIndex() const {
}

assert(CachedFieldIndex && "failed to find field in parent");
return CachedFieldIndex - 1;
}

SourceRange FieldDecl::getSourceRange() const {
Expand Down
81 changes: 33 additions & 48 deletions clang/lib/AST/RecordLayoutBuilder.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -138,9 +138,9 @@ class EmptySubobjectMap {
return Offset <= MaxEmptyClassOffset;
}

CharUnits
getFieldOffset(const ASTRecordLayout &Layout, unsigned FieldNo) const {
uint64_t FieldOffset = Layout.getFieldOffset(FieldNo);
CharUnits getFieldOffset(const ASTRecordLayout &Layout,
const FieldDecl *Field) const {
uint64_t FieldOffset = Layout.getFieldOffset(Field->getFieldIndex());
assert(FieldOffset % CharWidth == 0 &&
"Field offset not at char boundary!");

Expand Down Expand Up @@ -298,14 +298,12 @@ EmptySubobjectMap::CanPlaceBaseSubobjectAtOffset(const BaseSubobjectInfo *Info,
}

// Traverse all member variables.
unsigned FieldNo = 0;
for (CXXRecordDecl::field_iterator I = Info->Class->field_begin(),
E = Info->Class->field_end(); I != E; ++I, ++FieldNo) {
if (I->isBitField())
for (const FieldDecl *Field : Info->Class->fields()) {
if (Field->isBitField())
continue;

CharUnits FieldOffset = Offset + getFieldOffset(Layout, FieldNo);
if (!CanPlaceFieldSubobjectAtOffset(*I, FieldOffset))
CharUnits FieldOffset = Offset + getFieldOffset(Layout, Field);
if (!CanPlaceFieldSubobjectAtOffset(Field, FieldOffset))
return false;
}

Expand Down Expand Up @@ -345,14 +343,12 @@ void EmptySubobjectMap::UpdateEmptyBaseSubobjects(const BaseSubobjectInfo *Info,
}

// Traverse all member variables.
unsigned FieldNo = 0;
for (CXXRecordDecl::field_iterator I = Info->Class->field_begin(),
E = Info->Class->field_end(); I != E; ++I, ++FieldNo) {
if (I->isBitField())
for (const FieldDecl *Field : Info->Class->fields()) {
if (Field->isBitField())
continue;

CharUnits FieldOffset = Offset + getFieldOffset(Layout, FieldNo);
UpdateEmptyFieldSubobjects(*I, FieldOffset, PlacingEmptyBase);
CharUnits FieldOffset = Offset + getFieldOffset(Layout, Field);
UpdateEmptyFieldSubobjects(Field, FieldOffset, PlacingEmptyBase);
}
}

Expand Down Expand Up @@ -410,15 +406,12 @@ EmptySubobjectMap::CanPlaceFieldSubobjectAtOffset(const CXXRecordDecl *RD,
}

// Traverse all member variables.
unsigned FieldNo = 0;
for (CXXRecordDecl::field_iterator I = RD->field_begin(), E = RD->field_end();
I != E; ++I, ++FieldNo) {
if (I->isBitField())
for (const FieldDecl *Field : RD->fields()) {
if (Field->isBitField())
continue;

CharUnits FieldOffset = Offset + getFieldOffset(Layout, FieldNo);

if (!CanPlaceFieldSubobjectAtOffset(*I, FieldOffset))
CharUnits FieldOffset = Offset + getFieldOffset(Layout, Field);
if (!CanPlaceFieldSubobjectAtOffset(Field, FieldOffset))
return false;
}

Expand Down Expand Up @@ -465,9 +458,8 @@ EmptySubobjectMap::CanPlaceFieldSubobjectAtOffset(const FieldDecl *FD,
return true;
}

bool
EmptySubobjectMap::CanPlaceFieldAtOffset(const FieldDecl *FD,
CharUnits Offset) {
bool EmptySubobjectMap::CanPlaceFieldAtOffset(const FieldDecl *FD,
CharUnits Offset) {
if (!CanPlaceFieldSubobjectAtOffset(FD, Offset))
return false;

Expand Down Expand Up @@ -521,15 +513,12 @@ void EmptySubobjectMap::UpdateEmptyFieldSubobjects(
}

// Traverse all member variables.
unsigned FieldNo = 0;
for (CXXRecordDecl::field_iterator I = RD->field_begin(), E = RD->field_end();
I != E; ++I, ++FieldNo) {
if (I->isBitField())
for (const FieldDecl *Field : RD->fields()) {
if (Field->isBitField())
continue;

CharUnits FieldOffset = Offset + getFieldOffset(Layout, FieldNo);

UpdateEmptyFieldSubobjects(*I, FieldOffset, PlacingOverlappingField);
CharUnits FieldOffset = Offset + getFieldOffset(Layout, Field);
UpdateEmptyFieldSubobjects(Field, FieldOffset, PlacingOverlappingField);
}
}

Expand Down Expand Up @@ -1455,10 +1444,8 @@ void ItaniumRecordLayoutBuilder::LayoutFields(const RecordDecl *D) {
bool InsertExtraPadding = D->mayInsertExtraPadding(/*EmitRemark=*/true);
bool HasFlexibleArrayMember = D->hasFlexibleArrayMember();
for (auto I = D->field_begin(), End = D->field_end(); I != End; ++I) {
auto Next(I);
++Next;
LayoutField(*I,
InsertExtraPadding && (Next != End || !HasFlexibleArrayMember));
LayoutField(*I, InsertExtraPadding &&
(std::next(I) != End || !HasFlexibleArrayMember));
}
}

Expand Down Expand Up @@ -3672,35 +3659,33 @@ static void DumpRecordLayout(raw_ostream &OS, const RecordDecl *RD,
}

// Dump fields.
uint64_t FieldNo = 0;
for (RecordDecl::field_iterator I = RD->field_begin(),
E = RD->field_end(); I != E; ++I, ++FieldNo) {
const FieldDecl &Field = **I;
uint64_t LocalFieldOffsetInBits = Layout.getFieldOffset(FieldNo);
for (const FieldDecl *Field : RD->fields()) {
uint64_t LocalFieldOffsetInBits =
Layout.getFieldOffset(Field->getFieldIndex());
CharUnits FieldOffset =
Offset + C.toCharUnitsFromBits(LocalFieldOffsetInBits);

// Recursively dump fields of record type.
if (auto RT = Field.getType()->getAs<RecordType>()) {
if (auto RT = Field->getType()->getAs<RecordType>()) {
DumpRecordLayout(OS, RT->getDecl(), C, FieldOffset, IndentLevel,
Field.getName().data(),
Field->getName().data(),
/*PrintSizeInfo=*/false,
/*IncludeVirtualBases=*/true);
continue;
}

if (Field.isBitField()) {
if (Field->isBitField()) {
uint64_t LocalFieldByteOffsetInBits = C.toBits(FieldOffset - Offset);
unsigned Begin = LocalFieldOffsetInBits - LocalFieldByteOffsetInBits;
unsigned Width = Field.getBitWidthValue(C);
unsigned Width = Field->getBitWidthValue(C);
PrintBitFieldOffset(OS, FieldOffset, Begin, Width, IndentLevel);
} else {
PrintOffset(OS, FieldOffset, IndentLevel);
}
const QualType &FieldType = C.getLangOpts().DumpRecordLayoutsCanonical
? Field.getType().getCanonicalType()
: Field.getType();
OS << FieldType << ' ' << Field << '\n';
? Field->getType().getCanonicalType()
: Field->getType();
OS << FieldType << ' ' << *Field << '\n';
}

// Dump virtual bases.
Expand Down
6 changes: 3 additions & 3 deletions clang/lib/CodeGen/CGRecordLayoutBuilder.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -182,7 +182,7 @@ struct CGRecordLowering {
llvm::Type *StorageType);
/// Lowers an ASTRecordLayout to a llvm type.
void lower(bool NonVirtualBaseType);
void lowerUnion(bool isNoUniqueAddress);
void lowerUnion(bool isNonVirtualBaseType);
void accumulateFields(bool isNonVirtualBaseType);
RecordDecl::field_iterator
accumulateBitFields(bool isNonVirtualBaseType,
Expand Down Expand Up @@ -310,9 +310,9 @@ void CGRecordLowering::lower(bool NVBaseType) {
computeVolatileBitfields();
}

void CGRecordLowering::lowerUnion(bool isNoUniqueAddress) {
void CGRecordLowering::lowerUnion(bool isNonVirtualBaseType) {
CharUnits LayoutSize =
isNoUniqueAddress ? Layout.getDataSize() : Layout.getSize();
isNonVirtualBaseType ? Layout.getDataSize() : Layout.getSize();
llvm::Type *StorageType = nullptr;
bool SeenNamedMember = false;
// Iterate through the fields setting bitFieldInfo and the Fields array. Also
Expand Down

0 comments on commit 26aa20a

Please sign in to comment.