Implement more of the inductive case for vtable layout involving
virtual base primaries and improve the layout of classes with virtual
bases. WIP.
Hey, I've decided I want a change to FileCheck, I need to ensure that
the group is together, nothing in between. Can we change it to check
the match line is from the line immediately following the last matched
line, if the source for the matched line is immediately after the
source for the previously matched line?
// CHECK: 1
// CHECK: 2
// CHECK: 3
// CHECK: 4
// CHECK: 5
// CHECK: 6
would require 1 2 and 3 to be continuous in the output, and 4 5 and 6
to be continuous.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@78638 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/lib/CodeGen/CGCXX.cpp b/lib/CodeGen/CGCXX.cpp
index 18c06cf..aff85fa 100644
--- a/lib/CodeGen/CGCXX.cpp
+++ b/lib/CodeGen/CGCXX.cpp
@@ -635,15 +635,24 @@
if (RD && !RD->isDynamicClass())
return;
- if (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);
- methods.push_back(m);
- }
- }
+ 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) {
@@ -653,17 +662,39 @@
methods.push_back(m);
}
}
-
- 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);
+ 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);
+ }
}
- methods.push_back(m);
- methods.push_back(rtti);
+ // 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);
+ methods.push_back(m);
+ }
+ }
- if (RD)
+ 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);
+ }
+
+ if (!isPrimary && RD)
for (meth_iter mi = RD->method_begin(), me = RD->method_end(); mi != me;
++mi) {
if (mi->isVirtual()) {
@@ -709,18 +740,6 @@
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);