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 /// 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