1 //===- ObjCARCInstKind.h - ARC instruction equivalence classes --*- C++ -*-===//
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
7 //===----------------------------------------------------------------------===//
9 #ifndef LLVM_ANALYSIS_OBJCARCINSTKIND_H
10 #define LLVM_ANALYSIS_OBJCARCINSTKIND_H
12 #include "llvm/IR/Function.h"
13 #include "llvm/IR/Intrinsics.h"
14 #include "llvm/IR/Instructions.h"
21 /// Equivalence classes of instructions in the ARC Model.
23 /// Since we do not have "instructions" to represent ARC concepts in LLVM IR,
24 /// we instead operate on equivalence classes of instructions.
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)
51 IntrinsicUser
, ///< llvm.objc.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.
58 raw_ostream
&operator<<(raw_ostream
&OS
, const ARCInstKind Class
);
60 /// Test if the given class is a kind of user.
61 bool IsUser(ARCInstKind Class
);
63 /// Test if the given class is objc_retain or equivalent.
64 bool IsRetain(ARCInstKind Class
);
66 /// Test if the given class is objc_autorelease or equivalent.
67 bool IsAutorelease(ARCInstKind Class
);
69 /// Test if the given class represents instructions which return their
70 /// argument verbatim.
71 bool IsForwarding(ARCInstKind Class
);
73 /// Test if the given class represents instructions which do nothing if
74 /// passed a null pointer.
75 bool IsNoopOnNull(ARCInstKind Class
);
77 /// Test if the given class represents instructions which do nothing if
78 /// passed a global variable.
79 bool IsNoopOnGlobal(ARCInstKind Class
);
81 /// Test if the given class represents instructions which are always safe
82 /// to mark with the "tail" keyword.
83 bool IsAlwaysTail(ARCInstKind Class
);
85 /// Test if the given class represents instructions which are never safe
86 /// to mark with the "tail" keyword.
87 bool IsNeverTail(ARCInstKind Class
);
89 /// Test if the given class represents instructions which are always safe
90 /// to mark with the nounwind attribute.
91 bool IsNoThrow(ARCInstKind Class
);
93 /// Test whether the given instruction can autorelease any pointer or cause an
94 /// autoreleasepool pop.
95 bool CanInterruptRV(ARCInstKind Class
);
97 /// Determine if F is one of the special known Functions. If it isn't,
98 /// return ARCInstKind::CallOrUser.
99 ARCInstKind
GetFunctionClass(const Function
*F
);
101 /// Determine which objc runtime call instruction class V belongs to.
103 /// This is similar to GetARCInstKind except that it only detects objc
104 /// runtime calls. This allows it to be faster.
106 inline ARCInstKind
GetBasicARCInstKind(const Value
*V
) {
107 if (const CallInst
*CI
= dyn_cast
<CallInst
>(V
)) {
108 if (const Function
*F
= CI
->getCalledFunction())
109 return GetFunctionClass(F
);
110 // Otherwise, be conservative.
111 return ARCInstKind::CallOrUser
;
114 // Otherwise, be conservative.
115 return isa
<InvokeInst
>(V
) ? ARCInstKind::CallOrUser
: ARCInstKind::User
;
118 /// Map V to its ARCInstKind equivalence class.
119 ARCInstKind
GetARCInstKind(const Value
*V
);
121 /// Returns false if conservatively we can prove that any instruction mapped to
122 /// this kind can not decrement ref counts. Returns true otherwise.
123 bool CanDecrementRefCount(ARCInstKind Kind
);
125 } // end namespace objcarc
126 } // end namespace llvm