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