[C++] Use 'nullptr'.
[oota-llvm.git] / lib / Transforms / ObjCARC / ARCRuntimeEntryPoints.h
1 //===- ARCRuntimeEntryPoints.h - ObjC ARC Optimization --*- C++ -*---------===//
2 //
3 //                     The LLVM Compiler Infrastructure
4 //
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
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_TRANSFORMS_SCALAR_ARCRUNTIMEENTRYPOINTS_H
23 #define LLVM_TRANSFORMS_SCALAR_ARCRUNTIMEENTRYPOINTS_H
24
25 #include "ObjCARC.h"
26
27 namespace llvm {
28 namespace objcarc {
29
30 /// Declarations for ObjC runtime functions and constants. These are initialized
31 /// lazily to avoid cluttering up the Module with unused declarations.
32 class ARCRuntimeEntryPoints {
33 public:
34   enum EntryPointType {
35     EPT_AutoreleaseRV,
36     EPT_Release,
37     EPT_Retain,
38     EPT_RetainBlock,
39     EPT_Autorelease,
40     EPT_StoreStrong,
41     EPT_RetainRV,
42     EPT_RetainAutorelease,
43     EPT_RetainAutoreleaseRV
44   };
45
46   ARCRuntimeEntryPoints() : TheModule(nullptr),
47                             AutoreleaseRV(nullptr),
48                             Release(nullptr),
49                             Retain(nullptr),
50                             RetainBlock(nullptr),
51                             Autorelease(nullptr),
52                             StoreStrong(nullptr),
53                             RetainRV(nullptr),
54                             RetainAutorelease(nullptr),
55                             RetainAutoreleaseRV(nullptr) { }
56
57   ~ARCRuntimeEntryPoints() { }
58
59   void Initialize(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   Constant *get(const EntryPointType entry) {
73     assert(TheModule != nullptr && "Not initialized.");
74
75     switch (entry) {
76     case EPT_AutoreleaseRV:
77       return getI8XRetI8XEntryPoint(AutoreleaseRV,
78                                     "objc_autoreleaseReturnValue", true);
79     case EPT_Release:
80       return getVoidRetI8XEntryPoint(Release, "objc_release");
81     case EPT_Retain:
82       return getI8XRetI8XEntryPoint(Retain, "objc_retain", true);
83     case EPT_RetainBlock:
84       return getI8XRetI8XEntryPoint(RetainBlock, "objc_retainBlock", false);
85     case EPT_Autorelease:
86       return getI8XRetI8XEntryPoint(Autorelease, "objc_autorelease", true);
87     case EPT_StoreStrong:
88       return getI8XRetI8XXI8XEntryPoint(StoreStrong, "objc_storeStrong");
89     case EPT_RetainRV:
90       return getI8XRetI8XEntryPoint(RetainRV,
91                                     "objc_retainAutoreleasedReturnValue", true);
92     case EPT_RetainAutorelease:
93       return getI8XRetI8XEntryPoint(RetainAutorelease, "objc_retainAutorelease",
94                                     true);
95     case EPT_RetainAutoreleaseRV:
96       return getI8XRetI8XEntryPoint(RetainAutoreleaseRV,
97                                     "objc_retainAutoreleaseReturnValue", true);
98     }
99
100     llvm_unreachable("Switch should be a covered switch.");
101   }
102
103 private:
104   /// Cached reference to the module which we will insert declarations into.
105   Module *TheModule;
106
107   /// Declaration for ObjC runtime function objc_autoreleaseReturnValue.
108   Constant *AutoreleaseRV;
109   /// Declaration for ObjC runtime function objc_release.
110   Constant *Release;
111   /// Declaration for ObjC runtime function objc_retain.
112   Constant *Retain;
113   /// Declaration for ObjC runtime function objc_retainBlock.
114   Constant *RetainBlock;
115   /// Declaration for ObjC runtime function objc_autorelease.
116   Constant *Autorelease;
117   /// Declaration for objc_storeStrong().
118   Constant *StoreStrong;
119   /// Declaration for objc_retainAutoreleasedReturnValue().
120   Constant *RetainRV;
121   /// Declaration for objc_retainAutorelease().
122   Constant *RetainAutorelease;
123   /// Declaration for objc_retainAutoreleaseReturnValue().
124   Constant *RetainAutoreleaseRV;
125
126   Constant *getVoidRetI8XEntryPoint(Constant *&Decl,
127                                     const char *Name) {
128     if (Decl)
129       return Decl;
130
131     LLVMContext &C = TheModule->getContext();
132     Type *Params[] = { PointerType::getUnqual(Type::getInt8Ty(C)) };
133     AttributeSet Attr =
134       AttributeSet().addAttribute(C, AttributeSet::FunctionIndex,
135                                   Attribute::NoUnwind);
136     FunctionType *Fty = FunctionType::get(Type::getVoidTy(C), Params,
137                                           /*isVarArg=*/false);
138     return Decl = TheModule->getOrInsertFunction(Name, Fty, Attr);
139   }
140
141   Constant *getI8XRetI8XEntryPoint(Constant *& Decl,
142                                    const char *Name,
143                                    bool NoUnwind = false) {
144     if (Decl)
145       return Decl;
146
147     LLVMContext &C = TheModule->getContext();
148     Type *I8X = PointerType::getUnqual(Type::getInt8Ty(C));
149     Type *Params[] = { I8X };
150     FunctionType *Fty = FunctionType::get(I8X, Params, /*isVarArg=*/false);
151     AttributeSet Attr = AttributeSet();
152
153     if (NoUnwind)
154       Attr = Attr.addAttribute(C, AttributeSet::FunctionIndex,
155                                Attribute::NoUnwind);
156
157     return Decl = TheModule->getOrInsertFunction(Name, Fty, Attr);
158   }
159
160   Constant *getI8XRetI8XXI8XEntryPoint(Constant *&Decl,
161                                        const char *Name) {
162     if (Decl)
163       return Decl;
164
165     LLVMContext &C = TheModule->getContext();
166     Type *I8X = PointerType::getUnqual(Type::getInt8Ty(C));
167     Type *I8XX = PointerType::getUnqual(I8X);
168     Type *Params[] = { I8XX, I8X };
169
170     AttributeSet Attr =
171       AttributeSet().addAttribute(C, AttributeSet::FunctionIndex,
172                                   Attribute::NoUnwind);
173     Attr = Attr.addAttribute(C, 1, Attribute::NoCapture);
174
175     FunctionType *Fty = FunctionType::get(Type::getVoidTy(C), Params,
176                                           /*isVarArg=*/false);
177
178     return Decl = TheModule->getOrInsertFunction(Name, Fty, Attr);
179   }
180
181 }; // class ARCRuntimeEntryPoints
182
183 } // namespace objcarc
184 } // namespace llvm
185
186 #endif // LLVM_TRANSFORMS_SCALAR_ARCRUNTIMEENTRYPOINTS_H