1 | //===- ARCRuntimeEntryPoints.h - ObjC ARC Optimization ----------*- 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 | /// \file |
10 | /// This file contains a class ARCRuntimeEntryPoints for use in |
11 | /// creating/managing references to entry points to the arc objective c runtime. |
12 | /// |
13 | /// WARNING: This file knows about certain library functions. It recognizes them |
14 | /// by name, and hardwires knowledge of their semantics. |
15 | /// |
16 | /// WARNING: This file knows about how certain Objective-C library functions are |
17 | /// used. Naive LLVM IR transformations which would otherwise be |
18 | /// behavior-preserving may break these assumptions. |
19 | // |
20 | //===----------------------------------------------------------------------===// |
21 | |
22 | #ifndef LLVM_LIB_TRANSFORMS_OBJCARC_ARCRUNTIMEENTRYPOINTS_H |
23 | #define LLVM_LIB_TRANSFORMS_OBJCARC_ARCRUNTIMEENTRYPOINTS_H |
24 | |
25 | #include "llvm/IR/Attributes.h" |
26 | #include "llvm/IR/Intrinsics.h" |
27 | #include "llvm/Support/ErrorHandling.h" |
28 | #include <cassert> |
29 | |
30 | namespace llvm { |
31 | |
32 | class Function; |
33 | class Module; |
34 | |
35 | namespace objcarc { |
36 | |
37 | enum class ARCRuntimeEntryPointKind { |
38 | AutoreleaseRV, |
39 | Release, |
40 | Retain, |
41 | RetainBlock, |
42 | Autorelease, |
43 | StoreStrong, |
44 | RetainRV, |
45 | UnsafeClaimRV, |
46 | RetainAutorelease, |
47 | RetainAutoreleaseRV, |
48 | }; |
49 | |
50 | /// Declarations for ObjC runtime functions and constants. These are initialized |
51 | /// lazily to avoid cluttering up the Module with unused declarations. |
52 | class ARCRuntimeEntryPoints { |
53 | public: |
54 | ARCRuntimeEntryPoints() = default; |
55 | |
56 | void init(Module *M) { |
57 | TheModule = M; |
58 | AutoreleaseRV = nullptr; |
59 | Release = nullptr; |
60 | Retain = nullptr; |
61 | RetainBlock = nullptr; |
62 | Autorelease = nullptr; |
63 | StoreStrong = nullptr; |
64 | RetainRV = nullptr; |
65 | UnsafeClaimRV = nullptr; |
66 | RetainAutorelease = nullptr; |
67 | RetainAutoreleaseRV = nullptr; |
68 | } |
69 | |
70 | Function *get(ARCRuntimeEntryPointKind kind) { |
71 | assert(TheModule != nullptr && "Not initialized." ); |
72 | |
73 | switch (kind) { |
74 | case ARCRuntimeEntryPointKind::AutoreleaseRV: |
75 | return getIntrinsicEntryPoint(Decl&: AutoreleaseRV, |
76 | IntID: Intrinsic::objc_autoreleaseReturnValue); |
77 | case ARCRuntimeEntryPointKind::Release: |
78 | return getIntrinsicEntryPoint(Decl&: Release, IntID: Intrinsic::objc_release); |
79 | case ARCRuntimeEntryPointKind::Retain: |
80 | return getIntrinsicEntryPoint(Decl&: Retain, IntID: Intrinsic::objc_retain); |
81 | case ARCRuntimeEntryPointKind::RetainBlock: |
82 | return getIntrinsicEntryPoint(Decl&: RetainBlock, IntID: Intrinsic::objc_retainBlock); |
83 | case ARCRuntimeEntryPointKind::Autorelease: |
84 | return getIntrinsicEntryPoint(Decl&: Autorelease, IntID: Intrinsic::objc_autorelease); |
85 | case ARCRuntimeEntryPointKind::StoreStrong: |
86 | return getIntrinsicEntryPoint(Decl&: StoreStrong, IntID: Intrinsic::objc_storeStrong); |
87 | case ARCRuntimeEntryPointKind::RetainRV: |
88 | return getIntrinsicEntryPoint(Decl&: RetainRV, |
89 | IntID: Intrinsic::objc_retainAutoreleasedReturnValue); |
90 | case ARCRuntimeEntryPointKind::UnsafeClaimRV: |
91 | return getIntrinsicEntryPoint( |
92 | Decl&: UnsafeClaimRV, IntID: Intrinsic::objc_unsafeClaimAutoreleasedReturnValue); |
93 | case ARCRuntimeEntryPointKind::RetainAutorelease: |
94 | return getIntrinsicEntryPoint(Decl&: RetainAutorelease, |
95 | IntID: Intrinsic::objc_retainAutorelease); |
96 | case ARCRuntimeEntryPointKind::RetainAutoreleaseRV: |
97 | return getIntrinsicEntryPoint(Decl&: RetainAutoreleaseRV, |
98 | IntID: Intrinsic::objc_retainAutoreleaseReturnValue); |
99 | } |
100 | |
101 | llvm_unreachable("Switch should be a covered switch." ); |
102 | } |
103 | |
104 | private: |
105 | /// Cached reference to the module which we will insert declarations into. |
106 | Module *TheModule = nullptr; |
107 | |
108 | /// Declaration for ObjC runtime function objc_autoreleaseReturnValue. |
109 | Function *AutoreleaseRV = nullptr; |
110 | |
111 | /// Declaration for ObjC runtime function objc_release. |
112 | Function *Release = nullptr; |
113 | |
114 | /// Declaration for ObjC runtime function objc_retain. |
115 | Function *Retain = nullptr; |
116 | |
117 | /// Declaration for ObjC runtime function objc_retainBlock. |
118 | Function *RetainBlock = nullptr; |
119 | |
120 | /// Declaration for ObjC runtime function objc_autorelease. |
121 | Function *Autorelease = nullptr; |
122 | |
123 | /// Declaration for objc_storeStrong(). |
124 | Function *StoreStrong = nullptr; |
125 | |
126 | /// Declaration for objc_retainAutoreleasedReturnValue(). |
127 | Function *RetainRV = nullptr; |
128 | |
129 | /// Declaration for objc_unsafeClaimAutoreleasedReturnValue(). |
130 | Function *UnsafeClaimRV = nullptr; |
131 | |
132 | /// Declaration for objc_retainAutorelease(). |
133 | Function *RetainAutorelease = nullptr; |
134 | |
135 | /// Declaration for objc_retainAutoreleaseReturnValue(). |
136 | Function *RetainAutoreleaseRV = nullptr; |
137 | |
138 | Function *getIntrinsicEntryPoint(Function *&Decl, Intrinsic::ID IntID) { |
139 | if (Decl) |
140 | return Decl; |
141 | |
142 | return Decl = Intrinsic::getDeclaration(M: TheModule, id: IntID); |
143 | } |
144 | }; |
145 | |
146 | } // end namespace objcarc |
147 | |
148 | } // end namespace llvm |
149 | |
150 | #endif // LLVM_LIB_TRANSFORMS_OBJCARC_ARCRUNTIMEENTRYPOINTS_H |
151 | |