зеркало из 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,
|
||||
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<FunctionType>()->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<NonNullAttr>() */ );
|
||||
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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<const CXXRecordDecl *, uint64_t> CtorVtable_t;
|
||||
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
|
||||
/// name to the given output stream.
|
||||
void MangleContext::mangleCovariantThunk(const FunctionDecl *FD, int64_t nv_t,
|
||||
int64_t v_t, int64_t nv_r, int64_t v_r,
|
||||
llvm::SmallVectorImpl<char> &Res) {
|
||||
void
|
||||
MangleContext::mangleCovariantThunk(const FunctionDecl *FD,
|
||||
const CovariantThunkAdjustment& Adjustment,
|
||||
llvm::SmallVectorImpl<char> &Res) {
|
||||
// FIXME: Hum, we might have to thunk these, fix.
|
||||
assert(!isa<CXXDestructorDecl>(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);
|
||||
}
|
||||
|
||||
|
|
|
@ -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<char> &);
|
||||
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<char> &);
|
||||
void mangleGuardVariable(const VarDecl *D, llvm::SmallVectorImpl<char> &);
|
||||
void mangleCXXVtable(const CXXRecordDecl *RD, llvm::SmallVectorImpl<char> &);
|
||||
|
|
Загрузка…
Ссылка в новой задаче