diff options
author | John McCall <rjmccall@apple.com> | 2016-10-26 23:46:34 +0000 |
---|---|---|
committer | John McCall <rjmccall@apple.com> | 2016-10-26 23:46:34 +0000 |
commit | a896e9a7d27788e7573f3ca13066cc5fc6d91da6 (patch) | |
tree | 5c973ba5e89c894464a6365f764955ff10e54b97 /lib/CodeGen/CGExprCXX.cpp | |
parent | 9b0930125c1489b2a4dbe3bce28cd1f31a662baa (diff) |
Refactor call emission to package the function pointer together with
abstract information about the callee. NFC.
The goal here is to make it easier to recognize indirect calls and
trigger additional logic in certain cases. That logic will come in
a later patch; in the meantime, I felt that this was a significant
improvement to the code.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@285258 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/CodeGen/CGExprCXX.cpp')
-rw-r--r-- | lib/CodeGen/CGExprCXX.cpp | 103 |
1 files changed, 82 insertions, 21 deletions
diff --git a/lib/CodeGen/CGExprCXX.cpp b/lib/CodeGen/CGExprCXX.cpp index 011000fc19..88a5f35d2d 100644 --- a/lib/CodeGen/CGExprCXX.cpp +++ b/lib/CodeGen/CGExprCXX.cpp @@ -80,26 +80,78 @@ commonEmitCXXMemberOrOperatorCall(CodeGenFunction &CGF, const CXXMethodDecl *MD, } RValue CodeGenFunction::EmitCXXMemberOrOperatorCall( - const CXXMethodDecl *MD, llvm::Value *Callee, ReturnValueSlot ReturnValue, + const CXXMethodDecl *MD, const CGCallee &Callee, + ReturnValueSlot ReturnValue, llvm::Value *This, llvm::Value *ImplicitParam, QualType ImplicitParamTy, const CallExpr *CE, CallArgList *RtlArgs) { const FunctionProtoType *FPT = MD->getType()->castAs<FunctionProtoType>(); CallArgList Args; RequiredArgs required = commonEmitCXXMemberOrOperatorCall( *this, MD, This, ImplicitParam, ImplicitParamTy, CE, Args, RtlArgs); - return EmitCall(CGM.getTypes().arrangeCXXMethodCall(Args, FPT, required), - Callee, ReturnValue, Args, MD); + auto &FnInfo = CGM.getTypes().arrangeCXXMethodCall(Args, FPT, required); + return EmitCall(FnInfo, Callee, ReturnValue, Args); } RValue CodeGenFunction::EmitCXXDestructorCall( - const CXXDestructorDecl *DD, llvm::Value *Callee, llvm::Value *This, + const CXXDestructorDecl *DD, const CGCallee &Callee, llvm::Value *This, llvm::Value *ImplicitParam, QualType ImplicitParamTy, const CallExpr *CE, StructorType Type) { CallArgList Args; commonEmitCXXMemberOrOperatorCall(*this, DD, This, ImplicitParam, ImplicitParamTy, CE, Args, nullptr); return EmitCall(CGM.getTypes().arrangeCXXStructorDeclaration(DD, Type), - Callee, ReturnValueSlot(), Args, DD); + Callee, ReturnValueSlot(), Args); +} + +RValue CodeGenFunction::EmitCXXPseudoDestructorExpr( + const CXXPseudoDestructorExpr *E) { + QualType DestroyedType = E->getDestroyedType(); + if (DestroyedType.hasStrongOrWeakObjCLifetime()) { + // Automatic Reference Counting: + // If the pseudo-expression names a retainable object with weak or + // strong lifetime, the object shall be released. + Expr *BaseExpr = E->getBase(); + Address BaseValue = Address::invalid(); + Qualifiers BaseQuals; + + // If this is s.x, emit s as an lvalue. If it is s->x, emit s as a scalar. + if (E->isArrow()) { + BaseValue = EmitPointerWithAlignment(BaseExpr); + const PointerType *PTy = BaseExpr->getType()->getAs<PointerType>(); + BaseQuals = PTy->getPointeeType().getQualifiers(); + } else { + LValue BaseLV = EmitLValue(BaseExpr); + BaseValue = BaseLV.getAddress(); + QualType BaseTy = BaseExpr->getType(); + BaseQuals = BaseTy.getQualifiers(); + } + + switch (DestroyedType.getObjCLifetime()) { + case Qualifiers::OCL_None: + case Qualifiers::OCL_ExplicitNone: + case Qualifiers::OCL_Autoreleasing: + break; + + case Qualifiers::OCL_Strong: + EmitARCRelease(Builder.CreateLoad(BaseValue, + DestroyedType.isVolatileQualified()), + ARCPreciseLifetime); + break; + + case Qualifiers::OCL_Weak: + EmitARCDestroyWeak(BaseValue); + break; + } + } else { + // C++ [expr.pseudo]p1: + // The result shall only be used as the operand for the function call + // operator (), and the result of such a call has type void. The only + // effect is the evaluation of the postfix-expression before the dot or + // arrow. + EmitIgnoredExpr(E->getBase()); + } + + return RValue::get(nullptr); } static CXXRecordDecl *getCXXRecord(const Expr *E) { @@ -124,8 +176,8 @@ RValue CodeGenFunction::EmitCXXMemberCallExpr(const CXXMemberCallExpr *CE, if (MD->isStatic()) { // The method is static, emit it as we would a regular call. - llvm::Value *Callee = CGM.GetAddrOfFunction(MD); - return EmitCall(getContext().getPointerType(MD->getType()), Callee, CE, + CGCallee callee = CGCallee::forDirect(CGM.GetAddrOfFunction(MD), MD); + return EmitCall(getContext().getPointerType(MD->getType()), callee, CE, ReturnValue); } @@ -251,8 +303,7 @@ RValue CodeGenFunction::EmitCXXMemberOrOperatorMemberCallExpr( // We also don't emit a virtual call if the base expression has a record type // because then we know what the type is. bool UseVirtualCall = CanUseVirtualCall && !DevirtualizedMethod; - llvm::Value *Callee; - + if (const CXXDestructorDecl *Dtor = dyn_cast<CXXDestructorDecl>(MD)) { assert(CE->arg_begin() == CE->arg_end() && "Destructor shouldn't have explicit parameters"); @@ -261,15 +312,19 @@ RValue CodeGenFunction::EmitCXXMemberOrOperatorMemberCallExpr( CGM.getCXXABI().EmitVirtualDestructorCall( *this, Dtor, Dtor_Complete, This, cast<CXXMemberCallExpr>(CE)); } else { + CGCallee Callee; if (getLangOpts().AppleKext && MD->isVirtual() && HasQualifier) Callee = BuildAppleKextVirtualCall(MD, Qualifier, Ty); else if (!DevirtualizedMethod) - Callee = - CGM.getAddrOfCXXStructor(Dtor, StructorType::Complete, FInfo, Ty); + Callee = CGCallee::forDirect( + CGM.getAddrOfCXXStructor(Dtor, StructorType::Complete, FInfo, Ty), + Dtor); else { const CXXDestructorDecl *DDtor = cast<CXXDestructorDecl>(DevirtualizedMethod); - Callee = CGM.GetAddrOfFunction(GlobalDecl(DDtor, Dtor_Complete), Ty); + Callee = CGCallee::forDirect( + CGM.GetAddrOfFunction(GlobalDecl(DDtor, Dtor_Complete), Ty), + DDtor); } EmitCXXMemberOrOperatorCall( CalleeDecl, Callee, ReturnValue, This.getPointer(), @@ -278,8 +333,11 @@ RValue CodeGenFunction::EmitCXXMemberOrOperatorMemberCallExpr( return RValue::get(nullptr); } + CGCallee Callee; if (const CXXConstructorDecl *Ctor = dyn_cast<CXXConstructorDecl>(MD)) { - Callee = CGM.GetAddrOfFunction(GlobalDecl(Ctor, Ctor_Complete), Ty); + Callee = CGCallee::forDirect( + CGM.GetAddrOfFunction(GlobalDecl(Ctor, Ctor_Complete), Ty), + Ctor); } else if (UseVirtualCall) { Callee = CGM.getCXXABI().getVirtualFunctionPointer(*this, MD, This, Ty, CE->getLocStart()); @@ -294,9 +352,11 @@ RValue CodeGenFunction::EmitCXXMemberOrOperatorMemberCallExpr( if (getLangOpts().AppleKext && MD->isVirtual() && HasQualifier) Callee = BuildAppleKextVirtualCall(MD, Qualifier, Ty); else if (!DevirtualizedMethod) - Callee = CGM.GetAddrOfFunction(MD, Ty); + Callee = CGCallee::forDirect(CGM.GetAddrOfFunction(MD, Ty), MD); else { - Callee = CGM.GetAddrOfFunction(DevirtualizedMethod, Ty); + Callee = CGCallee::forDirect( + CGM.GetAddrOfFunction(DevirtualizedMethod, Ty), + DevirtualizedMethod); } } @@ -341,7 +401,7 @@ CodeGenFunction::EmitCXXMemberPointerCallExpr(const CXXMemberCallExpr *E, // Ask the ABI to load the callee. Note that This is modified. llvm::Value *ThisPtrForCall = nullptr; - llvm::Value *Callee = + CGCallee Callee = CGM.getCXXABI().EmitLoadOfMemberFunctionPointer(*this, BO, This, ThisPtrForCall, MemFnPtr, MPT); @@ -1173,23 +1233,24 @@ static void EmitNewInitializer(CodeGenFunction &CGF, const CXXNewExpr *E, /// Emit a call to an operator new or operator delete function, as implicitly /// created by new-expressions and delete-expressions. static RValue EmitNewDeleteCall(CodeGenFunction &CGF, - const FunctionDecl *Callee, + const FunctionDecl *CalleeDecl, const FunctionProtoType *CalleeType, const CallArgList &Args) { llvm::Instruction *CallOrInvoke; - llvm::Value *CalleeAddr = CGF.CGM.GetAddrOfFunction(Callee); + llvm::Constant *CalleePtr = CGF.CGM.GetAddrOfFunction(CalleeDecl); + CGCallee Callee = CGCallee::forDirect(CalleePtr, CalleeDecl); RValue RV = CGF.EmitCall(CGF.CGM.getTypes().arrangeFreeFunctionCall( Args, CalleeType, /*chainCall=*/false), - CalleeAddr, ReturnValueSlot(), Args, Callee, &CallOrInvoke); + Callee, ReturnValueSlot(), Args, &CallOrInvoke); /// C++1y [expr.new]p10: /// [In a new-expression,] an implementation is allowed to omit a call /// to a replaceable global allocation function. /// /// We model such elidable calls with the 'builtin' attribute. - llvm::Function *Fn = dyn_cast<llvm::Function>(CalleeAddr); - if (Callee->isReplaceableGlobalAllocationFunction() && + llvm::Function *Fn = dyn_cast<llvm::Function>(CalleePtr); + if (CalleeDecl->isReplaceableGlobalAllocationFunction() && Fn && Fn->hasFnAttribute(llvm::Attribute::NoBuiltin)) { // FIXME: Add addAttribute to CallSite. if (llvm::CallInst *CI = dyn_cast<llvm::CallInst>(CallOrInvoke)) |