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  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.
52class ARCRuntimeEntryPoints {
53public:
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    ClaimRV = 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::ClaimRV:
91      return getIntrinsicEntryPoint(
92          ClaimRV, 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
104private:
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 *ClaimRV = 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