diff options
author | Mike Stump <mrs@apple.com> | 2009-09-11 23:25:56 +0000 |
---|---|---|
committer | Mike Stump <mrs@apple.com> | 2009-09-11 23:25:56 +0000 |
commit | 6e319f6adc2a06c31cf99265854eef1321bcecf2 (patch) | |
tree | 2027f38d9a837bc0176049e8fe0410bb5db5d9cb | |
parent | 4719f4e86a84dec6f5a45771ae51d4ec72e4617a (diff) |
Add basic covariant thunk generation support. WIP.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@81585 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r-- | lib/CodeGen/CGCXX.cpp | 99 | ||||
-rw-r--r-- | lib/CodeGen/CodeGenFunction.h | 4 | ||||
-rw-r--r-- | lib/CodeGen/CodeGenModule.h | 4 | ||||
-rw-r--r-- | lib/CodeGen/Mangle.h | 7 |
4 files changed, 106 insertions, 8 deletions
diff --git a/lib/CodeGen/CGCXX.cpp b/lib/CodeGen/CGCXX.cpp index e739a9ce6c..742077f3ff 100644 --- a/lib/CodeGen/CGCXX.cpp +++ b/lib/CodeGen/CGCXX.cpp @@ -832,9 +832,12 @@ private: llvm::DenseMap<const CXXMethodDecl *, Index_t> Index; llvm::DenseMap<const CXXMethodDecl *, Index_t> VCall; llvm::DenseMap<const CXXMethodDecl *, Index_t> VCallOffset; - typedef llvm::DenseMap<const CXXMethodDecl *, - std::pair<Index_t, Index_t> > Thunks_t; + typedef std::pair<Index_t, Index_t> CallOffset; + typedef llvm::DenseMap<const CXXMethodDecl *, CallOffset> Thunks_t; Thunks_t Thunks; + typedef llvm::DenseMap<const CXXMethodDecl *, + std::pair<CallOffset, CallOffset> > CovariantThunks_t; + CovariantThunks_t CovariantThunks; std::vector<Index_t> VCalls; typedef CXXRecordDecl::method_iterator method_iter; // FIXME: Linkage should follow vtable @@ -907,6 +910,15 @@ public: // FIXME: begin_overridden_methods might be too lax, covariance */ if (submethods[i] != om) continue; + QualType nc_oret = OMD->getType()->getAsFunctionType()->getResultType(); + CanQualType oret = CGM.getContext().getCanonicalType(nc_oret); + QualType nc_ret = MD->getType()->getAsFunctionType()->getResultType(); + CanQualType ret = CGM.getContext().getCanonicalType(nc_ret); + CallOffset ReturnOffset = std::make_pair(0, 0); + if (oret != ret) { + // FIXME: calculate offsets for covariance + ReturnOffset = std::make_pair(42,42); + } Index[MD] = i; submethods[i] = m; @@ -922,8 +934,13 @@ public: VCalls[idx-1] = -VCallOffset[OMD] + Offset/8; } VCall[MD] = idx; - // FIXME: 0? - Thunks[MD] = std::make_pair(0, -((idx+extra+2)*LLVMPointerWidth/8)); + CallOffset ThisOffset; + // FIXME: calculate non-virtual offset + ThisOffset = std::make_pair(0, -((idx+extra+2)*LLVMPointerWidth/8)); + if (ReturnOffset.first || ReturnOffset.second) + CovariantThunks[MD] = std::make_pair(ThisOffset, ReturnOffset); + else + Thunks[MD] = ThisOffset; return true; } #if 0 @@ -950,6 +967,19 @@ public: submethods[idx] = CGM.BuildThunk(MD, Extern, nv_O, v_O); } Thunks.clear(); + for (CovariantThunks_t::iterator i = CovariantThunks.begin(), + e = CovariantThunks.end(); + i != e; ++i) { + const CXXMethodDecl *MD = i->first; + Index_t idx = Index[MD]; + Index_t nv_t = i->second.first.first; + Index_t v_t = i->second.first.second; + Index_t nv_r = i->second.second.first; + Index_t v_r = i->second.second.second; + submethods[idx] = CGM.BuildCovariantThunk(MD, Extern, nv_t, v_t, nv_r, + v_r); + } + CovariantThunks.clear(); } void OverrideMethods(std::vector<std::pair<const CXXRecordDecl *, @@ -1261,6 +1291,41 @@ llvm::Constant *CodeGenFunction::GenerateThunk(llvm::Function *Fn, return Fn; } +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) { + QualType R = MD->getType()->getAsFunctionType()->getResultType(); + + FunctionArgList Args; + ImplicitParamDecl *ThisDecl = + ImplicitParamDecl::Create(getContext(), 0, SourceLocation(), 0, + MD->getThisType(getContext())); + Args.push_back(std::make_pair(ThisDecl, ThisDecl->getType())); + for (FunctionDecl::param_const_iterator i = MD->param_begin(), + e = MD->param_end(); + i != e; ++i) { + ParmVarDecl *D = *i; + Args.push_back(std::make_pair(D, D->getType())); + } + IdentifierInfo *II + = &CGM.getContext().Idents.get("__thunk_named_foo_"); + FunctionDecl *FD = FunctionDecl::Create(getContext(), + getContext().getTranslationUnitDecl(), + SourceLocation(), II, R, 0, + Extern + ? FunctionDecl::Extern + : FunctionDecl::Static, + false, true); + StartFunction(FD, R, Fn, Args, SourceLocation()); + // FIXME: generate body + FinishFunction(); + return Fn; +} + llvm::Constant *CodeGenModule::BuildThunk(const CXXMethodDecl *MD, bool Extern, int64_t nv, int64_t v) { llvm::SmallString<256> OutName; @@ -1284,6 +1349,32 @@ llvm::Constant *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::SmallString<256> OutName; + llvm::raw_svector_ostream Out(OutName); + mangleCovariantThunk(MD, nv_t, v_t, nv_r, v_r, getContext(), Out); + llvm::GlobalVariable::LinkageTypes linktype; + linktype = llvm::GlobalValue::WeakAnyLinkage; + if (!Extern) + linktype = llvm::GlobalValue::InternalLinkage; + llvm::Type *Ptr8Ty=llvm::PointerType::get(llvm::Type::getInt8Ty(VMContext),0); + const FunctionProtoType *FPT = MD->getType()->getAsFunctionProtoType(); + const llvm::FunctionType *FTy = + getTypes().GetFunctionType(getTypes().getFunctionInfo(MD), + FPT->isVariadic()); + + llvm::Function *Fn = llvm::Function::Create(FTy, linktype, Out.str(), + &getModule()); + CodeGenFunction(*this).GenerateCovariantThunk(Fn, MD, Extern, nv_t, v_t, nv_r, + v_r); + // Fn = Builder.CreateBitCast(Fn, Ptr8Ty); + llvm::Constant *m = llvm::ConstantExpr::getBitCast(Fn, Ptr8Ty); + return m; +} + llvm::Value * CodeGenFunction::BuildVirtualCall(const CXXMethodDecl *MD, llvm::Value *&This, const llvm::Type *Ty) { diff --git a/lib/CodeGen/CodeGenFunction.h b/lib/CodeGen/CodeGenFunction.h index c7aefb64e2..5886035f29 100644 --- a/lib/CodeGen/CodeGenFunction.h +++ b/lib/CodeGen/CodeGenFunction.h @@ -365,6 +365,10 @@ public: /// GenerateThunk - Generate a thunk for the given method llvm::Constant *GenerateThunk(llvm::Function *Fn, const CXXMethodDecl *MD, bool Extern, int64_t nv, int64_t v); + 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); void EmitCtorPrologue(const CXXConstructorDecl *CD); diff --git a/lib/CodeGen/CodeGenModule.h b/lib/CodeGen/CodeGenModule.h index c8ac249540..aa92269406 100644 --- a/lib/CodeGen/CodeGenModule.h +++ b/lib/CodeGen/CodeGenModule.h @@ -247,6 +247,10 @@ public: /// BuildThunk - Build a thunk for the given method llvm::Constant *BuildThunk(const CXXMethodDecl *MD, bool Extern, int64_t nv, int64_t v); + /// 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); /// GetStringForStringLiteral - Return the appropriate bytes for a string /// literal, properly padded to match the literal type. If only the address of diff --git a/lib/CodeGen/Mangle.h b/lib/CodeGen/Mangle.h index 16f1ae6d3f..91143a5c4b 100644 --- a/lib/CodeGen/Mangle.h +++ b/lib/CodeGen/Mangle.h @@ -37,10 +37,9 @@ namespace clang { llvm::raw_ostream &os); void mangleThunk(const FunctionDecl *FD, int64_t n, int64_t vn, ASTContext &Context, llvm::raw_ostream &os); - void mangleCovariantThunk(const NamedDecl *D, bool VirtualThis, int64_t nv_t, - int64_t v_t, bool VirtualResult, int64_t nv_r, - int64_t v_r, ASTContext &Context, - llvm::raw_ostream &os); + void mangleCovariantThunk(const FunctionDecl *FD, int64_t nv_t, int64_t v_t, + int64_t nv_r, int64_t v_r, ASTContext &Context, + llvm::raw_ostream &os); void mangleGuardVariable(const VarDecl *D, ASTContext &Context, llvm::raw_ostream &os); void mangleCXXVtable(QualType T, ASTContext &Context, llvm::raw_ostream &os); |