diff options
author | Anders Carlsson <andersca@mac.com> | 2009-09-24 05:21:31 +0000 |
---|---|---|
committer | Anders Carlsson <andersca@mac.com> | 2009-09-24 05:21:31 +0000 |
commit | bb66bc8e843d87dd452e37ec1e781ae9cd2a0e20 (patch) | |
tree | a27140c9532073da0281857063c46971ddf5f5ed /clang/lib/AST/RecordLayoutBuilder.cpp | |
parent | b3b1e53d33f07053a8fd30a7c48898c7f84c1971 (diff) | |
download | bcm5719-llvm-bb66bc8e843d87dd452e37ec1e781ae9cd2a0e20.tar.gz bcm5719-llvm-bb66bc8e843d87dd452e37ec1e781ae9cd2a0e20.zip |
More improvements with laying out empty bases.
llvm-svn: 82682
Diffstat (limited to 'clang/lib/AST/RecordLayoutBuilder.cpp')
-rw-r--r-- | clang/lib/AST/RecordLayoutBuilder.cpp | 61 |
1 files changed, 52 insertions, 9 deletions
diff --git a/clang/lib/AST/RecordLayoutBuilder.cpp b/clang/lib/AST/RecordLayoutBuilder.cpp index 062ce4f5bc2..dec6402d369 100644 --- a/clang/lib/AST/RecordLayoutBuilder.cpp +++ b/clang/lib/AST/RecordLayoutBuilder.cpp @@ -230,7 +230,25 @@ bool ASTRecordLayoutBuilder::canPlaceRecordAtOffset(const CXXRecordDecl *RD, return false; } - // FIXME: Bases and fields. + const ASTRecordLayout &Info = Ctx.getASTRecordLayout(RD); + + // Check bases. + for (CXXRecordDecl::base_class_const_iterator I = RD->bases_begin(), + E = RD->bases_end(); I != E; ++I) { + if (I->isVirtual()) + continue; + + const CXXRecordDecl *Base = + cast<CXXRecordDecl>(I->getType()->getAs<RecordType>()->getDecl()); + + uint64_t BaseClassOffset = Info.getBaseClassOffset(Base); + + if (!canPlaceRecordAtOffset(Base, Offset + BaseClassOffset)) + return false; + } + + // FIXME: fields. + // FIXME: virtual bases. return true; } @@ -238,8 +256,23 @@ void ASTRecordLayoutBuilder::UpdateEmptyClassOffsets(const CXXRecordDecl *RD, uint64_t Offset) { if (RD->isEmpty()) EmptyClassOffsets.insert(std::make_pair(Offset, RD)); + + const ASTRecordLayout &Info = Ctx.getASTRecordLayout(RD); + + // Update bases. + for (CXXRecordDecl::base_class_const_iterator I = RD->bases_begin(), + E = RD->bases_end(); I != E; ++I) { + if (I->isVirtual()) + continue; + + const CXXRecordDecl *Base = + cast<CXXRecordDecl>(I->getType()->getAs<RecordType>()->getDecl()); - // FIXME: Update bases and fields. + uint64_t BaseClassOffset = Info.getBaseClassOffset(Base); + UpdateEmptyClassOffsets(Base, Offset + BaseClassOffset); + } + + // FIXME: Update fields and virtual bases. } uint64_t ASTRecordLayoutBuilder::LayoutBase(const CXXRecordDecl *RD) { @@ -248,25 +281,35 @@ uint64_t ASTRecordLayoutBuilder::LayoutBase(const CXXRecordDecl *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. - // Since the base is empty we don't have to update the size or alignment. UpdateEmptyClassOffsets(RD, 0); - + + Size = std::max(Size, BaseInfo.getNonVirtualSize()); + return 0; } unsigned BaseAlign = BaseInfo.getNonVirtualAlign(); + // Round up the current record size to the base's alignment boundary. uint64_t Offset = llvm::RoundUpToAlignment(Size, BaseAlign); - // Reserve space for this base. - Size = Offset + BaseInfo.getNonVirtualSize(); - + // Try to place the base. + while (true) { + if (canPlaceRecordAtOffset(RD, Offset)) + break; + + Offset += BaseAlign; + } + // Remember the next available offset. - NextOffset = Size; + NextOffset = Offset + BaseInfo.getNonVirtualSize(); + + Size = std::max(Size, NextOffset); // Remember max struct/class alignment. UpdateAlignment(BaseAlign); - + + UpdateEmptyClassOffsets(RD, Offset); return Offset; } |