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_LIB_TRANSFORMS_OBJCARC_ARCRUNTIMEENTRYPOINTS_H 23 #define LLVM_LIB_TRANSFORMS_OBJCARC_ARCRUNTIMEENTRYPOINTS_H 24 25 #include "ObjCARC.h" 26 27 namespace llvm { 28 namespace objcarc { 29 30 enum class ARCRuntimeEntryPointKind { 31 AutoreleaseRV, 32 Release, 33 Retain, 34 RetainBlock, 35 Autorelease, 36 StoreStrong, 37 RetainRV, 38 RetainAutorelease, 39 RetainAutoreleaseRV, 40 }; 41 42 /// Declarations for ObjC runtime functions and constants. These are initialized 43 /// lazily to avoid cluttering up the Module with unused declarations. 44 class ARCRuntimeEntryPoints { 45 public: ARCRuntimeEntryPoints()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 init(Module * M)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 RetainAutorelease = nullptr; 67 RetainAutoreleaseRV = nullptr; 68 } 69 get(ARCRuntimeEntryPointKind kind)70 Constant *get(ARCRuntimeEntryPointKind kind) { 71 assert(TheModule != nullptr && "Not initialized."); 72 73 switch (kind) { 74 case ARCRuntimeEntryPointKind::AutoreleaseRV: 75 return getI8XRetI8XEntryPoint(AutoreleaseRV, 76 "objc_autoreleaseReturnValue", true); 77 case ARCRuntimeEntryPointKind::Release: 78 return getVoidRetI8XEntryPoint(Release, "objc_release"); 79 case ARCRuntimeEntryPointKind::Retain: 80 return getI8XRetI8XEntryPoint(Retain, "objc_retain", true); 81 case ARCRuntimeEntryPointKind::RetainBlock: 82 return getI8XRetI8XEntryPoint(RetainBlock, "objc_retainBlock", false); 83 case ARCRuntimeEntryPointKind::Autorelease: 84 return getI8XRetI8XEntryPoint(Autorelease, "objc_autorelease", true); 85 case ARCRuntimeEntryPointKind::StoreStrong: 86 return getI8XRetI8XXI8XEntryPoint(StoreStrong, "objc_storeStrong"); 87 case ARCRuntimeEntryPointKind::RetainRV: 88 return getI8XRetI8XEntryPoint(RetainRV, 89 "objc_retainAutoreleasedReturnValue", true); 90 case ARCRuntimeEntryPointKind::RetainAutorelease: 91 return getI8XRetI8XEntryPoint(RetainAutorelease, "objc_retainAutorelease", 92 true); 93 case ARCRuntimeEntryPointKind::RetainAutoreleaseRV: 94 return getI8XRetI8XEntryPoint(RetainAutoreleaseRV, 95 "objc_retainAutoreleaseReturnValue", true); 96 } 97 98 llvm_unreachable("Switch should be a covered switch."); 99 } 100 101 private: 102 /// Cached reference to the module which we will insert declarations into. 103 Module *TheModule; 104 105 /// Declaration for ObjC runtime function objc_autoreleaseReturnValue. 106 Constant *AutoreleaseRV; 107 /// Declaration for ObjC runtime function objc_release. 108 Constant *Release; 109 /// Declaration for ObjC runtime function objc_retain. 110 Constant *Retain; 111 /// Declaration for ObjC runtime function objc_retainBlock. 112 Constant *RetainBlock; 113 /// Declaration for ObjC runtime function objc_autorelease. 114 Constant *Autorelease; 115 /// Declaration for objc_storeStrong(). 116 Constant *StoreStrong; 117 /// Declaration for objc_retainAutoreleasedReturnValue(). 118 Constant *RetainRV; 119 /// Declaration for objc_retainAutorelease(). 120 Constant *RetainAutorelease; 121 /// Declaration for objc_retainAutoreleaseReturnValue(). 122 Constant *RetainAutoreleaseRV; 123 getVoidRetI8XEntryPoint(Constant * & Decl,const char * Name)124 Constant *getVoidRetI8XEntryPoint(Constant *&Decl, 125 const char *Name) { 126 if (Decl) 127 return Decl; 128 129 LLVMContext &C = TheModule->getContext(); 130 Type *Params[] = { PointerType::getUnqual(Type::getInt8Ty(C)) }; 131 AttributeSet Attr = 132 AttributeSet().addAttribute(C, AttributeSet::FunctionIndex, 133 Attribute::NoUnwind); 134 FunctionType *Fty = FunctionType::get(Type::getVoidTy(C), Params, 135 /*isVarArg=*/false); 136 return Decl = TheModule->getOrInsertFunction(Name, Fty, Attr); 137 } 138 139 Constant *getI8XRetI8XEntryPoint(Constant *& Decl, 140 const char *Name, 141 bool NoUnwind = false) { 142 if (Decl) 143 return Decl; 144 145 LLVMContext &C = TheModule->getContext(); 146 Type *I8X = PointerType::getUnqual(Type::getInt8Ty(C)); 147 Type *Params[] = { I8X }; 148 FunctionType *Fty = FunctionType::get(I8X, Params, /*isVarArg=*/false); 149 AttributeSet Attr = AttributeSet(); 150 151 if (NoUnwind) 152 Attr = Attr.addAttribute(C, AttributeSet::FunctionIndex, 153 Attribute::NoUnwind); 154 155 return Decl = TheModule->getOrInsertFunction(Name, Fty, Attr); 156 } 157 getI8XRetI8XXI8XEntryPoint(Constant * & Decl,const char * Name)158 Constant *getI8XRetI8XXI8XEntryPoint(Constant *&Decl, 159 const char *Name) { 160 if (Decl) 161 return Decl; 162 163 LLVMContext &C = TheModule->getContext(); 164 Type *I8X = PointerType::getUnqual(Type::getInt8Ty(C)); 165 Type *I8XX = PointerType::getUnqual(I8X); 166 Type *Params[] = { I8XX, I8X }; 167 168 AttributeSet Attr = 169 AttributeSet().addAttribute(C, AttributeSet::FunctionIndex, 170 Attribute::NoUnwind); 171 Attr = Attr.addAttribute(C, 1, Attribute::NoCapture); 172 173 FunctionType *Fty = FunctionType::get(Type::getVoidTy(C), Params, 174 /*isVarArg=*/false); 175 176 return Decl = TheModule->getOrInsertFunction(Name, Fty, Attr); 177 } 178 179 }; // class ARCRuntimeEntryPoints 180 181 } // namespace objcarc 182 } // namespace llvm 183 184 #endif 185