diff options
author | David Majnemer <david.majnemer@gmail.com> | 2014-10-31 20:09:12 +0000 |
---|---|---|
committer | David Majnemer <david.majnemer@gmail.com> | 2014-10-31 20:09:12 +0000 |
commit | 0c0b6d9ac6b37724807f1cf0c0c05b1bba3c3b48 (patch) | |
tree | 5acc8db1d3c1a830e9df04a21ad87aa231c8ac84 /clang/lib/CodeGen/MicrosoftCXXABI.cpp | |
parent | 6e21338abb6e4017a30323943daf074917601dd1 (diff) | |
download | bcm5719-llvm-0c0b6d9ac6b37724807f1cf0c0c05b1bba3c3b48.tar.gz bcm5719-llvm-0c0b6d9ac6b37724807f1cf0c0c05b1bba3c3b48.zip |
MS ABI: Properly call global delete when invoking virtual destructors
Summary:
The Itanium ABI approach of using offset-to-top isn't possible with the
MS ABI, it doesn't have that kind of information lying around.
Instead, we do the following:
- Call the virtual deleting destructor with the "don't delete the object
flag" set. The virtual deleting destructor will return a pointer to
'this' adjusted to the most derived class.
- Call the global delete using the adjusted 'this' pointer.
Reviewers: rnk
Subscribers: cfe-commits
Differential Revision: http://reviews.llvm.org/D5996
llvm-svn: 220993
Diffstat (limited to 'clang/lib/CodeGen/MicrosoftCXXABI.cpp')
-rw-r--r-- | clang/lib/CodeGen/MicrosoftCXXABI.cpp | 78 |
1 files changed, 46 insertions, 32 deletions
diff --git a/clang/lib/CodeGen/MicrosoftCXXABI.cpp b/clang/lib/CodeGen/MicrosoftCXXABI.cpp index 9e5bbd130bb..49907c965d3 100644 --- a/clang/lib/CodeGen/MicrosoftCXXABI.cpp +++ b/clang/lib/CodeGen/MicrosoftCXXABI.cpp @@ -43,6 +43,7 @@ public: CompleteObjectLocatorType(nullptr) {} bool HasThisReturn(GlobalDecl GD) const override; + bool hasMostDerivedReturn(GlobalDecl GD) const override; bool classifyReturnType(CGFunctionInfo &FI) const override; @@ -65,9 +66,11 @@ public: StringRef GetPureVirtualCallName() override { return "_purecall"; } StringRef GetDeletedVirtualCallName() override { return "_purecall"; } - llvm::Value *adjustToCompleteObject(CodeGenFunction &CGF, - llvm::Value *ptr, - QualType type) override; + void emitVirtualObjectDelete(CodeGenFunction &CGF, + const FunctionDecl *OperatorDelete, + llvm::Value *Ptr, QualType ElementType, + bool UseGlobalDelete, + const CXXDestructorDecl *Dtor) override; llvm::GlobalVariable *getMSCompleteObjectLocator(const CXXRecordDecl *RD, const VPtrInfo *Info); @@ -211,10 +214,11 @@ public: llvm::Value *This, llvm::Type *Ty) override; - void EmitVirtualDestructorCall(CodeGenFunction &CGF, - const CXXDestructorDecl *Dtor, - CXXDtorType DtorType, llvm::Value *This, - const CXXMemberCallExpr *CE) override; + llvm::Value *EmitVirtualDestructorCall(CodeGenFunction &CGF, + const CXXDestructorDecl *Dtor, + CXXDtorType DtorType, + llvm::Value *This, + const CXXMemberCallExpr *CE) override; void adjustCallArgsForDestructorThunk(CodeGenFunction &CGF, GlobalDecl GD, CallArgList &CallArgs) override { @@ -641,11 +645,16 @@ MicrosoftCXXABI::getRecordArgABI(const CXXRecordDecl *RD) const { llvm_unreachable("invalid enum"); } -llvm::Value *MicrosoftCXXABI::adjustToCompleteObject(CodeGenFunction &CGF, - llvm::Value *ptr, - QualType type) { - // FIXME: implement - return ptr; +void MicrosoftCXXABI::emitVirtualObjectDelete( + CodeGenFunction &CGF, const FunctionDecl *OperatorDelete, llvm::Value *Ptr, + QualType ElementType, bool UseGlobalDelete, const CXXDestructorDecl *Dtor) { + // FIXME: Provide a source location here even though there's no + // CXXMemberCallExpr for dtor call. + CXXDtorType DtorType = UseGlobalDelete ? Dtor_Complete : Dtor_Deleting; + llvm::Value *MDThis = + EmitVirtualDestructorCall(CGF, Dtor, DtorType, Ptr, /*CE=*/nullptr); + if (UseGlobalDelete) + CGF.EmitDeleteCall(OperatorDelete, MDThis, ElementType); } /// \brief Gets the offset to the virtual base that contains the vfptr for @@ -795,6 +804,15 @@ bool MicrosoftCXXABI::HasThisReturn(GlobalDecl GD) const { return isa<CXXConstructorDecl>(GD.getDecl()); } +static bool isDeletingDtor(GlobalDecl GD) { + return isa<CXXDestructorDecl>(GD.getDecl()) && + GD.getDtorType() == Dtor_Deleting; +} + +bool MicrosoftCXXABI::hasMostDerivedReturn(GlobalDecl GD) const { + return isDeletingDtor(GD); +} + bool MicrosoftCXXABI::classifyReturnType(CGFunctionInfo &FI) const { const CXXRecordDecl *RD = FI.getReturnType()->getAsCXXRecordDecl(); if (!RD) @@ -1059,14 +1077,6 @@ llvm::Value *MicrosoftCXXABI::adjustThisArgumentForVirtualFunctionCall( return This; } -static bool IsDeletingDtor(GlobalDecl GD) { - const CXXMethodDecl* MD = cast<CXXMethodDecl>(GD.getDecl()); - if (isa<CXXDestructorDecl>(MD)) { - return GD.getDtorType() == Dtor_Deleting; - } - return false; -} - void MicrosoftCXXABI::addImplicitStructorParams(CodeGenFunction &CGF, QualType &ResTy, FunctionArgList &Params) { @@ -1087,7 +1097,7 @@ void MicrosoftCXXABI::addImplicitStructorParams(CodeGenFunction &CGF, else Params.push_back(IsMostDerived); getStructorImplicitParamDecl(CGF) = IsMostDerived; - } else if (IsDeletingDtor(CGF.CurGD)) { + } else if (isDeletingDtor(CGF.CurGD)) { ImplicitParamDecl *ShouldDelete = ImplicitParamDecl::Create(Context, nullptr, CGF.CurGD.getDecl()->getLocation(), @@ -1133,6 +1143,9 @@ void MicrosoftCXXABI::EmitInstanceFunctionProlog(CodeGenFunction &CGF) { /// HasThisReturn only specifies a contract, not the implementation if (HasThisReturn(CGF.CurGD)) CGF.Builder.CreateStore(getThisValue(CGF), CGF.ReturnValue); + else if (hasMostDerivedReturn(CGF.CurGD)) + CGF.Builder.CreateStore(CGF.EmitCastToVoidPtr(getThisValue(CGF)), + CGF.ReturnValue); const CXXMethodDecl *MD = cast<CXXMethodDecl>(CGF.CurGD.getDecl()); if (isa<CXXConstructorDecl>(MD) && MD->getParent()->getNumVBases()) { @@ -1144,7 +1157,7 @@ void MicrosoftCXXABI::EmitInstanceFunctionProlog(CodeGenFunction &CGF) { "is_most_derived"); } - if (IsDeletingDtor(CGF.CurGD)) { + if (isDeletingDtor(CGF.CurGD)) { assert(getStructorImplicitParamDecl(CGF) && "no implicit parameter for a deleting destructor?"); getStructorImplicitParamValue(CGF) @@ -1192,9 +1205,10 @@ void MicrosoftCXXABI::EmitDestructorCall(CodeGenFunction &CGF, This, false); } - CGF.EmitCXXMemberOrOperatorCall(DD, Callee, ReturnValueSlot(), This, - /*ImplicitParam=*/nullptr, - /*ImplicitParamTy=*/QualType(), nullptr); + CGF.EmitCXXStructorCall(DD, Callee, ReturnValueSlot(), This, + /*ImplicitParam=*/nullptr, + /*ImplicitParamTy=*/QualType(), nullptr, + getFromDtorType(Type)); } void MicrosoftCXXABI::emitVTableDefinitions(CodeGenVTables &CGVT, @@ -1402,11 +1416,9 @@ llvm::Value *MicrosoftCXXABI::getVirtualFunctionPointer(CodeGenFunction &CGF, return Builder.CreateLoad(VFuncPtr); } -void MicrosoftCXXABI::EmitVirtualDestructorCall(CodeGenFunction &CGF, - const CXXDestructorDecl *Dtor, - CXXDtorType DtorType, - llvm::Value *This, - const CXXMemberCallExpr *CE) { +llvm::Value *MicrosoftCXXABI::EmitVirtualDestructorCall( + CodeGenFunction &CGF, const CXXDestructorDecl *Dtor, CXXDtorType DtorType, + llvm::Value *This, const CXXMemberCallExpr *CE) { assert(CE == nullptr || CE->arg_begin() == CE->arg_end()); assert(DtorType == Dtor_Deleting || DtorType == Dtor_Complete); @@ -1424,8 +1436,10 @@ void MicrosoftCXXABI::EmitVirtualDestructorCall(CodeGenFunction &CGF, DtorType == Dtor_Deleting); This = adjustThisArgumentForVirtualFunctionCall(CGF, GD, This, true); - CGF.EmitCXXMemberOrOperatorCall(Dtor, Callee, ReturnValueSlot(), This, - ImplicitParam, Context.IntTy, CE); + RValue RV = CGF.EmitCXXStructorCall(Dtor, Callee, ReturnValueSlot(), This, + ImplicitParam, Context.IntTy, CE, + StructorType::Deleting); + return RV.getScalarVal(); } const VBTableGlobals & |