diff options
author | Eli Friedman <eli.friedman@gmail.com> | 2009-12-18 23:47:41 +0000 |
---|---|---|
committer | Eli Friedman <eli.friedman@gmail.com> | 2009-12-18 23:47:41 +0000 |
commit | e12e77bed10f87bdc7305d0dbd1de89e48f280c1 (patch) | |
tree | 4e40c3fbb96446c7bf69ad36b1eb257bf03feb52 | |
parent | c2c0d562bb1d03501433b450bb97df7812598d4c (diff) |
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
-rw-r--r-- | lib/CodeGen/CGCXX.cpp | 66 | ||||
-rw-r--r-- | lib/CodeGen/CodeGenFunction.h | 6 | ||||
-rw-r--r-- | lib/CodeGen/CodeGenModule.h | 4 |
3 files changed, 63 insertions, 13 deletions
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<CXXRecordDecl>(Base.getType()->getAs<RecordType>()->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<CXXRecordDecl>(Base.getType()->getAs<RecordType>()->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<const CXXRecordDecl *, uint64_t> CtorVtable_t; - typedef llvm::DenseMap<const CXXRecordDecl *, - llvm::DenseMap<CtorVtable_t, int64_t>*> AddrMap_t; + typedef llvm::DenseMap<CtorVtable_t, int64_t> AddrSubMap_t; + typedef llvm::DenseMap<const CXXRecordDecl *, AddrSubMap_t *> AddrMap_t; llvm::DenseMap<const CXXRecordDecl *, AddrMap_t*> AddressPoints; /// GetCXXBaseClassOffset - Returns the offset from a derived class to its |