xref: /freebsd-src/contrib/llvm-project/llvm/lib/Transforms/ObjCARC/ObjCARC.cpp (revision 0fca6ea1d4eea4c934cfff25ac9ee8ad6fe95583)
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