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