зеркало из https://github.com/microsoft/clang-1.git
Add a SizeOfLargestEmptySubobject member to ASTRecordLayout. For C++ classes this will hold the largest empty subobject or 0 if the class doesn't have any empty subobjects.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@103359 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Родитель
1f10962edd
Коммит
c3fddeb438
|
@ -109,6 +109,11 @@ private:
|
|||
/// which is the alignment of the object without virtual bases.
|
||||
uint64_t NonVirtualAlign;
|
||||
|
||||
/// SizeOfLargestEmptySubobject - The size of the largest empty subobject
|
||||
/// (either a base or a member). Will be zero if the class doesn't contain
|
||||
/// any empty subobjects.
|
||||
uint64_t SizeOfLargestEmptySubobject;
|
||||
|
||||
/// PrimaryBase - The primary base info for this record.
|
||||
PrimaryBaseInfo PrimaryBase;
|
||||
|
||||
|
@ -139,6 +144,7 @@ private:
|
|||
uint64_t size, unsigned alignment, uint64_t datasize,
|
||||
const uint64_t *fieldoffsets, unsigned fieldcount,
|
||||
uint64_t nonvirtualsize, unsigned nonvirtualalign,
|
||||
uint64_t SizeOfLargestEmptySubobject,
|
||||
const PrimaryBaseInfo &PrimaryBase,
|
||||
const BaseOffsetsMapTy& BaseOffsets,
|
||||
const BaseOffsetsMapTy& VBaseOffsets);
|
||||
|
|
|
@ -44,6 +44,7 @@ ASTRecordLayout::ASTRecordLayout(ASTContext &Ctx,
|
|||
unsigned fieldcount,
|
||||
uint64_t nonvirtualsize,
|
||||
unsigned nonvirtualalign,
|
||||
uint64_t SizeOfLargestEmptySubobject,
|
||||
const PrimaryBaseInfo &PrimaryBase,
|
||||
const BaseOffsetsMapTy& BaseOffsets,
|
||||
const BaseOffsetsMapTy& VBaseOffsets)
|
||||
|
@ -58,6 +59,7 @@ ASTRecordLayout::ASTRecordLayout(ASTContext &Ctx,
|
|||
CXXInfo->PrimaryBase = PrimaryBase;
|
||||
CXXInfo->NonVirtualSize = nonvirtualsize;
|
||||
CXXInfo->NonVirtualAlign = nonvirtualalign;
|
||||
CXXInfo->SizeOfLargestEmptySubobject = SizeOfLargestEmptySubobject;
|
||||
CXXInfo->BaseOffsets = BaseOffsets;
|
||||
CXXInfo->VBaseOffsets = VBaseOffsets;
|
||||
|
||||
|
|
|
@ -24,7 +24,8 @@ using namespace clang;
|
|||
ASTRecordLayoutBuilder::ASTRecordLayoutBuilder(ASTContext &Context)
|
||||
: Context(Context), Size(0), Alignment(8), Packed(false),
|
||||
UnfilledBitsInLastByte(0), MaxFieldAlignment(0), DataSize(0), IsUnion(false),
|
||||
NonVirtualSize(0), NonVirtualAlignment(8), FirstNearlyEmptyVBase(0) { }
|
||||
SizeOfLargestEmptySubobject(0), NonVirtualSize(0), NonVirtualAlignment(8),
|
||||
FirstNearlyEmptyVBase(0) { }
|
||||
|
||||
/// IsNearlyEmpty - Indicates when a class has a vtable pointer, but
|
||||
/// no other data.
|
||||
|
@ -321,19 +322,19 @@ void ASTRecordLayoutBuilder::LayoutVirtualBase(const CXXRecordDecl *RD) {
|
|||
}
|
||||
|
||||
uint64_t ASTRecordLayoutBuilder::LayoutBase(const CXXRecordDecl *RD) {
|
||||
const ASTRecordLayout &BaseInfo = Context.getASTRecordLayout(RD);
|
||||
const ASTRecordLayout &Layout = Context.getASTRecordLayout(RD);
|
||||
|
||||
// If we have an empty base class, try to place it at offset 0.
|
||||
if (RD->isEmpty() && canPlaceRecordAtOffset(RD, 0)) {
|
||||
// We were able to place the class at offset 0.
|
||||
UpdateEmptyClassOffsets(RD, 0);
|
||||
|
||||
Size = std::max(Size, BaseInfo.getSize());
|
||||
Size = std::max(Size, Layout.getSize());
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
unsigned BaseAlign = BaseInfo.getNonVirtualAlign();
|
||||
unsigned BaseAlign = Layout.getNonVirtualAlign();
|
||||
|
||||
// Round up the current record size to the base's alignment boundary.
|
||||
uint64_t Offset = llvm::RoundUpToAlignment(DataSize, BaseAlign);
|
||||
|
@ -348,11 +349,11 @@ uint64_t ASTRecordLayoutBuilder::LayoutBase(const CXXRecordDecl *RD) {
|
|||
|
||||
if (!RD->isEmpty()) {
|
||||
// Update the data size.
|
||||
DataSize = Offset + BaseInfo.getNonVirtualSize();
|
||||
DataSize = Offset + Layout.getNonVirtualSize();
|
||||
|
||||
Size = std::max(Size, DataSize);
|
||||
} else
|
||||
Size = std::max(Size, Offset + BaseInfo.getSize());
|
||||
Size = std::max(Size, Offset + Layout.getSize());
|
||||
|
||||
// Remember max struct/class alignment.
|
||||
UpdateAlignment(BaseAlign);
|
||||
|
@ -424,7 +425,7 @@ bool ASTRecordLayoutBuilder::canPlaceFieldAtOffset(const FieldDecl *FD,
|
|||
if (!RD)
|
||||
return true;
|
||||
|
||||
const ASTRecordLayout &Info = Context.getASTRecordLayout(RD);
|
||||
const ASTRecordLayout &Layout = Context.getASTRecordLayout(RD);
|
||||
|
||||
uint64_t NumElements = Context.getConstantArrayElementCount(AT);
|
||||
uint64_t ElementOffset = Offset;
|
||||
|
@ -432,7 +433,7 @@ bool ASTRecordLayoutBuilder::canPlaceFieldAtOffset(const FieldDecl *FD,
|
|||
if (!canPlaceRecordAtOffset(RD, ElementOffset))
|
||||
return false;
|
||||
|
||||
ElementOffset += Info.getSize();
|
||||
ElementOffset += Layout.getSize();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -444,7 +445,7 @@ void ASTRecordLayoutBuilder::UpdateEmptyClassOffsets(const CXXRecordDecl *RD,
|
|||
if (RD->isEmpty())
|
||||
EmptyClassOffsets.insert(std::make_pair(Offset, RD));
|
||||
|
||||
const ASTRecordLayout &Info = Context.getASTRecordLayout(RD);
|
||||
const ASTRecordLayout &Layout = Context.getASTRecordLayout(RD);
|
||||
|
||||
// Update bases.
|
||||
for (CXXRecordDecl::base_class_const_iterator I = RD->bases_begin(),
|
||||
|
@ -457,7 +458,7 @@ void ASTRecordLayoutBuilder::UpdateEmptyClassOffsets(const CXXRecordDecl *RD,
|
|||
const CXXRecordDecl *Base =
|
||||
cast<CXXRecordDecl>(I->getType()->getAs<RecordType>()->getDecl());
|
||||
|
||||
uint64_t BaseClassOffset = Info.getBaseClassOffset(Base);
|
||||
uint64_t BaseClassOffset = Layout.getBaseClassOffset(Base);
|
||||
UpdateEmptyClassOffsets(Base, Offset + BaseClassOffset);
|
||||
}
|
||||
|
||||
|
@ -467,7 +468,7 @@ void ASTRecordLayoutBuilder::UpdateEmptyClassOffsets(const CXXRecordDecl *RD,
|
|||
I != E; ++I, ++FieldNo) {
|
||||
const FieldDecl *FD = *I;
|
||||
|
||||
uint64_t FieldOffset = Info.getFieldOffset(FieldNo);
|
||||
uint64_t FieldOffset = Layout.getFieldOffset(FieldNo);
|
||||
UpdateEmptyClassOffsets(FD, Offset + FieldOffset);
|
||||
}
|
||||
|
||||
|
@ -838,6 +839,7 @@ ASTRecordLayoutBuilder::ComputeLayout(ASTContext &Ctx,
|
|||
Builder.FieldOffsets.size(),
|
||||
NonVirtualSize,
|
||||
Builder.NonVirtualAlignment,
|
||||
Builder.SizeOfLargestEmptySubobject,
|
||||
Builder.PrimaryBase,
|
||||
Builder.Bases, Builder.VBases);
|
||||
}
|
||||
|
|
|
@ -78,6 +78,11 @@ class ASTRecordLayoutBuilder {
|
|||
/// avoid visiting virtual bases more than once.
|
||||
llvm::SmallPtrSet<const CXXRecordDecl *, 4> VisitedVirtualBases;
|
||||
|
||||
/// SizeOfLargestEmptySubobject - When laying out C++ classes, this holds the
|
||||
/// size of the largest empty subobject (either a base or a member).
|
||||
/// Will be zero if the record being built doesn't contain any empty classes.
|
||||
uint64_t SizeOfLargestEmptySubobject;
|
||||
|
||||
/// EmptyClassOffsets - A map from offsets to empty record decls.
|
||||
typedef std::multimap<uint64_t, const CXXRecordDecl *> EmptyClassOffsetsTy;
|
||||
EmptyClassOffsetsTy EmptyClassOffsets;
|
||||
|
|
Загрузка…
Ссылка в новой задаче