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