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:
Anders Carlsson 2009-11-26 03:09:37 +00:00
Родитель e9d6554ba7
Коммит 7622cd3410
7 изменённых файлов: 93 добавлений и 67 удалений

Просмотреть файл

@ -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> &);