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