1 | //===- ObjCARC.h - ObjC ARC Optimization --------------*- C++ -*-----------===// |
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 | /// \file |
9 | /// This file defines common definitions/declarations used by the ObjC ARC |
10 | /// Optimizer. ARC stands for Automatic Reference Counting and is a system for |
11 | /// managing reference counts for objects in Objective C. |
12 | /// |
13 | /// WARNING: This file knows about certain library functions. It recognizes them |
14 | /// by name, and hardwires knowledge of their semantics. |
15 | /// |
16 | /// WARNING: This file knows about how certain Objective-C library functions are |
17 | /// used. Naive LLVM IR transformations which would otherwise be |
18 | /// behavior-preserving may break these assumptions. |
19 | /// |
20 | //===----------------------------------------------------------------------===// |
21 | |
22 | #ifndef LLVM_LIB_TRANSFORMS_OBJCARC_OBJCARC_H |
23 | #define LLVM_LIB_TRANSFORMS_OBJCARC_OBJCARC_H |
24 | |
25 | #include "ARCRuntimeEntryPoints.h" |
26 | #include "llvm/Analysis/ObjCARCAnalysisUtils.h" |
27 | #include "llvm/Analysis/ObjCARCUtil.h" |
28 | #include "llvm/IR/EHPersonalities.h" |
29 | #include "llvm/Transforms/Utils/Local.h" |
30 | |
31 | namespace llvm { |
32 | namespace objcarc { |
33 | |
34 | /// Erase the given instruction. |
35 | /// |
36 | /// Many ObjC calls return their argument verbatim, |
37 | /// so if it's such a call and the return value has users, replace them with the |
38 | /// argument value. |
39 | /// |
40 | static inline void EraseInstruction(Instruction *CI) { |
41 | Value *OldArg = cast<CallInst>(Val: CI)->getArgOperand(i: 0); |
42 | |
43 | bool Unused = CI->use_empty(); |
44 | |
45 | if (!Unused) { |
46 | // Replace the return value with the argument. |
47 | assert((IsForwarding(GetBasicARCInstKind(CI)) || |
48 | (IsNoopOnNull(GetBasicARCInstKind(CI)) && |
49 | IsNullOrUndef(OldArg->stripPointerCasts()))) && |
50 | "Can't delete non-forwarding instruction with users!" ); |
51 | CI->replaceAllUsesWith(V: OldArg); |
52 | } |
53 | |
54 | CI->eraseFromParent(); |
55 | |
56 | if (Unused) |
57 | RecursivelyDeleteTriviallyDeadInstructions(V: OldArg); |
58 | } |
59 | |
60 | /// If Inst is a ReturnRV and its operand is a call or invoke, return the |
61 | /// operand. Otherwise return null. |
62 | static inline const Instruction *getreturnRVOperand(const Instruction &Inst, |
63 | ARCInstKind Class) { |
64 | if (Class != ARCInstKind::RetainRV) |
65 | return nullptr; |
66 | |
67 | const auto *Opnd = Inst.getOperand(i: 0)->stripPointerCasts(); |
68 | if (const auto *C = dyn_cast<CallInst>(Val: Opnd)) |
69 | return C; |
70 | return dyn_cast<InvokeInst>(Val: Opnd); |
71 | } |
72 | |
73 | /// Return the list of PHI nodes that are equivalent to PN. |
74 | template<class PHINodeTy, class VectorTy> |
75 | void getEquivalentPHIs(PHINodeTy &PN, VectorTy &PHIList) { |
76 | auto *BB = PN.getParent(); |
77 | for (auto &P : BB->phis()) { |
78 | if (&P == &PN) // Do not add PN to the list. |
79 | continue; |
80 | unsigned I = 0, E = PN.getNumIncomingValues(); |
81 | for (; I < E; ++I) { |
82 | auto *BB = PN.getIncomingBlock(I); |
83 | auto *PNOpnd = PN.getIncomingValue(I)->stripPointerCasts(); |
84 | auto *POpnd = P.getIncomingValueForBlock(BB)->stripPointerCasts(); |
85 | if (PNOpnd != POpnd) |
86 | break; |
87 | } |
88 | if (I == E) |
89 | PHIList.push_back(&P); |
90 | } |
91 | } |
92 | |
93 | static inline MDString *getRVInstMarker(Module &M) { |
94 | const char *MarkerKey = getRVMarkerModuleFlagStr(); |
95 | return dyn_cast_or_null<MDString>(Val: M.getModuleFlag(Key: MarkerKey)); |
96 | } |
97 | |
98 | /// Create a call instruction with the correct funclet token. This should be |
99 | /// called instead of calling CallInst::Create directly unless the call is |
100 | /// going to be removed from the IR before WinEHPrepare. |
101 | CallInst *createCallInstWithColors( |
102 | FunctionCallee Func, ArrayRef<Value *> Args, const Twine &NameStr, |
103 | BasicBlock::iterator InsertBefore, |
104 | const DenseMap<BasicBlock *, ColorVector> &BlockColors); |
105 | |
106 | class BundledRetainClaimRVs { |
107 | public: |
108 | BundledRetainClaimRVs(ARCRuntimeEntryPoints &EP, bool ContractPass, |
109 | bool UseClaimRV) |
110 | : EP(EP), ContractPass(ContractPass), UseClaimRV(UseClaimRV) {} |
111 | ~BundledRetainClaimRVs(); |
112 | |
113 | /// Insert a retainRV/claimRV call to the normal destination blocks of invokes |
114 | /// with operand bundle "clang.arc.attachedcall". If the edge to the normal |
115 | /// destination block is a critical edge, split it. |
116 | std::pair<bool, bool> insertAfterInvokes(Function &F, DominatorTree *DT); |
117 | |
118 | /// Insert a retainRV/claimRV call. |
119 | CallInst *insertRVCall(BasicBlock::iterator InsertPt, |
120 | CallBase *AnnotatedCall); |
121 | |
122 | /// Insert a retainRV/claimRV call with colors. |
123 | CallInst *insertRVCallWithColors( |
124 | BasicBlock::iterator InsertPt, CallBase *AnnotatedCall, |
125 | const DenseMap<BasicBlock *, ColorVector> &BlockColors); |
126 | |
127 | /// See if an instruction is a bundled retainRV/claimRV call. |
128 | bool contains(const Instruction *I) const { |
129 | if (auto *CI = dyn_cast<CallInst>(Val: I)) |
130 | return RVCalls.count(Val: CI); |
131 | return false; |
132 | } |
133 | |
134 | /// Remove a retainRV/claimRV call entirely. |
135 | void eraseInst(CallInst *CI) { |
136 | auto It = RVCalls.find(Val: CI); |
137 | if (It != RVCalls.end()) { |
138 | // Remove call to @llvm.objc.clang.arc.noop.use. |
139 | for (User *U : It->second->users()) |
140 | if (auto *CI = dyn_cast<CallInst>(Val: U)) |
141 | if (CI->getIntrinsicID() == Intrinsic::objc_clang_arc_noop_use) { |
142 | CI->eraseFromParent(); |
143 | break; |
144 | } |
145 | |
146 | auto *NewCall = CallBase::removeOperandBundle( |
147 | CB: It->second, ID: LLVMContext::OB_clang_arc_attachedcall, |
148 | InsertPt: It->second->getIterator()); |
149 | NewCall->copyMetadata(SrcInst: *It->second); |
150 | It->second->replaceAllUsesWith(V: NewCall); |
151 | It->second->eraseFromParent(); |
152 | RVCalls.erase(I: It); |
153 | } |
154 | EraseInstruction(CI); |
155 | } |
156 | |
157 | private: |
158 | /// A map of inserted retainRV/claimRV calls to annotated calls/invokes. |
159 | DenseMap<CallInst *, CallBase *> RVCalls; |
160 | |
161 | ARCRuntimeEntryPoints &EP; |
162 | bool ContractPass; |
163 | bool UseClaimRV; |
164 | }; |
165 | |
166 | } // end namespace objcarc |
167 | } // end namespace llvm |
168 | |
169 | #endif |
170 | |