Details | Last modification | View Log | RSS feed
Rev | Author | Line No. | Line |
---|---|---|---|
14 | pmbaty | 1 | //===- ObjCARCInstKind.h - ARC instruction equivalence classes --*- 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 | |||
9 | #ifndef LLVM_ANALYSIS_OBJCARCINSTKIND_H |
||
10 | #define LLVM_ANALYSIS_OBJCARCINSTKIND_H |
||
11 | |||
12 | #include "llvm/IR/Instructions.h" |
||
13 | |||
14 | namespace llvm { |
||
15 | namespace objcarc { |
||
16 | |||
17 | /// \enum ARCInstKind |
||
18 | /// |
||
19 | /// Equivalence classes of instructions in the ARC Model. |
||
20 | /// |
||
21 | /// Since we do not have "instructions" to represent ARC concepts in LLVM IR, |
||
22 | /// we instead operate on equivalence classes of instructions. |
||
23 | /// |
||
24 | /// TODO: This should be split into two enums: a runtime entry point enum |
||
25 | /// (possibly united with the ARCRuntimeEntrypoint class) and an enum that deals |
||
26 | /// with effects of instructions in the ARC model (which would handle the notion |
||
27 | /// of a User or CallOrUser). |
||
28 | enum class ARCInstKind { |
||
29 | Retain, ///< objc_retain |
||
30 | RetainRV, ///< objc_retainAutoreleasedReturnValue |
||
31 | UnsafeClaimRV, ///< objc_unsafeClaimAutoreleasedReturnValue |
||
32 | RetainBlock, ///< objc_retainBlock |
||
33 | Release, ///< objc_release |
||
34 | Autorelease, ///< objc_autorelease |
||
35 | AutoreleaseRV, ///< objc_autoreleaseReturnValue |
||
36 | AutoreleasepoolPush, ///< objc_autoreleasePoolPush |
||
37 | AutoreleasepoolPop, ///< objc_autoreleasePoolPop |
||
38 | NoopCast, ///< objc_retainedObject, etc. |
||
39 | FusedRetainAutorelease, ///< objc_retainAutorelease |
||
40 | FusedRetainAutoreleaseRV, ///< objc_retainAutoreleaseReturnValue |
||
41 | LoadWeakRetained, ///< objc_loadWeakRetained (primitive) |
||
42 | StoreWeak, ///< objc_storeWeak (primitive) |
||
43 | InitWeak, ///< objc_initWeak (derived) |
||
44 | LoadWeak, ///< objc_loadWeak (derived) |
||
45 | MoveWeak, ///< objc_moveWeak (derived) |
||
46 | CopyWeak, ///< objc_copyWeak (derived) |
||
47 | DestroyWeak, ///< objc_destroyWeak (derived) |
||
48 | StoreStrong, ///< objc_storeStrong (derived) |
||
49 | IntrinsicUser, ///< llvm.objc.clang.arc.use |
||
50 | CallOrUser, ///< could call objc_release and/or "use" pointers |
||
51 | Call, ///< could call objc_release |
||
52 | User, ///< could "use" a pointer |
||
53 | None ///< anything that is inert from an ARC perspective. |
||
54 | }; |
||
55 | |||
56 | raw_ostream &operator<<(raw_ostream &OS, const ARCInstKind Class); |
||
57 | |||
58 | /// Test if the given class is a kind of user. |
||
59 | bool IsUser(ARCInstKind Class); |
||
60 | |||
61 | /// Test if the given class is objc_retain or equivalent. |
||
62 | bool IsRetain(ARCInstKind Class); |
||
63 | |||
64 | /// Test if the given class is objc_autorelease or equivalent. |
||
65 | bool IsAutorelease(ARCInstKind Class); |
||
66 | |||
67 | /// Test if the given class represents instructions which return their |
||
68 | /// argument verbatim. |
||
69 | bool IsForwarding(ARCInstKind Class); |
||
70 | |||
71 | /// Test if the given class represents instructions which do nothing if |
||
72 | /// passed a null pointer. |
||
73 | bool IsNoopOnNull(ARCInstKind Class); |
||
74 | |||
75 | /// Test if the given class represents instructions which do nothing if |
||
76 | /// passed a global variable. |
||
77 | bool IsNoopOnGlobal(ARCInstKind Class); |
||
78 | |||
79 | /// Test if the given class represents instructions which are always safe |
||
80 | /// to mark with the "tail" keyword. |
||
81 | bool IsAlwaysTail(ARCInstKind Class); |
||
82 | |||
83 | /// Test if the given class represents instructions which are never safe |
||
84 | /// to mark with the "tail" keyword. |
||
85 | bool IsNeverTail(ARCInstKind Class); |
||
86 | |||
87 | /// Test if the given class represents instructions which are always safe |
||
88 | /// to mark with the nounwind attribute. |
||
89 | bool IsNoThrow(ARCInstKind Class); |
||
90 | |||
91 | /// Test whether the given instruction can autorelease any pointer or cause an |
||
92 | /// autoreleasepool pop. |
||
93 | bool CanInterruptRV(ARCInstKind Class); |
||
94 | |||
95 | /// Determine if F is one of the special known Functions. If it isn't, |
||
96 | /// return ARCInstKind::CallOrUser. |
||
97 | ARCInstKind GetFunctionClass(const Function *F); |
||
98 | |||
99 | /// Determine which objc runtime call instruction class V belongs to. |
||
100 | /// |
||
101 | /// This is similar to GetARCInstKind except that it only detects objc |
||
102 | /// runtime calls. This allows it to be faster. |
||
103 | /// |
||
104 | inline ARCInstKind GetBasicARCInstKind(const Value *V) { |
||
105 | if (const CallInst *CI = dyn_cast<CallInst>(V)) { |
||
106 | if (const Function *F = CI->getCalledFunction()) |
||
107 | return GetFunctionClass(F); |
||
108 | // Otherwise, be conservative. |
||
109 | return ARCInstKind::CallOrUser; |
||
110 | } |
||
111 | |||
112 | // Otherwise, be conservative. |
||
113 | return isa<InvokeInst>(V) ? ARCInstKind::CallOrUser : ARCInstKind::User; |
||
114 | } |
||
115 | |||
116 | /// Map V to its ARCInstKind equivalence class. |
||
117 | ARCInstKind GetARCInstKind(const Value *V); |
||
118 | |||
119 | /// Returns false if conservatively we can prove that any instruction mapped to |
||
120 | /// this kind can not decrement ref counts. Returns true otherwise. |
||
121 | bool CanDecrementRefCount(ARCInstKind Kind); |
||
122 | |||
123 | } // end namespace objcarc |
||
124 | } // end namespace llvm |
||
125 | |||
126 | #endif |