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-c/Initialization.h"
17 #include "llvm/Analysis/ObjCARCUtil.h"
18 #include "llvm/IR/IRBuilder.h"
19 #include "llvm/IR/InlineAsm.h"
20 #include "llvm/IR/Instructions.h"
21 #include "llvm/InitializePasses.h"
22 #include "llvm/Transforms/Utils/BasicBlockUtils.h"
23 
24 namespace llvm {
25   class PassRegistry;
26 }
27 
28 using namespace llvm;
29 using namespace llvm::objcarc;
30 
31 /// initializeObjCARCOptsPasses - Initialize all passes linked into the
32 /// ObjCARCOpts library.
initializeObjCARCOpts(PassRegistry & Registry)33 void llvm::initializeObjCARCOpts(PassRegistry &Registry) {
34   initializeObjCARCAAWrapperPassPass(Registry);
35   initializeObjCARCAPElimPass(Registry);
36   initializeObjCARCExpandPass(Registry);
37   initializeObjCARCContractLegacyPassPass(Registry);
38   initializeObjCARCOptLegacyPassPass(Registry);
39   initializePAEvalPass(Registry);
40 }
41 
LLVMInitializeObjCARCOpts(LLVMPassRegistryRef R)42 void LLVMInitializeObjCARCOpts(LLVMPassRegistryRef R) {
43   initializeObjCARCOpts(*unwrap(R));
44 }
45 
createCallInstWithColors(FunctionCallee Func,ArrayRef<Value * > Args,const Twine & NameStr,Instruction * InsertBefore,const DenseMap<BasicBlock *,ColorVector> & BlockColors)46 CallInst *objcarc::createCallInstWithColors(
47     FunctionCallee Func, ArrayRef<Value *> Args, const Twine &NameStr,
48     Instruction *InsertBefore,
49     const DenseMap<BasicBlock *, ColorVector> &BlockColors) {
50   FunctionType *FTy = Func.getFunctionType();
51   Value *Callee = Func.getCallee();
52   SmallVector<OperandBundleDef, 1> OpBundles;
53 
54   if (!BlockColors.empty()) {
55     const ColorVector &CV = BlockColors.find(InsertBefore->getParent())->second;
56     assert(CV.size() == 1 && "non-unique color for block!");
57     Instruction *EHPad = CV.front()->getFirstNonPHI();
58     if (EHPad->isEHPad())
59       OpBundles.emplace_back("funclet", EHPad);
60   }
61 
62   return CallInst::Create(FTy, Callee, Args, OpBundles, NameStr, InsertBefore);
63 }
64 
65 std::pair<bool, bool>
insertAfterInvokes(Function & F,DominatorTree * DT)66 BundledRetainClaimRVs::insertAfterInvokes(Function &F, DominatorTree *DT) {
67   bool Changed = false, CFGChanged = false;
68 
69   for (BasicBlock &BB : F) {
70     auto *I = dyn_cast<InvokeInst>(BB.getTerminator());
71 
72     if (!I)
73       continue;
74 
75     if (!objcarc::hasAttachedCallOpBundle(I))
76       continue;
77 
78     BasicBlock *DestBB = I->getNormalDest();
79 
80     if (!DestBB->getSinglePredecessor()) {
81       assert(I->getSuccessor(0) == DestBB &&
82              "the normal dest is expected to be the first successor");
83       DestBB = SplitCriticalEdge(I, 0, CriticalEdgeSplittingOptions(DT));
84       CFGChanged = true;
85     }
86 
87     // We don't have to call insertRVCallWithColors since DestBB is the normal
88     // destination of the invoke.
89     insertRVCall(&*DestBB->getFirstInsertionPt(), I);
90     Changed = true;
91   }
92 
93   return std::make_pair(Changed, CFGChanged);
94 }
95 
insertRVCall(Instruction * InsertPt,CallBase * AnnotatedCall)96 CallInst *BundledRetainClaimRVs::insertRVCall(Instruction *InsertPt,
97                                               CallBase *AnnotatedCall) {
98   DenseMap<BasicBlock *, ColorVector> BlockColors;
99   return insertRVCallWithColors(InsertPt, AnnotatedCall, BlockColors);
100 }
101 
insertRVCallWithColors(Instruction * InsertPt,CallBase * AnnotatedCall,const DenseMap<BasicBlock *,ColorVector> & BlockColors)102 CallInst *BundledRetainClaimRVs::insertRVCallWithColors(
103     Instruction *InsertPt, CallBase *AnnotatedCall,
104     const DenseMap<BasicBlock *, ColorVector> &BlockColors) {
105   IRBuilder<> Builder(InsertPt);
106   bool IsRetainRV = objcarc::hasAttachedCallOpBundle(AnnotatedCall, true);
107   Function *Func = EP.get(IsRetainRV ? ARCRuntimeEntryPointKind::RetainRV
108                                      : ARCRuntimeEntryPointKind::ClaimRV);
109   Type *ParamTy = Func->getArg(0)->getType();
110   Value *CallArg = Builder.CreateBitCast(AnnotatedCall, ParamTy);
111   auto *Call =
112       createCallInstWithColors(Func, CallArg, "", InsertPt, BlockColors);
113   RVCalls[Call] = AnnotatedCall;
114   return Call;
115 }
116 
~BundledRetainClaimRVs()117 BundledRetainClaimRVs::~BundledRetainClaimRVs() {
118   if (ContractPass) {
119     // At this point, we know that the annotated calls can't be tail calls as
120     // they are followed by marker instructions and retainRV/claimRV calls. Mark
121     // them as notail, so that the backend knows these calls can't be tail
122     // calls.
123     for (auto P : RVCalls)
124       if (auto *CI = dyn_cast<CallInst>(P.second))
125         CI->setTailCallKind(CallInst::TCK_NoTail);
126   } else {
127     for (auto P : RVCalls)
128       EraseInstruction(P.first);
129   }
130 
131   RVCalls.clear();
132 }
133