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 |