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(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 AutoreleaseRV = 0; 62 Release = 0; 63 Retain = 0; 64 RetainBlock = 0; 65 Autorelease = 0; 66 StoreStrong = 0; 67 RetainRV = 0; 68 RetainAutorelease = 0; 69 RetainAutoreleaseRV = 0; 70 } 71 72 Constant *get(const EntryPointType entry) { 73 assert(TheModule != 0 && "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 187