diff options
author | Anders Carlsson <andersca@mac.com> | 2010-02-13 22:05:23 +0000 |
---|---|---|
committer | Anders Carlsson <andersca@mac.com> | 2010-02-13 22:05:23 +0000 |
commit | 76f1aa7658c34532785e6f44c99af65f3e4bd194 (patch) | |
tree | 8a2ccb5b365b3cd50cfab9581aa63e84f2464e75 | |
parent | a4699882abd8bedd159fa979508f8f6deb64a121 (diff) |
Start laying out secondary vtables.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@96123 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r-- | lib/CodeGen/CGVtable.cpp | 27 | ||||
-rw-r--r-- | test/CodeGenCXX/vtable-layout.cpp | 41 |
2 files changed, 57 insertions, 11 deletions
diff --git a/lib/CodeGen/CGVtable.cpp b/lib/CodeGen/CGVtable.cpp index 8bdb713f6c..4b2a703493 100644 --- a/lib/CodeGen/CGVtable.cpp +++ b/lib/CodeGen/CGVtable.cpp @@ -758,16 +758,15 @@ private: /// primary bases to the vtable components vector. void AddMethods(BaseSubobject Base, PrimaryBasesSetTy &PrimaryBases); - /// layoutSimpleVtable - A test function that will layout very simple vtables - /// without any bases. Just used for testing for now. - void layoutSimpleVtable(BaseSubobject Base); + /// layoutVtable - Layout a vtable and all its secondary vtables. + void layoutVtable(BaseSubobject Base); public: VtableBuilder(CGVtableInfo &VtableInfo, const CXXRecordDecl *MostDerivedClass) : VtableInfo(VtableInfo), MostDerivedClass(MostDerivedClass), Context(MostDerivedClass->getASTContext()), Overriders(MostDerivedClass) { - layoutSimpleVtable(BaseSubobject(MostDerivedClass, 0)); + layoutVtable(BaseSubobject(MostDerivedClass, 0)); } /// dumpLayout - Dump the vtable layout. @@ -849,7 +848,7 @@ VtableBuilder::AddMethods(BaseSubobject Base, PrimaryBasesSetTy &PrimaryBases) { assert(Layout.getBaseClassOffset(PrimaryBase) == 0 && "Primary base should have a zero offset!"); - AddMethods(BaseSubobject(PrimaryBase, 0), PrimaryBases); + AddMethods(BaseSubobject(PrimaryBase, Base.getBaseOffset()), PrimaryBases); if (!PrimaryBases.insert(PrimaryBase)) assert(false && "Found a duplicate primary base!"); @@ -887,14 +886,17 @@ VtableBuilder::AddMethods(BaseSubobject Base, PrimaryBasesSetTy &PrimaryBases) { } } -void VtableBuilder::layoutSimpleVtable(BaseSubobject Base) { +void VtableBuilder::layoutVtable(BaseSubobject Base) { const CXXRecordDecl *RD = Base.getBase(); // First, add the offset to top. - Components.push_back(VtableComponent::MakeOffsetToTop(0)); + // FIXME: This is not going to be right for construction vtables. + // FIXME: We should not use -8 here. + int64_t OffsetToTop = -(int64_t)Base.getBaseOffset() / 8; + Components.push_back(VtableComponent::MakeOffsetToTop(OffsetToTop)); // Next, add the RTTI. - Components.push_back(VtableComponent::MakeRTTI(RD)); + Components.push_back(VtableComponent::MakeRTTI(MostDerivedClass)); uint64_t AddressPoint = Components.size(); @@ -919,7 +921,7 @@ void VtableBuilder::layoutSimpleVtable(BaseSubobject Base) { const ASTRecordLayout &Layout = Context.getASTRecordLayout(RD); const CXXRecordDecl *PrimaryBase = Layout.getPrimaryBase(); - // Traverse bases. + // Layout secondary vtables. for (CXXRecordDecl::base_class_const_iterator I = RD->bases_begin(), E = RD->bases_end(); I != E; ++I) { const CXXRecordDecl *BaseDecl = @@ -931,7 +933,12 @@ void VtableBuilder::layoutSimpleVtable(BaseSubobject Base) { assert(!I->isVirtual() && "FIXME: Handle virtual bases"); - assert(false && "FIXME: Handle secondary virtual tables!"); + // Get the base offset of this base. + uint64_t BaseOffset = Base.getBaseOffset() + + Layout.getBaseClassOffset(BaseDecl); + + // Layout this secondary vtable. + layoutVtable(BaseSubobject(BaseDecl, BaseOffset)); } } diff --git a/test/CodeGenCXX/vtable-layout.cpp b/test/CodeGenCXX/vtable-layout.cpp index 622983f7c8..d509431a52 100644 --- a/test/CodeGenCXX/vtable-layout.cpp +++ b/test/CodeGenCXX/vtable-layout.cpp @@ -196,11 +196,50 @@ struct F : A { virtual void g(); virtual R3 *f() = 0; }; - void F::g() { } } +namespace Test5 { + +// Simple secondary vtables without this-adjustments. +struct A { + virtual void f(); + virtual void g(); + int a; +}; + +struct B1 : A { + virtual void f(); + int b1; +}; + +struct B2 : A { + virtual void g(); + int b2; +}; + +// CHECK: Vtable for 'Test5::C' (9 entries). +// CHECK-NEXT: 0 | offset_to_top (0) +// CHECK-NEXT: 1 | Test5::C RTTI +// CHECK-NEXT: -- (Test5::A, 0) vtable address -- +// CHECK-NEXT: -- (Test5::B1, 0) vtable address -- +// CHECK-NEXT: -- (Test5::C, 0) vtable address -- +// CHECK-NEXT: 2 | void Test5::B1::f() +// CHECK-NEXT: 3 | void Test5::A::g() +// CHECK-NEXT: 4 | void Test5::C::h() +// CHECK-NEXT: 5 | offset_to_top (-16) +// CHECK-NEXT: 6 | Test5::C RTTI +// CHECK-NEXT: -- (Test5::A, 16) vtable address -- +// CHECK-NEXT: -- (Test5::B2, 16) vtable address -- +// CHECK-NEXT: 7 | void Test5::A::f() +// CHECK-NEXT: 8 | void Test5::B2::g() +struct C : B1, B2 { + virtual void h(); +}; +void C::h() { } +} + // For now, just verify this doesn't crash. namespace test0 { struct Obj {}; |