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