зеркало из https://github.com/microsoft/clang-1.git
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
This commit is contained in:
Родитель
e9d6554ba7
Коммит
7622cd3410
|
@ -824,49 +824,50 @@ CodeGenFunction::GenerateThunk(llvm::Function *Fn, const CXXMethodDecl *MD,
|
||||||
bool Extern,
|
bool Extern,
|
||||||
const ThunkAdjustment &ThisAdjustment) {
|
const ThunkAdjustment &ThisAdjustment) {
|
||||||
return GenerateCovariantThunk(Fn, MD, Extern,
|
return GenerateCovariantThunk(Fn, MD, Extern,
|
||||||
ThisAdjustment.NonVirtual,
|
CovariantThunkAdjustment(ThisAdjustment,
|
||||||
ThisAdjustment.Virtual, 0, 0);
|
ThunkAdjustment()));
|
||||||
}
|
}
|
||||||
|
|
||||||
llvm::Value *CodeGenFunction::DynamicTypeAdjust(llvm::Value *V, int64_t nv,
|
llvm::Value *
|
||||||
int64_t v) {
|
CodeGenFunction::DynamicTypeAdjust(llvm::Value *V,
|
||||||
llvm::Type *Ptr8Ty = llvm::PointerType::get(llvm::Type::getInt8Ty(VMContext),
|
const ThunkAdjustment &Adjustment) {
|
||||||
0);
|
const llvm::Type *Int8PtrTy = llvm::Type::getInt8PtrTy(VMContext);
|
||||||
|
|
||||||
const llvm::Type *OrigTy = V->getType();
|
const llvm::Type *OrigTy = V->getType();
|
||||||
if (nv) {
|
if (Adjustment.NonVirtual) {
|
||||||
// Do the non-virtual adjustment
|
// Do the non-virtual adjustment
|
||||||
V = Builder.CreateBitCast(V, Ptr8Ty);
|
V = Builder.CreateBitCast(V, Int8PtrTy);
|
||||||
V = Builder.CreateConstInBoundsGEP1_64(V, nv);
|
V = Builder.CreateConstInBoundsGEP1_64(V, Adjustment.NonVirtual);
|
||||||
V = Builder.CreateBitCast(V, OrigTy);
|
V = Builder.CreateBitCast(V, OrigTy);
|
||||||
}
|
}
|
||||||
if (v) {
|
|
||||||
// Do the virtual this adjustment
|
if (!Adjustment.Virtual)
|
||||||
const llvm::Type *PtrDiffTy =
|
return V;
|
||||||
ConvertType(getContext().getPointerDiffType());
|
|
||||||
llvm::Type *PtrPtr8Ty, *PtrPtrDiffTy;
|
assert(Adjustment.Virtual % (LLVMPointerWidth / 8) == 0 &&
|
||||||
PtrPtr8Ty = llvm::PointerType::get(Ptr8Ty, 0);
|
"vtable entry unaligned");
|
||||||
PtrPtrDiffTy = llvm::PointerType::get(PtrDiffTy, 0);
|
|
||||||
llvm::Value *ThisVal = Builder.CreateBitCast(V, Ptr8Ty);
|
// Do the virtual this adjustment
|
||||||
V = Builder.CreateBitCast(V, PtrPtrDiffTy->getPointerTo());
|
const llvm::Type *PtrDiffTy = ConvertType(getContext().getPointerDiffType());
|
||||||
V = Builder.CreateLoad(V, "vtable");
|
const llvm::Type *PtrDiffPtrTy = PtrDiffTy->getPointerTo();
|
||||||
llvm::Value *VTablePtr = V;
|
|
||||||
assert(v % (LLVMPointerWidth/8) == 0 && "vtable entry unaligned");
|
llvm::Value *ThisVal = Builder.CreateBitCast(V, Int8PtrTy);
|
||||||
v /= LLVMPointerWidth/8;
|
V = Builder.CreateBitCast(V, PtrDiffPtrTy->getPointerTo());
|
||||||
V = Builder.CreateConstInBoundsGEP1_64(VTablePtr, v);
|
V = Builder.CreateLoad(V, "vtable");
|
||||||
V = Builder.CreateLoad(V);
|
|
||||||
V = Builder.CreateGEP(ThisVal, V);
|
llvm::Value *VTablePtr = V;
|
||||||
V = Builder.CreateBitCast(V, OrigTy);
|
uint64_t VirtualAdjustment = Adjustment.Virtual / (LLVMPointerWidth / 8);
|
||||||
}
|
V = Builder.CreateConstInBoundsGEP1_64(VTablePtr, VirtualAdjustment);
|
||||||
return V;
|
V = Builder.CreateLoad(V);
|
||||||
|
V = Builder.CreateGEP(ThisVal, V);
|
||||||
|
|
||||||
|
return Builder.CreateBitCast(V, OrigTy);
|
||||||
}
|
}
|
||||||
|
|
||||||
llvm::Constant *CodeGenFunction::GenerateCovariantThunk(llvm::Function *Fn,
|
llvm::Constant *
|
||||||
const CXXMethodDecl *MD,
|
CodeGenFunction::GenerateCovariantThunk(llvm::Function *Fn,
|
||||||
bool Extern,
|
const CXXMethodDecl *MD, bool Extern,
|
||||||
int64_t nv_t,
|
const CovariantThunkAdjustment &Adjustment) {
|
||||||
int64_t v_t,
|
|
||||||
int64_t nv_r,
|
|
||||||
int64_t v_r) {
|
|
||||||
QualType ResultType = MD->getType()->getAs<FunctionType>()->getResultType();
|
QualType ResultType = MD->getType()->getAs<FunctionType>()->getResultType();
|
||||||
|
|
||||||
FunctionArgList Args;
|
FunctionArgList Args;
|
||||||
|
@ -899,16 +900,23 @@ llvm::Constant *CodeGenFunction::GenerateCovariantThunk(llvm::Function *Fn,
|
||||||
llvm::Value *Callee = CGM.GetAddrOfFunction(MD, Ty);
|
llvm::Value *Callee = CGM.GetAddrOfFunction(MD, Ty);
|
||||||
CallArgList CallArgs;
|
CallArgList CallArgs;
|
||||||
|
|
||||||
|
bool ShouldAdjustReturnPointer = true;
|
||||||
QualType ArgType = MD->getThisType(getContext());
|
QualType ArgType = MD->getThisType(getContext());
|
||||||
llvm::Value *Arg = Builder.CreateLoad(LocalDeclMap[ThisDecl], "this");
|
llvm::Value *Arg = Builder.CreateLoad(LocalDeclMap[ThisDecl], "this");
|
||||||
if (nv_t || v_t) {
|
if (!Adjustment.ThisAdjustment.isEmpty()) {
|
||||||
// Do the this adjustment.
|
// Do the this adjustment.
|
||||||
const llvm::Type *OrigTy = Callee->getType();
|
const llvm::Type *OrigTy = Callee->getType();
|
||||||
Arg = DynamicTypeAdjust(Arg, nv_t, v_t);
|
Arg = DynamicTypeAdjust(Arg, Adjustment.ThisAdjustment);
|
||||||
if (nv_r || v_r) {
|
|
||||||
Callee = CGM.BuildCovariantThunk(MD, Extern, 0, 0, nv_r, v_r);
|
if (!Adjustment.ReturnAdjustment.isEmpty()) {
|
||||||
|
const CovariantThunkAdjustment &ReturnAdjustment =
|
||||||
|
CovariantThunkAdjustment(ThunkAdjustment(),
|
||||||
|
Adjustment.ReturnAdjustment);
|
||||||
|
|
||||||
|
Callee = CGM.BuildCovariantThunk(MD, Extern, ReturnAdjustment);
|
||||||
|
|
||||||
Callee = Builder.CreateBitCast(Callee, OrigTy);
|
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),
|
RValue RV = EmitCall(CGM.getTypes().getFunctionInfo(ResultType, CallArgs),
|
||||||
Callee, CallArgs, MD);
|
Callee, CallArgs, MD);
|
||||||
if (nv_r || v_r) {
|
if (ShouldAdjustReturnPointer && !Adjustment.ReturnAdjustment.isEmpty()) {
|
||||||
bool CanBeZero = !(ResultType->isReferenceType()
|
bool CanBeZero = !(ResultType->isReferenceType()
|
||||||
// FIXME: attr nonnull can't be zero either
|
// FIXME: attr nonnull can't be zero either
|
||||||
/* || ResultType->hasAttr<NonNullAttr>() */ );
|
/* || ResultType->hasAttr<NonNullAttr>() */ );
|
||||||
|
@ -942,7 +950,8 @@ llvm::Constant *CodeGenFunction::GenerateCovariantThunk(llvm::Function *Fn,
|
||||||
Builder.CreateCondBr(Builder.CreateICmpNE(RV.getScalarVal(), Zero),
|
Builder.CreateCondBr(Builder.CreateICmpNE(RV.getScalarVal(), Zero),
|
||||||
NonZeroBlock, ZeroBlock);
|
NonZeroBlock, ZeroBlock);
|
||||||
EmitBlock(NonZeroBlock);
|
EmitBlock(NonZeroBlock);
|
||||||
llvm::Value *NZ = DynamicTypeAdjust(RV.getScalarVal(), nv_r, v_r);
|
llvm::Value *NZ =
|
||||||
|
DynamicTypeAdjust(RV.getScalarVal(), Adjustment.ReturnAdjustment);
|
||||||
EmitBranch(ContBlock);
|
EmitBranch(ContBlock);
|
||||||
EmitBlock(ZeroBlock);
|
EmitBlock(ZeroBlock);
|
||||||
llvm::Value *Z = RV.getScalarVal();
|
llvm::Value *Z = RV.getScalarVal();
|
||||||
|
@ -953,7 +962,8 @@ llvm::Constant *CodeGenFunction::GenerateCovariantThunk(llvm::Function *Fn,
|
||||||
RVOrZero->addIncoming(Z, ZeroBlock);
|
RVOrZero->addIncoming(Z, ZeroBlock);
|
||||||
RV = RValue::get(RVOrZero);
|
RV = RValue::get(RVOrZero);
|
||||||
} else
|
} else
|
||||||
RV = RValue::get(DynamicTypeAdjust(RV.getScalarVal(), nv_r, v_r));
|
RV = RValue::get(DynamicTypeAdjust(RV.getScalarVal(),
|
||||||
|
Adjustment.ReturnAdjustment));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!ResultType->isVoidType())
|
if (!ResultType->isVoidType())
|
||||||
|
@ -987,12 +997,11 @@ CodeGenModule::BuildThunk(const CXXMethodDecl *MD, bool Extern,
|
||||||
return m;
|
return m;
|
||||||
}
|
}
|
||||||
|
|
||||||
llvm::Constant *CodeGenModule::BuildCovariantThunk(const CXXMethodDecl *MD,
|
llvm::Constant *
|
||||||
bool Extern, int64_t nv_t,
|
CodeGenModule::BuildCovariantThunk(const CXXMethodDecl *MD, bool Extern,
|
||||||
int64_t v_t, int64_t nv_r,
|
const CovariantThunkAdjustment &Adjustment) {
|
||||||
int64_t v_r) {
|
|
||||||
llvm::SmallString<256> OutName;
|
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;
|
llvm::GlobalVariable::LinkageTypes linktype;
|
||||||
linktype = llvm::GlobalValue::WeakAnyLinkage;
|
linktype = llvm::GlobalValue::WeakAnyLinkage;
|
||||||
if (!Extern)
|
if (!Extern)
|
||||||
|
@ -1005,8 +1014,7 @@ llvm::Constant *CodeGenModule::BuildCovariantThunk(const CXXMethodDecl *MD,
|
||||||
|
|
||||||
llvm::Function *Fn = llvm::Function::Create(FTy, linktype, OutName.str(),
|
llvm::Function *Fn = llvm::Function::Create(FTy, linktype, OutName.str(),
|
||||||
&getModule());
|
&getModule());
|
||||||
CodeGenFunction(*this).GenerateCovariantThunk(Fn, MD, Extern, nv_t, v_t, nv_r,
|
CodeGenFunction(*this).GenerateCovariantThunk(Fn, MD, Extern, Adjustment);
|
||||||
v_r);
|
|
||||||
llvm::Constant *m = llvm::ConstantExpr::getBitCast(Fn, Ptr8Ty);
|
llvm::Constant *m = llvm::ConstantExpr::getBitCast(Fn, Ptr8Ty);
|
||||||
return m;
|
return m;
|
||||||
}
|
}
|
||||||
|
|
|
@ -349,8 +349,10 @@ public:
|
||||||
Index_t v_t = i->second.first.first.second;
|
Index_t v_t = i->second.first.first.second;
|
||||||
Index_t nv_r = i->second.first.second.first;
|
Index_t nv_r = i->second.first.second.first;
|
||||||
Index_t v_r = i->second.first.second.second;
|
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();
|
CovariantThunks.clear();
|
||||||
for (Pures_t::iterator i = Pures.begin(), e = Pures.end();
|
for (Pures_t::iterator i = Pures.begin(), e = Pures.end();
|
||||||
|
|
|
@ -49,6 +49,19 @@ struct ThunkAdjustment {
|
||||||
int64_t Virtual;
|
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 {
|
class CGVtableInfo {
|
||||||
CodeGenModule &CGM;
|
CodeGenModule &CGM;
|
||||||
|
|
||||||
|
|
|
@ -437,16 +437,17 @@ public:
|
||||||
/// DynamicTypeAdjust - Do the non-virtual and virtual adjustments on an
|
/// DynamicTypeAdjust - Do the non-virtual and virtual adjustments on an
|
||||||
/// object pointer to alter the dynamic type of the pointer. Used by
|
/// object pointer to alter the dynamic type of the pointer. Used by
|
||||||
/// GenerateCovariantThunk for building thunks.
|
/// 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
|
/// GenerateThunk - Generate a thunk for the given method
|
||||||
llvm::Constant *GenerateThunk(llvm::Function *Fn, const CXXMethodDecl *MD,
|
llvm::Constant *GenerateThunk(llvm::Function *Fn, const CXXMethodDecl *MD,
|
||||||
bool Extern,
|
bool Extern,
|
||||||
const ThunkAdjustment &ThisAdjustment);
|
const ThunkAdjustment &ThisAdjustment);
|
||||||
llvm::Constant *GenerateCovariantThunk(llvm::Function *Fn,
|
llvm::Constant *
|
||||||
const CXXMethodDecl *MD, bool Extern,
|
GenerateCovariantThunk(llvm::Function *Fn, const CXXMethodDecl *MD,
|
||||||
int64_t nv_t, int64_t v_t,
|
bool Extern,
|
||||||
int64_t nv_r, int64_t v_r);
|
const CovariantThunkAdjustment &Adjustment);
|
||||||
|
|
||||||
void EmitCtorPrologue(const CXXConstructorDecl *CD, CXXCtorType Type);
|
void EmitCtorPrologue(const CXXConstructorDecl *CD, CXXCtorType Type);
|
||||||
|
|
||||||
|
|
|
@ -238,9 +238,9 @@ public:
|
||||||
const ThunkAdjustment &ThisAdjustment);
|
const ThunkAdjustment &ThisAdjustment);
|
||||||
|
|
||||||
/// BuildCoVariantThunk - Build a thunk for the given method
|
/// BuildCoVariantThunk - Build a thunk for the given method
|
||||||
llvm::Constant *BuildCovariantThunk(const CXXMethodDecl *MD, bool Extern,
|
llvm::Constant *
|
||||||
int64_t nv_t, int64_t v_t,
|
BuildCovariantThunk(const CXXMethodDecl *MD, bool Extern,
|
||||||
int64_t nv_r, int64_t v_r);
|
const CovariantThunkAdjustment &Adjustment);
|
||||||
|
|
||||||
typedef std::pair<const CXXRecordDecl *, uint64_t> CtorVtable_t;
|
typedef std::pair<const CXXRecordDecl *, uint64_t> CtorVtable_t;
|
||||||
typedef llvm::DenseMap<const CXXRecordDecl *,
|
typedef llvm::DenseMap<const CXXRecordDecl *,
|
||||||
|
|
|
@ -1371,9 +1371,10 @@ void MangleContext::mangleThunk(const FunctionDecl *FD,
|
||||||
|
|
||||||
/// \brief Mangles the a covariant thunk for the declaration D and emits that
|
/// \brief Mangles the a covariant thunk for the declaration D and emits that
|
||||||
/// name to the given output stream.
|
/// name to the given output stream.
|
||||||
void MangleContext::mangleCovariantThunk(const FunctionDecl *FD, int64_t nv_t,
|
void
|
||||||
int64_t v_t, int64_t nv_r, int64_t v_r,
|
MangleContext::mangleCovariantThunk(const FunctionDecl *FD,
|
||||||
llvm::SmallVectorImpl<char> &Res) {
|
const CovariantThunkAdjustment& Adjustment,
|
||||||
|
llvm::SmallVectorImpl<char> &Res) {
|
||||||
// FIXME: Hum, we might have to thunk these, fix.
|
// FIXME: Hum, we might have to thunk these, fix.
|
||||||
assert(!isa<CXXDestructorDecl>(FD) &&
|
assert(!isa<CXXDestructorDecl>(FD) &&
|
||||||
"Use mangleCXXDtor for destructor decls!");
|
"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
|
// # second call-offset is result adjustment
|
||||||
CXXNameMangler Mangler(*this, Res);
|
CXXNameMangler Mangler(*this, Res);
|
||||||
Mangler.getStream() << "_ZTc";
|
Mangler.getStream() << "_ZTc";
|
||||||
Mangler.mangleCallOffset(ThunkAdjustment(nv_t, v_t));
|
Mangler.mangleCallOffset(Adjustment.ThisAdjustment);
|
||||||
Mangler.mangleCallOffset(ThunkAdjustment(nv_r, v_r));
|
Mangler.mangleCallOffset(Adjustment.ReturnAdjustment);
|
||||||
Mangler.mangleFunctionEncoding(FD);
|
Mangler.mangleFunctionEncoding(FD);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -35,6 +35,7 @@ namespace clang {
|
||||||
class VarDecl;
|
class VarDecl;
|
||||||
|
|
||||||
namespace CodeGen {
|
namespace CodeGen {
|
||||||
|
class CovariantThunkAdjustment;
|
||||||
class ThunkAdjustment;
|
class ThunkAdjustment;
|
||||||
|
|
||||||
/// MangleContext - Context for tracking state which persists across multiple
|
/// MangleContext - Context for tracking state which persists across multiple
|
||||||
|
@ -66,8 +67,8 @@ public:
|
||||||
void mangleThunk(const FunctionDecl *FD,
|
void mangleThunk(const FunctionDecl *FD,
|
||||||
const ThunkAdjustment &ThisAdjustment,
|
const ThunkAdjustment &ThisAdjustment,
|
||||||
llvm::SmallVectorImpl<char> &);
|
llvm::SmallVectorImpl<char> &);
|
||||||
void mangleCovariantThunk(const FunctionDecl *FD, int64_t nv_t, int64_t v_t,
|
void mangleCovariantThunk(const FunctionDecl *FD,
|
||||||
int64_t nv_r, int64_t v_r,
|
const CovariantThunkAdjustment& Adjustment,
|
||||||
llvm::SmallVectorImpl<char> &);
|
llvm::SmallVectorImpl<char> &);
|
||||||
void mangleGuardVariable(const VarDecl *D, llvm::SmallVectorImpl<char> &);
|
void mangleGuardVariable(const VarDecl *D, llvm::SmallVectorImpl<char> &);
|
||||||
void mangleCXXVtable(const CXXRecordDecl *RD, llvm::SmallVectorImpl<char> &);
|
void mangleCXXVtable(const CXXRecordDecl *RD, llvm::SmallVectorImpl<char> &);
|
||||||
|
|
Загрузка…
Ссылка в новой задаче