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
127