From: Eli Friedman Date: Fri, 18 Dec 2009 23:47:41 +0000 (+0000) Subject: Work in progress for setting the vtable pointers for all bases correctly in X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=e12e77bed10f87bdc7305d0dbd1de89e48f280c1;p=clang Work in progress for setting the vtable pointers for all bases correctly in the constructor. This doesn't handle cases requiring the VTT at the moment, and generates unnecessary stores, but I think it's essentially correct. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@91731 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/lib/CodeGen/CGCXX.cpp b/lib/CodeGen/CGCXX.cpp index e860c295a5..0237a322a5 100644 --- a/lib/CodeGen/CGCXX.cpp +++ b/lib/CodeGen/CGCXX.cpp @@ -1700,21 +1700,65 @@ void CodeGenFunction::EmitCtorPrologue(const CXXConstructorDecl *CD, void CodeGenFunction::InitializeVtablePtrs(const CXXRecordDecl *ClassDecl) { if (!ClassDecl->isDynamicClass()) return; - - // Initialize the vtable pointer. - // FIXME: This needs to initialize secondary vtable pointers too. - llvm::Value *ThisPtr = LoadCXXThis(); llvm::Constant *Vtable = CGM.getVtableInfo().getVtable(ClassDecl); - uint64_t AddressPoint = CGM.getVtableInfo().getVtableAddressPoint(ClassDecl); + CodeGenModule::AddrSubMap_t& AddressPoints = + *(*CGM.AddressPoints[ClassDecl])[ClassDecl]; + llvm::Value *ThisPtr = LoadCXXThis(); + const ASTRecordLayout &Layout = getContext().getASTRecordLayout(ClassDecl); + + // Store address points for virtual bases + for (CXXRecordDecl::base_class_const_iterator I = + ClassDecl->vbases_begin(), E = ClassDecl->vbases_end(); I != E; ++I) { + const CXXBaseSpecifier &Base = *I; + CXXRecordDecl *BaseClassDecl + = cast(Base.getType()->getAs()->getDecl()); + uint64_t Offset = Layout.getVBaseClassOffset(BaseClassDecl); + InitializeVtablePtrsRecursive(BaseClassDecl, Vtable, AddressPoints, + ThisPtr, Offset); + } + + // Store address points for non-virtual bases and current class + InitializeVtablePtrsRecursive(ClassDecl, Vtable, AddressPoints, ThisPtr, 0); +} + +void CodeGenFunction::InitializeVtablePtrsRecursive( + const CXXRecordDecl *ClassDecl, + llvm::Constant *Vtable, + CodeGenModule::AddrSubMap_t& AddressPoints, + llvm::Value *ThisPtr, + uint64_t Offset) { + if (!ClassDecl->isDynamicClass()) + return; + + // Store address points for non-virtual bases + const ASTRecordLayout &Layout = getContext().getASTRecordLayout(ClassDecl); + for (CXXRecordDecl::base_class_const_iterator I = + ClassDecl->bases_begin(), E = ClassDecl->bases_end(); I != E; ++I) { + const CXXBaseSpecifier &Base = *I; + if (Base.isVirtual()) + continue; + CXXRecordDecl *BaseClassDecl + = cast(Base.getType()->getAs()->getDecl()); + uint64_t NewOffset = Offset + Layout.getBaseClassOffset(BaseClassDecl); + InitializeVtablePtrsRecursive(BaseClassDecl, Vtable, AddressPoints, + ThisPtr, NewOffset); + } + // Compute the address point + uint64_t AddressPoint = AddressPoints[std::make_pair(ClassDecl, Offset)]; llvm::Value *VtableAddressPoint = - Builder.CreateConstInBoundsGEP2_64(Vtable, 0, AddressPoint); - - llvm::Value *VtableField = - Builder.CreateBitCast(ThisPtr, - VtableAddressPoint->getType()->getPointerTo()); - + Builder.CreateConstInBoundsGEP2_64(Vtable, 0, AddressPoint); + + // Compute the address to store the address point + const llvm::Type *Int8PtrTy = llvm::Type::getInt8PtrTy(CGM.getLLVMContext()); + llvm::Value *VtableField = Builder.CreateBitCast(ThisPtr, Int8PtrTy); + VtableField = Builder.CreateConstInBoundsGEP1_64(VtableField, Offset/8); + const llvm::Type *AddressPointPtrTy = + VtableAddressPoint->getType()->getPointerTo(); + VtableField = Builder.CreateBitCast(ThisPtr, AddressPointPtrTy); + + // Store address point Builder.CreateStore(VtableAddressPoint, VtableField); } diff --git a/lib/CodeGen/CodeGenFunction.h b/lib/CodeGen/CodeGenFunction.h index 4bacd16f92..c2e59c01eb 100644 --- a/lib/CodeGen/CodeGenFunction.h +++ b/lib/CodeGen/CodeGenFunction.h @@ -515,6 +515,12 @@ public: void InitializeVtablePtrs(const CXXRecordDecl *ClassDecl); + void InitializeVtablePtrsRecursive(const CXXRecordDecl *ClassDecl, + llvm::Constant *Vtable, + CodeGenModule::AddrSubMap_t& AddressPoints, + llvm::Value *ThisPtr, + uint64_t Offset); + void SynthesizeCXXCopyConstructor(const CXXConstructorDecl *Ctor, CXXCtorType Type, llvm::Function *Fn, diff --git a/lib/CodeGen/CodeGenModule.h b/lib/CodeGen/CodeGenModule.h index 814b1ef694..939c66ca31 100644 --- a/lib/CodeGen/CodeGenModule.h +++ b/lib/CodeGen/CodeGenModule.h @@ -233,8 +233,8 @@ public: const CovariantThunkAdjustment &Adjustment); typedef std::pair CtorVtable_t; - typedef llvm::DenseMap*> AddrMap_t; + typedef llvm::DenseMap AddrSubMap_t; + typedef llvm::DenseMap AddrMap_t; llvm::DenseMap AddressPoints; /// GetCXXBaseClassOffset - Returns the offset from a derived class to its