ARCRuntimeEntryPoints.h revision 462e998f076b625507d134c8c341f8cf960d1eb0
1//===- ARCRuntimeEntryPoints.h - ObjC ARC Optimization --*- mode: 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
27namespace llvm {
28namespace objcarc {
29
30/// Declarations for ObjC runtime functions and constants. These are initialized
31/// lazily to avoid cluttering up the Module with unused declarations.
32class ARCRuntimeEntryPoints {
33public:
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(0),
47                            AutoreleaseRV(0),
48                            Release(0),
49                            Retain(0),
50                            RetainBlock(0),
51                            Autorelease(0),
52                            StoreStrong(0),
53                            RetainRV(0),
54                            RetainAutorelease(0),
55                            RetainAutoreleaseRV(0) { }
56
57  ~ARCRuntimeEntryPoints() { }
58
59  void Initialize(Module *M) {
60    TheModule = M;
61  }
62
63  Constant *get(const EntryPointType entry) {
64    assert(TheModule != 0 && "Not initialized.");
65
66    switch (entry) {
67    case EPT_AutoreleaseRV:
68      return getI8XRetI8XEntryPoint(AutoreleaseRV,
69                                    "objc_autoreleaseReturnValue", true);
70    case EPT_Release:
71      return getVoidRetI8XEntryPoint(Release, "objc_release");
72    case EPT_Retain:
73      return getI8XRetI8XEntryPoint(Retain, "objc_retain", true);
74    case EPT_RetainBlock:
75      return getI8XRetI8XEntryPoint(RetainBlock, "objc_retainBlock", false);
76    case EPT_Autorelease:
77      return getI8XRetI8XEntryPoint(Autorelease, "objc_autorelease", true);
78    case EPT_StoreStrong:
79      return getI8XRetI8XXI8XEntryPoint(StoreStrong, "objc_storeStrong");
80    case EPT_RetainRV:
81      return getI8XRetI8XEntryPoint(RetainRV,
82                                    "objc_retainAutoreleasedReturnValue", true);
83    case EPT_RetainAutorelease:
84      return getI8XRetI8XEntryPoint(RetainAutorelease, "objc_retainAutorelease",
85                                    true);
86    case EPT_RetainAutoreleaseRV:
87      return getI8XRetI8XEntryPoint(RetainAutoreleaseRV,
88                                    "objc_retainAutoreleaseReturnValue", true);
89    }
90
91    llvm_unreachable("Switch should be a covered switch.");
92  }
93
94private:
95  /// Cached reference to the module which we will insert declarations into.
96  Module *TheModule;
97
98  /// Declaration for ObjC runtime function objc_autoreleaseReturnValue.
99  Constant *AutoreleaseRV;
100  /// Declaration for ObjC runtime function objc_release.
101  Constant *Release;
102  /// Declaration for ObjC runtime function objc_retain.
103  Constant *Retain;
104  /// Declaration for ObjC runtime function objc_retainBlock.
105  Constant *RetainBlock;
106  /// Declaration for ObjC runtime function objc_autorelease.
107  Constant *Autorelease;
108  /// Declaration for objc_storeStrong().
109  Constant *StoreStrong;
110  /// Declaration for objc_retainAutoreleasedReturnValue().
111  Constant *RetainRV;
112  /// Declaration for objc_retainAutorelease().
113  Constant *RetainAutorelease;
114  /// Declaration for objc_retainAutoreleaseReturnValue().
115  Constant *RetainAutoreleaseRV;
116
117  Constant *getVoidRetI8XEntryPoint(Constant *&Decl,
118                                    const char *Name) {
119    if (Decl)
120      return Decl;
121
122    LLVMContext &C = TheModule->getContext();
123    Type *Params[] = { PointerType::getUnqual(Type::getInt8Ty(C)) };
124    AttributeSet Attr =
125      AttributeSet().addAttribute(C, AttributeSet::FunctionIndex,
126                                  Attribute::NoUnwind);
127    FunctionType *Fty = FunctionType::get(Type::getVoidTy(C), Params,
128                                          /*isVarArg=*/false);
129    return Decl = TheModule->getOrInsertFunction(Name, Fty, Attr);
130  }
131
132  Constant *getI8XRetI8XEntryPoint(Constant *& Decl,
133                                   const char *Name,
134                                   bool NoUnwind = false) {
135    if (Decl)
136      return Decl;
137
138    LLVMContext &C = TheModule->getContext();
139    Type *I8X = PointerType::getUnqual(Type::getInt8Ty(C));
140    Type *Params[] = { I8X };
141    FunctionType *Fty = FunctionType::get(I8X, Params, /*isVarArg=*/false);
142    AttributeSet Attr = AttributeSet();
143
144    if (NoUnwind)
145      Attr = Attr.addAttribute(C, AttributeSet::FunctionIndex,
146                               Attribute::NoUnwind);
147
148    return Decl = TheModule->getOrInsertFunction(Name, Fty, Attr);
149  }
150
151  Constant *getI8XRetI8XXI8XEntryPoint(Constant *&Decl,
152                                       const char *Name) {
153    if (Decl)
154      return Decl;
155
156    LLVMContext &C = TheModule->getContext();
157    Type *I8X = PointerType::getUnqual(Type::getInt8Ty(C));
158    Type *I8XX = PointerType::getUnqual(I8X);
159    Type *Params[] = { I8XX, I8X };
160
161    AttributeSet Attr =
162      AttributeSet().addAttribute(C, AttributeSet::FunctionIndex,
163                                  Attribute::NoUnwind);
164    Attr = Attr.addAttribute(C, 1, Attribute::NoCapture);
165
166    FunctionType *Fty = FunctionType::get(Type::getVoidTy(C), Params,
167                                          /*isVarArg=*/false);
168
169    return Decl = TheModule->getOrInsertFunction(Name, Fty, Attr);
170  }
171
172}; // class ARCRuntimeEntryPoints
173
174} // namespace objcarc
175} // namespace llvm
176
177#endif // LLVM_TRANSFORMS_SCALAR_ARCRUNTIMEENTRYPOINTS_H
178