diff options
| author | Anders Carlsson <andersca@mac.com> | 2010-03-11 00:15:35 +0000 |
|---|---|---|
| committer | Anders Carlsson <andersca@mac.com> | 2010-03-11 00:15:35 +0000 |
| commit | 8630b5b09bef17c555fb321d5f74e80f8f894ab5 (patch) | |
| tree | f5c13d3a70c60434a94bbfd4ac413497818909e8 /clang/lib/AST/RecordLayoutBuilder.cpp | |
| parent | 7bbe14337bffcf7623a3494559e36ad512f753f6 (diff) | |
| download | bcm5719-llvm-8630b5b09bef17c555fb321d5f74e80f8f894ab5.tar.gz bcm5719-llvm-8630b5b09bef17c555fb321d5f74e80f8f894ab5.zip | |
More cleanup and simplification of the record layout builder.
llvm-svn: 98208
Diffstat (limited to 'clang/lib/AST/RecordLayoutBuilder.cpp')
| -rw-r--r-- | clang/lib/AST/RecordLayoutBuilder.cpp | 140 |
1 files changed, 75 insertions, 65 deletions
diff --git a/clang/lib/AST/RecordLayoutBuilder.cpp b/clang/lib/AST/RecordLayoutBuilder.cpp index f90bf907e94..0253327d09a 100644 --- a/clang/lib/AST/RecordLayoutBuilder.cpp +++ b/clang/lib/AST/RecordLayoutBuilder.cpp @@ -23,23 +23,7 @@ using namespace clang; ASTRecordLayoutBuilder::ASTRecordLayoutBuilder(ASTContext &Ctx) : Ctx(Ctx), Size(0), Alignment(8), Packed(false), UnfilledBitsInLastByte(0), MaxFieldAlignment(0), DataSize(0), IsUnion(false), NonVirtualSize(0), - NonVirtualAlignment(8) { } - -/// LayoutVtable - Lay out the vtable and set PrimaryBase. -void ASTRecordLayoutBuilder::LayoutVtable(const CXXRecordDecl *RD) { - if (!RD->isDynamicClass()) { - // There is no primary base in this case. - return; - } - - SelectPrimaryBase(RD); - if (!PrimaryBase.getBase()) { - int AS = 0; - UpdateAlignment(Ctx.Target.getPointerAlign(AS)); - Size += Ctx.Target.getPointerWidth(AS); - DataSize = Size; - } -} + NonVirtualAlignment(8), FirstNearlyEmptyVBase(0) { } /// IsNearlyEmpty - Indicates when a class has a vtable pointer, but /// no other data. @@ -78,8 +62,8 @@ void ASTRecordLayoutBuilder::IdentifyPrimaryBases(const CXXRecordDecl *RD) { } void -ASTRecordLayoutBuilder::SelectPrimaryVBase(const CXXRecordDecl *RD, - const CXXRecordDecl *&FirstPrimary) { +ASTRecordLayoutBuilder::SelectPrimaryVBase(const CXXRecordDecl *RD) { + for (CXXRecordDecl::base_class_const_iterator i = RD->bases_begin(), e = RD->bases_end(); i != e; ++i) { assert(!i->getType()->isDependentType() && @@ -87,35 +71,42 @@ ASTRecordLayoutBuilder::SelectPrimaryVBase(const CXXRecordDecl *RD, const CXXRecordDecl *Base = cast<CXXRecordDecl>(i->getType()->getAs<RecordType>()->getDecl()); if (!i->isVirtual()) { - SelectPrimaryVBase(Base, FirstPrimary); + SelectPrimaryVBase(Base); if (PrimaryBase.getBase()) return; continue; } if (IsNearlyEmpty(Base)) { - if (FirstPrimary==0) - FirstPrimary = Base; + // Is this the first nearly empty primary virtual base? + if (!FirstNearlyEmptyVBase) + FirstNearlyEmptyVBase = Base; + if (!IndirectPrimaryBases.count(Base)) { - setPrimaryBase(Base, /*IsVirtual=*/true); + PrimaryBase = ASTRecordLayout::PrimaryBaseInfo(Base, + /*IsVirtual=*/true); return; } } + assert(i->isVirtual()); - SelectPrimaryVBase(Base, FirstPrimary); + SelectPrimaryVBase(Base); if (PrimaryBase.getBase()) return; } } -/// SelectPrimaryBase - Selects the primary base for the given class and -/// record that with setPrimaryBase. We also calculate the IndirectPrimaries. -void ASTRecordLayoutBuilder::SelectPrimaryBase(const CXXRecordDecl *RD) { +/// DeterminePrimaryBase - Determine the primary base of the given class. +void ASTRecordLayoutBuilder::DeterminePrimaryBase(const CXXRecordDecl *RD) { + // If the class isn't dynamic, it won't have a primary base. + if (!RD->isDynamicClass()) + return; + // Compute all the primary virtual bases for all of our direct and // indirect bases, and record all their primary virtual base classes. for (CXXRecordDecl::base_class_const_iterator i = RD->bases_begin(), e = RD->bases_end(); i != e; ++i) { assert(!i->getType()->isDependentType() && - "Cannot layout class with dependent bases."); + "Cannot lay out class with dependent bases."); const CXXRecordDecl *Base = cast<CXXRecordDecl>(i->getType()->getAs<RecordType>()->getDecl()); IdentifyPrimaryBases(Base); @@ -142,20 +133,32 @@ void ASTRecordLayoutBuilder::SelectPrimaryBase(const CXXRecordDecl *RD) { // Otherwise, it is the first nearly empty virtual base that is not an // indirect primary virtual base class, if one exists. + if (RD->getNumVBases() != 0) { + SelectPrimaryVBase(RD); + if (PrimaryBase.getBase()) + return; + } - // If we have no virtual bases at this point, bail out as the searching below - // is expensive. - if (RD->getNumVBases() == 0) + // Otherwise, it is the first nearly empty virtual base that is not an + // indirect primary virtual base class, if one exists. + if (FirstNearlyEmptyVBase) { + PrimaryBase = + ASTRecordLayout::PrimaryBaseInfo(FirstNearlyEmptyVBase, /*IsVirtual=*/true); return; + } - // Then we can search for the first nearly empty virtual base itself. - const CXXRecordDecl *FirstPrimary = 0; - SelectPrimaryVBase(RD, FirstPrimary); - - // Otherwise if is the first nearly empty virtual base, if one exists, - // otherwise there is no primary base class. - if (!PrimaryBase.getBase()) - setPrimaryBase(FirstPrimary, /*IsVirtual=*/true); + // Otherwise there is no primary base class. + assert(!PrimaryBase.getBase() && "Should not get here with a primary base!"); + + // Allocate the virtual table pointer at offset zero. + assert(DataSize == 0 && "Vtable pointer must be at offset zero!"); + + // Update the size. + Size += Ctx.Target.getPointerWidth(0); + DataSize = Size; + + // Update the alignment. + UpdateAlignment(Ctx.Target.getPointerAlign(0)); } uint64_t ASTRecordLayoutBuilder::getBaseOffset(const CXXRecordDecl *Base) { @@ -173,19 +176,38 @@ uint64_t ASTRecordLayoutBuilder::getBaseOffset(const CXXRecordDecl *Base) { void ASTRecordLayoutBuilder::LayoutNonVirtualBases(const CXXRecordDecl *RD) { - for (CXXRecordDecl::base_class_const_iterator i = RD->bases_begin(), - e = RD->bases_end(); i != e; ++i) { - if (!i->isVirtual()) { - assert(!i->getType()->isDependentType() && - "Cannot layout class with dependent bases."); - const CXXRecordDecl *Base = - cast<CXXRecordDecl>(i->getType()->getAs<RecordType>()->getDecl()); - // Skip the PrimaryBase here, as it is laid down first. - if (Base != PrimaryBase.getBase() || PrimaryBase.isVirtual()) { - // Lay out the base. - LayoutNonVirtualBase(Base); - } - } + // First, determine the primary base class. + DeterminePrimaryBase(RD); + + // If we have a primary base class, lay it out. + if (const CXXRecordDecl *Base = PrimaryBase.getBase()) { + printf("found primary base %s\n", Base->getQualifiedNameAsString().c_str()); + if (PrimaryBase.isVirtual()) { + // We have a virtual primary base, insert it as an indirect primary base. + IndirectPrimaryBases.insert(Base); + + LayoutVirtualBase(Base); + } else + LayoutNonVirtualBase(Base); + } + + // Now lay out the non-virtual bases. + for (CXXRecordDecl::base_class_const_iterator I = RD->bases_begin(), + E = RD->bases_end(); I != E; ++I) { + + // Ignore virtual bases. + if (I->isVirtual()) + continue; + + const CXXRecordDecl *Base = + cast<CXXRecordDecl>(I->getType()->getAs<RecordType>()->getDecl()); + + // Skip the primary base. + if (Base == PrimaryBase.getBase() && !PrimaryBase.isVirtual()) + continue; + + // Lay out the base. + LayoutNonVirtualBase(Base); } } @@ -458,20 +480,8 @@ 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<CXXRecordDecl>(D); - if (RD) { - LayoutVtable(RD); - // PrimaryBase goes first. - if (PrimaryBase.getBase()) { - if (PrimaryBase.isVirtual()) { - IndirectPrimaryBases.insert(PrimaryBase.getBase()); - - LayoutVirtualBase(PrimaryBase.getBase()); - } else { - LayoutNonVirtualBase(PrimaryBase.getBase()); - } - } + if (RD) LayoutNonVirtualBases(RD); - } LayoutFields(D); |

