Handle constructors and destructors a bit more uniformly in CodeGen.

There were code paths that are duplicated for constructors and destructors just
because we have both CXXCtorType and CXXDtorsTypes.

This patch introduces an unified enum and reduces code deplication a bit.

llvm-svn: 217383
This commit is contained in:
Rafael Espindola 2014-09-08 16:01:27 +00:00
parent 6a2f62cbd3
commit 8d2a19b478
9 changed files with 161 additions and 173 deletions

View File

@ -213,7 +213,7 @@ void CodeGenModule::EmitCXXConstructor(const CXXConstructorDecl *ctor,
}
const CGFunctionInfo &fnInfo =
getTypes().arrangeCXXConstructorDeclaration(ctor, ctorType);
getTypes().arrangeCXXStructorDeclaration(ctor, getFromCtorType(ctorType));
auto *fn = cast<llvm::Function>(
GetAddrOfCXXConstructor(ctor, ctorType, &fnInfo, true));
@ -225,26 +225,39 @@ void CodeGenModule::EmitCXXConstructor(const CXXConstructorDecl *ctor,
SetLLVMFunctionAttributesForDefinition(ctor, fn);
}
llvm::GlobalValue *
CodeGenModule::GetAddrOfCXXConstructor(const CXXConstructorDecl *ctor,
CXXCtorType ctorType,
const CGFunctionInfo *fnInfo,
bool DontDefer) {
GlobalDecl GD(ctor, ctorType);
StringRef name = getMangledName(GD);
if (llvm::GlobalValue *existing = GetGlobalValue(name))
return existing;
llvm::GlobalValue *CodeGenModule::getAddrOfCXXStructor(
const CXXMethodDecl *MD, StructorType Type, const CGFunctionInfo *FnInfo,
llvm::FunctionType *FnType, bool DontDefer) {
GlobalDecl GD;
if (auto *CD = dyn_cast<CXXConstructorDecl>(MD)) {
GD = GlobalDecl(CD, toCXXCtorType(Type));
} else {
auto *DD = dyn_cast<CXXDestructorDecl>(MD);
GD = GlobalDecl(DD, toCXXDtorType(Type));
}
if (!fnInfo)
fnInfo = &getTypes().arrangeCXXConstructorDeclaration(ctor, ctorType);
StringRef Name = getMangledName(GD);
if (llvm::GlobalValue *Existing = GetGlobalValue(Name))
return Existing;
llvm::FunctionType *fnType = getTypes().GetFunctionType(*fnInfo);
return cast<llvm::Function>(GetOrCreateLLVMFunction(name, fnType, GD,
if (!FnType) {
if (!FnInfo)
FnInfo = &getTypes().arrangeCXXStructorDeclaration(MD, Type);
FnType = getTypes().GetFunctionType(*FnInfo);
}
return cast<llvm::Function>(GetOrCreateLLVMFunction(Name, FnType, GD,
/*ForVTable=*/false,
DontDefer));
}
llvm::GlobalValue *CodeGenModule::GetAddrOfCXXConstructor(
const CXXConstructorDecl *ctor, CXXCtorType ctorType,
const CGFunctionInfo *fnInfo, bool DontDefer) {
return getAddrOfCXXStructor(ctor, getFromCtorType(ctorType), fnInfo, nullptr,
DontDefer);
}
void CodeGenModule::EmitCXXDestructor(const CXXDestructorDecl *dtor,
CXXDtorType dtorType) {
// The complete destructor is equivalent to the base destructor for
@ -270,7 +283,7 @@ void CodeGenModule::EmitCXXDestructor(const CXXDestructorDecl *dtor,
return;
const CGFunctionInfo &fnInfo =
getTypes().arrangeCXXDestructor(dtor, dtorType);
getTypes().arrangeCXXStructorDeclaration(dtor, getFromDtorType(dtorType));
auto *fn = cast<llvm::Function>(
GetAddrOfCXXDestructor(dtor, dtorType, &fnInfo, nullptr, true));
@ -288,19 +301,8 @@ CodeGenModule::GetAddrOfCXXDestructor(const CXXDestructorDecl *dtor,
const CGFunctionInfo *fnInfo,
llvm::FunctionType *fnType,
bool DontDefer) {
GlobalDecl GD(dtor, dtorType);
StringRef name = getMangledName(GD);
if (llvm::GlobalValue *existing = GetGlobalValue(name))
return existing;
if (!fnType) {
if (!fnInfo) fnInfo = &getTypes().arrangeCXXDestructor(dtor, dtorType);
fnType = getTypes().GetFunctionType(*fnInfo);
}
return cast<llvm::Function>(GetOrCreateLLVMFunction(name, fnType, GD,
/*ForVTable=*/false,
DontDefer));
return getAddrOfCXXStructor(dtor, getFromDtorType(dtorType), fnInfo, fnType,
DontDefer);
}
static llvm::Value *BuildAppleKextVirtualCall(CodeGenFunction &CGF,
@ -360,8 +362,8 @@ CodeGenFunction::BuildAppleKextVirtualDestructorCall(
// -O does that. But need to support -O0 as well.
if (MD->isVirtual() && Type != Dtor_Base) {
// Compute the function type we're calling.
const CGFunctionInfo &FInfo =
CGM.getTypes().arrangeCXXDestructor(DD, Dtor_Complete);
const CGFunctionInfo &FInfo = CGM.getTypes().arrangeCXXStructorDeclaration(
DD, StructorType::Complete);
llvm::Type *Ty = CGM.getTypes().GetFunctionType(FInfo);
return ::BuildAppleKextVirtualCall(*this, GlobalDecl(DD, Type), Ty, RD);
}

View File

@ -241,20 +241,6 @@ public:
const CXXRecordDecl *ClassDecl,
const CXXRecordDecl *BaseClassDecl) = 0;
/// Build the signature of the given constructor variant by adding
/// any required parameters. For convenience, ArgTys has been initialized
/// with the type of 'this' and ResTy has been initialized with the type of
/// 'this' if HasThisReturn(GlobalDecl(Ctor, T)) is true or 'void' otherwise
/// (although both may be changed by the ABI).
///
/// If there are ever any ABIs where the implicit parameters are
/// intermixed with the formal parameters, we can address those
/// then.
virtual void BuildConstructorSignature(const CXXConstructorDecl *Ctor,
CXXCtorType T,
CanQualType &ResTy,
SmallVectorImpl<CanQualType> &ArgTys) = 0;
virtual llvm::BasicBlock *EmitCtorCompleteObjectHandler(CodeGenFunction &CGF,
const CXXRecordDecl *RD);
@ -267,15 +253,11 @@ public:
/// Emit constructor variants required by this ABI.
virtual void EmitCXXConstructors(const CXXConstructorDecl *D) = 0;
/// Build the signature of the given destructor variant by adding
/// any required parameters. For convenience, ArgTys has been initialized
/// with the type of 'this' and ResTy has been initialized with the type of
/// 'this' if HasThisReturn(GlobalDecl(Dtor, T)) is true or 'void' otherwise
/// (although both may be changed by the ABI).
virtual void BuildDestructorSignature(const CXXDestructorDecl *Dtor,
CXXDtorType T,
CanQualType &ResTy,
SmallVectorImpl<CanQualType> &ArgTys) = 0;
/// Build the signature of the given constructor or destructor variant by
/// adding any required parameters. For convenience, ArgTys has been
/// initialized with the type of 'this'.
virtual void buildStructorSignature(const CXXMethodDecl *MD, StructorType T,
SmallVectorImpl<CanQualType> &ArgTys) = 0;
/// Returns true if the given destructor type should be emitted as a linkonce
/// delegating thunk, regardless of whether the dtor is defined in this TU or

View File

@ -181,30 +181,35 @@ CodeGenTypes::arrangeCXXMethodDeclaration(const CXXMethodDecl *MD) {
return arrangeFreeFunctionType(prototype);
}
/// Arrange the argument and result information for a declaration
/// or definition to the given constructor variant.
const CGFunctionInfo &
CodeGenTypes::arrangeCXXConstructorDeclaration(const CXXConstructorDecl *D,
CXXCtorType ctorKind) {
CodeGenTypes::arrangeCXXStructorDeclaration(const CXXMethodDecl *MD,
StructorType Type) {
SmallVector<CanQualType, 16> argTypes;
argTypes.push_back(GetThisType(Context, D->getParent()));
argTypes.push_back(GetThisType(Context, MD->getParent()));
GlobalDecl GD(D, ctorKind);
CanQualType resultType =
TheCXXABI.HasThisReturn(GD) ? argTypes.front() : Context.VoidTy;
GlobalDecl GD;
if (auto *CD = dyn_cast<CXXConstructorDecl>(MD)) {
GD = GlobalDecl(CD, toCXXCtorType(Type));
} else {
auto *DD = dyn_cast<CXXDestructorDecl>(MD);
GD = GlobalDecl(DD, toCXXDtorType(Type));
}
CanQual<FunctionProtoType> FTP = GetFormalType(D);
CanQual<FunctionProtoType> FTP = GetFormalType(MD);
// Add the formal parameters.
for (unsigned i = 0, e = FTP->getNumParams(); i != e; ++i)
argTypes.push_back(FTP->getParamType(i));
TheCXXABI.BuildConstructorSignature(D, ctorKind, resultType, argTypes);
TheCXXABI.buildStructorSignature(MD, Type, argTypes);
RequiredArgs required =
(D->isVariadic() ? RequiredArgs(argTypes.size()) : RequiredArgs::All);
(MD->isVariadic() ? RequiredArgs(argTypes.size()) : RequiredArgs::All);
FunctionType::ExtInfo extInfo = FTP->getExtInfo();
CanQualType resultType =
TheCXXABI.HasThisReturn(GD) ? argTypes.front() : Context.VoidTy;
return arrangeLLVMFunctionInfo(resultType, true, argTypes, extInfo, required);
}
@ -229,30 +234,6 @@ CodeGenTypes::arrangeCXXConstructorCall(const CallArgList &args,
return arrangeLLVMFunctionInfo(ResultType, true, ArgTypes, Info, Required);
}
/// Arrange the argument and result information for a declaration,
/// definition, or call to the given destructor variant. It so
/// happens that all three cases produce the same information.
const CGFunctionInfo &
CodeGenTypes::arrangeCXXDestructor(const CXXDestructorDecl *D,
CXXDtorType dtorKind) {
SmallVector<CanQualType, 2> argTypes;
argTypes.push_back(GetThisType(Context, D->getParent()));
GlobalDecl GD(D, dtorKind);
CanQualType resultType =
TheCXXABI.HasThisReturn(GD) ? argTypes.front() : Context.VoidTy;
TheCXXABI.BuildDestructorSignature(D, dtorKind, resultType, argTypes);
CanQual<FunctionProtoType> FTP = GetFormalType(D);
assert(FTP->getNumParams() == 0 && "dtor with formal parameters");
assert(FTP->isVariadic() == 0 && "dtor with formal parameters");
FunctionType::ExtInfo extInfo = FTP->getExtInfo();
return arrangeLLVMFunctionInfo(resultType, true, argTypes, extInfo,
RequiredArgs::All);
}
/// Arrange the argument and result information for the declaration or
/// definition of the given function.
const CGFunctionInfo &
@ -324,10 +305,10 @@ CodeGenTypes::arrangeGlobalDeclaration(GlobalDecl GD) {
const FunctionDecl *FD = cast<FunctionDecl>(GD.getDecl());
if (const CXXConstructorDecl *CD = dyn_cast<CXXConstructorDecl>(FD))
return arrangeCXXConstructorDeclaration(CD, GD.getCtorType());
return arrangeCXXStructorDeclaration(CD, getFromCtorType(GD.getCtorType()));
if (const CXXDestructorDecl *DD = dyn_cast<CXXDestructorDecl>(FD))
return arrangeCXXDestructor(DD, GD.getDtorType());
return arrangeCXXStructorDeclaration(DD, getFromDtorType(GD.getDtorType()));
return arrangeFunctionDeclaration(FD);
}
@ -1029,7 +1010,8 @@ llvm::Type *CodeGenTypes::GetFunctionTypeForVTable(GlobalDecl GD) {
const CGFunctionInfo *Info;
if (isa<CXXDestructorDecl>(MD))
Info = &arrangeCXXDestructor(cast<CXXDestructorDecl>(MD), GD.getDtorType());
Info =
&arrangeCXXStructorDeclaration(MD, getFromDtorType(GD.getDtorType()));
else
Info = &arrangeCXXMethodDeclaration(MD);
return GetFunctionType(*Info);

View File

@ -1758,7 +1758,8 @@ CodeGenFunction::EmitDelegateCXXConstructorCall(const CXXConstructorDecl *Ctor,
}
llvm::Value *Callee = CGM.GetAddrOfCXXConstructor(Ctor, CtorType);
EmitCall(CGM.getTypes().arrangeCXXConstructorDeclaration(Ctor, CtorType),
EmitCall(CGM.getTypes()
.arrangeCXXStructorDeclaration(Ctor, getFromCtorType(CtorType)),
Callee, ReturnValueSlot(), DelegateArgs, Ctor);
}

View File

@ -170,11 +170,11 @@ RValue CodeGenFunction::EmitCXXMemberCallExpr(const CXXMemberCallExpr *CE,
const CXXMethodDecl *CalleeDecl = DevirtualizedMethod ? DevirtualizedMethod : MD;
const CGFunctionInfo *FInfo = nullptr;
if (const CXXDestructorDecl *Dtor = dyn_cast<CXXDestructorDecl>(CalleeDecl))
FInfo = &CGM.getTypes().arrangeCXXDestructor(Dtor,
Dtor_Complete);
FInfo = &CGM.getTypes().arrangeCXXStructorDeclaration(
Dtor, StructorType::Complete);
else if (const CXXConstructorDecl *Ctor = dyn_cast<CXXConstructorDecl>(CalleeDecl))
FInfo = &CGM.getTypes().arrangeCXXConstructorDeclaration(Ctor,
Ctor_Complete);
FInfo = &CGM.getTypes().arrangeCXXStructorDeclaration(
Ctor, StructorType::Complete);
else
FInfo = &CGM.getTypes().arrangeCXXMethodDeclaration(CalleeDecl);

View File

@ -803,6 +803,13 @@ public:
QualType getObjCFastEnumerationStateType();
/// Return the address of the constructor of the given type.
llvm::GlobalValue *
getAddrOfCXXStructor(const CXXMethodDecl *MD, StructorType Type,
const CGFunctionInfo *FnInfo = nullptr,
llvm::FunctionType *FnType = nullptr,
bool DontDefer = false);
llvm::GlobalValue *
GetAddrOfCXXConstructor(const CXXConstructorDecl *ctor, CXXCtorType ctorType,
const CGFunctionInfo *fnInfo = nullptr,

View File

@ -56,6 +56,60 @@ class CGRecordLayout;
class CodeGenModule;
class RequiredArgs;
enum class StructorType {
Complete, // constructor or destructor
Base, // constructor or destructor
Deleting // destructor only
};
inline CXXCtorType toCXXCtorType(StructorType T) {
switch (T) {
case StructorType::Complete:
return Ctor_Complete;
case StructorType::Base:
return Ctor_Base;
case StructorType::Deleting:
llvm_unreachable("cannot have a deleting ctor");
}
llvm_unreachable("not a StructorType");
}
inline StructorType getFromCtorType(CXXCtorType T) {
switch (T) {
case Ctor_Complete:
return StructorType::Complete;
case Ctor_Base:
return StructorType::Base;
case Ctor_CompleteAllocating:
llvm_unreachable("invalid enum");
}
llvm_unreachable("not a CXXCtorType");
}
inline CXXDtorType toCXXDtorType(StructorType T) {
switch (T) {
case StructorType::Complete:
return Dtor_Complete;
case StructorType::Base:
return Dtor_Base;
case StructorType::Deleting:
return Dtor_Deleting;
}
llvm_unreachable("not a StructorType");
}
inline StructorType getFromDtorType(CXXDtorType T) {
switch (T) {
case Dtor_Deleting:
return StructorType::Deleting;
case Dtor_Complete:
return StructorType::Complete;
case Dtor_Base:
return StructorType::Base;
}
llvm_unreachable("not a CXXDtorType");
}
/// CodeGenTypes - This class organizes the cross-module state that is used
/// while lowering AST types to LLVM types.
class CodeGenTypes {
@ -185,16 +239,12 @@ public:
QualType receiverType);
const CGFunctionInfo &arrangeCXXMethodDeclaration(const CXXMethodDecl *MD);
const CGFunctionInfo &arrangeCXXConstructorDeclaration(
const CXXConstructorDecl *D,
CXXCtorType Type);
const CGFunctionInfo &arrangeCXXStructorDeclaration(const CXXMethodDecl *MD,
StructorType Type);
const CGFunctionInfo &arrangeCXXConstructorCall(const CallArgList &Args,
const CXXConstructorDecl *D,
CXXCtorType CtorKind,
unsigned ExtraArgs);
const CGFunctionInfo &arrangeCXXDestructor(const CXXDestructorDecl *D,
CXXDtorType Type);
const CGFunctionInfo &arrangeFreeFunctionCall(const CallArgList &Args,
const FunctionType *Ty);
const CGFunctionInfo &arrangeFreeFunctionCall(QualType ResTy,

View File

@ -138,15 +138,10 @@ public:
const CXXRecordDecl *ClassDecl,
const CXXRecordDecl *BaseClassDecl) override;
void BuildConstructorSignature(const CXXConstructorDecl *Ctor,
CXXCtorType T, CanQualType &ResTy,
SmallVectorImpl<CanQualType> &ArgTys) override;
void EmitCXXConstructors(const CXXConstructorDecl *D) override;
void BuildDestructorSignature(const CXXDestructorDecl *Dtor,
CXXDtorType T, CanQualType &ResTy,
SmallVectorImpl<CanQualType> &ArgTys) override;
void buildStructorSignature(const CXXMethodDecl *MD, StructorType T,
SmallVectorImpl<CanQualType> &ArgTys) override;
bool useThunkForDtorVariant(const CXXDestructorDecl *Dtor,
CXXDtorType DT) const override {
@ -1066,23 +1061,6 @@ ItaniumCXXABI::GetVirtualBaseClassOffset(CodeGenFunction &CGF,
return VBaseOffset;
}
/// The generic ABI passes 'this', plus a VTT if it's initializing a
/// base subobject.
void
ItaniumCXXABI::BuildConstructorSignature(const CXXConstructorDecl *Ctor,
CXXCtorType Type, CanQualType &ResTy,
SmallVectorImpl<CanQualType> &ArgTys) {
ASTContext &Context = getContext();
// All parameters are already in place except VTT, which goes after 'this'.
// These are Clang types, so we don't need to worry about sret yet.
// Check if we need to add a VTT parameter (which has type void **).
if (Type == Ctor_Base && Ctor->getParent()->getNumVBases() != 0)
ArgTys.insert(ArgTys.begin() + 1,
Context.getPointerType(Context.VoidPtrTy));
}
void ItaniumCXXABI::EmitCXXConstructors(const CXXConstructorDecl *D) {
// Just make sure we're in sync with TargetCXXABI.
assert(CGM.getTarget().getCXXABI().hasConstructorVariants());
@ -1099,20 +1077,18 @@ void ItaniumCXXABI::EmitCXXConstructors(const CXXConstructorDecl *D) {
}
}
/// The generic ABI passes 'this', plus a VTT if it's destroying a
/// base subobject.
void ItaniumCXXABI::BuildDestructorSignature(const CXXDestructorDecl *Dtor,
CXXDtorType Type,
CanQualType &ResTy,
SmallVectorImpl<CanQualType> &ArgTys) {
void
ItaniumCXXABI::buildStructorSignature(const CXXMethodDecl *MD, StructorType T,
SmallVectorImpl<CanQualType> &ArgTys) {
ASTContext &Context = getContext();
// 'this' parameter is already there, as well as 'this' return if
// HasThisReturn(GlobalDecl(Dtor, Type)) is true
// All parameters are already in place except VTT, which goes after 'this'.
// These are Clang types, so we don't need to worry about sret yet.
// Check if we need to add a VTT parameter (which has type void **).
if (Type == Dtor_Base && Dtor->getParent()->getNumVBases() != 0)
ArgTys.push_back(Context.getPointerType(Context.VoidPtrTy));
if (T == StructorType::Base && MD->getParent()->getNumVBases() != 0)
ArgTys.insert(ArgTys.begin() + 1,
Context.getPointerType(Context.VoidPtrTy));
}
void ItaniumCXXABI::EmitCXXDestructors(const CXXDestructorDecl *D) {
@ -1346,8 +1322,8 @@ void ItaniumCXXABI::EmitVirtualDestructorCall(CodeGenFunction &CGF,
assert(CE == nullptr || CE->arg_begin() == CE->arg_end());
assert(DtorType == Dtor_Deleting || DtorType == Dtor_Complete);
const CGFunctionInfo *FInfo
= &CGM.getTypes().arrangeCXXDestructor(Dtor, DtorType);
const CGFunctionInfo *FInfo = &CGM.getTypes().arrangeCXXStructorDeclaration(
Dtor, getFromDtorType(DtorType));
llvm::Type *Ty = CGF.CGM.getTypes().GetFunctionType(*FInfo);
llvm::Value *Callee =
getVirtualFunctionPointer(CGF, GlobalDecl(Dtor, DtorType), This, Ty);

View File

@ -89,10 +89,6 @@ public:
const CXXRecordDecl *ClassDecl,
const CXXRecordDecl *BaseClassDecl) override;
void BuildConstructorSignature(const CXXConstructorDecl *Ctor,
CXXCtorType Type, CanQualType &ResTy,
SmallVectorImpl<CanQualType> &ArgTys) override;
llvm::BasicBlock *
EmitCtorCompleteObjectHandler(CodeGenFunction &CGF,
const CXXRecordDecl *RD) override;
@ -134,10 +130,8 @@ public:
// lacks a definition for the destructor, non-base destructors must always
// delegate to or alias the base destructor.
void BuildDestructorSignature(const CXXDestructorDecl *Dtor,
CXXDtorType Type,
CanQualType &ResTy,
SmallVectorImpl<CanQualType> &ArgTys) override;
void buildStructorSignature(const CXXMethodDecl *MD, StructorType T,
SmallVectorImpl<CanQualType> &ArgTys) override;
/// Non-base dtors should be emitted as delegating thunks in this ABI.
bool useThunkForDtorVariant(const CXXDestructorDecl *Dtor,
@ -785,23 +779,6 @@ bool MicrosoftCXXABI::classifyReturnType(CGFunctionInfo &FI) const {
return false;
}
void MicrosoftCXXABI::BuildConstructorSignature(
const CXXConstructorDecl *Ctor, CXXCtorType Type, CanQualType &ResTy,
SmallVectorImpl<CanQualType> &ArgTys) {
// All parameters are already in place except is_most_derived, which goes
// after 'this' if it's variadic and last if it's not.
const CXXRecordDecl *Class = Ctor->getParent();
const FunctionProtoType *FPT = Ctor->getType()->castAs<FunctionProtoType>();
if (Class->getNumVBases()) {
if (FPT->isVariadic())
ArgTys.insert(ArgTys.begin() + 1, CGM.getContext().IntTy);
else
ArgTys.push_back(CGM.getContext().IntTy);
}
}
llvm::BasicBlock *
MicrosoftCXXABI::EmitCtorCompleteObjectHandler(CodeGenFunction &CGF,
const CXXRecordDecl *RD) {
@ -910,18 +887,29 @@ void MicrosoftCXXABI::EmitVBPtrStores(CodeGenFunction &CGF,
}
}
void MicrosoftCXXABI::BuildDestructorSignature(const CXXDestructorDecl *Dtor,
CXXDtorType Type,
CanQualType &ResTy,
void
MicrosoftCXXABI::buildStructorSignature(const CXXMethodDecl *MD, StructorType T,
SmallVectorImpl<CanQualType> &ArgTys) {
// 'this' is already in place
// TODO: 'for base' flag
if (Type == Dtor_Deleting) {
if (T == StructorType::Deleting) {
// The scalar deleting destructor takes an implicit int parameter.
ArgTys.push_back(CGM.getContext().IntTy);
}
auto *CD = dyn_cast<CXXConstructorDecl>(MD);
if (!CD)
return;
// All parameters are already in place except is_most_derived, which goes
// after 'this' if it's variadic and last if it's not.
const CXXRecordDecl *Class = CD->getParent();
const FunctionProtoType *FPT = CD->getType()->castAs<FunctionProtoType>();
if (Class->getNumVBases()) {
if (FPT->isVariadic())
ArgTys.insert(ArgTys.begin() + 1, CGM.getContext().IntTy);
else
ArgTys.push_back(CGM.getContext().IntTy);
}
}
void MicrosoftCXXABI::EmitCXXDestructors(const CXXDestructorDecl *D) {
@ -1387,8 +1375,8 @@ void MicrosoftCXXABI::EmitVirtualDestructorCall(CodeGenFunction &CGF,
// We have only one destructor in the vftable but can get both behaviors
// by passing an implicit int parameter.
GlobalDecl GD(Dtor, Dtor_Deleting);
const CGFunctionInfo *FInfo =
&CGM.getTypes().arrangeCXXDestructor(Dtor, Dtor_Deleting);
const CGFunctionInfo *FInfo = &CGM.getTypes().arrangeCXXStructorDeclaration(
Dtor, StructorType::Deleting);
llvm::Type *Ty = CGF.CGM.getTypes().GetFunctionType(*FInfo);
llvm::Value *Callee = getVirtualFunctionPointer(CGF, GD, This, Ty);