From a661a54d50e33d8b58735ef4ded06b1ad639b165 Mon Sep 17 00:00:00 2001 From: Anders Carlsson Date: Tue, 16 Feb 2010 04:49:44 +0000 Subject: [PATCH] More work on the new layout code. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@96328 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/CodeGen/CGVtable.cpp | 77 ++++++++++++++++++++++++++++++++++------ 1 file changed, 66 insertions(+), 11 deletions(-) diff --git a/lib/CodeGen/CGVtable.cpp b/lib/CodeGen/CGVtable.cpp index 2f952c54b6..9233838c93 100644 --- a/lib/CodeGen/CGVtable.cpp +++ b/lib/CodeGen/CGVtable.cpp @@ -612,6 +612,10 @@ public: CK_DeletingDtorPointer }; + static VtableComponent MakeVBaseOffset(int64_t Offset) { + return VtableComponent(CK_VBaseOffset, Offset); + } + static VtableComponent MakeOffsetToTop(int64_t Offset) { return VtableComponent(CK_OffsetToTop, Offset); } @@ -643,6 +647,12 @@ public: return (Kind)(Value & 0x7); } + int64_t getVBaseOffset() const { + assert(getKind() == CK_VBaseOffset && "Invalid component kind!"); + + return getOffset(); + } + int64_t getOffsetToTop() const { assert(getKind() == CK_OffsetToTop && "Invalid component kind!"); @@ -735,6 +745,10 @@ private: /// FinalOverriders - The final overriders of the most derived class. FinalOverriders Overriders; + /// VCallAndVBaseOffsets - The vcall and vbase offset, of the vtable we're + // building (in reverse order). + llvm::SmallVector VCallAndVBaseOffsets; + /// Components - The components of the vtable being built. llvm::SmallVector Components; @@ -777,6 +791,17 @@ private: llvm::SmallVector, 16> ThisAdjustments; + typedef llvm::SmallPtrSet VisitedVirtualBasesSetTy; + + /// AddVCallAndVBaseOffsets - Add vcall offsets and vbase offsets for the + /// given class. + void AddVCallAndVBaseOffsets(const CXXRecordDecl *RD, int64_t OffsetToTop, + VisitedVirtualBasesSetTy &VBases); + + /// AddVBaseOffsets - Add vbase offsets for the given class. + void AddVBaseOffsets(const CXXRecordDecl *RD, int64_t OffsetToTop, + VisitedVirtualBasesSetTy &VBases); + /// ComputeReturnAdjustment - Compute the return adjustment given a return /// adjustment base offset. ReturnAdjustment ComputeReturnAdjustment(FinalOverriders::BaseOffset Offset); @@ -794,15 +819,15 @@ private: /// primary bases to the vtable components vector. void AddMethods(BaseSubobject Base, PrimaryBasesSetTy &PrimaryBases); - /// layoutVtable - Layout a vtable and all its secondary vtables. - void layoutVtable(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) { - layoutVtable(BaseSubobject(MostDerivedClass, 0)); + LayoutVtable(BaseSubobject(MostDerivedClass, 0)); } /// dumpLayout - Dump the vtable layout. @@ -863,6 +888,32 @@ VtableBuilder::ComputeThisAdjustment(FinalOverriders::BaseOffset Offset) { return Adjustment; } +void +VtableBuilder::AddVCallAndVBaseOffsets(const CXXRecordDecl *RD, + int64_t OffsetToTop, + VisitedVirtualBasesSetTy &VBases) { + const ASTRecordLayout &Layout = Context.getASTRecordLayout(RD); + + // Itanium C++ ABI 2.5.2: + // ..in classes sharing a virtual table with a primary base class, the vcall + // and vbase offsets added by the derived class all come before the vcall + // and vbase offsets required by the base class, so that the latter may be + // laid out as required by the base class without regard to additions from + // the derived class(es). + + // (Since we're emitting the vcall and vbase offsets in reverse order, we'll + // emit them for the primary base first). + if (const CXXRecordDecl *PrimaryBase = Layout.getPrimaryBase()) + AddVCallAndVBaseOffsets(PrimaryBase, OffsetToTop, VBases); + + AddVBaseOffsets(RD, OffsetToTop, VBases); +} + +void VtableBuilder::AddVBaseOffsets(const CXXRecordDecl *RD, + int64_t OffsetToTop, + VisitedVirtualBasesSetTy &VBases) { +} + void VtableBuilder::AddMethod(const CXXMethodDecl *MD, ReturnAdjustment ReturnAdjustment, @@ -955,7 +1006,7 @@ VtableBuilder::AddMethods(BaseSubobject Base, PrimaryBasesSetTy &PrimaryBases) { } } -void VtableBuilder::layoutVtable(BaseSubobject Base) { +void VtableBuilder::LayoutVtable(BaseSubobject Base) { const CXXRecordDecl *RD = Base.getBase(); assert(RD->isDynamicClass() && "class does not have a vtable!"); @@ -998,23 +1049,27 @@ void VtableBuilder::layoutVtable(BaseSubobject Base) { const CXXRecordDecl *BaseDecl = cast(I->getType()->getAs()->getDecl()); + // Ignore bases that don't have a vtable. + if (!BaseDecl->isDynamicClass()) + continue; + // Ignore the primary base. if (BaseDecl == PrimaryBase) continue; - // Ignore bases that don't have a vtable. - if (!BaseDecl->isDynamicClass()) + // Ignore virtual bases, we'll emit them later. + if (I->isVirtual()) continue; - - assert(!I->isVirtual() && "FIXME: Handle virtual bases"); // Get the base offset of this base. uint64_t BaseOffset = Base.getBaseOffset() + Layout.getBaseClassOffset(BaseDecl); // Layout this secondary vtable. - layoutVtable(BaseSubobject(BaseDecl, BaseOffset)); + LayoutVtable(BaseSubobject(BaseDecl, BaseOffset)); } + + // FIXME: Emit vtables for virtual bases here. } /// dumpLayout - Dump the vtable layout. @@ -2327,8 +2382,8 @@ void CGVtableInfo::ComputeMethodVtableIndices(const CXXRecordDecl *RD) { if (ImplicitVirtualDtor) { // Itanium C++ ABI 2.5.2: - // If a class has an implicitly-defined virtual destructor, - // its entries come after the declared virtual function pointers. + // If a class has an implicitly-defined virtual destructor, + // its entries come after the declared virtual function pointers. // Add the complete dtor. MethodVtableIndices[GlobalDecl(ImplicitVirtualDtor, Dtor_Complete)] = -- 2.50.1