aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMike Stump <mrs@apple.com>2009-09-11 23:25:56 +0000
committerMike Stump <mrs@apple.com>2009-09-11 23:25:56 +0000
commit6e319f6adc2a06c31cf99265854eef1321bcecf2 (patch)
tree2027f38d9a837bc0176049e8fe0410bb5db5d9cb
parent4719f4e86a84dec6f5a45771ae51d4ec72e4617a (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.cpp99
-rw-r--r--lib/CodeGen/CodeGenFunction.h4
-rw-r--r--lib/CodeGen/CodeGenModule.h4
-rw-r--r--lib/CodeGen/Mangle.h7
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);