Andrew Scull | 5e1ddfa | 2018-08-14 10:06:54 +0100 | [diff] [blame] | 1 | //===- ObjCARCInstKind.h - ARC instruction equivalence classes --*- C++ -*-===// |
| 2 | // |
Andrew Walbran | 16937d0 | 2019-10-22 13:54:20 +0100 | [diff] [blame] | 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 |
Andrew Scull | 5e1ddfa | 2018-08-14 10:06:54 +0100 | [diff] [blame] | 6 | // |
| 7 | //===----------------------------------------------------------------------===// |
| 8 | |
| 9 | #ifndef LLVM_ANALYSIS_OBJCARCINSTKIND_H |
| 10 | #define LLVM_ANALYSIS_OBJCARCINSTKIND_H |
| 11 | |
| 12 | #include "llvm/IR/Function.h" |
Andrew Walbran | 16937d0 | 2019-10-22 13:54:20 +0100 | [diff] [blame] | 13 | #include "llvm/IR/Intrinsics.h" |
Andrew Scull | 5e1ddfa | 2018-08-14 10:06:54 +0100 | [diff] [blame] | 14 | #include "llvm/IR/Instructions.h" |
| 15 | |
| 16 | namespace llvm { |
| 17 | namespace objcarc { |
| 18 | |
| 19 | /// \enum ARCInstKind |
| 20 | /// |
Andrew Scull | cdfcccc | 2018-10-05 20:58:37 +0100 | [diff] [blame] | 21 | /// Equivalence classes of instructions in the ARC Model. |
Andrew Scull | 5e1ddfa | 2018-08-14 10:06:54 +0100 | [diff] [blame] | 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 | 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) |
Andrew Walbran | 16937d0 | 2019-10-22 13:54:20 +0100 | [diff] [blame] | 51 | IntrinsicUser, ///< llvm.objc.clang.arc.use |
Andrew Scull | 5e1ddfa | 2018-08-14 10:06:54 +0100 | [diff] [blame] | 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 | |
| 58 | raw_ostream &operator<<(raw_ostream &OS, const ARCInstKind Class); |
| 59 | |
Andrew Scull | cdfcccc | 2018-10-05 20:58:37 +0100 | [diff] [blame] | 60 | /// Test if the given class is a kind of user. |
Andrew Scull | 5e1ddfa | 2018-08-14 10:06:54 +0100 | [diff] [blame] | 61 | bool IsUser(ARCInstKind Class); |
| 62 | |
Andrew Scull | cdfcccc | 2018-10-05 20:58:37 +0100 | [diff] [blame] | 63 | /// Test if the given class is objc_retain or equivalent. |
Andrew Scull | 5e1ddfa | 2018-08-14 10:06:54 +0100 | [diff] [blame] | 64 | bool IsRetain(ARCInstKind Class); |
| 65 | |
Andrew Scull | cdfcccc | 2018-10-05 20:58:37 +0100 | [diff] [blame] | 66 | /// Test if the given class is objc_autorelease or equivalent. |
Andrew Scull | 5e1ddfa | 2018-08-14 10:06:54 +0100 | [diff] [blame] | 67 | bool IsAutorelease(ARCInstKind Class); |
| 68 | |
Andrew Scull | cdfcccc | 2018-10-05 20:58:37 +0100 | [diff] [blame] | 69 | /// Test if the given class represents instructions which return their |
Andrew Scull | 5e1ddfa | 2018-08-14 10:06:54 +0100 | [diff] [blame] | 70 | /// argument verbatim. |
| 71 | bool IsForwarding(ARCInstKind Class); |
| 72 | |
Andrew Scull | cdfcccc | 2018-10-05 20:58:37 +0100 | [diff] [blame] | 73 | /// Test if the given class represents instructions which do nothing if |
Andrew Scull | 5e1ddfa | 2018-08-14 10:06:54 +0100 | [diff] [blame] | 74 | /// passed a null pointer. |
| 75 | bool IsNoopOnNull(ARCInstKind Class); |
| 76 | |
Andrew Scull | cdfcccc | 2018-10-05 20:58:37 +0100 | [diff] [blame] | 77 | /// Test if the given class represents instructions which are always safe |
Andrew Scull | 5e1ddfa | 2018-08-14 10:06:54 +0100 | [diff] [blame] | 78 | /// to mark with the "tail" keyword. |
| 79 | bool IsAlwaysTail(ARCInstKind Class); |
| 80 | |
Andrew Scull | cdfcccc | 2018-10-05 20:58:37 +0100 | [diff] [blame] | 81 | /// Test if the given class represents instructions which are never safe |
Andrew Scull | 5e1ddfa | 2018-08-14 10:06:54 +0100 | [diff] [blame] | 82 | /// to mark with the "tail" keyword. |
| 83 | bool IsNeverTail(ARCInstKind Class); |
| 84 | |
Andrew Scull | cdfcccc | 2018-10-05 20:58:37 +0100 | [diff] [blame] | 85 | /// Test if the given class represents instructions which are always safe |
Andrew Scull | 5e1ddfa | 2018-08-14 10:06:54 +0100 | [diff] [blame] | 86 | /// to mark with the nounwind attribute. |
| 87 | bool IsNoThrow(ARCInstKind Class); |
| 88 | |
| 89 | /// Test whether the given instruction can autorelease any pointer or cause an |
| 90 | /// autoreleasepool pop. |
| 91 | bool CanInterruptRV(ARCInstKind Class); |
| 92 | |
Andrew Scull | cdfcccc | 2018-10-05 20:58:37 +0100 | [diff] [blame] | 93 | /// Determine if F is one of the special known Functions. If it isn't, |
Andrew Scull | 5e1ddfa | 2018-08-14 10:06:54 +0100 | [diff] [blame] | 94 | /// return ARCInstKind::CallOrUser. |
| 95 | ARCInstKind GetFunctionClass(const Function *F); |
| 96 | |
Andrew Scull | cdfcccc | 2018-10-05 20:58:37 +0100 | [diff] [blame] | 97 | /// Determine which objc runtime call instruction class V belongs to. |
Andrew Scull | 5e1ddfa | 2018-08-14 10:06:54 +0100 | [diff] [blame] | 98 | /// |
| 99 | /// This is similar to GetARCInstKind except that it only detects objc |
| 100 | /// runtime calls. This allows it to be faster. |
| 101 | /// |
| 102 | inline 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. |
| 115 | ARCInstKind 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. |
| 119 | bool CanDecrementRefCount(ARCInstKind Kind); |
| 120 | |
| 121 | } // end namespace objcarc |
| 122 | } // end namespace llvm |
| 123 | |
| 124 | #endif |