Abstract out emitting the vdtor calls and do it properly when using -cxx-abi microsoft; also fix vdtor calls for the ARM ABI
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@175271 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/lib/CodeGen/CGCXXABI.h b/lib/CodeGen/CGCXXABI.h
index 80798e7..4764247 100644
--- a/lib/CodeGen/CGCXXABI.h
+++ b/lib/CodeGen/CGCXXABI.h
@@ -207,6 +207,14 @@
/// Emit the ABI-specific prolog for the function.
virtual void EmitInstanceFunctionProlog(CodeGenFunction &CGF) = 0;
+ /// Emit the ABI-specific virtual destructor call.
+ virtual RValue EmitVirtualDestructorCall(CodeGenFunction &CGF,
+ const CXXDestructorDecl *Dtor,
+ CXXDtorType DtorType,
+ SourceLocation CallLoc,
+ ReturnValueSlot ReturnValue,
+ llvm::Value *This) = 0;
+
virtual void EmitReturnFromThunk(CodeGenFunction &CGF,
RValue RV, QualType ResultType);
diff --git a/lib/CodeGen/CGExprCXX.cpp b/lib/CodeGen/CGExprCXX.cpp
index 1aaa667..e09e06c 100644
--- a/lib/CodeGen/CGExprCXX.cpp
+++ b/lib/CodeGen/CGExprCXX.cpp
@@ -284,7 +284,12 @@
llvm::Value *Callee;
if (const CXXDestructorDecl *Dtor = dyn_cast<CXXDestructorDecl>(MD)) {
if (UseVirtualCall) {
- Callee = BuildVirtualCall(Dtor, Dtor_Complete, This, Ty);
+ assert(CE->arg_begin() == CE->arg_end() &&
+ "Virtual destructor shouldn't have explicit parameters");
+ return CGM.getCXXABI().EmitVirtualDestructorCall(*this, Dtor,
+ Dtor_Complete,
+ CE->getExprLoc(),
+ ReturnValue, This);
} else {
if (getLangOpts().AppleKext &&
MD->isVirtual() &&
@@ -1399,18 +1404,12 @@
completePtr, OperatorDelete,
ElementType);
}
-
- llvm::Type *Ty =
- CGF.getTypes().GetFunctionType(
- CGF.getTypes().arrangeCXXDestructor(Dtor, Dtor_Complete));
-
- llvm::Value *Callee
- = CGF.BuildVirtualCall(Dtor,
- UseGlobalDelete? Dtor_Complete : Dtor_Deleting,
- Ptr, Ty);
+
// FIXME: Provide a source location here.
- CGF.EmitCXXMemberCall(Dtor, SourceLocation(), Callee, ReturnValueSlot(),
- Ptr, /*ImplicitParam=*/0, QualType(), 0, 0);
+ CXXDtorType DtorType = UseGlobalDelete ? Dtor_Complete : Dtor_Deleting;
+ CGF.CGM.getCXXABI().EmitVirtualDestructorCall(CGF, Dtor, DtorType,
+ SourceLocation(),
+ ReturnValueSlot(), Ptr);
if (UseGlobalDelete) {
CGF.PopCleanupBlock();
diff --git a/lib/CodeGen/ItaniumCXXABI.cpp b/lib/CodeGen/ItaniumCXXABI.cpp
index a3d8cec..bb2c93b 100644
--- a/lib/CodeGen/ItaniumCXXABI.cpp
+++ b/lib/CodeGen/ItaniumCXXABI.cpp
@@ -112,6 +112,13 @@
void EmitInstanceFunctionProlog(CodeGenFunction &CGF);
+ RValue EmitVirtualDestructorCall(CodeGenFunction &CGF,
+ const CXXDestructorDecl *Dtor,
+ CXXDtorType DtorType,
+ SourceLocation CallLoc,
+ ReturnValueSlot ReturnValue,
+ llvm::Value *This);
+
StringRef GetPureVirtualCallName() { return "__cxa_pure_virtual"; }
StringRef GetDeletedVirtualCallName() { return "__cxa_deleted_virtual"; }
@@ -819,6 +826,23 @@
CGF.Builder.CreateStore(getThisValue(CGF), CGF.ReturnValue);
}
+RValue ItaniumCXXABI::EmitVirtualDestructorCall(CodeGenFunction &CGF,
+ const CXXDestructorDecl *Dtor,
+ CXXDtorType DtorType,
+ SourceLocation CallLoc,
+ ReturnValueSlot ReturnValue,
+ llvm::Value *This) {
+ assert(DtorType == Dtor_Deleting || DtorType == Dtor_Complete);
+
+ const CGFunctionInfo *FInfo
+ = &CGM.getTypes().arrangeCXXDestructor(Dtor, DtorType);
+ llvm::Type *Ty = CGF.CGM.getTypes().GetFunctionType(*FInfo);
+ llvm::Value *Callee = CGF.BuildVirtualCall(Dtor, DtorType, This, Ty);
+
+ return CGF.EmitCXXMemberCall(Dtor, CallLoc, Callee, ReturnValue, This,
+ /*ImplicitParam=*/0, QualType(), 0, 0);
+}
+
void ARMCXXABI::EmitReturnFromThunk(CodeGenFunction &CGF,
RValue RV, QualType ResultType) {
if (!isa<CXXDestructorDecl>(CGF.CurGD.getDecl()))
diff --git a/lib/CodeGen/MicrosoftCXXABI.cpp b/lib/CodeGen/MicrosoftCXXABI.cpp
index 537e457..6c9a6fd 100644
--- a/lib/CodeGen/MicrosoftCXXABI.cpp
+++ b/lib/CodeGen/MicrosoftCXXABI.cpp
@@ -53,6 +53,13 @@
void EmitInstanceFunctionProlog(CodeGenFunction &CGF);
+ RValue EmitVirtualDestructorCall(CodeGenFunction &CGF,
+ const CXXDestructorDecl *Dtor,
+ CXXDtorType DtorType,
+ SourceLocation CallLoc,
+ ReturnValueSlot ReturnValue,
+ llvm::Value *This);
+
void EmitGuardedInit(CodeGenFunction &CGF, const VarDecl &D,
llvm::GlobalVariable *DeclPtr,
bool PerformInit);
@@ -174,6 +181,30 @@
}
}
+RValue MicrosoftCXXABI::EmitVirtualDestructorCall(CodeGenFunction &CGF,
+ const CXXDestructorDecl *Dtor,
+ CXXDtorType DtorType,
+ SourceLocation CallLoc,
+ ReturnValueSlot ReturnValue,
+ llvm::Value *This) {
+ assert(DtorType == Dtor_Deleting || DtorType == Dtor_Complete);
+
+ // We have only one destructor in the vftable but can get both behaviors
+ // by passing an implicit bool parameter.
+ const CGFunctionInfo *FInfo
+ = &CGM.getTypes().arrangeCXXDestructor(Dtor, Dtor_Deleting);
+ llvm::Type *Ty = CGF.CGM.getTypes().GetFunctionType(*FInfo);
+ llvm::Value *Callee = CGF.BuildVirtualCall(Dtor, Dtor_Deleting, This, Ty);
+
+ ASTContext &Context = CGF.getContext();
+ llvm::Value *ImplicitParam
+ = llvm::ConstantInt::get(llvm::IntegerType::getInt1Ty(CGF.getLLVMContext()),
+ DtorType == Dtor_Deleting);
+
+ return CGF.EmitCXXMemberCall(Dtor, CallLoc, Callee, ReturnValue, This,
+ ImplicitParam, Context.BoolTy, 0, 0);
+}
+
bool MicrosoftCXXABI::requiresArrayCookie(const CXXDeleteExpr *expr,
QualType elementType) {
// Microsoft seems to completely ignore the possibility of a