From 968db3364611a475909b5e76969d2f5472e65597 Mon Sep 17 00:00:00 2001 From: Mike Stump Date: Thu, 5 Nov 2009 04:02:15 +0000 Subject: [PATCH] Refine layout for indirect virtual base classes. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@86116 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/AST/RecordLayoutBuilder.cpp | 69 +++++++++++++++------------------ lib/AST/RecordLayoutBuilder.h | 9 +++-- 2 files changed, 38 insertions(+), 40 deletions(-) diff --git a/lib/AST/RecordLayoutBuilder.cpp b/lib/AST/RecordLayoutBuilder.cpp index 0b159c3a7b..021c53e951 100644 --- a/lib/AST/RecordLayoutBuilder.cpp +++ b/lib/AST/RecordLayoutBuilder.cpp @@ -174,9 +174,24 @@ void ASTRecordLayoutBuilder::LayoutVirtualBase(const CXXRecordDecl *RD) { LayoutBaseNonVirtually(RD, true); } -void ASTRecordLayoutBuilder::LayoutVirtualBases(const CXXRecordDecl *RD, +uint64_t ASTRecordLayoutBuilder::getBaseOffset(const CXXRecordDecl *Base) { + for (size_t i = 0; i < Bases.size(); ++i) { + if (Bases[i].first == Base) + return Bases[i].second; + } + for (size_t i = 0; i < VBases.size(); ++i) { + if (VBases[i].first == Base) + return VBases[i].second; + } + assert(0 && "missing base"); + return 0; +} + + +void ASTRecordLayoutBuilder::LayoutVirtualBases(const CXXRecordDecl *Class, + const CXXRecordDecl *RD, const CXXRecordDecl *PB, - int64_t Offset, + uint64_t Offset, llvm::SmallSet &mark, llvm::SmallSet &IndirectPrimary) { for (CXXRecordDecl::base_class_const_iterator i = RD->bases_begin(), @@ -185,20 +200,7 @@ void ASTRecordLayoutBuilder::LayoutVirtualBases(const CXXRecordDecl *RD, "Cannot layout class with dependent bases."); const CXXRecordDecl *Base = cast(i->getType()->getAs()->getDecl()); -#if 0 - const ASTRecordLayout &L = Ctx.getASTRecordLayout(Base); - const CXXRecordDecl *PB = L.getPrimaryBase(); - if (PB && L.getPrimaryBaseWasVirtual() - && IndirectPrimary.count(PB)) { - int64_t BaseOffset; - // FIXME: calculate this. - BaseOffset = (1<<63) | (1<<31); - VBases.push_back(PB); - VBaseOffsets.push_back(BaseOffset); - } -#endif - int64_t BaseOffset = Offset;; - // FIXME: Calculate BaseOffset. + uint64_t BaseOffset = Offset; if (i->isVirtual()) { if (Base == PB) { // Only lay things out once. @@ -220,11 +222,20 @@ void ASTRecordLayoutBuilder::LayoutVirtualBases(const CXXRecordDecl *RD, LayoutVirtualBase(Base); BaseOffset = VBases.back().second; } + } else { + if (RD == Class) + BaseOffset = getBaseOffset(Base); + else { + const ASTRecordLayout &Layout + = Ctx.getASTRecordLayout(RD); + BaseOffset = Offset + Layout.getBaseClassOffset(Base); + } } + if (Base->getNumVBases()) { const ASTRecordLayout &L = Ctx.getASTRecordLayout(Base); const CXXRecordDecl *PB = L.getPrimaryBase(); - LayoutVirtualBases(Base, PB, BaseOffset, mark, IndirectPrimary); + LayoutVirtualBases(Class, Base, PB, BaseOffset, mark, IndirectPrimary); } } } @@ -295,7 +306,7 @@ bool ASTRecordLayoutBuilder::canPlaceFieldAtOffset(const FieldDecl *FD, const ASTRecordLayout &Info = Ctx.getASTRecordLayout(RD); uint64_t NumElements = Ctx.getConstantArrayElementCount(AT); - unsigned ElementOffset = Offset; + uint64_t ElementOffset = Offset; for (uint64_t I = 0; I != NumElements; ++I) { if (!canPlaceRecordAtOffset(RD, ElementOffset)) return false; @@ -366,7 +377,7 @@ ASTRecordLayoutBuilder::UpdateEmptyClassOffsets(const FieldDecl *FD, const ASTRecordLayout &Info = Ctx.getASTRecordLayout(RD); uint64_t NumElements = Ctx.getConstantArrayElementCount(AT); - unsigned ElementOffset = Offset; + uint64_t ElementOffset = Offset; for (uint64_t I = 0; I != NumElements; ++I) { UpdateEmptyClassOffsets(RD, ElementOffset); @@ -419,29 +430,13 @@ uint64_t ASTRecordLayoutBuilder::LayoutBase(const CXXRecordDecl *RD) { void ASTRecordLayoutBuilder::LayoutBaseNonVirtually(const CXXRecordDecl *RD, bool IsVirtualBase) { // Layout the base. - unsigned Offset = LayoutBase(RD); + uint64_t Offset = LayoutBase(RD); // Add base class offsets. if (IsVirtualBase) VBases.push_back(std::make_pair(RD, Offset)); else Bases.push_back(std::make_pair(RD, Offset)); - -#if 0 - // And now add offsets for all our primary virtual bases as well, so - // they all have offsets. - const ASTRecordLayout *L = &BaseInfo; - const CXXRecordDecl *PB = L->getPrimaryBase(); - while (PB) { - if (L->getPrimaryBaseWasVirtual()) { - VBases.push_back(PB); - VBaseOffsets.push_back(Size); - } - PB = L->getPrimaryBase(); - if (PB) - L = &Ctx.getASTRecordLayout(PB); - } -#endif } void ASTRecordLayoutBuilder::Layout(const RecordDecl *D) { @@ -476,7 +471,7 @@ void ASTRecordLayoutBuilder::Layout(const RecordDecl *D) { if (RD) { llvm::SmallSet mark; - LayoutVirtualBases(RD, PrimaryBase, 0, mark, IndirectPrimaryBases); + LayoutVirtualBases(RD, RD, PrimaryBase, 0, mark, IndirectPrimaryBases); } // Finally, round the size of the total struct up to the alignment of the diff --git a/lib/AST/RecordLayoutBuilder.h b/lib/AST/RecordLayoutBuilder.h index b57b37d0df..077072343b 100644 --- a/lib/AST/RecordLayoutBuilder.h +++ b/lib/AST/RecordLayoutBuilder.h @@ -99,9 +99,9 @@ class ASTRecordLayoutBuilder { void LayoutNonVirtualBases(const CXXRecordDecl *RD); void LayoutBaseNonVirtually(const CXXRecordDecl *RD, bool IsVBase); void LayoutVirtualBase(const CXXRecordDecl *RD); - void LayoutVirtualBases(const CXXRecordDecl *RD, const CXXRecordDecl *PB, - int64_t Offset, - llvm::SmallSet &mark, + void LayoutVirtualBases(const CXXRecordDecl *Class, const CXXRecordDecl *RD, + const CXXRecordDecl *PB, uint64_t Offset, + llvm::SmallSet &mark, llvm::SmallSet &IndirectPrimary); /// canPlaceRecordAtOffset - Return whether a record (either a base class @@ -124,6 +124,9 @@ class ASTRecordLayoutBuilder { /// given offset. void UpdateEmptyClassOffsets(const FieldDecl *FD, uint64_t Offset); + /// getBaseOffset - Get the offset of a direct base class. + uint64_t getBaseOffset(const CXXRecordDecl *Base); + /// FinishLayout - Finalize record layout. Adjust record size based on the /// alignment. void FinishLayout(); -- 2.40.0