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(AutoreleaseRV,
76                                     Intrinsic::objc_autoreleaseReturnValue);
77     case ARCRuntimeEntryPointKind::Release:
78       return getIntrinsicEntryPoint(Release, Intrinsic::objc_release);
79     case ARCRuntimeEntryPointKind::Retain:
80       return getIntrinsicEntryPoint(Retain, Intrinsic::objc_retain);
81     case ARCRuntimeEntryPointKind::RetainBlock:
82       return getIntrinsicEntryPoint(RetainBlock, Intrinsic::objc_retainBlock);
83     case ARCRuntimeEntryPointKind::Autorelease:
84       return getIntrinsicEntryPoint(Autorelease, Intrinsic::objc_autorelease);
85     case ARCRuntimeEntryPointKind::StoreStrong:
86       return getIntrinsicEntryPoint(StoreStrong, Intrinsic::objc_storeStrong);
87     case ARCRuntimeEntryPointKind::RetainRV:
88       return getIntrinsicEntryPoint(RetainRV,
89                                 Intrinsic::objc_retainAutoreleasedReturnValue);
90     case ARCRuntimeEntryPointKind::UnsafeClaimRV:
91       return getIntrinsicEntryPoint(
92           UnsafeClaimRV, Intrinsic::objc_unsafeClaimAutoreleasedReturnValue);
93     case ARCRuntimeEntryPointKind::RetainAutorelease:
94       return getIntrinsicEntryPoint(RetainAutorelease,
95                                     Intrinsic::objc_retainAutorelease);
96     case ARCRuntimeEntryPointKind::RetainAutoreleaseRV:
97       return getIntrinsicEntryPoint(RetainAutoreleaseRV,
98                                 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(TheModule, IntID);
143   }
144 };
145 
146 } // end namespace objcarc
147 
148 } // end namespace llvm
149 
150 #endif // LLVM_LIB_TRANSFORMS_OBJCARC_ARCRUNTIMEENTRYPOINTS_H
151