diff options
Diffstat (limited to 'lib/CodeGen')
-rw-r--r-- | lib/CodeGen/CGCXX.cpp | 46 | ||||
-rw-r--r-- | lib/CodeGen/CGVtable.cpp | 58 | ||||
-rw-r--r-- | lib/CodeGen/CGVtable.h | 14 | ||||
-rw-r--r-- | lib/CodeGen/CodeGenModule.cpp | 8 |
4 files changed, 72 insertions, 54 deletions
diff --git a/lib/CodeGen/CGCXX.cpp b/lib/CodeGen/CGCXX.cpp index 77bee48b58..d82f935971 100644 --- a/lib/CodeGen/CGCXX.cpp +++ b/lib/CodeGen/CGCXX.cpp @@ -1030,23 +1030,14 @@ CodeGenModule::GetAddrOfCovariantThunk(GlobalDecl GD, } void CodeGenModule::BuildThunksForVirtual(GlobalDecl GD) { - BuildThunksForVirtualRecursive(GD, GD); -} - -void -CodeGenModule::BuildThunksForVirtualRecursive(GlobalDecl GD, - GlobalDecl BaseOGD) { + CGVtableInfo::AdjustmentVectorTy *AdjPtr = getVtableInfo().getAdjustments(GD); + if (!AdjPtr) + return; + CGVtableInfo::AdjustmentVectorTy &Adj = *AdjPtr; const CXXMethodDecl *MD = cast<CXXMethodDecl>(GD.getDecl()); - const CXXMethodDecl *BaseOMD = cast<CXXMethodDecl>(BaseOGD.getDecl()); - for (CXXMethodDecl::method_iterator mi = BaseOMD->begin_overridden_methods(), - e = BaseOMD->end_overridden_methods(); - mi != e; ++mi) { - GlobalDecl OGD; - const CXXMethodDecl *OMD = *mi; - if (const CXXDestructorDecl *DD = dyn_cast<CXXDestructorDecl>(OMD)) - OGD = GlobalDecl(DD, GD.getDtorType()); - else - OGD = GlobalDecl(OMD); + for (unsigned i = 0; i < Adj.size(); i++) { + GlobalDecl OGD = Adj[i].first; + const CXXMethodDecl *OMD = cast<CXXMethodDecl>(OGD.getDecl()); QualType nc_oret = OMD->getType()->getAs<FunctionType>()->getResultType(); CanQualType oret = getContext().getCanonicalType(nc_oret); QualType nc_ret = MD->getType()->getAs<FunctionType>()->getResultType(); @@ -1059,8 +1050,7 @@ CodeGenModule::BuildThunksForVirtualRecursive(GlobalDecl GD, CXXRecordDecl *B = cast<CXXRecordDecl>(qB->getAs<RecordType>()->getDecl()); ReturnAdjustment = ComputeThunkAdjustment(D, B); } - ThunkAdjustment ThisAdjustment = - getVtableInfo().getThisAdjustment(GD, OGD); + ThunkAdjustment ThisAdjustment = Adj[i].second; bool Extern = !cast<CXXRecordDecl>(OMD->getDeclContext())->isInAnonymousNamespace(); if (!ReturnAdjustment.isEmpty() || !ThisAdjustment.isEmpty()) { CovariantThunkAdjustment CoAdj(ThisAdjustment, ReturnAdjustment); @@ -1070,7 +1060,24 @@ CodeGenModule::BuildThunksForVirtualRecursive(GlobalDecl GD, else FnConst = GetAddrOfThunk(GD, ThisAdjustment); if (!isa<llvm::Function>(FnConst)) { - assert(0 && "Figure out how to handle incomplete-type cases!"); + llvm::Constant *SubExpr = + cast<llvm::ConstantExpr>(FnConst)->getOperand(0); + llvm::Function *OldFn = cast<llvm::Function>(SubExpr); + std::string Name = OldFn->getNameStr(); + GlobalDeclMap.erase(UniqueMangledName(Name.data(), + Name.data() + Name.size() + 1)); + llvm::Constant *NewFnConst; + if (!ReturnAdjustment.isEmpty()) + NewFnConst = GetAddrOfCovariantThunk(GD, CoAdj); + else + NewFnConst = GetAddrOfThunk(GD, ThisAdjustment); + llvm::Function *NewFn = cast<llvm::Function>(NewFnConst); + NewFn->takeName(OldFn); + llvm::Constant *NewPtrForOldDecl = + llvm::ConstantExpr::getBitCast(NewFn, OldFn->getType()); + OldFn->replaceAllUsesWith(NewPtrForOldDecl); + OldFn->eraseFromParent(); + FnConst = NewFn; } llvm::Function *Fn = cast<llvm::Function>(FnConst); if (Fn->isDeclaration()) { @@ -1085,7 +1092,6 @@ CodeGenModule::BuildThunksForVirtualRecursive(GlobalDecl GD, CodeGenFunction(*this).GenerateCovariantThunk(Fn, GD, Extern, CoAdj); } } - BuildThunksForVirtualRecursive(GD, OGD); } } diff --git a/lib/CodeGen/CGVtable.cpp b/lib/CodeGen/CGVtable.cpp index bca893e5b6..7efa88b8e1 100644 --- a/lib/CodeGen/CGVtable.cpp +++ b/lib/CodeGen/CGVtable.cpp @@ -26,6 +26,9 @@ class VtableBuilder { public: /// Index_t - Vtable index type. typedef uint64_t Index_t; + typedef std::vector<std::pair<GlobalDecl, + std::pair<GlobalDecl, ThunkAdjustment> > > + SavedAdjustmentsVectorTy; private: // VtableComponents - The components of the vtable being built. @@ -142,9 +145,7 @@ private: typedef llvm::DenseMap<uint64_t, ThunkAdjustment> ThisAdjustmentsMapTy; ThisAdjustmentsMapTy ThisAdjustments; - typedef std::vector<std::pair<std::pair<GlobalDecl, GlobalDecl>, - ThunkAdjustment> > SavedThisAdjustmentsVectorTy; - SavedThisAdjustmentsVectorTy SavedThisAdjustments; + SavedAdjustmentsVectorTy SavedAdjustments; /// BaseReturnTypes - Contains the base return types of methods who have been /// overridden with methods whose return types require adjustment. Used for @@ -213,8 +214,8 @@ public: llvm::DenseMap<const CXXRecordDecl *, Index_t> &getVBIndex() { return VBIndex; } - SavedThisAdjustmentsVectorTy &getSavedThisAdjustments() - { return SavedThisAdjustments; } + SavedAdjustmentsVectorTy &getSavedAdjustments() + { return SavedAdjustments; } llvm::Constant *wrap(Index_t i) { llvm::Constant *m; @@ -376,8 +377,9 @@ public: D1(printf(" vfn for %s at %d\n", MD->getNameAsString().c_str(), (int)Index[GD])); + + VCallOffset[GD] = Offset/8; if (MorallyVirtual) { - VCallOffset[GD] = Offset/8; Index_t &idx = VCall[GD]; // Allocate the first one, after that, we reuse the previous one. if (idx == 0) { @@ -838,22 +840,21 @@ bool VtableBuilder::OverrideMethod(GlobalDecl GD, bool MorallyVirtual, if (!isPure && !ThisAdjustment.isEmpty()) { ThisAdjustments[Index] = ThisAdjustment; - SavedThisAdjustments.push_back(std::make_pair(std::make_pair(GD, OGD), - ThisAdjustment)); + SavedAdjustments.push_back( + std::make_pair(GD, std::make_pair(OGD, ThisAdjustment))); } return true; } - // FIXME: finish off - int64_t NonVirtualAdjustment = VCallOffset[OGD] - OverrideOffset/8; + int64_t NonVirtualAdjustment = -VCallOffset[OGD] + OverrideOffset/8; if (NonVirtualAdjustment) { ThunkAdjustment ThisAdjustment(NonVirtualAdjustment, 0); if (!isPure) { ThisAdjustments[Index] = ThisAdjustment; - SavedThisAdjustments.push_back(std::make_pair(std::make_pair(GD, OGD), - ThisAdjustment)); + SavedAdjustments.push_back( + std::make_pair(GD, std::make_pair(OGD, ThisAdjustment))); } } return true; @@ -1070,30 +1071,31 @@ uint64_t CGVtableInfo::getMethodVtableIndex(GlobalDecl GD) { return I->second; } -ThunkAdjustment CGVtableInfo::getThisAdjustment(GlobalDecl GD, - GlobalDecl OGD) { - SavedThisAdjustmentsTy::iterator I = - SavedThisAdjustments.find(std::make_pair(GD, OGD)); - if (I != SavedThisAdjustments.end()) - return I->second; +CGVtableInfo::AdjustmentVectorTy* +CGVtableInfo::getAdjustments(GlobalDecl GD) { + SavedAdjustmentsTy::iterator I = SavedAdjustments.find(GD); + if (I != SavedAdjustments.end()) + return &I->second; const CXXRecordDecl *RD = cast<CXXRecordDecl>(GD.getDecl()->getDeclContext()); - if (!SavedThisAdjustmentRecords.insert(RD).second) - return ThunkAdjustment(); + if (!SavedAdjustmentRecords.insert(RD).second) + return 0; VtableBuilder b(RD, RD, 0, CGM, false); D1(printf("vtable %s\n", RD->getNameAsCString())); b.GenerateVtableForBase(RD); b.GenerateVtableForVBases(RD); - - SavedThisAdjustments.insert(b.getSavedThisAdjustments().begin(), - b.getSavedThisAdjustments().end()); - I = SavedThisAdjustments.find(std::make_pair(GD, OGD)); - if (I != SavedThisAdjustments.end()) - return I->second; + for (VtableBuilder::SavedAdjustmentsVectorTy::iterator + i = b.getSavedAdjustments().begin(), + e = b.getSavedAdjustments().end(); i != e; i++) + SavedAdjustments[i->first].push_back(i->second); + + I = SavedAdjustments.find(GD); + if (I != SavedAdjustments.end()) + return &I->second; - return ThunkAdjustment(); + return 0; } int64_t CGVtableInfo::getVirtualBaseOffsetIndex(const CXXRecordDecl *RD, @@ -1470,7 +1472,7 @@ void CGVtableInfo::MaybeEmitVtable(GlobalDecl GD) { for (CXXRecordDecl::method_iterator i = RD->method_begin(), e = RD->method_end(); i != e; ++i) { - if ((*i)->isVirtual() && (*i)->hasInlineBody()) { + if ((*i)->isVirtual() && ((*i)->hasInlineBody() || (*i)->isImplicit())) { if (const CXXDestructorDecl *DD = dyn_cast<CXXDestructorDecl>(*i)) { CGM.BuildThunksForVirtual(GlobalDecl(DD, Dtor_Complete)); CGM.BuildThunksForVirtual(GlobalDecl(DD, Dtor_Deleting)); diff --git a/lib/CodeGen/CGVtable.h b/lib/CodeGen/CGVtable.h index 1507725f0f..eed5b64085 100644 --- a/lib/CodeGen/CGVtable.h +++ b/lib/CodeGen/CGVtable.h @@ -62,6 +62,11 @@ public: }; class CGVtableInfo { +public: + typedef std::vector<std::pair<GlobalDecl, ThunkAdjustment> > + AdjustmentVectorTy; + +private: CodeGenModule &CGM; /// MethodVtableIndices - Contains the index (relative to the vtable address @@ -84,10 +89,9 @@ class CGVtableInfo { /// pointers in the vtable for a given record decl. llvm::DenseMap<const CXXRecordDecl *, uint64_t> NumVirtualFunctionPointers; - typedef llvm::DenseMap<std::pair<GlobalDecl, GlobalDecl>, - ThunkAdjustment> SavedThisAdjustmentsTy; - SavedThisAdjustmentsTy SavedThisAdjustments; - llvm::DenseSet<const CXXRecordDecl*> SavedThisAdjustmentRecords; + typedef llvm::DenseMap<GlobalDecl, AdjustmentVectorTy> SavedAdjustmentsTy; + SavedAdjustmentsTy SavedAdjustments; + llvm::DenseSet<const CXXRecordDecl*> SavedAdjustmentRecords; /// getNumVirtualFunctionPointers - Return the number of virtual function /// pointers in the vtable for a given record decl. @@ -128,7 +132,7 @@ public: int64_t getVirtualBaseOffsetIndex(const CXXRecordDecl *RD, const CXXRecordDecl *VBase); - ThunkAdjustment getThisAdjustment(GlobalDecl GD, GlobalDecl OGD); + AdjustmentVectorTy *getAdjustments(GlobalDecl GD); /// getVtableAddressPoint - returns the address point of the vtable for the /// given record decl. diff --git a/lib/CodeGen/CodeGenModule.cpp b/lib/CodeGen/CodeGenModule.cpp index 5f822f509f..6250e6952d 100644 --- a/lib/CodeGen/CodeGenModule.cpp +++ b/lib/CodeGen/CodeGenModule.cpp @@ -625,7 +625,13 @@ void CodeGenModule::EmitGlobalDefinition(GlobalDecl GD) { getVtableInfo().MaybeEmitVtable(GD); if (MD->isVirtual() && MD->isOutOfLine() && (!isa<CXXDestructorDecl>(D) || GD.getDtorType() != Dtor_Base)) { - BuildThunksForVirtual(GD); + if (isa<CXXDestructorDecl>(D)) { + GlobalDecl CanonGD(cast<CXXDestructorDecl>(D->getCanonicalDecl()), + GD.getDtorType()); + BuildThunksForVirtual(CanonGD); + } else { + BuildThunksForVirtual(MD->getCanonicalDecl()); + } } } |