Author: timurrrr Date: Fri Feb 15 08:45:22 2013 New Revision: 175271 URL: http://llvm.org/viewvc/llvm-project?rev=175271&view=rev Log: Abstract out emitting the vdtor calls and do it properly when using -cxx-abi microsoft; also fix vdtor calls for the ARM ABI
Modified: cfe/trunk/lib/CodeGen/CGCXXABI.h cfe/trunk/lib/CodeGen/CGExprCXX.cpp cfe/trunk/lib/CodeGen/ItaniumCXXABI.cpp cfe/trunk/lib/CodeGen/MicrosoftCXXABI.cpp cfe/trunk/test/CodeGenCXX/arm.cpp cfe/trunk/test/CodeGenCXX/microsoft-abi-structors.cpp Modified: cfe/trunk/lib/CodeGen/CGCXXABI.h URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGCXXABI.h?rev=175271&r1=175270&r2=175271&view=diff ============================================================================== --- cfe/trunk/lib/CodeGen/CGCXXABI.h (original) +++ cfe/trunk/lib/CodeGen/CGCXXABI.h Fri Feb 15 08:45:22 2013 @@ -207,6 +207,14 @@ public: /// 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); Modified: cfe/trunk/lib/CodeGen/CGExprCXX.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGExprCXX.cpp?rev=175271&r1=175270&r2=175271&view=diff ============================================================================== --- cfe/trunk/lib/CodeGen/CGExprCXX.cpp (original) +++ cfe/trunk/lib/CodeGen/CGExprCXX.cpp Fri Feb 15 08:45:22 2013 @@ -284,7 +284,12 @@ RValue CodeGenFunction::EmitCXXMemberCal 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 @@ static void EmitObjectDelete(CodeGenFunc 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(); Modified: cfe/trunk/lib/CodeGen/ItaniumCXXABI.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/ItaniumCXXABI.cpp?rev=175271&r1=175270&r2=175271&view=diff ============================================================================== --- cfe/trunk/lib/CodeGen/ItaniumCXXABI.cpp (original) +++ cfe/trunk/lib/CodeGen/ItaniumCXXABI.cpp Fri Feb 15 08:45:22 2013 @@ -112,6 +112,13 @@ public: 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 @@ void ARMCXXABI::EmitInstanceFunctionProl 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())) Modified: cfe/trunk/lib/CodeGen/MicrosoftCXXABI.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/MicrosoftCXXABI.cpp?rev=175271&r1=175270&r2=175271&view=diff ============================================================================== --- cfe/trunk/lib/CodeGen/MicrosoftCXXABI.cpp (original) +++ cfe/trunk/lib/CodeGen/MicrosoftCXXABI.cpp Fri Feb 15 08:45:22 2013 @@ -53,6 +53,13 @@ public: 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 @@ void MicrosoftCXXABI::EmitInstanceFuncti } } +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 Modified: cfe/trunk/test/CodeGenCXX/arm.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGenCXX/arm.cpp?rev=175271&r1=175270&r2=175271&view=diff ============================================================================== --- cfe/trunk/test/CodeGenCXX/arm.cpp (original) +++ cfe/trunk/test/CodeGenCXX/arm.cpp Fri Feb 15 08:45:22 2013 @@ -274,11 +274,11 @@ namespace test6 { // CHECK-NEXT: [[V:%.*]] = load [[A]]** [[AVAR]], align 4 // CHECK-NEXT: [[ISNULL:%.*]] = icmp eq [[A]]* [[V]], null // CHECK-NEXT: br i1 [[ISNULL]] - // CHECK: [[T0:%.*]] = bitcast [[A]]* [[V]] to [[A]]* ([[A]]*)*** - // CHECK-NEXT: [[T1:%.*]] = load [[A]]* ([[A]]*)*** [[T0]] - // CHECK-NEXT: [[T2:%.*]] = getelementptr inbounds [[A]]* ([[A]]*)** [[T1]], i64 1 - // CHECK-NEXT: [[T3:%.*]] = load [[A]]* ([[A]]*)** [[T2]] - // CHECK-NEXT: call [[A]]* [[T3]]([[A]]* [[V]]) + // CHECK: [[T0:%.*]] = bitcast [[A]]* [[V]] to void ([[A]]*)*** + // CHECK-NEXT: [[T1:%.*]] = load void ([[A]]*)*** [[T0]] + // CHECK-NEXT: [[T2:%.*]] = getelementptr inbounds void ([[A]]*)** [[T1]], i64 1 + // CHECK-NEXT: [[T3:%.*]] = load void ([[A]]*)** [[T2]] + // CHECK-NEXT: call void [[T3]]([[A]]* [[V]]) // CHECK-NEXT: br label // CHECK: ret void delete a; Modified: cfe/trunk/test/CodeGenCXX/microsoft-abi-structors.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGenCXX/microsoft-abi-structors.cpp?rev=175271&r1=175270&r2=175271&view=diff ============================================================================== --- cfe/trunk/test/CodeGenCXX/microsoft-abi-structors.cpp (original) +++ cfe/trunk/test/CodeGenCXX/microsoft-abi-structors.cpp Fri Feb 15 08:45:22 2013 @@ -32,7 +32,9 @@ struct B { // DTORS: define {{.*}} x86_thiscallcc void @"\01??1B@@UAE@XZ"(%struct.B* %this) // Then, the scalar deleting destructor (used in the vtable): -// DTORS: define {{.*}} x86_thiscallcc void @"\01??_GB@@UAEPAXI@Z"(%struct.B* %this, i1 zeroext %should_call_delete) +// FIXME: add a test that verifies that the out-of-line scalar deleting +// destructor is linkonce_odr too. +// DTORS: define linkonce_odr x86_thiscallcc void @"\01??_GB@@UAEPAXI@Z"(%struct.B* %this, i1 zeroext %should_call_delete) // DTORS: %[[FROMBOOL:[0-9a-z]+]] = zext i1 %should_call_delete to i8 // DTORS-NEXT: store i8 %[[FROMBOOL]], i8* %[[SHOULD_DELETE_VAR:[0-9a-z._]+]], align 1 // DTORS: %[[SHOULD_DELETE_VALUE:[0-9a-z._]+]] = load i8* %[[SHOULD_DELETE_VAR]] @@ -61,17 +63,29 @@ void check_vftable_offset() { // CHECK: store i8** getelementptr inbounds ([2 x i8*]* @"\01??_7B@@6B@", i64 0, i64 0), i8*** [[THIS_PTR]] } -// FIXME: Enable the following block and add expectations when calls -// to virtual complete dtor are supported. -#if 0 void call_complete_dtor(B *obj_ptr) { +// CHECK: define void @"\01?call_complete_dtor@@YAXPAUB@@@Z"(%struct.B* %obj_ptr) obj_ptr->~B(); +// CHECK: %[[OBJ_PTR_VALUE:.*]] = load %struct.B** %{{.*}}, align 4 +// CHECK-NEXT: %[[PVTABLE:.*]] = bitcast %struct.B* %[[OBJ_PTR_VALUE]] to void (%struct.B*, i1)*** +// CHECK-NEXT: %[[VTABLE:.*]] = load void (%struct.B*, i1)*** %[[PVTABLE]] +// CHECK-NEXT: %[[PVDTOR:.*]] = getelementptr inbounds void (%struct.B*, i1)** %[[VTABLE]], i64 0 +// CHECK-NEXT: %[[VDTOR:.*]] = load void (%struct.B*, i1)** %[[PVDTOR]] +// CHECK-NEXT: call x86_thiscallcc void %[[VDTOR]](%struct.B* %[[OBJ_PTR_VALUE]], i1 zeroext false) +// CHECK-NEXT: ret void } -#endif void call_deleting_dtor(B *obj_ptr) { -// FIXME: Add CHECKs when calls to virtual deleting dtor are generated properly. +// CHECK: define void @"\01?call_deleting_dtor@@YAXPAUB@@@Z"(%struct.B* %obj_ptr) delete obj_ptr; +// CHECK: %[[OBJ_PTR_VALUE:.*]] = load %struct.B** %{{.*}}, align 4 +// CHECK: {{.*}}:{{%{0,1}[0-9]*}} +// CHECK-NEXT: %[[PVTABLE:.*]] = bitcast %struct.B* %[[OBJ_PTR_VALUE]] to void (%struct.B*, i1)*** +// CHECK-NEXT: %[[VTABLE:.*]] = load void (%struct.B*, i1)*** %[[PVTABLE]] +// CHECK-NEXT: %[[PVDTOR:.*]] = getelementptr inbounds void (%struct.B*, i1)** %[[VTABLE]], i64 0 +// CHECK-NEXT: %[[VDTOR:.*]] = load void (%struct.B*, i1)** %[[PVDTOR]] +// CHECK-NEXT: call x86_thiscallcc void %[[VDTOR]](%struct.B* %[[OBJ_PTR_VALUE]], i1 zeroext true) +// CHECK: ret void } struct C { _______________________________________________ cfe-commits mailing list cfe-commits@cs.uiuc.edu http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits