From: Anders Carlsson Date: Tue, 16 Feb 2010 04:59:55 +0000 (+0000) Subject: Emit vbase offsets. X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=852213e54a1b2c2246776b4bb4e9527d70c98807;p=clang Emit vbase offsets. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@96329 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/lib/CodeGen/CGVtable.cpp b/lib/CodeGen/CGVtable.cpp index 9233838c93..970bbd777f 100644 --- a/lib/CodeGen/CGVtable.cpp +++ b/lib/CodeGen/CGVtable.cpp @@ -912,6 +912,27 @@ VtableBuilder::AddVCallAndVBaseOffsets(const CXXRecordDecl *RD, void VtableBuilder::AddVBaseOffsets(const CXXRecordDecl *RD, int64_t OffsetToTop, VisitedVirtualBasesSetTy &VBases) { + const ASTRecordLayout &MostDerivedClassLayout = + Context.getASTRecordLayout(MostDerivedClass); + + // Add vbase offsets. + for (CXXRecordDecl::base_class_const_iterator I = RD->bases_begin(), + E = RD->bases_end(); I != E; ++I) { + const CXXRecordDecl *BaseDecl = + cast(I->getType()->getAs()->getDecl()); + + // Check if this is a virtual base that we haven't visited before. + if (I->isVirtual() && VBases.insert(BaseDecl)) { + // FIXME: We shouldn't use / 8 here. + uint64_t Offset = + OffsetToTop + MostDerivedClassLayout.getVBaseClassOffset(BaseDecl) / 8; + + VCallAndVBaseOffsets.push_back(VtableComponent::MakeVBaseOffset(Offset)); + } + + // Check the base class looking for more vbase offsets. + AddVBaseOffsets(BaseDecl, OffsetToTop, VBases); + } } void @@ -1008,13 +1029,22 @@ VtableBuilder::AddMethods(BaseSubobject Base, PrimaryBasesSetTy &PrimaryBases) { void VtableBuilder::LayoutVtable(BaseSubobject Base) { const CXXRecordDecl *RD = Base.getBase(); - assert(RD->isDynamicClass() && "class does not have a vtable!"); - // First, add the offset to top. + int64_t OffsetToTop = -(int64_t)Base.getBaseOffset() / 8; + + // Add vcall and vbase offsets for this vtable. + VisitedVirtualBasesSetTy VBases; + AddVCallAndVBaseOffsets(RD, OffsetToTop, VBases); + + // Reverse them and add them to the vtable components. + std::reverse(VCallAndVBaseOffsets.begin(), VCallAndVBaseOffsets.end()); + Components.append(VCallAndVBaseOffsets.begin(), VCallAndVBaseOffsets.end()); + VCallAndVBaseOffsets.clear(); + + // Add the offset to top. // 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. @@ -1137,7 +1167,11 @@ void VtableBuilder::dumpLayout(llvm::raw_ostream& Out) { default: assert(false && "Unhandled component kind!"); break; - + + case VtableComponent::CK_VBaseOffset: + Out << "vbase_offset (" << Component.getVBaseOffset() << ")"; + break; + case VtableComponent::CK_OffsetToTop: Out << "offset_to_top (" << Component.getOffsetToTop() << ")"; break; diff --git a/test/CodeGenCXX/vtable-layout.cpp b/test/CodeGenCXX/vtable-layout.cpp index a41aad41f9..8fbe486faa 100644 --- a/test/CodeGenCXX/vtable-layout.cpp +++ b/test/CodeGenCXX/vtable-layout.cpp @@ -340,3 +340,28 @@ struct B : A { void B::f() { } } + +namespace Test9 { + +// Simple test of vbase offsets. + +struct A1 { int a1; }; +struct A2 { int a2; }; + +// CHECK: Vtable for 'Test9::B' (5 entries). +// CHECK-NEXT: 0 | vbase_offset (16) +// CHECK-NEXT: 1 | vbase_offset (12) +// CHECK-NEXT: 2 | offset_to_top (0) +// CHECK-NEXT: 3 | Test9::B RTTI +// CHECK-NEXT: -- (Test9::B, 0) vtable address -- +// CHECK-NEXT: 4 | void Test9::B::f() +struct B : virtual A1, virtual A2 { + int b; + + virtual void f(); +}; + + +void B::f() { } + +}