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