1 //===-- ObjCARC.cpp -------------------------------------------------------===// 2 // 3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 // See https://llvm.org/LICENSE.txt for license information. 5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 // 7 //===----------------------------------------------------------------------===// 8 // 9 // This file implements common infrastructure for libLLVMObjCARCOpts.a, which 10 // implements several scalar transformations over the LLVM intermediate 11 // representation, including the C bindings for that library. 12 // 13 //===----------------------------------------------------------------------===// 14 15 #include "ObjCARC.h" 16 #include "llvm/Analysis/ObjCARCUtil.h" 17 #include "llvm/IR/IRBuilder.h" 18 #include "llvm/IR/Instructions.h" 19 #include "llvm/Transforms/Utils/BasicBlockUtils.h" 20 21 using namespace llvm; 22 using namespace llvm::objcarc; 23 24 CallInst *objcarc::createCallInstWithColors( 25 FunctionCallee Func, ArrayRef<Value *> Args, const Twine &NameStr, 26 Instruction *InsertBefore, 27 const DenseMap<BasicBlock *, ColorVector> &BlockColors) { 28 FunctionType *FTy = Func.getFunctionType(); 29 Value *Callee = Func.getCallee(); 30 SmallVector<OperandBundleDef, 1> OpBundles; 31 32 if (!BlockColors.empty()) { 33 const ColorVector &CV = BlockColors.find(InsertBefore->getParent())->second; 34 assert(CV.size() == 1 && "non-unique color for block!"); 35 Instruction *EHPad = CV.front()->getFirstNonPHI(); 36 if (EHPad->isEHPad()) 37 OpBundles.emplace_back("funclet", EHPad); 38 } 39 40 return CallInst::Create(FTy, Callee, Args, OpBundles, NameStr, InsertBefore); 41 } 42 43 std::pair<bool, bool> 44 BundledRetainClaimRVs::insertAfterInvokes(Function &F, DominatorTree *DT) { 45 bool Changed = false, CFGChanged = false; 46 47 for (BasicBlock &BB : F) { 48 auto *I = dyn_cast<InvokeInst>(BB.getTerminator()); 49 50 if (!I) 51 continue; 52 53 if (!objcarc::hasAttachedCallOpBundle(I)) 54 continue; 55 56 BasicBlock *DestBB = I->getNormalDest(); 57 58 if (!DestBB->getSinglePredecessor()) { 59 assert(I->getSuccessor(0) == DestBB && 60 "the normal dest is expected to be the first successor"); 61 DestBB = SplitCriticalEdge(I, 0, CriticalEdgeSplittingOptions(DT)); 62 CFGChanged = true; 63 } 64 65 // We don't have to call insertRVCallWithColors since DestBB is the normal 66 // destination of the invoke. 67 insertRVCall(&*DestBB->getFirstInsertionPt(), I); 68 Changed = true; 69 } 70 71 return std::make_pair(Changed, CFGChanged); 72 } 73 74 CallInst *BundledRetainClaimRVs::insertRVCall(Instruction *InsertPt, 75 CallBase *AnnotatedCall) { 76 DenseMap<BasicBlock *, ColorVector> BlockColors; 77 return insertRVCallWithColors(InsertPt, AnnotatedCall, BlockColors); 78 } 79 80 CallInst *BundledRetainClaimRVs::insertRVCallWithColors( 81 Instruction *InsertPt, CallBase *AnnotatedCall, 82 const DenseMap<BasicBlock *, ColorVector> &BlockColors) { 83 IRBuilder<> Builder(InsertPt); 84 Function *Func = *objcarc::getAttachedARCFunction(AnnotatedCall); 85 assert(Func && "operand isn't a Function"); 86 Type *ParamTy = Func->getArg(0)->getType(); 87 Value *CallArg = Builder.CreateBitCast(AnnotatedCall, ParamTy); 88 auto *Call = 89 createCallInstWithColors(Func, CallArg, "", InsertPt, BlockColors); 90 RVCalls[Call] = AnnotatedCall; 91 return Call; 92 } 93 94 BundledRetainClaimRVs::~BundledRetainClaimRVs() { 95 for (auto P : RVCalls) { 96 if (ContractPass) { 97 CallBase *CB = P.second; 98 // At this point, we know that the annotated calls can't be tail calls 99 // as they are followed by marker instructions and retainRV/claimRV 100 // calls. Mark them as notail so that the backend knows these calls 101 // can't be tail calls. 102 if (auto *CI = dyn_cast<CallInst>(CB)) 103 CI->setTailCallKind(CallInst::TCK_NoTail); 104 } 105 106 EraseInstruction(P.first); 107 } 108 109 RVCalls.clear(); 110 } 111