forked from OSchip/llvm-project
Add overidding for methods for vtable building for the secondary
vtables. Add thunk generation. WIP. llvm-svn: 81014
This commit is contained in:
parent
0da4a5dcab
commit
5a522353c3
|
@ -246,8 +246,8 @@ CodeGenFunction::EmitCXXOperatorMemberCallExpr(const CXXOperatorCallExpr *E,
|
||||||
|
|
||||||
const FunctionProtoType *FPT = MD->getType()->getAsFunctionProtoType();
|
const FunctionProtoType *FPT = MD->getType()->getAsFunctionProtoType();
|
||||||
const llvm::Type *Ty =
|
const llvm::Type *Ty =
|
||||||
CGM.getTypes().GetFunctionType(CGM.getTypes().getFunctionInfo(MD),
|
CGM.getTypes().GetFunctionType(CGM.getTypes().getFunctionInfo(MD),
|
||||||
FPT->isVariadic());
|
FPT->isVariadic());
|
||||||
llvm::Constant *Callee = CGM.GetAddrOfFunction(GlobalDecl(MD), Ty);
|
llvm::Constant *Callee = CGM.GetAddrOfFunction(GlobalDecl(MD), Ty);
|
||||||
|
|
||||||
llvm::Value *This = EmitLValue(E->getArg(0)).getAddress();
|
llvm::Value *This = EmitLValue(E->getArg(0)).getAddress();
|
||||||
|
@ -849,13 +849,15 @@ private:
|
||||||
llvm::DenseMap<const CXXMethodDecl *, Index_t> VCallOffset;
|
llvm::DenseMap<const CXXMethodDecl *, Index_t> VCallOffset;
|
||||||
std::vector<Index_t> VCalls;
|
std::vector<Index_t> VCalls;
|
||||||
typedef CXXRecordDecl::method_iterator method_iter;
|
typedef CXXRecordDecl::method_iterator method_iter;
|
||||||
|
// FIXME: Linkage should follow vtable
|
||||||
|
const bool Extern;
|
||||||
public:
|
public:
|
||||||
VtableBuilder(std::vector<llvm::Constant *> &meth,
|
VtableBuilder(std::vector<llvm::Constant *> &meth,
|
||||||
const CXXRecordDecl *c,
|
const CXXRecordDecl *c,
|
||||||
CodeGenModule &cgm)
|
CodeGenModule &cgm)
|
||||||
: methods(meth), Class(c), BLayout(cgm.getContext().getASTRecordLayout(c)),
|
: methods(meth), Class(c), BLayout(cgm.getContext().getASTRecordLayout(c)),
|
||||||
rtti(cgm.GenerateRtti(c)), VMContext(cgm.getModule().getContext()),
|
rtti(cgm.GenerateRtti(c)), VMContext(cgm.getModule().getContext()),
|
||||||
CGM(cgm) {
|
CGM(cgm), Extern(true) {
|
||||||
Ptr8Ty = llvm::PointerType::get(llvm::Type::getInt8Ty(VMContext), 0);
|
Ptr8Ty = llvm::PointerType::get(llvm::Type::getInt8Ty(VMContext), 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -893,7 +895,9 @@ public:
|
||||||
}
|
}
|
||||||
|
|
||||||
bool OverrideMethod(const CXXMethodDecl *MD, llvm::Constant *m,
|
bool OverrideMethod(const CXXMethodDecl *MD, llvm::Constant *m,
|
||||||
bool MorallyVirtual, Index_t Offset) {
|
bool MorallyVirtual, Index_t Offset,
|
||||||
|
std::vector<llvm::Constant *> &submethods,
|
||||||
|
Index_t AddressPoint) {
|
||||||
typedef CXXMethodDecl::method_iterator meth_iter;
|
typedef CXXMethodDecl::method_iterator meth_iter;
|
||||||
|
|
||||||
// FIXME: Don't like the nested loops. For very large inheritance
|
// FIXME: Don't like the nested loops. For very large inheritance
|
||||||
|
@ -910,13 +914,18 @@ public:
|
||||||
om = CGM.GetAddrOfFunction(GlobalDecl(OMD), Ptr8Ty);
|
om = CGM.GetAddrOfFunction(GlobalDecl(OMD), Ptr8Ty);
|
||||||
om = llvm::ConstantExpr::getBitCast(om, Ptr8Ty);
|
om = llvm::ConstantExpr::getBitCast(om, Ptr8Ty);
|
||||||
|
|
||||||
for (Index_t i = 0, e = submethods.size();
|
for (Index_t i = AddressPoint, e = submethods.size();
|
||||||
i != e; ++i) {
|
i != e; ++i) {
|
||||||
// FIXME: begin_overridden_methods might be too lax, covariance */
|
// FIXME: begin_overridden_methods might be too lax, covariance */
|
||||||
if (submethods[i] == om) {
|
if (submethods[i] == om) {
|
||||||
|
int64_t O = VCallOffset[OMD] - Offset/8;
|
||||||
// FIXME: thunks
|
// FIXME: thunks
|
||||||
submethods[i] = m;
|
if (O) {
|
||||||
Index[MD] = i;
|
submethods[i] = CGM.BuildThunk(MD, Extern, true, 0, O);
|
||||||
|
} else
|
||||||
|
submethods[i] = m;
|
||||||
|
// FIXME: audit
|
||||||
|
Index[MD] = i - AddressPoint;
|
||||||
if (MorallyVirtual) {
|
if (MorallyVirtual) {
|
||||||
VCallOffset[MD] = Offset/8;
|
VCallOffset[MD] = Offset/8;
|
||||||
VCalls[VCall[OMD]] = Offset/8 - VCallOffset[OMD];
|
VCalls[VCall[OMD]] = Offset/8 - VCallOffset[OMD];
|
||||||
|
@ -937,14 +946,14 @@ public:
|
||||||
if (mi->isVirtual()) {
|
if (mi->isVirtual()) {
|
||||||
const CXXMethodDecl *MD = *mi;
|
const CXXMethodDecl *MD = *mi;
|
||||||
llvm::Constant *m = wrap(CGM.GetAddrOfFunction(GlobalDecl(MD), Ptr8Ty));
|
llvm::Constant *m = wrap(CGM.GetAddrOfFunction(GlobalDecl(MD), Ptr8Ty));
|
||||||
OverrideMethod(MD, m, MorallyVirtual, Offset);
|
OverrideMethod(MD, m, MorallyVirtual, Offset, methods, AddressPoint);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void AddMethod(const CXXMethodDecl *MD, Index_t AddressPoint,
|
void AddMethod(const CXXMethodDecl *MD, Index_t AddressPoint,
|
||||||
bool MorallyVirtual, Index_t Offset) {
|
bool MorallyVirtual, Index_t Offset) {
|
||||||
llvm::Constant *m = wrap(CGM.GetAddrOfFunction(GlobalDecl(MD), Ptr8Ty));
|
llvm::Constant *m = wrap(CGM.GetAddrOfFunction(GlobalDecl(MD), Ptr8Ty));
|
||||||
if (OverrideMethod(MD, m, MorallyVirtual, Offset))
|
if (OverrideMethod(MD, m, MorallyVirtual, Offset, submethods, 0))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
// else allocate a new slot.
|
// else allocate a new slot.
|
||||||
|
@ -1048,7 +1057,9 @@ public:
|
||||||
if (Base != PrimaryBase || PrimaryBaseWasVirtual) {
|
if (Base != PrimaryBase || PrimaryBaseWasVirtual) {
|
||||||
uint64_t o = Offset + Layout.getBaseClassOffset(Base);
|
uint64_t o = Offset + Layout.getBaseClassOffset(Base);
|
||||||
StartNewTable();
|
StartNewTable();
|
||||||
GenerateVtableForBase(Base, true, true, false, o, false);
|
Index_t AP;
|
||||||
|
AP = GenerateVtableForBase(Base, true, true, MorallyVirtual, o, false);
|
||||||
|
OverrideMethods(RD, AP, MorallyVirtual, o);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return AddressPoint;
|
return AddressPoint;
|
||||||
|
@ -1065,7 +1076,9 @@ public:
|
||||||
IndirectPrimary.insert(Base);
|
IndirectPrimary.insert(Base);
|
||||||
StartNewTable();
|
StartNewTable();
|
||||||
int64_t BaseOffset = BLayout.getVBaseClassOffset(Base);
|
int64_t BaseOffset = BLayout.getVBaseClassOffset(Base);
|
||||||
GenerateVtableForBase(Base, false, true, true, BaseOffset, true);
|
Index_t AP;
|
||||||
|
AP = GenerateVtableForBase(Base, false, true, true, BaseOffset, true);
|
||||||
|
OverrideMethods(RD, AP, true, BaseOffset);
|
||||||
}
|
}
|
||||||
if (Base->getNumVBases())
|
if (Base->getNumVBases())
|
||||||
GenerateVtableForVBases(Base, Class);
|
GenerateVtableForVBases(Base, Class);
|
||||||
|
@ -1145,6 +1158,62 @@ llvm::Value *CodeGenFunction::GenerateVtable(const CXXRecordDecl *RD) {
|
||||||
// FIXME: move to Context
|
// FIXME: move to Context
|
||||||
static VtableInfo *vtableinfo;
|
static VtableInfo *vtableinfo;
|
||||||
|
|
||||||
|
llvm::Constant *CodeGenFunction::GenerateThunk(llvm::Function *Fn,
|
||||||
|
const CXXMethodDecl *MD,
|
||||||
|
bool Extern, bool Virtual,
|
||||||
|
int64_t nv, int64_t v) {
|
||||||
|
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, bool Virtual, int64_t nv,
|
||||||
|
int64_t v) {
|
||||||
|
llvm::SmallString<256> OutName;
|
||||||
|
llvm::raw_svector_ostream Out(OutName);
|
||||||
|
mangleThunk(MD, Virtual, nv, v, 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).GenerateThunk(Fn, MD, Extern, Virtual, nv, v);
|
||||||
|
// Fn = Builder.CreateBitCast(Fn, Ptr8Ty);
|
||||||
|
llvm::Constant *m = llvm::ConstantExpr::getBitCast(Fn, Ptr8Ty);
|
||||||
|
return m;
|
||||||
|
}
|
||||||
|
|
||||||
llvm::Value *
|
llvm::Value *
|
||||||
CodeGenFunction::BuildVirtualCall(const CXXMethodDecl *MD, llvm::Value *&This,
|
CodeGenFunction::BuildVirtualCall(const CXXMethodDecl *MD, llvm::Value *&This,
|
||||||
const llvm::Type *Ty) {
|
const llvm::Type *Ty) {
|
||||||
|
@ -1309,8 +1378,7 @@ void CodeGenFunction::EmitClassAggrCopyAssignment(llvm::Value *Dest,
|
||||||
// Push the Src ptr.
|
// Push the Src ptr.
|
||||||
CallArgs.push_back(std::make_pair(RValue::get(Src),
|
CallArgs.push_back(std::make_pair(RValue::get(Src),
|
||||||
MD->getParamDecl(0)->getType()));
|
MD->getParamDecl(0)->getType()));
|
||||||
QualType ResultType =
|
QualType ResultType = MD->getType()->getAsFunctionType()->getResultType();
|
||||||
MD->getType()->getAsFunctionType()->getResultType();
|
|
||||||
EmitCall(CGM.getTypes().getFunctionInfo(ResultType, CallArgs),
|
EmitCall(CGM.getTypes().getFunctionInfo(ResultType, CallArgs),
|
||||||
Callee, CallArgs, MD);
|
Callee, CallArgs, MD);
|
||||||
}
|
}
|
||||||
|
|
|
@ -364,6 +364,11 @@ public:
|
||||||
/// GenerateVtable - Generate the vtable for the given type.
|
/// GenerateVtable - Generate the vtable for the given type.
|
||||||
llvm::Value *GenerateVtable(const CXXRecordDecl *RD);
|
llvm::Value *GenerateVtable(const CXXRecordDecl *RD);
|
||||||
|
|
||||||
|
/// GenerateThunk - Generate a thunk for the given method
|
||||||
|
llvm::Constant *GenerateThunk(llvm::Function *Fn, const CXXMethodDecl *MD,
|
||||||
|
bool Extern, bool Virtual, int64_t nv,
|
||||||
|
int64_t v);
|
||||||
|
|
||||||
void EmitCtorPrologue(const CXXConstructorDecl *CD);
|
void EmitCtorPrologue(const CXXConstructorDecl *CD);
|
||||||
|
|
||||||
void SynthesizeCXXCopyConstructor(const CXXConstructorDecl *CD,
|
void SynthesizeCXXCopyConstructor(const CXXConstructorDecl *CD,
|
||||||
|
|
|
@ -235,6 +235,10 @@ public:
|
||||||
/// GenerateRtti - Generate the rtti information for the given type.
|
/// GenerateRtti - Generate the rtti information for the given type.
|
||||||
llvm::Constant *GenerateRtti(const CXXRecordDecl *RD);
|
llvm::Constant *GenerateRtti(const CXXRecordDecl *RD);
|
||||||
|
|
||||||
|
/// BuildThunk - Build a thunk for the given method
|
||||||
|
llvm::Constant *BuildThunk(const CXXMethodDecl *MD, bool Extern, bool Virtual,
|
||||||
|
int64_t nv, int64_t v);
|
||||||
|
|
||||||
/// GetStringForStringLiteral - Return the appropriate bytes for a string
|
/// GetStringForStringLiteral - Return the appropriate bytes for a string
|
||||||
/// literal, properly padded to match the literal type. If only the address of
|
/// literal, properly padded to match the literal type. If only the address of
|
||||||
/// a constant is needed consider using GetAddrOfConstantStringLiteral.
|
/// a constant is needed consider using GetAddrOfConstantStringLiteral.
|
||||||
|
|
Loading…
Reference in New Issue