From: Eli Friedman Date: Mon, 7 Dec 2009 23:56:34 +0000 (+0000) Subject: A bunch more thunk fixes from misc testing. X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=b455f0e74be0144ab9738ef574d07bd661959525;p=clang A bunch more thunk fixes from misc testing. (Yes, I do intend to commit some tests for this.) git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@90818 91177308-0d34-0410-b5e6-96231b3b80d8 --- 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(GD.getDecl()); - const CXXMethodDecl *BaseOMD = cast(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(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(OGD.getDecl()); QualType nc_oret = OMD->getType()->getAs()->getResultType(); CanQualType oret = getContext().getCanonicalType(nc_oret); QualType nc_ret = MD->getType()->getAs()->getResultType(); @@ -1059,8 +1050,7 @@ CodeGenModule::BuildThunksForVirtualRecursive(GlobalDecl GD, CXXRecordDecl *B = cast(qB->getAs()->getDecl()); ReturnAdjustment = ComputeThunkAdjustment(D, B); } - ThunkAdjustment ThisAdjustment = - getVtableInfo().getThisAdjustment(GD, OGD); + ThunkAdjustment ThisAdjustment = Adj[i].second; bool Extern = !cast(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(FnConst)) { - assert(0 && "Figure out how to handle incomplete-type cases!"); + llvm::Constant *SubExpr = + cast(FnConst)->getOperand(0); + llvm::Function *OldFn = cast(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(NewFnConst); + NewFn->takeName(OldFn); + llvm::Constant *NewPtrForOldDecl = + llvm::ConstantExpr::getBitCast(NewFn, OldFn->getType()); + OldFn->replaceAllUsesWith(NewPtrForOldDecl); + OldFn->eraseFromParent(); + FnConst = NewFn; } llvm::Function *Fn = cast(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 > > + SavedAdjustmentsVectorTy; private: // VtableComponents - The components of the vtable being built. @@ -142,9 +145,7 @@ private: typedef llvm::DenseMap ThisAdjustmentsMapTy; ThisAdjustmentsMapTy ThisAdjustments; - typedef std::vector, - 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 &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(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(*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 > + 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 NumVirtualFunctionPointers; - typedef llvm::DenseMap, - ThunkAdjustment> SavedThisAdjustmentsTy; - SavedThisAdjustmentsTy SavedThisAdjustments; - llvm::DenseSet SavedThisAdjustmentRecords; + typedef llvm::DenseMap SavedAdjustmentsTy; + SavedAdjustmentsTy SavedAdjustments; + llvm::DenseSet 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(D) || GD.getDtorType() != Dtor_Base)) { - BuildThunksForVirtual(GD); + if (isa(D)) { + GlobalDecl CanonGD(cast(D->getCanonicalDecl()), + GD.getDtorType()); + BuildThunksForVirtual(CanonGD); + } else { + BuildThunksForVirtual(MD->getCanonicalDecl()); + } } }