diff options
Diffstat (limited to 'lib/CodeGen')
-rw-r--r-- | lib/CodeGen/CGCXX.cpp | 37 | ||||
-rw-r--r-- | lib/CodeGen/CGCXXExpr.cpp | 39 | ||||
-rw-r--r-- | lib/CodeGen/CodeGenFunction.h | 5 |
3 files changed, 53 insertions, 28 deletions
diff --git a/lib/CodeGen/CGCXX.cpp b/lib/CodeGen/CGCXX.cpp index 9651c1ae83..b6818aa74a 100644 --- a/lib/CodeGen/CGCXX.cpp +++ b/lib/CodeGen/CGCXX.cpp @@ -985,20 +985,35 @@ CodeGenFunction::GetVirtualCXXBaseClassOffset(llvm::Value *This, return VBaseOffset; } +static llvm::Value *BuildVirtualCall(CodeGenFunction &CGF, int64_t VtableIndex, + llvm::Value *This, const llvm::Type *Ty) { + Ty = Ty->getPointerTo()->getPointerTo()->getPointerTo(); + + llvm::Value *Vtable = CGF.Builder.CreateBitCast(This, Ty); + Vtable = CGF.Builder.CreateLoad(Vtable); + + llvm::Value *VFuncPtr = + CGF.Builder.CreateConstInBoundsGEP1_64(Vtable, VtableIndex, "vfn"); + return CGF.Builder.CreateLoad(VFuncPtr); +} + llvm::Value * -CodeGenFunction::BuildVirtualCall(const CXXMethodDecl *MD, llvm::Value *&This, +CodeGenFunction::BuildVirtualCall(const CXXMethodDecl *MD, llvm::Value *This, const llvm::Type *Ty) { - int64_t Index = CGM.getVtableInfo().getMethodVtableIndex(MD); + MD = MD->getCanonicalDecl(); + int64_t VtableIndex = CGM.getVtableInfo().getMethodVtableIndex(MD); - Ty = llvm::PointerType::get(Ty, 0); - Ty = llvm::PointerType::get(Ty, 0); - Ty = llvm::PointerType::get(Ty, 0); - llvm::Value *vtbl = Builder.CreateBitCast(This, Ty); - vtbl = Builder.CreateLoad(vtbl); - llvm::Value *vfn = Builder.CreateConstInBoundsGEP1_64(vtbl, - Index, "vfn"); - vfn = Builder.CreateLoad(vfn); - return vfn; + return ::BuildVirtualCall(*this, VtableIndex, This, Ty); +} + +llvm::Value * +CodeGenFunction::BuildVirtualCall(const CXXDestructorDecl *DD, CXXDtorType Type, + llvm::Value *&This, const llvm::Type *Ty) { + DD = cast<CXXDestructorDecl>(DD->getCanonicalDecl()); + int64_t VtableIndex = + CGM.getVtableInfo().getMethodVtableIndex(DD); + + return ::BuildVirtualCall(*this, VtableIndex, This, Ty); } /// EmitClassAggrMemberwiseCopy - This routine generates code to copy a class diff --git a/lib/CodeGen/CGCXXExpr.cpp b/lib/CodeGen/CGCXXExpr.cpp index 8b0490fe32..a21149973d 100644 --- a/lib/CodeGen/CGCXXExpr.cpp +++ b/lib/CodeGen/CGCXXExpr.cpp @@ -265,7 +265,9 @@ void CodeGenFunction::EmitCXXDeleteExpr(const CXXDeleteExpr *E) { Builder.CreateCondBr(IsNull, DeleteEnd, DeleteNotNull); EmitBlock(DeleteNotNull); - + + bool ShouldCallDelete = true; + // Call the destructor if necessary. if (const RecordType *RT = DeleteTy->getAs<RecordType>()) { if (CXXRecordDecl *RD = dyn_cast<CXXRecordDecl>(RT->getDecl())) { @@ -276,30 +278,35 @@ void CodeGenFunction::EmitCXXDeleteExpr(const CXXDeleteExpr *E) { CGM.getTypes().GetFunctionType(CGM.getTypes().getFunctionInfo(Dtor), /*isVariadic=*/false); - llvm::Value *Callee = BuildVirtualCall(Dtor, Ptr, Ty); + llvm::Value *Callee = BuildVirtualCall(Dtor, Dtor_Deleting, Ptr, Ty); EmitCXXMemberCall(Dtor, Callee, Ptr, 0, 0); + + // The dtor took care of deleting the object. + ShouldCallDelete = false; } else EmitCXXDestructorCall(Dtor, Dtor_Complete, Ptr); } } } - // Call delete. - FunctionDecl *DeleteFD = E->getOperatorDelete(); - const FunctionProtoType *DeleteFTy = - DeleteFD->getType()->getAs<FunctionProtoType>(); + if (ShouldCallDelete) { + // Call delete. + FunctionDecl *DeleteFD = E->getOperatorDelete(); + const FunctionProtoType *DeleteFTy = + DeleteFD->getType()->getAs<FunctionProtoType>(); - CallArgList DeleteArgs; + CallArgList DeleteArgs; - QualType ArgTy = DeleteFTy->getArgType(0); - llvm::Value *DeletePtr = Builder.CreateBitCast(Ptr, ConvertType(ArgTy)); - DeleteArgs.push_back(std::make_pair(RValue::get(DeletePtr), ArgTy)); - - // Emit the call to delete. - EmitCall(CGM.getTypes().getFunctionInfo(DeleteFTy->getResultType(), - DeleteArgs), - CGM.GetAddrOfFunction(DeleteFD), - DeleteArgs, DeleteFD); + QualType ArgTy = DeleteFTy->getArgType(0); + llvm::Value *DeletePtr = Builder.CreateBitCast(Ptr, ConvertType(ArgTy)); + DeleteArgs.push_back(std::make_pair(RValue::get(DeletePtr), ArgTy)); + // Emit the call to delete. + EmitCall(CGM.getTypes().getFunctionInfo(DeleteFTy->getResultType(), + DeleteArgs), + CGM.GetAddrOfFunction(DeleteFD), + DeleteArgs, DeleteFD); + } + EmitBlock(DeleteEnd); } diff --git a/lib/CodeGen/CodeGenFunction.h b/lib/CodeGen/CodeGenFunction.h index f42376b623..1b1f03424d 100644 --- a/lib/CodeGen/CodeGenFunction.h +++ b/lib/CodeGen/CodeGenFunction.h @@ -883,8 +883,11 @@ public: const Decl *TargetDecl = 0); RValue EmitCallExpr(const CallExpr *E); - llvm::Value *BuildVirtualCall(const CXXMethodDecl *MD, llvm::Value *&This, + llvm::Value *BuildVirtualCall(const CXXMethodDecl *MD, llvm::Value *This, const llvm::Type *Ty); + llvm::Value *BuildVirtualCall(const CXXDestructorDecl *DD, CXXDtorType Type, + llvm::Value *&This, const llvm::Type *Ty); + RValue EmitCXXMemberCall(const CXXMethodDecl *MD, llvm::Value *Callee, llvm::Value *This, |