From f9c95be2f64f5ce9a58f7451275604e41179069d Mon Sep 17 00:00:00 2001 From: Mike Stump Date: Fri, 18 Sep 2009 19:06:35 +0000 Subject: [PATCH] Generate more of the vbase virtual offset for covariant thunks. WIP. llvm-svn: 82253 --- clang/lib/CodeGen/CGCXX.cpp | 80 +++++++++++++++++++++++++++++++++---- 1 file changed, 72 insertions(+), 8 deletions(-) diff --git a/clang/lib/CodeGen/CGCXX.cpp b/clang/lib/CodeGen/CGCXX.cpp index 878d5ba4ca78..715f1b0d0d19 100644 --- a/clang/lib/CodeGen/CGCXX.cpp +++ b/clang/lib/CodeGen/CGCXX.cpp @@ -768,6 +768,7 @@ private: llvm::DenseMap Index; llvm::DenseMap VCall; llvm::DenseMap VCallOffset; + llvm::DenseMap VBIndex; typedef std::pair CallOffset; typedef llvm::DenseMap Thunks_t; Thunks_t Thunks; @@ -792,6 +793,8 @@ public: } llvm::DenseMap &getIndex() { return Index; } + llvm::DenseMap &getVBIndex() + { return VBIndex; } llvm::Constant *wrap(Index_t i) { llvm::Constant *m; @@ -805,7 +808,7 @@ public: void GenerateVBaseOffsets(std::vector &offsets, const CXXRecordDecl *RD, uint64_t Offset) { - for (CXXRecordDecl::base_class_const_iterator i =RD->bases_begin(), + for (CXXRecordDecl::base_class_const_iterator i = RD->bases_begin(), e = RD->bases_end(); i != e; ++i) { const CXXRecordDecl *Base = cast(i->getType()->getAs()->getDecl()); @@ -814,6 +817,8 @@ public: int64_t BaseOffset = -(Offset/8) + BLayout.getVBaseClassOffset(Base)/8; llvm::Constant *m = wrap(BaseOffset); m = wrap((0?700:0) + BaseOffset); + VBIndex[Base] = -(offsets.size()*LLVMPointerWidth/8) + - 3*LLVMPointerWidth/8; offsets.push_back(m); } GenerateVBaseOffsets(offsets, Base, Offset); @@ -824,6 +829,27 @@ public: SeenVBase.clear(); } + Index_t VBlookup(CXXRecordDecl *D, CXXRecordDecl *B); + + /// getVbaseOffset - Returns the index into the vtable for the virtual base + /// offset for the given (B) virtual base of the derived class D. + Index_t getVbaseOffset(QualType qB, QualType qD) { + qD = qD->getAs()->getPointeeType(); + qB = qB->getAs()->getPointeeType(); + CXXRecordDecl *D = cast(qD->getAs()->getDecl()); + CXXRecordDecl *B = cast(qB->getAs()->getDecl()); + if (D != Class) + return VBlookup(D, B); + llvm::DenseMap::iterator i; + i = VBIndex.find(B); + if (i != VBIndex.end()) + return i->second; + // FIXME: temporal botch, is this data here, by the time we need it? + + // FIXME: Locate the containing virtual base first. + return 42; + } + bool OverrideMethod(const CXXMethodDecl *MD, llvm::Constant *m, bool MorallyVirtual, Index_t Offset) { typedef CXXMethodDecl::method_iterator meth_iter; @@ -853,7 +879,7 @@ public: CallOffset ReturnOffset = std::make_pair(0, 0); if (oret != ret) { // FIXME: calculate offsets for covariance - ReturnOffset = std::make_pair(42,42); + ReturnOffset = std::make_pair(42,getVbaseOffset(oret, ret)); } Index[MD] = i; submethods[i] = m; @@ -1132,33 +1158,74 @@ private: typedef llvm::DenseMap MapTy; // FIXME: Move to Context. static MapTy IndexFor; + + typedef llvm::DenseMap VBElTy; + typedef llvm::DenseMap VBMapTy; + // FIXME: Move to Context. + static VBMapTy VBIndexFor; public: VtableInfo(CodeGenModule &cgm) : CGM(cgm) { } - void register_index(const CXXRecordDecl *RD, const ElTy &e) { + void RegisterIndex(const CXXRecordDecl *RD, const ElTy &e) { assert(IndexFor.find(RD) == IndexFor.end() && "Don't compute vtbl twice"); // We own a copy of this, it will go away shortly. - new ElTy (e); IndexFor[RD] = new ElTy (e); } + void RegisterVBIndex(const CXXRecordDecl *RD, const VBElTy &e) { + assert(VBIndexFor.find(RD) == VBIndexFor.end() && "Don't compute vtbl twice"); + // We own a copy of this, it will go away shortly. + VBIndexFor[RD] = new VBElTy (e); + } Index_t lookup(const CXXMethodDecl *MD) { const CXXRecordDecl *RD = MD->getParent(); MapTy::iterator I = IndexFor.find(RD); if (I == IndexFor.end()) { std::vector methods; + // FIXME: This seems expensive. Can we do a partial job to get + // just this data. VtableBuilder b(methods, RD, CGM); b.GenerateVtableForBase(RD); b.GenerateVtableForVBases(RD); - register_index(RD, b.getIndex()); + RegisterIndex(RD, b.getIndex()); I = IndexFor.find(RD); } assert(I->second->find(MD)!=I->second->end() && "Can't find vtable index"); return (*I->second)[MD]; } + Index_t VBlookup(const CXXRecordDecl *RD, const CXXRecordDecl *BD) { + VBMapTy::iterator I = VBIndexFor.find(RD); + if (I == VBIndexFor.end()) { + std::vector methods; + // FIXME: This seems expensive. Can we do a partial job to get + // just this data. + VtableBuilder b(methods, RD, CGM); + b.GenerateVtableForBase(RD); + b.GenerateVtableForVBases(RD); + RegisterVBIndex(RD, b.getVBIndex()); + I = VBIndexFor.find(RD); + } + assert(I->second->find(BD)!=I->second->end() && "Can't find vtable index"); + return (*I->second)[BD]; + } }; +// FIXME: move to Context +static VtableInfo *vtableinfo; + +VtableBuilder::Index_t VtableBuilder::VBlookup(CXXRecordDecl *D, + CXXRecordDecl *B) { + if (vtableinfo == 0) + vtableinfo = new VtableInfo(CGM); + + return vtableinfo->VBlookup(D, B); +} + + // FIXME: Move to Context. VtableInfo::MapTy VtableInfo::IndexFor; +// FIXME: Move to Context. +VtableInfo::VBMapTy VtableInfo::VBIndexFor; + llvm::Value *CodeGenFunction::GenerateVtable(const CXXRecordDecl *RD) { llvm::SmallString<256> OutName; llvm::raw_svector_ostream Out(OutName); @@ -1191,9 +1258,6 @@ llvm::Value *CodeGenFunction::GenerateVtable(const CXXRecordDecl *RD) { return vtable; } -// FIXME: move to Context -static VtableInfo *vtableinfo; - llvm::Constant *CodeGenFunction::GenerateThunk(llvm::Function *Fn, const CXXMethodDecl *MD, bool Extern, int64_t nv,