xref: /freebsd/contrib/llvm-project/llvm/lib/Transforms/ObjCARC/ObjCARC.cpp (revision 700637cbb5e582861067a11aaca4d053546871d2)
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 
createCallInstWithColors(FunctionCallee Func,ArrayRef<Value * > Args,const Twine & NameStr,BasicBlock::iterator InsertBefore,const DenseMap<BasicBlock *,ColorVector> & BlockColors)24 CallInst *objcarc::createCallInstWithColors(
25     FunctionCallee Func, ArrayRef<Value *> Args, const Twine &NameStr,
26     BasicBlock::iterator 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     BasicBlock::iterator EHPad = CV.front()->getFirstNonPHIIt();
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>
insertAfterInvokes(Function & F,DominatorTree * DT)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 
insertRVCall(BasicBlock::iterator InsertPt,CallBase * AnnotatedCall)74 CallInst *BundledRetainClaimRVs::insertRVCall(BasicBlock::iterator InsertPt,
75                                               CallBase *AnnotatedCall) {
76   DenseMap<BasicBlock *, ColorVector> BlockColors;
77   return insertRVCallWithColors(InsertPt, AnnotatedCall, BlockColors);
78 }
79 
insertRVCallWithColors(BasicBlock::iterator InsertPt,CallBase * AnnotatedCall,const DenseMap<BasicBlock *,ColorVector> & BlockColors)80 CallInst *BundledRetainClaimRVs::insertRVCallWithColors(
81     BasicBlock::iterator InsertPt, CallBase *AnnotatedCall,
82     const DenseMap<BasicBlock *, ColorVector> &BlockColors) {
83   IRBuilder<> Builder(InsertPt->getParent(), 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 
~BundledRetainClaimRVs()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       // We can also do one final optimization: modify the bundle in the
106       // annotated call, to change the bundle operand from
107       //   objc_retainAutoreleasedReturnValue
108       // to:
109       //   objc_claimAutoreleasedReturnValue
110       // allowing the marker to be omitted from the bundle expansion later.
111       //
112       // Note that, confusingly, ClaimRV is semantically equivalent to RetainRV,
113       // and only differs in that it doesn't require the marker.
114       // The bundle provides the guarantee that we're emitting the ClaimRV call
115       // adjacent to the original call, and providing that guarantee is the
116       // only difference between ClaimRV and RetainRV.
117       //
118       // UnsafeClaimRV has a different RC contract entirely.
119 
120       // Find the clang.arc.attachedcall bundle, and rewrite its operand.
121       if (UseClaimRV) {
122         for (auto OBI : CB->bundle_op_infos()) {
123           auto OBU = CB->operandBundleFromBundleOpInfo(OBI);
124           if (OBU.getTagID() == LLVMContext::OB_clang_arc_attachedcall &&
125               OBU.Inputs[0] == EP.get(ARCRuntimeEntryPointKind::RetainRV)) {
126             CB->setOperand(OBI.Begin,
127                            EP.get(ARCRuntimeEntryPointKind::ClaimRV));
128             break;
129           }
130         }
131       }
132     }
133 
134     // Erase the RV call we emitted earlier: it's already in the bundle.
135     EraseInstruction(P.first);
136   }
137 
138   RVCalls.clear();
139 }
140