Home | History | Annotate | Line # | Download | only in Analysis
      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   ClaimRV,                  ///< 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