diff options
Diffstat (limited to 'lib')
-rw-r--r-- | lib/AST/RecordLayoutBuilder.cpp | 45 | ||||
-rw-r--r-- | lib/CodeGen/CGCXX.cpp | 71 |
2 files changed, 67 insertions, 49 deletions
diff --git a/lib/AST/RecordLayoutBuilder.cpp b/lib/AST/RecordLayoutBuilder.cpp index 68350daa6c..8e09e9e65b 100644 --- a/lib/AST/RecordLayoutBuilder.cpp +++ b/lib/AST/RecordLayoutBuilder.cpp @@ -74,26 +74,27 @@ bool ASTRecordLayoutBuilder::IsNearlyEmpty(const CXXRecordDecl *RD) { void ASTRecordLayoutBuilder::SelectPrimaryForBase(const CXXRecordDecl *RD, llvm::SmallSet<const CXXRecordDecl*, 32> &IndirectPrimary) { + const ASTRecordLayout &Layout = Ctx.getASTRecordLayout(RD); + const CXXRecordDecl *PrimaryBase = Layout.getPrimaryBase(); + const bool PrimaryBaseWasVirtual = Layout.getPrimaryBaseWasVirtual(); + if (PrimaryBaseWasVirtual) { + IndirectPrimary.insert(PrimaryBase); + } for (CXXRecordDecl::base_class_const_iterator i = RD->bases_begin(), e = RD->bases_end(); i != e; ++i) { - if (!i->isVirtual()) { - const CXXRecordDecl *Base = - cast<CXXRecordDecl>(i->getType()->getAs<RecordType>()->getDecl()); - // Only bases with virtual bases participate in computing the - // indirect primary base classes. - // FIXME: audit indirect virtual bases - if (Base->getNumVBases() == 0) - return; - // FIXME: This information is recomputed a whole lot, cache it instead. - SelectPrimaryBase(Base); - IndirectPrimary.insert(PrimaryBase); - SelectPrimaryForBase(Base, IndirectPrimary); - } + const CXXRecordDecl *Base = + cast<CXXRecordDecl>(i->getType()->getAs<RecordType>()->getDecl()); + // Only bases with virtual bases participate in computing the + // indirect primary virtual base classes. + // FIXME: audit indirect virtual bases + if (Base->getNumVBases() == 0) + continue; + SelectPrimaryForBase(Base, IndirectPrimary); } } /// SelectPrimaryBase - Selects the primary base for the given class and -/// records that with setPrimaryBase. +/// record that with setPrimaryBase. void ASTRecordLayoutBuilder::SelectPrimaryBase(const CXXRecordDecl *RD) { // The primary base is the first non-virtual indirect or direct base class, // if one exists. @@ -110,7 +111,7 @@ void ASTRecordLayoutBuilder::SelectPrimaryBase(const CXXRecordDecl *RD) { } // Otherwise, it is the first nearly empty virtual base that is not an - // indirect primary base class, if one exists. + // indirect primary virtual base class, if one exists. // If we have no virtual bases at this point, bail out as the searching below // is expensive. @@ -120,21 +121,19 @@ void ASTRecordLayoutBuilder::SelectPrimaryBase(const CXXRecordDecl *RD) { return; } - // First, we compute all the primary bases for all of our direct and indirect - // non-virtual bases, and record all their primary base classes. + // First, we compute all the primary virtual bases for all of our direct and + // indirect bases, and record all their primary virtual base classes. const CXXRecordDecl *FirstPrimary = 0; llvm::SmallSet<const CXXRecordDecl*, 32> IndirectPrimary; for (CXXRecordDecl::base_class_const_iterator i = RD->bases_begin(), e = RD->bases_end(); i != e; ++i) { - if (!i->isVirtual()) { - const CXXRecordDecl *Base = - cast<CXXRecordDecl>(i->getType()->getAs<RecordType>()->getDecl()); - SelectPrimaryForBase(Base, IndirectPrimary); - } + const CXXRecordDecl *Base = + cast<CXXRecordDecl>(i->getType()->getAs<RecordType>()->getDecl()); + SelectPrimaryForBase(Base, IndirectPrimary); } // Then we can search for the first nearly empty virtual base itself. - // FIXME: audit indirect virtual bases + // FIXME: audit indirect virtual bases and order (backwards?) for (CXXRecordDecl::base_class_const_iterator i = RD->vbases_begin(), e = RD->vbases_end(); i != e; ++i) { const CXXRecordDecl *Base = diff --git a/lib/CodeGen/CGCXX.cpp b/lib/CodeGen/CGCXX.cpp index 18c06cffb6..aff85fa5d4 100644 --- a/lib/CodeGen/CGCXX.cpp +++ b/lib/CodeGen/CGCXX.cpp @@ -635,18 +635,48 @@ void CodeGenFunction::GenerateVtableForBase(const CXXRecordDecl *RD, if (RD && !RD->isDynamicClass()) return; - if (RD && ForVirtualBase) - for (meth_iter mi = RD->method_begin(), me = RD->method_end(); mi != me; - ++mi) { + const ASTRecordLayout &Layout = getContext().getASTRecordLayout(Class); + + // The virtual base offsets come first... + for (CXXRecordDecl::reverse_base_class_const_iterator i + = Class->bases_rbegin(), + e = Class->bases_rend(); i != e; ++i) { + if (!i->isVirtual()) + continue; + const CXXRecordDecl *Base = + cast<CXXRecordDecl>(i->getType()->getAs<RecordType>()->getDecl()); + int64_t BaseOffset = Layout.getBaseClassOffset(Base) / 8; + llvm::Constant *m; + m = llvm::ConstantInt::get(llvm::Type::Int64Ty, BaseOffset); + m = llvm::ConstantExpr::getIntToPtr(m, Ptr8Ty); + methods.push_back(m); + } + + // then comes the the vcall offsets for all our functions... + if (isPrimary && ForVirtualBase) + for (meth_iter mi = Class->method_begin(), + me = Class->method_end(); mi != me; ++mi) { if (mi->isVirtual()) { // FIXME: vcall: offset for virtual base for this function m = llvm::Constant::getNullValue(Ptr8Ty); methods.push_back(m); } } - if (isPrimary && ForVirtualBase) - for (meth_iter mi = Class->method_begin(), - me = Class->method_end(); mi != me; ++mi) { + bool TopPrimary = true; + // Primary tables are composed from the chain of primaries. + if (isPrimary) { + const CXXRecordDecl *PrimaryBase = Layout.getPrimaryBase(); + const bool PrimaryBaseWasVirtual = Layout.getPrimaryBaseWasVirtual(); + if (PrimaryBase) { + TopPrimary = false; + GenerateVtableForBase(0, PrimaryBase, rtti, methods, true, + PrimaryBaseWasVirtual); + } + } + // then come the vcall offsets for all our virtual bases. + if (!isPrimary && RD && ForVirtualBase) + for (meth_iter mi = RD->method_begin(), me = RD->method_end(); mi != me; + ++mi) { if (mi->isVirtual()) { // FIXME: vcall: offset for virtual base for this function m = llvm::Constant::getNullValue(Ptr8Ty); @@ -654,16 +684,17 @@ void CodeGenFunction::GenerateVtableForBase(const CXXRecordDecl *RD, } } - if (RD) { - const ASTRecordLayout &Layout = getContext().getASTRecordLayout(Class); - int64_t BaseOffset = -(Layout.getBaseClassOffset(RD) / 8); - m = llvm::ConstantInt::get(llvm::Type::Int64Ty, BaseOffset); - m = llvm::ConstantExpr::getIntToPtr(m, Ptr8Ty); + if (TopPrimary) { + if (RD) { + int64_t BaseOffset = -(Layout.getBaseClassOffset(RD) / 8); + m = llvm::ConstantInt::get(llvm::Type::Int64Ty, BaseOffset); + m = llvm::ConstantExpr::getIntToPtr(m, Ptr8Ty); + } + methods.push_back(m); + methods.push_back(rtti); } - methods.push_back(m); - methods.push_back(rtti); - if (RD) + if (!isPrimary && RD) for (meth_iter mi = RD->method_begin(), me = RD->method_end(); mi != me; ++mi) { if (mi->isVirtual()) { @@ -709,18 +740,6 @@ llvm::Value *CodeGenFunction::GenerateVtable(const CXXRecordDecl *RD) { const CXXRecordDecl *PrimaryBase = Layout.getPrimaryBase(); const bool PrimaryBaseWasVirtual = Layout.getPrimaryBaseWasVirtual(); - // The virtual base offsets come first. - for (CXXRecordDecl::reverse_base_class_const_iterator i = RD->vbases_rbegin(), - e = RD->vbases_rend(); i != e; ++i) { - const CXXRecordDecl *Base = - cast<CXXRecordDecl>(i->getType()->getAs<RecordType>()->getDecl()); - int64_t BaseOffset = Layout.getBaseClassOffset(Base) / 8; - llvm::Constant *m; - m = llvm::ConstantInt::get(llvm::Type::Int64Ty, BaseOffset); - m = llvm::ConstantExpr::getIntToPtr(m, Ptr8Ty); - methods.push_back(m); - } - // The primary base comes first. GenerateVtableForBase(PrimaryBase, RD, rtti, methods, true, PrimaryBaseWasVirtual); |