Details | Last modification | View Log | RSS feed
| Rev | Author | Line No. | Line |
|---|---|---|---|
| 14 | pmbaty | 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 |