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
createCallInstWithColors(FunctionCallee Func,ArrayRef<Value * > Args,const Twine & NameStr,BasicBlock::iterator InsertBefore,const DenseMap<BasicBlock *,ColorVector> & BlockColors)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>
insertAfterInvokes(Function & F,DominatorTree * DT)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
insertRVCall(BasicBlock::iterator InsertPt,CallBase * AnnotatedCall)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
insertRVCallWithColors(BasicBlock::iterator InsertPt,CallBase * AnnotatedCall,const DenseMap<BasicBlock *,ColorVector> & BlockColors)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
~BundledRetainClaimRVs()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