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