aboutsummaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
Diffstat (limited to 'lib')
-rw-r--r--lib/AST/RecordLayoutBuilder.cpp45
-rw-r--r--lib/CodeGen/CGCXX.cpp71
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);