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
30namespace llvm {
31
32class Function;
33class Module;
34
35namespace objcarc {
36
37enum class ARCRuntimeEntryPointKind {
38 AutoreleaseRV,
39 Release,
40 Retain,
41 RetainBlock,
42 Autorelease,
43 StoreStrong,
44 RetainRV,
45 ClaimRV,
46 UnsafeClaimRV,
47 RetainAutorelease,
48 RetainAutoreleaseRV,
49};
50
51/// Declarations for ObjC runtime functions and constants. These are initialized
52/// lazily to avoid cluttering up the Module with unused declarations.
53class ARCRuntimeEntryPoints {
54public:
55 ARCRuntimeEntryPoints() = default;
56
57 void init(Module *M) {
58 TheModule = M;
59 AutoreleaseRV = nullptr;
60 Release = nullptr;
61 Retain = nullptr;
62 RetainBlock = nullptr;
63 Autorelease = nullptr;
64 StoreStrong = nullptr;
65 RetainRV = nullptr;
66 ClaimRV = nullptr;
67 UnsafeClaimRV = nullptr;
68 RetainAutorelease = nullptr;
69 RetainAutoreleaseRV = nullptr;
70 }
71
72 Function *get(ARCRuntimeEntryPointKind kind) {
73 assert(TheModule != nullptr && "Not initialized.");
74
75 switch (kind) {
76 case ARCRuntimeEntryPointKind::AutoreleaseRV:
77 return getIntrinsicEntryPoint(Decl&: AutoreleaseRV,
78 IntID: Intrinsic::objc_autoreleaseReturnValue);
79 case ARCRuntimeEntryPointKind::Release:
80 return getIntrinsicEntryPoint(Decl&: Release, IntID: Intrinsic::objc_release);
81 case ARCRuntimeEntryPointKind::Retain:
82 return getIntrinsicEntryPoint(Decl&: Retain, IntID: Intrinsic::objc_retain);
83 case ARCRuntimeEntryPointKind::RetainBlock:
84 return getIntrinsicEntryPoint(Decl&: RetainBlock, IntID: Intrinsic::objc_retainBlock);
85 case ARCRuntimeEntryPointKind::Autorelease:
86 return getIntrinsicEntryPoint(Decl&: Autorelease, IntID: Intrinsic::objc_autorelease);
87 case ARCRuntimeEntryPointKind::StoreStrong:
88 return getIntrinsicEntryPoint(Decl&: StoreStrong, IntID: Intrinsic::objc_storeStrong);
89 case ARCRuntimeEntryPointKind::RetainRV:
90 return getIntrinsicEntryPoint(Decl&: RetainRV,
91 IntID: Intrinsic::objc_retainAutoreleasedReturnValue);
92 case ARCRuntimeEntryPointKind::ClaimRV:
93 return getIntrinsicEntryPoint(
94 Decl&: ClaimRV, IntID: Intrinsic::objc_claimAutoreleasedReturnValue);
95 case ARCRuntimeEntryPointKind::UnsafeClaimRV:
96 return getIntrinsicEntryPoint(
97 Decl&: UnsafeClaimRV, IntID: Intrinsic::objc_unsafeClaimAutoreleasedReturnValue);
98 case ARCRuntimeEntryPointKind::RetainAutorelease:
99 return getIntrinsicEntryPoint(Decl&: RetainAutorelease,
100 IntID: Intrinsic::objc_retainAutorelease);
101 case ARCRuntimeEntryPointKind::RetainAutoreleaseRV:
102 return getIntrinsicEntryPoint(Decl&: RetainAutoreleaseRV,
103 IntID: Intrinsic::objc_retainAutoreleaseReturnValue);
104 }
105
106 llvm_unreachable("Switch should be a covered switch.");
107 }
108
109private:
110 /// Cached reference to the module which we will insert declarations into.
111 Module *TheModule = nullptr;
112
113 /// Declaration for ObjC runtime function objc_autoreleaseReturnValue.
114 Function *AutoreleaseRV = nullptr;
115
116 /// Declaration for ObjC runtime function objc_release.
117 Function *Release = nullptr;
118
119 /// Declaration for ObjC runtime function objc_retain.
120 Function *Retain = nullptr;
121
122 /// Declaration for ObjC runtime function objc_retainBlock.
123 Function *RetainBlock = nullptr;
124
125 /// Declaration for ObjC runtime function objc_autorelease.
126 Function *Autorelease = nullptr;
127
128 /// Declaration for objc_storeStrong().
129 Function *StoreStrong = nullptr;
130
131 /// Declaration for objc_retainAutoreleasedReturnValue().
132 Function *RetainRV = nullptr;
133
134 /// Declaration for objc_claimAutoreleasedReturnValue().
135 Function *ClaimRV = nullptr;
136
137 /// Declaration for objc_unsafeClaimAutoreleasedReturnValue().
138 Function *UnsafeClaimRV = nullptr;
139
140 /// Declaration for objc_retainAutorelease().
141 Function *RetainAutorelease = nullptr;
142
143 /// Declaration for objc_retainAutoreleaseReturnValue().
144 Function *RetainAutoreleaseRV = nullptr;
145
146 Function *getIntrinsicEntryPoint(Function *&Decl, Intrinsic::ID IntID) {
147 if (Decl)
148 return Decl;
149
150 return Decl = Intrinsic::getOrInsertDeclaration(M: TheModule, id: IntID);
151 }
152};
153
154} // end namespace objcarc
155
156} // end namespace llvm
157
158#endif // LLVM_LIB_TRANSFORMS_OBJCARC_ARCRUNTIMEENTRYPOINTS_H
159