xref: /freebsd/contrib/llvm-project/llvm/lib/Transforms/ObjCARC/ObjCARC.cpp (revision 8ddb146abcdf061be9f2c0db7e391697dafad85c)
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.
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 
42 void LLVMInitializeObjCARCOpts(LLVMPassRegistryRef R) {
43   initializeObjCARCOpts(*unwrap(R));
44 }
45 
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>
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 
96 CallInst *BundledRetainClaimRVs::insertRVCall(Instruction *InsertPt,
97                                               CallBase *AnnotatedCall) {
98   DenseMap<BasicBlock *, ColorVector> BlockColors;
99   return insertRVCallWithColors(InsertPt, AnnotatedCall, BlockColors);
100 }
101 
102 CallInst *BundledRetainClaimRVs::insertRVCallWithColors(
103     Instruction *InsertPt, CallBase *AnnotatedCall,
104     const DenseMap<BasicBlock *, ColorVector> &BlockColors) {
105   IRBuilder<> Builder(InsertPt);
106   Function *Func = *objcarc::getAttachedARCFunction(AnnotatedCall);
107   assert(Func && "operand isn't a Function");
108   Type *ParamTy = Func->getArg(0)->getType();
109   Value *CallArg = Builder.CreateBitCast(AnnotatedCall, ParamTy);
110   auto *Call =
111       createCallInstWithColors(Func, CallArg, "", InsertPt, BlockColors);
112   RVCalls[Call] = AnnotatedCall;
113   return Call;
114 }
115 
116 BundledRetainClaimRVs::~BundledRetainClaimRVs() {
117   for (auto P : RVCalls) {
118     if (ContractPass) {
119       CallBase *CB = P.second;
120       // At this point, we know that the annotated calls can't be tail calls
121       // as they are followed by marker instructions and retainRV/claimRV
122       // calls. Mark them as notail so that the backend knows these calls
123       // can't be tail calls.
124       if (auto *CI = dyn_cast<CallInst>(CB))
125         CI->setTailCallKind(CallInst::TCK_NoTail);
126     }
127 
128     EraseInstruction(P.first);
129   }
130 
131   RVCalls.clear();
132 }
133