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
14namespace llvm {
15namespace 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).
28enum 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
56raw_ostream &operator<<(raw_ostream &OS, const ARCInstKind Class);
57
58/// Test if the given class is a kind of user.
59bool IsUser(ARCInstKind Class);
60
61/// Test if the given class is objc_retain or equivalent.
62bool IsRetain(ARCInstKind Class);
63
64/// Test if the given class is objc_autorelease or equivalent.
65bool IsAutorelease(ARCInstKind Class);
66
67/// Test if the given class represents instructions which return their
68/// argument verbatim.
69bool IsForwarding(ARCInstKind Class);
70
71/// Test if the given class represents instructions which do nothing if
72/// passed a null pointer.
73bool IsNoopOnNull(ARCInstKind Class);
74
75/// Test if the given class represents instructions which do nothing if
76/// passed a global variable.
77bool IsNoopOnGlobal(ARCInstKind Class);
78
79/// Test if the given class represents instructions which are always safe
80/// to mark with the "tail" keyword.
81bool IsAlwaysTail(ARCInstKind Class);
82
83/// Test if the given class represents instructions which are never safe
84/// to mark with the "tail" keyword.
85bool IsNeverTail(ARCInstKind Class);
86
87/// Test if the given class represents instructions which are always safe
88/// to mark with the nounwind attribute.
89bool IsNoThrow(ARCInstKind Class);
90
91/// Test whether the given instruction can autorelease any pointer or cause an
92/// autoreleasepool pop.
93bool CanInterruptRV(ARCInstKind Class);
94
95/// Determine if F is one of the special known Functions. If it isn't,
96/// return ARCInstKind::CallOrUser.
97ARCInstKind 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///
104inline ARCInstKind GetBasicARCInstKind(const Value *V) {
105 if (const CallInst *CI = dyn_cast<CallInst>(Val: 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>(Val: V) ? ARCInstKind::CallOrUser : ARCInstKind::User;
114}
115
116/// Map V to its ARCInstKind equivalence class.
117ARCInstKind 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.
121bool CanDecrementRefCount(ARCInstKind Kind);
122
123} // end namespace objcarc
124} // end namespace llvm
125
126#endif
127