From 7622cd3410846d28862ecfe862117894a259a7fa Mon Sep 17 00:00:00 2001 From: Anders Carlsson Date: Thu, 26 Nov 2009 03:09:37 +0000 Subject: [PATCH] Add a CovariantThunkAdjustment struct that represents the adjustments needed for a covariant thunk. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@89933 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/CodeGen/CGCXX.cpp | 108 ++++++++++++++++++---------------- lib/CodeGen/CGVtable.cpp | 6 +- lib/CodeGen/CGVtable.h | 13 ++++ lib/CodeGen/CodeGenFunction.h | 11 ++-- lib/CodeGen/CodeGenModule.h | 6 +- lib/CodeGen/Mangle.cpp | 11 ++-- lib/CodeGen/Mangle.h | 5 +- 7 files changed, 93 insertions(+), 67 deletions(-) diff --git a/lib/CodeGen/CGCXX.cpp b/lib/CodeGen/CGCXX.cpp index 7dc4b1e961..ceff7508b2 100644 --- a/lib/CodeGen/CGCXX.cpp +++ b/lib/CodeGen/CGCXX.cpp @@ -824,49 +824,50 @@ CodeGenFunction::GenerateThunk(llvm::Function *Fn, const CXXMethodDecl *MD, bool Extern, const ThunkAdjustment &ThisAdjustment) { return GenerateCovariantThunk(Fn, MD, Extern, - ThisAdjustment.NonVirtual, - ThisAdjustment.Virtual, 0, 0); + CovariantThunkAdjustment(ThisAdjustment, + ThunkAdjustment())); } -llvm::Value *CodeGenFunction::DynamicTypeAdjust(llvm::Value *V, int64_t nv, - int64_t v) { - llvm::Type *Ptr8Ty = llvm::PointerType::get(llvm::Type::getInt8Ty(VMContext), - 0); +llvm::Value * +CodeGenFunction::DynamicTypeAdjust(llvm::Value *V, + const ThunkAdjustment &Adjustment) { + const llvm::Type *Int8PtrTy = llvm::Type::getInt8PtrTy(VMContext); + const llvm::Type *OrigTy = V->getType(); - if (nv) { + if (Adjustment.NonVirtual) { // Do the non-virtual adjustment - V = Builder.CreateBitCast(V, Ptr8Ty); - V = Builder.CreateConstInBoundsGEP1_64(V, nv); + V = Builder.CreateBitCast(V, Int8PtrTy); + V = Builder.CreateConstInBoundsGEP1_64(V, Adjustment.NonVirtual); V = Builder.CreateBitCast(V, OrigTy); } - if (v) { - // Do the virtual this adjustment - const llvm::Type *PtrDiffTy = - ConvertType(getContext().getPointerDiffType()); - llvm::Type *PtrPtr8Ty, *PtrPtrDiffTy; - PtrPtr8Ty = llvm::PointerType::get(Ptr8Ty, 0); - PtrPtrDiffTy = llvm::PointerType::get(PtrDiffTy, 0); - llvm::Value *ThisVal = Builder.CreateBitCast(V, Ptr8Ty); - V = Builder.CreateBitCast(V, PtrPtrDiffTy->getPointerTo()); - V = Builder.CreateLoad(V, "vtable"); - llvm::Value *VTablePtr = V; - assert(v % (LLVMPointerWidth/8) == 0 && "vtable entry unaligned"); - v /= LLVMPointerWidth/8; - V = Builder.CreateConstInBoundsGEP1_64(VTablePtr, v); - V = Builder.CreateLoad(V); - V = Builder.CreateGEP(ThisVal, V); - V = Builder.CreateBitCast(V, OrigTy); - } - return V; + + if (!Adjustment.Virtual) + return V; + + assert(Adjustment.Virtual % (LLVMPointerWidth / 8) == 0 && + "vtable entry unaligned"); + + // Do the virtual this adjustment + const llvm::Type *PtrDiffTy = ConvertType(getContext().getPointerDiffType()); + const llvm::Type *PtrDiffPtrTy = PtrDiffTy->getPointerTo(); + + llvm::Value *ThisVal = Builder.CreateBitCast(V, Int8PtrTy); + V = Builder.CreateBitCast(V, PtrDiffPtrTy->getPointerTo()); + V = Builder.CreateLoad(V, "vtable"); + + llvm::Value *VTablePtr = V; + uint64_t VirtualAdjustment = Adjustment.Virtual / (LLVMPointerWidth / 8); + V = Builder.CreateConstInBoundsGEP1_64(VTablePtr, VirtualAdjustment); + V = Builder.CreateLoad(V); + V = Builder.CreateGEP(ThisVal, V); + + return Builder.CreateBitCast(V, OrigTy); } -llvm::Constant *CodeGenFunction::GenerateCovariantThunk(llvm::Function *Fn, - const CXXMethodDecl *MD, - bool Extern, - int64_t nv_t, - int64_t v_t, - int64_t nv_r, - int64_t v_r) { +llvm::Constant * +CodeGenFunction::GenerateCovariantThunk(llvm::Function *Fn, + const CXXMethodDecl *MD, bool Extern, + const CovariantThunkAdjustment &Adjustment) { QualType ResultType = MD->getType()->getAs()->getResultType(); FunctionArgList Args; @@ -899,16 +900,23 @@ llvm::Constant *CodeGenFunction::GenerateCovariantThunk(llvm::Function *Fn, llvm::Value *Callee = CGM.GetAddrOfFunction(MD, Ty); CallArgList CallArgs; + bool ShouldAdjustReturnPointer = true; QualType ArgType = MD->getThisType(getContext()); llvm::Value *Arg = Builder.CreateLoad(LocalDeclMap[ThisDecl], "this"); - if (nv_t || v_t) { + if (!Adjustment.ThisAdjustment.isEmpty()) { // Do the this adjustment. const llvm::Type *OrigTy = Callee->getType(); - Arg = DynamicTypeAdjust(Arg, nv_t, v_t); - if (nv_r || v_r) { - Callee = CGM.BuildCovariantThunk(MD, Extern, 0, 0, nv_r, v_r); + Arg = DynamicTypeAdjust(Arg, Adjustment.ThisAdjustment); + + if (!Adjustment.ReturnAdjustment.isEmpty()) { + const CovariantThunkAdjustment &ReturnAdjustment = + CovariantThunkAdjustment(ThunkAdjustment(), + Adjustment.ReturnAdjustment); + + Callee = CGM.BuildCovariantThunk(MD, Extern, ReturnAdjustment); + Callee = Builder.CreateBitCast(Callee, OrigTy); - nv_r = v_r = 0; + ShouldAdjustReturnPointer = false; } } @@ -927,7 +935,7 @@ llvm::Constant *CodeGenFunction::GenerateCovariantThunk(llvm::Function *Fn, RValue RV = EmitCall(CGM.getTypes().getFunctionInfo(ResultType, CallArgs), Callee, CallArgs, MD); - if (nv_r || v_r) { + if (ShouldAdjustReturnPointer && !Adjustment.ReturnAdjustment.isEmpty()) { bool CanBeZero = !(ResultType->isReferenceType() // FIXME: attr nonnull can't be zero either /* || ResultType->hasAttr() */ ); @@ -942,7 +950,8 @@ llvm::Constant *CodeGenFunction::GenerateCovariantThunk(llvm::Function *Fn, Builder.CreateCondBr(Builder.CreateICmpNE(RV.getScalarVal(), Zero), NonZeroBlock, ZeroBlock); EmitBlock(NonZeroBlock); - llvm::Value *NZ = DynamicTypeAdjust(RV.getScalarVal(), nv_r, v_r); + llvm::Value *NZ = + DynamicTypeAdjust(RV.getScalarVal(), Adjustment.ReturnAdjustment); EmitBranch(ContBlock); EmitBlock(ZeroBlock); llvm::Value *Z = RV.getScalarVal(); @@ -953,7 +962,8 @@ llvm::Constant *CodeGenFunction::GenerateCovariantThunk(llvm::Function *Fn, RVOrZero->addIncoming(Z, ZeroBlock); RV = RValue::get(RVOrZero); } else - RV = RValue::get(DynamicTypeAdjust(RV.getScalarVal(), nv_r, v_r)); + RV = RValue::get(DynamicTypeAdjust(RV.getScalarVal(), + Adjustment.ReturnAdjustment)); } if (!ResultType->isVoidType()) @@ -987,12 +997,11 @@ CodeGenModule::BuildThunk(const CXXMethodDecl *MD, bool Extern, return m; } -llvm::Constant *CodeGenModule::BuildCovariantThunk(const CXXMethodDecl *MD, - bool Extern, int64_t nv_t, - int64_t v_t, int64_t nv_r, - int64_t v_r) { +llvm::Constant * +CodeGenModule::BuildCovariantThunk(const CXXMethodDecl *MD, bool Extern, + const CovariantThunkAdjustment &Adjustment) { llvm::SmallString<256> OutName; - getMangleContext().mangleCovariantThunk(MD, nv_t, v_t, nv_r, v_r, OutName); + getMangleContext().mangleCovariantThunk(MD, Adjustment, OutName); llvm::GlobalVariable::LinkageTypes linktype; linktype = llvm::GlobalValue::WeakAnyLinkage; if (!Extern) @@ -1005,8 +1014,7 @@ llvm::Constant *CodeGenModule::BuildCovariantThunk(const CXXMethodDecl *MD, llvm::Function *Fn = llvm::Function::Create(FTy, linktype, OutName.str(), &getModule()); - CodeGenFunction(*this).GenerateCovariantThunk(Fn, MD, Extern, nv_t, v_t, nv_r, - v_r); + CodeGenFunction(*this).GenerateCovariantThunk(Fn, MD, Extern, Adjustment); llvm::Constant *m = llvm::ConstantExpr::getBitCast(Fn, Ptr8Ty); return m; } diff --git a/lib/CodeGen/CGVtable.cpp b/lib/CodeGen/CGVtable.cpp index 08690f23a8..69bf2e6ae1 100644 --- a/lib/CodeGen/CGVtable.cpp +++ b/lib/CodeGen/CGVtable.cpp @@ -349,8 +349,10 @@ public: Index_t v_t = i->second.first.first.second; Index_t nv_r = i->second.first.second.first; Index_t v_r = i->second.first.second.second; - submethods[idx] = CGM.BuildCovariantThunk(MD, Extern, nv_t, v_t, nv_r, - v_r); + + CovariantThunkAdjustment Adjustment(ThunkAdjustment(nv_t, v_t), + ThunkAdjustment(nv_r, v_r)); + submethods[idx] = CGM.BuildCovariantThunk(MD, Extern, Adjustment); } CovariantThunks.clear(); for (Pures_t::iterator i = Pures.begin(), e = Pures.end(); diff --git a/lib/CodeGen/CGVtable.h b/lib/CodeGen/CGVtable.h index 1d98bed4b2..9a25ce3033 100644 --- a/lib/CodeGen/CGVtable.h +++ b/lib/CodeGen/CGVtable.h @@ -49,6 +49,19 @@ struct ThunkAdjustment { int64_t Virtual; }; +/// CovariantThunkAdjustment - Adjustment of the 'this' pointer and the +/// return pointer for covariant thunks. +struct CovariantThunkAdjustment { + CovariantThunkAdjustment(const ThunkAdjustment &ThisAdjustment, + const ThunkAdjustment &ReturnAdjustment) + : ThisAdjustment(ThisAdjustment), ReturnAdjustment(ReturnAdjustment) { } + + CovariantThunkAdjustment() { } + + ThunkAdjustment ThisAdjustment; + ThunkAdjustment ReturnAdjustment; +}; + class CGVtableInfo { CodeGenModule &CGM; diff --git a/lib/CodeGen/CodeGenFunction.h b/lib/CodeGen/CodeGenFunction.h index b811c25b8a..078beabd1b 100644 --- a/lib/CodeGen/CodeGenFunction.h +++ b/lib/CodeGen/CodeGenFunction.h @@ -437,16 +437,17 @@ public: /// DynamicTypeAdjust - Do the non-virtual and virtual adjustments on an /// object pointer to alter the dynamic type of the pointer. Used by /// GenerateCovariantThunk for building thunks. - llvm::Value *DynamicTypeAdjust(llvm::Value *V, int64_t nv, int64_t v); + llvm::Value *DynamicTypeAdjust(llvm::Value *V, + const ThunkAdjustment &Adjustment); /// GenerateThunk - Generate a thunk for the given method llvm::Constant *GenerateThunk(llvm::Function *Fn, const CXXMethodDecl *MD, bool Extern, const ThunkAdjustment &ThisAdjustment); - llvm::Constant *GenerateCovariantThunk(llvm::Function *Fn, - const CXXMethodDecl *MD, bool Extern, - int64_t nv_t, int64_t v_t, - int64_t nv_r, int64_t v_r); + llvm::Constant * + GenerateCovariantThunk(llvm::Function *Fn, const CXXMethodDecl *MD, + bool Extern, + const CovariantThunkAdjustment &Adjustment); void EmitCtorPrologue(const CXXConstructorDecl *CD, CXXCtorType Type); diff --git a/lib/CodeGen/CodeGenModule.h b/lib/CodeGen/CodeGenModule.h index bc2d73edc1..5c3e633daa 100644 --- a/lib/CodeGen/CodeGenModule.h +++ b/lib/CodeGen/CodeGenModule.h @@ -238,9 +238,9 @@ public: const ThunkAdjustment &ThisAdjustment); /// BuildCoVariantThunk - Build a thunk for the given method - llvm::Constant *BuildCovariantThunk(const CXXMethodDecl *MD, bool Extern, - int64_t nv_t, int64_t v_t, - int64_t nv_r, int64_t v_r); + llvm::Constant * + BuildCovariantThunk(const CXXMethodDecl *MD, bool Extern, + const CovariantThunkAdjustment &Adjustment); typedef std::pair CtorVtable_t; typedef llvm::DenseMap &Res) { +void +MangleContext::mangleCovariantThunk(const FunctionDecl *FD, + const CovariantThunkAdjustment& Adjustment, + llvm::SmallVectorImpl &Res) { // FIXME: Hum, we might have to thunk these, fix. assert(!isa(FD) && "Use mangleCXXDtor for destructor decls!"); @@ -1384,8 +1385,8 @@ void MangleContext::mangleCovariantThunk(const FunctionDecl *FD, int64_t nv_t, // # second call-offset is result adjustment CXXNameMangler Mangler(*this, Res); Mangler.getStream() << "_ZTc"; - Mangler.mangleCallOffset(ThunkAdjustment(nv_t, v_t)); - Mangler.mangleCallOffset(ThunkAdjustment(nv_r, v_r)); + Mangler.mangleCallOffset(Adjustment.ThisAdjustment); + Mangler.mangleCallOffset(Adjustment.ReturnAdjustment); Mangler.mangleFunctionEncoding(FD); } diff --git a/lib/CodeGen/Mangle.h b/lib/CodeGen/Mangle.h index 81b73197d3..65b1d9f961 100644 --- a/lib/CodeGen/Mangle.h +++ b/lib/CodeGen/Mangle.h @@ -35,6 +35,7 @@ namespace clang { class VarDecl; namespace CodeGen { + class CovariantThunkAdjustment; class ThunkAdjustment; /// MangleContext - Context for tracking state which persists across multiple @@ -66,8 +67,8 @@ public: void mangleThunk(const FunctionDecl *FD, const ThunkAdjustment &ThisAdjustment, llvm::SmallVectorImpl &); - void mangleCovariantThunk(const FunctionDecl *FD, int64_t nv_t, int64_t v_t, - int64_t nv_r, int64_t v_r, + void mangleCovariantThunk(const FunctionDecl *FD, + const CovariantThunkAdjustment& Adjustment, llvm::SmallVectorImpl &); void mangleGuardVariable(const VarDecl *D, llvm::SmallVectorImpl &); void mangleCXXVtable(const CXXRecordDecl *RD, llvm::SmallVectorImpl &);