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