diff options
author | Anders Carlsson <andersca@mac.com> | 2010-03-28 20:34:31 +0000 |
---|---|---|
committer | Anders Carlsson <andersca@mac.com> | 2010-03-28 20:34:31 +0000 |
commit | bdb88655204ec14a20e51210bd50e84fe2f1cee9 (patch) | |
tree | 387f6ae8265ca7a4751331baceb4f6b099c2a862 /lib/CodeGen/CGClass.cpp | |
parent | d103f9f9b401b419e756f8c1849683cd77586067 (diff) |
More improvements to setting the vtable pointer. We now no longer set the vtable pointer for non-virtual primary bases. We also do a pre-order traversal of the class hierarchy; this is necessary in order to get the right vbase offset offsets in base ctors/dtors.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@99775 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/CodeGen/CGClass.cpp')
-rw-r--r-- | lib/CodeGen/CGClass.cpp | 99 |
1 files changed, 53 insertions, 46 deletions
diff --git a/lib/CodeGen/CGClass.cpp b/lib/CodeGen/CGClass.cpp index 2fa5837289..70c6e547bd 100644 --- a/lib/CodeGen/CGClass.cpp +++ b/lib/CodeGen/CGClass.cpp @@ -690,7 +690,7 @@ CodeGenFunction::SynthesizeCXXCopyConstructor(const FunctionArgList &Args) { } } - InitializeVtablePtrs(ClassDecl); + InitializeVTablePointers(ClassDecl); } /// SynthesizeCXXCopyAssignment - Implicitly define copy assignment operator. @@ -1010,7 +1010,7 @@ void CodeGenFunction::EmitCtorPrologue(const CXXConstructorDecl *CD, MemberInitializers.push_back(Member); } - InitializeVtablePtrs(ClassDecl); + InitializeVTablePointers(ClassDecl); for (unsigned I = 0, E = MemberInitializers.size(); I != E; ++I) { assert(LiveTemporaries.empty() && @@ -1060,7 +1060,7 @@ void CodeGenFunction::EmitDestructorBody(FunctionArgList &Args) { // Otherwise, we're in the base variant, so we need to ensure the // vtable ptrs are right before emitting the body. } else { - InitializeVtablePtrs(Dtor->getParent()); + InitializeVTablePointers(Dtor->getParent()); } // Emit the body of the statement. @@ -1584,59 +1584,66 @@ CodeGenFunction::InitializeVTablePointer(BaseSubobject Base, Builder.CreateStore(VTableAddressPoint, VTableField); } -void CodeGenFunction::InitializeVtablePtrs(const CXXRecordDecl *RD) { - if (!RD->isDynamicClass()) - return; - - // Get the VTable. - llvm::Constant *VTable = CGM.getVTables().GetAddrOfVTable(RD); - - // Store address points for the current class and its non-virtual bases. - InitializeVtablePtrs(BaseSubobject(RD, 0), VTable, RD); +void +CodeGenFunction::InitializeVTablePointers(BaseSubobject Base, + bool BaseIsMorallyVirtual, + bool BaseIsNonVirtualPrimaryBase, + llvm::Constant *VTable, + const CXXRecordDecl *VTableClass, + VisitedVirtualBasesSetTy& VBases) { + // If this base is a non-virtual primary base the address point has already + // been set. + if (true || !BaseIsNonVirtualPrimaryBase) { + // Initialize the vtable pointer for this base. + InitializeVTablePointer(Base, BaseIsMorallyVirtual, VTable, VTableClass); + } - if (!RD->getNumVBases()) - return; - - const ASTRecordLayout &Layout = getContext().getASTRecordLayout(RD); + const CXXRecordDecl *RD = Base.getBase(); - // Store address points for virtual basess. - for (CXXRecordDecl::base_class_const_iterator I = RD->vbases_begin(), - E = RD->vbases_end(); I != E; ++I) { + // Traverse bases. + for (CXXRecordDecl::base_class_const_iterator I = RD->bases_begin(), + E = RD->bases_end(); I != E; ++I) { CXXRecordDecl *BaseDecl = cast<CXXRecordDecl>(I->getType()->getAs<RecordType>()->getDecl()); - uint64_t BaseOffset = Layout.getVBaseClassOffset(BaseDecl); - InitializeVtablePtrs(BaseSubobject(BaseDecl, BaseOffset), VTable, RD); + uint64_t BaseOffset; + + if (I->isVirtual()) { + // Check if we've visited this virtual base before. + if (!VBases.insert(BaseDecl)) + continue; + + const ASTRecordLayout &Layout = + getContext().getASTRecordLayout(VTableClass); + + BaseIsMorallyVirtual = true; + BaseIsNonVirtualPrimaryBase = false; + + BaseOffset = Layout.getVBaseClassOffset(BaseDecl); + } else { + const ASTRecordLayout &Layout = getContext().getASTRecordLayout(RD); + + BaseOffset = Base.getBaseOffset() + Layout.getBaseClassOffset(BaseDecl); + BaseIsNonVirtualPrimaryBase = Layout.getPrimaryBase() == BaseDecl; + } + + InitializeVTablePointers(BaseSubobject(BaseDecl, BaseOffset), + BaseIsMorallyVirtual, BaseIsNonVirtualPrimaryBase, + VTable, VTableClass, VBases); } } -void CodeGenFunction::InitializeVtablePtrs(BaseSubobject Base, - llvm::Constant *VTable, - const CXXRecordDecl *VTableClass) { - const CXXRecordDecl *RD = Base.getBase(); - - // Ignore classes without a vtable pointer. +void CodeGenFunction::InitializeVTablePointers(const CXXRecordDecl *RD) { if (!RD->isDynamicClass()) return; - - const ASTRecordLayout &Layout = getContext().getASTRecordLayout(RD); - // Store address points for non-virtual bases. - for (CXXRecordDecl::base_class_const_iterator I = RD->bases_begin(), - E = RD->bases_end(); I != E; ++I) { - if (I->isVirtual()) - continue; - - CXXRecordDecl *BaseDecl - = cast<CXXRecordDecl>(I->getType()->getAs<RecordType>()->getDecl()); - uint64_t BaseOffset = Base.getBaseOffset() + - Layout.getBaseClassOffset(BaseDecl); - - InitializeVtablePtrs(BaseSubobject(BaseDecl, BaseOffset), - VTable, VTableClass); - } + // Get the VTable. + llvm::Constant *VTable = CGM.getVTables().GetAddrOfVTable(RD); - // FIXME: BaseIsMorallyVirtual is not correct here. - InitializeVTablePointer(Base, /*BaseIsMorallyVirtual=*/false, VTable, - VTableClass); + // Initialize the vtable pointers for this class and all of its bases. + VisitedVirtualBasesSetTy VBases; + InitializeVTablePointers(BaseSubobject(RD, 0), + /*BaseIsMorallyVirtual=*/false, + /*BaseIsNonVirtualPrimaryBase=*/false, + VTable, RD, VBases); } |