diff options
Diffstat (limited to 'lib/CodeGen')
-rw-r--r-- | lib/CodeGen/CGCXXABI.h | 13 | ||||
-rw-r--r-- | lib/CodeGen/CGClass.cpp | 41 | ||||
-rw-r--r-- | lib/CodeGen/CGExprCXX.cpp | 18 | ||||
-rw-r--r-- | lib/CodeGen/CodeGenFunction.cpp | 5 | ||||
-rw-r--r-- | lib/CodeGen/CodeGenFunction.h | 26 | ||||
-rw-r--r-- | lib/CodeGen/MicrosoftCXXABI.cpp | 45 |
6 files changed, 121 insertions, 27 deletions
diff --git a/lib/CodeGen/CGCXXABI.h b/lib/CodeGen/CGCXXABI.h index c319c062ef..80798e71f8 100644 --- a/lib/CodeGen/CGCXXABI.h +++ b/lib/CodeGen/CGCXXABI.h @@ -54,11 +54,20 @@ protected: return CGF.CXXABIThisValue; } + // FIXME: Every place that calls getVTT{Decl,Value} is something + // that needs to be abstracted properly. ImplicitParamDecl *&getVTTDecl(CodeGenFunction &CGF) { - return CGF.CXXVTTDecl; + return CGF.CXXStructorImplicitParamDecl; } llvm::Value *&getVTTValue(CodeGenFunction &CGF) { - return CGF.CXXVTTValue; + return CGF.CXXStructorImplicitParamValue; + } + + ImplicitParamDecl *&getStructorImplicitParamDecl(CodeGenFunction &CGF) { + return CGF.CXXStructorImplicitParamDecl; + } + llvm::Value *&getStructorImplicitParamValue(CodeGenFunction &CGF) { + return CGF.CXXStructorImplicitParamValue; } /// Build a parameter variable suitable for 'this'. diff --git a/lib/CodeGen/CGClass.cpp b/lib/CodeGen/CGClass.cpp index ce32acd0da..4e4acc8f12 100644 --- a/lib/CodeGen/CGClass.cpp +++ b/lib/CodeGen/CGClass.cpp @@ -953,6 +953,32 @@ namespace { } }; + struct CallDtorDeleteConditional : EHScopeStack::Cleanup { + llvm::Value *ShouldDeleteCondition; + public: + CallDtorDeleteConditional(llvm::Value *ShouldDeleteCondition) + : ShouldDeleteCondition(ShouldDeleteCondition) { + assert(ShouldDeleteCondition != NULL); + } + + void Emit(CodeGenFunction &CGF, Flags flags) { + llvm::BasicBlock *callDeleteBB = CGF.createBasicBlock("dtor.call_delete"); + llvm::BasicBlock *continueBB = CGF.createBasicBlock("dtor.continue"); + llvm::Value *ShouldCallDelete + = CGF.Builder.CreateIsNull(ShouldDeleteCondition); + CGF.Builder.CreateCondBr(ShouldCallDelete, continueBB, callDeleteBB); + + CGF.EmitBlock(callDeleteBB); + const CXXDestructorDecl *Dtor = cast<CXXDestructorDecl>(CGF.CurCodeDecl); + const CXXRecordDecl *ClassDecl = Dtor->getParent(); + CGF.EmitDeleteCall(Dtor->getOperatorDelete(), CGF.LoadCXXThis(), + CGF.getContext().getTagDeclType(ClassDecl)); + CGF.Builder.CreateBr(continueBB); + + CGF.EmitBlock(continueBB); + } + }; + class DestroyField : public EHScopeStack::Cleanup { const FieldDecl *field; CodeGenFunction::Destroyer *destroyer; @@ -991,7 +1017,14 @@ void CodeGenFunction::EnterDtorCleanups(const CXXDestructorDecl *DD, if (DtorType == Dtor_Deleting) { assert(DD->getOperatorDelete() && "operator delete missing - EmitDtorEpilogue"); - EHStack.pushCleanup<CallDtorDelete>(NormalAndEHCleanup); + if (CXXStructorImplicitParamValue) { + // If there is an implicit param to the deleting dtor, it's a boolean + // telling whether we should call delete at the end of the dtor. + EHStack.pushCleanup<CallDtorDeleteConditional>( + NormalAndEHCleanup, CXXStructorImplicitParamValue); + } else { + EHStack.pushCleanup<CallDtorDelete>(NormalAndEHCleanup); + } return; } @@ -1243,7 +1276,8 @@ CodeGenFunction::EmitCXXConstructorCall(const CXXConstructorDecl *D, // FIXME: Provide a source location here. EmitCXXMemberCall(D, SourceLocation(), Callee, ReturnValueSlot(), This, - VTT, ArgBeg, ArgEnd); + VTT, getContext().getPointerType(getContext().VoidPtrTy), + ArgBeg, ArgEnd); } void @@ -1399,7 +1433,8 @@ void CodeGenFunction::EmitCXXDestructorCall(const CXXDestructorDecl *DD, // FIXME: Provide a source location here. EmitCXXMemberCall(DD, SourceLocation(), Callee, ReturnValueSlot(), This, - VTT, 0, 0); + VTT, getContext().getPointerType(getContext().VoidPtrTy), + 0, 0); } namespace { diff --git a/lib/CodeGen/CGExprCXX.cpp b/lib/CodeGen/CGExprCXX.cpp index d2db71c071..1aaa667413 100644 --- a/lib/CodeGen/CGExprCXX.cpp +++ b/lib/CodeGen/CGExprCXX.cpp @@ -28,7 +28,8 @@ RValue CodeGenFunction::EmitCXXMemberCall(const CXXMethodDecl *MD, llvm::Value *Callee, ReturnValueSlot ReturnValue, llvm::Value *This, - llvm::Value *VTT, + llvm::Value *ImplicitParam, + QualType ImplicitParamTy, CallExpr::const_arg_iterator ArgBeg, CallExpr::const_arg_iterator ArgEnd) { assert(MD->isInstance() && @@ -46,10 +47,9 @@ RValue CodeGenFunction::EmitCXXMemberCall(const CXXMethodDecl *MD, // Push the this ptr. Args.add(RValue::get(This), MD->getThisType(getContext())); - // If there is a VTT parameter, emit it. - if (VTT) { - QualType T = getContext().getPointerType(getContext().VoidPtrTy); - Args.add(RValue::get(VTT), T); + // If there is an implicit parameter (e.g. VTT), emit it. + if (ImplicitParam) { + Args.add(RValue::get(ImplicitParam), ImplicitParamTy); } const FunctionProtoType *FPT = MD->getType()->castAs<FunctionProtoType>(); @@ -316,7 +316,8 @@ RValue CodeGenFunction::EmitCXXMemberCallExpr(const CXXMemberCallExpr *CE, } return EmitCXXMemberCall(MD, CE->getExprLoc(), Callee, ReturnValue, This, - /*VTT=*/0, CE->arg_begin(), CE->arg_end()); + /*ImplicitParam=*/0, QualType(), + CE->arg_begin(), CE->arg_end()); } RValue @@ -388,7 +389,8 @@ CodeGenFunction::EmitCXXOperatorMemberCallExpr(const CXXOperatorCallExpr *E, llvm::Value *Callee = EmitCXXOperatorMemberCallee(E, MD, This); return EmitCXXMemberCall(MD, E->getExprLoc(), Callee, ReturnValue, This, - /*VTT=*/0, E->arg_begin() + 1, E->arg_end()); + /*ImplicitParam=*/0, QualType(), + E->arg_begin() + 1, E->arg_end()); } RValue CodeGenFunction::EmitCUDAKernelCallExpr(const CUDAKernelCallExpr *E, @@ -1408,7 +1410,7 @@ static void EmitObjectDelete(CodeGenFunction &CGF, Ptr, Ty); // FIXME: Provide a source location here. CGF.EmitCXXMemberCall(Dtor, SourceLocation(), Callee, ReturnValueSlot(), - Ptr, /*VTT=*/0, 0, 0); + Ptr, /*ImplicitParam=*/0, QualType(), 0, 0); if (UseGlobalDelete) { CGF.PopCleanupBlock(); diff --git a/lib/CodeGen/CodeGenFunction.cpp b/lib/CodeGen/CodeGenFunction.cpp index ec139df3ef..cba3316600 100644 --- a/lib/CodeGen/CodeGenFunction.cpp +++ b/lib/CodeGen/CodeGenFunction.cpp @@ -43,8 +43,9 @@ CodeGenFunction::CodeGenFunction(CodeGenModule &cgm, bool suppressNewContext) FirstBlockInfo(0), EHResumeBlock(0), ExceptionSlot(0), EHSelectorSlot(0), DebugInfo(0), DisableDebugInfo(false), DidCallStackSave(false), IndirectBranch(0), SwitchInsn(0), CaseRangeBlock(0), UnreachableBlock(0), - CXXABIThisDecl(0), CXXABIThisValue(0), CXXThisValue(0), CXXVTTDecl(0), - CXXVTTValue(0), OutermostConditional(0), TerminateLandingPad(0), + CXXABIThisDecl(0), CXXABIThisValue(0), CXXThisValue(0), + CXXStructorImplicitParamDecl(0), CXXStructorImplicitParamValue(0), + OutermostConditional(0), TerminateLandingPad(0), TerminateHandler(0), TrapBB(0) { if (!suppressNewContext) CGM.getCXXABI().getMangleContext().startNewFunction(); diff --git a/lib/CodeGen/CodeGenFunction.h b/lib/CodeGen/CodeGenFunction.h index d43b58830b..ea5e8733d6 100644 --- a/lib/CodeGen/CodeGenFunction.h +++ b/lib/CodeGen/CodeGenFunction.h @@ -1179,11 +1179,10 @@ private: llvm::Value *CXXABIThisValue; llvm::Value *CXXThisValue; - /// CXXVTTDecl - When generating code for a base object constructor or - /// base object destructor with virtual bases, this will hold the implicit - /// VTT parameter. - ImplicitParamDecl *CXXVTTDecl; - llvm::Value *CXXVTTValue; + /// CXXStructorImplicitParamDecl - When generating code for a constructor or + /// destructor, this will hold the implicit argument (e.g. VTT). + ImplicitParamDecl *CXXStructorImplicitParamDecl; + llvm::Value *CXXStructorImplicitParamValue; /// OutermostConditional - Points to the outermost active /// conditional control. This is used so that we know if a @@ -1777,9 +1776,19 @@ public: /// LoadCXXVTT - Load the VTT parameter to base constructors/destructors have /// virtual bases. + // FIXME: Every place that calls LoadCXXVTT is something + // that needs to be abstracted properly. llvm::Value *LoadCXXVTT() { - assert(CXXVTTValue && "no VTT value for this function"); - return CXXVTTValue; + assert(CXXStructorImplicitParamValue && "no VTT value for this function"); + return CXXStructorImplicitParamValue; + } + + /// LoadCXXStructorImplicitParam - Load the implicit parameter + /// for a constructor/destructor. + llvm::Value *LoadCXXStructorImplicitParam() { + assert(CXXStructorImplicitParamValue && + "no implicit argument value for this function"); + return CXXStructorImplicitParamValue; } /// GetAddressOfBaseOfCompleteClass - Convert the given pointer to a @@ -2294,7 +2303,8 @@ public: llvm::Value *Callee, ReturnValueSlot ReturnValue, llvm::Value *This, - llvm::Value *VTT, + llvm::Value *ImplicitParam, + QualType ImplicitParamTy, CallExpr::const_arg_iterator ArgBeg, CallExpr::const_arg_iterator ArgEnd); RValue EmitCXXMemberCallExpr(const CXXMemberCallExpr *E, diff --git a/lib/CodeGen/MicrosoftCXXABI.cpp b/lib/CodeGen/MicrosoftCXXABI.cpp index 477720bd25..537e4574dd 100644 --- a/lib/CodeGen/MicrosoftCXXABI.cpp +++ b/lib/CodeGen/MicrosoftCXXABI.cpp @@ -45,10 +45,7 @@ public: void BuildDestructorSignature(const CXXDestructorDecl *Ctor, CXXDtorType Type, CanQualType &ResTy, - SmallVectorImpl<CanQualType> &ArgTys) { - // 'this' is already in place - // TODO: 'for base' flag - } + SmallVectorImpl<CanQualType> &ArgTys); void BuildInstanceFunctionParams(CodeGenFunction &CGF, QualType &ResTy, @@ -121,6 +118,27 @@ void MicrosoftCXXABI::BuildConstructorSignature(const CXXConstructorDecl *Ctor, ResTy = ArgTys[0]; } +void MicrosoftCXXABI::BuildDestructorSignature(const CXXDestructorDecl *Dtor, + CXXDtorType Type, + CanQualType &ResTy, + SmallVectorImpl<CanQualType> &ArgTys) { + // 'this' is already in place + // TODO: 'for base' flag + + if (Type == Dtor_Deleting) { + // The scalar deleting destructor takes an implicit bool parameter. + ArgTys.push_back(CGM.getContext().BoolTy); + } +} + +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::BuildInstanceFunctionParams(CodeGenFunction &CGF, QualType &ResTy, FunctionArgList &Params) { @@ -128,6 +146,17 @@ void MicrosoftCXXABI::BuildInstanceFunctionParams(CodeGenFunction &CGF, if (needThisReturn(CGF.CurGD)) { ResTy = Params[0]->getType(); } + if (IsDeletingDtor(CGF.CurGD)) { + ASTContext &Context = getContext(); + + ImplicitParamDecl *ShouldDelete + = ImplicitParamDecl::Create(Context, 0, + CGF.CurGD.getDecl()->getLocation(), + &Context.Idents.get("should_call_delete"), + Context.BoolTy); + Params.push_back(ShouldDelete); + getStructorImplicitParamDecl(CGF) = ShouldDelete; + } } void MicrosoftCXXABI::EmitInstanceFunctionProlog(CodeGenFunction &CGF) { @@ -135,6 +164,14 @@ void MicrosoftCXXABI::EmitInstanceFunctionProlog(CodeGenFunction &CGF) { if (needThisReturn(CGF.CurGD)) { CGF.Builder.CreateStore(getThisValue(CGF), CGF.ReturnValue); } + if (IsDeletingDtor(CGF.CurGD)) { + assert(getStructorImplicitParamDecl(CGF) && + "no implicit parameter for a deleting destructor?"); + getStructorImplicitParamValue(CGF) + = CGF.Builder.CreateLoad( + CGF.GetAddrOfLocalVar(getStructorImplicitParamDecl(CGF)), + "should_call_delete"); + } } bool MicrosoftCXXABI::requiresArrayCookie(const CXXDeleteExpr *expr, |