| 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 | 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. |
| 53 | class ARCRuntimeEntryPoints { |
| 54 | public: |
| 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 | |
| 109 | private: |
| 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 | |