From 836fc14e6cdad2362fc31f11bf7b14832cba34b9 Mon Sep 17 00:00:00 2001 From: Anders Carlsson Date: Sat, 8 May 2010 23:06:26 +0000 Subject: [PATCH] Actually compute the empty subobject sizes. No functionality change yet. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@103363 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/clang/AST/RecordLayout.h | 5 +++ lib/AST/RecordLayoutBuilder.cpp | 58 ++++++++++++++++++++++++++++++-- lib/AST/RecordLayoutBuilder.h | 6 +++- 3 files changed, 65 insertions(+), 4 deletions(-) diff --git a/include/clang/AST/RecordLayout.h b/include/clang/AST/RecordLayout.h index 0b05614a19..817f038435 100644 --- a/include/clang/AST/RecordLayout.h +++ b/include/clang/AST/RecordLayout.h @@ -228,6 +228,11 @@ public: return CXXInfo->VBaseOffsets[VBase]; } + uint64_t getSizeOfLargestEmptySubobject() const { + assert(CXXInfo && "Record layout does not have C++ specific info!"); + return CXXInfo->SizeOfLargestEmptySubobject; + } + primary_base_info_iterator primary_base_begin() const { assert(CXXInfo && "Record layout does not have C++ specific info!"); diff --git a/lib/AST/RecordLayoutBuilder.cpp b/lib/AST/RecordLayoutBuilder.cpp index 745e68f38f..2d4b769735 100644 --- a/lib/AST/RecordLayoutBuilder.cpp +++ b/lib/AST/RecordLayoutBuilder.cpp @@ -24,8 +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), - SizeOfLargestEmptySubobject(0), NonVirtualSize(0), NonVirtualAlignment(8), - FirstNearlyEmptyVBase(0) { } + NonVirtualSize(0), NonVirtualAlignment(8), FirstNearlyEmptyVBase(0), + SizeOfLargestEmptySubobject(0) { } /// IsNearlyEmpty - Indicates when a class has a vtable pointer, but /// no other data. @@ -39,6 +39,56 @@ bool ASTRecordLayoutBuilder::IsNearlyEmpty(const CXXRecordDecl *RD) const { return false; } +void +ASTRecordLayoutBuilder::ComputeEmptySubobjectSizes(const CXXRecordDecl *RD) { + // Check the bases. + for (CXXRecordDecl::base_class_const_iterator I = RD->bases_begin(), + E = RD->bases_end(); I != E; ++I) { + const CXXRecordDecl *BaseDecl = + cast(I->getType()->getAs()->getDecl()); + + uint64_t EmptySize = 0; + const ASTRecordLayout &Layout = Context.getASTRecordLayout(BaseDecl); + if (BaseDecl->isEmpty()) { + // If the class decl is empty, get its size. + EmptySize = Layout.getSize(); + } else { + // Otherwise, we get the largest empty subobject for the decl. + EmptySize = Layout.getSizeOfLargestEmptySubobject(); + } + + SizeOfLargestEmptySubobject = std::max(SizeOfLargestEmptySubobject, + EmptySize); + } + + // Check the fields. + for (CXXRecordDecl::field_iterator I = RD->field_begin(), E = RD->field_end(); + I != E; ++I) { + const FieldDecl *FD = *I; + + const RecordType *RT = + Context.getBaseElementType(FD->getType())->getAs(); + + // We only care about record types. + if (!RT) + continue; + + uint64_t EmptySize = 0; + const CXXRecordDecl *MemberDecl = cast(RT->getDecl()); + const ASTRecordLayout &Layout = Context.getASTRecordLayout(MemberDecl); + if (MemberDecl->isEmpty()) { + // If the class decl is empty, get its size. + EmptySize = Layout.getSize(); + } else { + // Otherwise, we get the largest empty subobject for the decl. + EmptySize = Layout.getSizeOfLargestEmptySubobject(); + } + + SizeOfLargestEmptySubobject = std::max(SizeOfLargestEmptySubobject, + EmptySize); + } +} + void ASTRecordLayoutBuilder::IdentifyPrimaryBases(const CXXRecordDecl *RD) { const ASTRecordLayout::PrimaryBaseInfo &BaseInfo = Context.getASTRecordLayout(RD).getPrimaryBaseInfo(); @@ -522,8 +572,10 @@ void ASTRecordLayoutBuilder::Layout(const RecordDecl *D) { // If this is a C++ class, lay out the vtable and the non-virtual bases. const CXXRecordDecl *RD = dyn_cast(D); - if (RD) + if (RD) { + ComputeEmptySubobjectSizes(RD); LayoutNonVirtualBases(RD); + } LayoutFields(D); diff --git a/lib/AST/RecordLayoutBuilder.h b/lib/AST/RecordLayoutBuilder.h index acbee9e1dc..f3da315ead 100644 --- a/lib/AST/RecordLayoutBuilder.h +++ b/lib/AST/RecordLayoutBuilder.h @@ -77,7 +77,7 @@ class ASTRecordLayoutBuilder { /// VisitedVirtualBases - A set of all the visited virtual bases, used to /// avoid visiting virtual bases more than once. llvm::SmallPtrSet 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. @@ -99,6 +99,10 @@ class ASTRecordLayoutBuilder { void LayoutWideBitField(uint64_t FieldSize, uint64_t TypeSize); void LayoutBitField(const FieldDecl *D); + /// ComputeEmptySubobjectSizes - Compute the size of the largest base or + /// member subobject that is empty. + void ComputeEmptySubobjectSizes(const CXXRecordDecl *RD); + /// DeterminePrimaryBase - Determine the primary base of the given class. void DeterminePrimaryBase(const CXXRecordDecl *RD); -- 2.40.0