1*9880d681SAndroid Build Coastguard Worker //===- ARCRuntimeEntryPoints.h - ObjC ARC Optimization --*- C++ -*---------===// 2*9880d681SAndroid Build Coastguard Worker // 3*9880d681SAndroid Build Coastguard Worker // The LLVM Compiler Infrastructure 4*9880d681SAndroid Build Coastguard Worker // 5*9880d681SAndroid Build Coastguard Worker // This file is distributed under the University of Illinois Open Source 6*9880d681SAndroid Build Coastguard Worker // License. See LICENSE.TXT for details. 7*9880d681SAndroid Build Coastguard Worker // 8*9880d681SAndroid Build Coastguard Worker //===----------------------------------------------------------------------===// 9*9880d681SAndroid Build Coastguard Worker /// \file 10*9880d681SAndroid Build Coastguard Worker /// This file contains a class ARCRuntimeEntryPoints for use in 11*9880d681SAndroid Build Coastguard Worker /// creating/managing references to entry points to the arc objective c runtime. 12*9880d681SAndroid Build Coastguard Worker /// 13*9880d681SAndroid Build Coastguard Worker /// WARNING: This file knows about certain library functions. It recognizes them 14*9880d681SAndroid Build Coastguard Worker /// by name, and hardwires knowledge of their semantics. 15*9880d681SAndroid Build Coastguard Worker /// 16*9880d681SAndroid Build Coastguard Worker /// WARNING: This file knows about how certain Objective-C library functions are 17*9880d681SAndroid Build Coastguard Worker /// used. Naive LLVM IR transformations which would otherwise be 18*9880d681SAndroid Build Coastguard Worker /// behavior-preserving may break these assumptions. 19*9880d681SAndroid Build Coastguard Worker /// 20*9880d681SAndroid Build Coastguard Worker //===----------------------------------------------------------------------===// 21*9880d681SAndroid Build Coastguard Worker 22*9880d681SAndroid Build Coastguard Worker #ifndef LLVM_LIB_TRANSFORMS_OBJCARC_ARCRUNTIMEENTRYPOINTS_H 23*9880d681SAndroid Build Coastguard Worker #define LLVM_LIB_TRANSFORMS_OBJCARC_ARCRUNTIMEENTRYPOINTS_H 24*9880d681SAndroid Build Coastguard Worker 25*9880d681SAndroid Build Coastguard Worker #include "ObjCARC.h" 26*9880d681SAndroid Build Coastguard Worker 27*9880d681SAndroid Build Coastguard Worker namespace llvm { 28*9880d681SAndroid Build Coastguard Worker namespace objcarc { 29*9880d681SAndroid Build Coastguard Worker 30*9880d681SAndroid Build Coastguard Worker enum class ARCRuntimeEntryPointKind { 31*9880d681SAndroid Build Coastguard Worker AutoreleaseRV, 32*9880d681SAndroid Build Coastguard Worker Release, 33*9880d681SAndroid Build Coastguard Worker Retain, 34*9880d681SAndroid Build Coastguard Worker RetainBlock, 35*9880d681SAndroid Build Coastguard Worker Autorelease, 36*9880d681SAndroid Build Coastguard Worker StoreStrong, 37*9880d681SAndroid Build Coastguard Worker RetainRV, 38*9880d681SAndroid Build Coastguard Worker RetainAutorelease, 39*9880d681SAndroid Build Coastguard Worker RetainAutoreleaseRV, 40*9880d681SAndroid Build Coastguard Worker }; 41*9880d681SAndroid Build Coastguard Worker 42*9880d681SAndroid Build Coastguard Worker /// Declarations for ObjC runtime functions and constants. These are initialized 43*9880d681SAndroid Build Coastguard Worker /// lazily to avoid cluttering up the Module with unused declarations. 44*9880d681SAndroid Build Coastguard Worker class ARCRuntimeEntryPoints { 45*9880d681SAndroid Build Coastguard Worker public: ARCRuntimeEntryPoints()46*9880d681SAndroid Build Coastguard Worker ARCRuntimeEntryPoints() : TheModule(nullptr), 47*9880d681SAndroid Build Coastguard Worker AutoreleaseRV(nullptr), 48*9880d681SAndroid Build Coastguard Worker Release(nullptr), 49*9880d681SAndroid Build Coastguard Worker Retain(nullptr), 50*9880d681SAndroid Build Coastguard Worker RetainBlock(nullptr), 51*9880d681SAndroid Build Coastguard Worker Autorelease(nullptr), 52*9880d681SAndroid Build Coastguard Worker StoreStrong(nullptr), 53*9880d681SAndroid Build Coastguard Worker RetainRV(nullptr), 54*9880d681SAndroid Build Coastguard Worker RetainAutorelease(nullptr), 55*9880d681SAndroid Build Coastguard Worker RetainAutoreleaseRV(nullptr) { } 56*9880d681SAndroid Build Coastguard Worker init(Module * M)57*9880d681SAndroid Build Coastguard Worker void init(Module *M) { 58*9880d681SAndroid Build Coastguard Worker TheModule = M; 59*9880d681SAndroid Build Coastguard Worker AutoreleaseRV = nullptr; 60*9880d681SAndroid Build Coastguard Worker Release = nullptr; 61*9880d681SAndroid Build Coastguard Worker Retain = nullptr; 62*9880d681SAndroid Build Coastguard Worker RetainBlock = nullptr; 63*9880d681SAndroid Build Coastguard Worker Autorelease = nullptr; 64*9880d681SAndroid Build Coastguard Worker StoreStrong = nullptr; 65*9880d681SAndroid Build Coastguard Worker RetainRV = nullptr; 66*9880d681SAndroid Build Coastguard Worker RetainAutorelease = nullptr; 67*9880d681SAndroid Build Coastguard Worker RetainAutoreleaseRV = nullptr; 68*9880d681SAndroid Build Coastguard Worker } 69*9880d681SAndroid Build Coastguard Worker get(ARCRuntimeEntryPointKind kind)70*9880d681SAndroid Build Coastguard Worker Constant *get(ARCRuntimeEntryPointKind kind) { 71*9880d681SAndroid Build Coastguard Worker assert(TheModule != nullptr && "Not initialized."); 72*9880d681SAndroid Build Coastguard Worker 73*9880d681SAndroid Build Coastguard Worker switch (kind) { 74*9880d681SAndroid Build Coastguard Worker case ARCRuntimeEntryPointKind::AutoreleaseRV: 75*9880d681SAndroid Build Coastguard Worker return getI8XRetI8XEntryPoint(AutoreleaseRV, 76*9880d681SAndroid Build Coastguard Worker "objc_autoreleaseReturnValue", true); 77*9880d681SAndroid Build Coastguard Worker case ARCRuntimeEntryPointKind::Release: 78*9880d681SAndroid Build Coastguard Worker return getVoidRetI8XEntryPoint(Release, "objc_release"); 79*9880d681SAndroid Build Coastguard Worker case ARCRuntimeEntryPointKind::Retain: 80*9880d681SAndroid Build Coastguard Worker return getI8XRetI8XEntryPoint(Retain, "objc_retain", true); 81*9880d681SAndroid Build Coastguard Worker case ARCRuntimeEntryPointKind::RetainBlock: 82*9880d681SAndroid Build Coastguard Worker return getI8XRetI8XEntryPoint(RetainBlock, "objc_retainBlock", false); 83*9880d681SAndroid Build Coastguard Worker case ARCRuntimeEntryPointKind::Autorelease: 84*9880d681SAndroid Build Coastguard Worker return getI8XRetI8XEntryPoint(Autorelease, "objc_autorelease", true); 85*9880d681SAndroid Build Coastguard Worker case ARCRuntimeEntryPointKind::StoreStrong: 86*9880d681SAndroid Build Coastguard Worker return getI8XRetI8XXI8XEntryPoint(StoreStrong, "objc_storeStrong"); 87*9880d681SAndroid Build Coastguard Worker case ARCRuntimeEntryPointKind::RetainRV: 88*9880d681SAndroid Build Coastguard Worker return getI8XRetI8XEntryPoint(RetainRV, 89*9880d681SAndroid Build Coastguard Worker "objc_retainAutoreleasedReturnValue", true); 90*9880d681SAndroid Build Coastguard Worker case ARCRuntimeEntryPointKind::RetainAutorelease: 91*9880d681SAndroid Build Coastguard Worker return getI8XRetI8XEntryPoint(RetainAutorelease, "objc_retainAutorelease", 92*9880d681SAndroid Build Coastguard Worker true); 93*9880d681SAndroid Build Coastguard Worker case ARCRuntimeEntryPointKind::RetainAutoreleaseRV: 94*9880d681SAndroid Build Coastguard Worker return getI8XRetI8XEntryPoint(RetainAutoreleaseRV, 95*9880d681SAndroid Build Coastguard Worker "objc_retainAutoreleaseReturnValue", true); 96*9880d681SAndroid Build Coastguard Worker } 97*9880d681SAndroid Build Coastguard Worker 98*9880d681SAndroid Build Coastguard Worker llvm_unreachable("Switch should be a covered switch."); 99*9880d681SAndroid Build Coastguard Worker } 100*9880d681SAndroid Build Coastguard Worker 101*9880d681SAndroid Build Coastguard Worker private: 102*9880d681SAndroid Build Coastguard Worker /// Cached reference to the module which we will insert declarations into. 103*9880d681SAndroid Build Coastguard Worker Module *TheModule; 104*9880d681SAndroid Build Coastguard Worker 105*9880d681SAndroid Build Coastguard Worker /// Declaration for ObjC runtime function objc_autoreleaseReturnValue. 106*9880d681SAndroid Build Coastguard Worker Constant *AutoreleaseRV; 107*9880d681SAndroid Build Coastguard Worker /// Declaration for ObjC runtime function objc_release. 108*9880d681SAndroid Build Coastguard Worker Constant *Release; 109*9880d681SAndroid Build Coastguard Worker /// Declaration for ObjC runtime function objc_retain. 110*9880d681SAndroid Build Coastguard Worker Constant *Retain; 111*9880d681SAndroid Build Coastguard Worker /// Declaration for ObjC runtime function objc_retainBlock. 112*9880d681SAndroid Build Coastguard Worker Constant *RetainBlock; 113*9880d681SAndroid Build Coastguard Worker /// Declaration for ObjC runtime function objc_autorelease. 114*9880d681SAndroid Build Coastguard Worker Constant *Autorelease; 115*9880d681SAndroid Build Coastguard Worker /// Declaration for objc_storeStrong(). 116*9880d681SAndroid Build Coastguard Worker Constant *StoreStrong; 117*9880d681SAndroid Build Coastguard Worker /// Declaration for objc_retainAutoreleasedReturnValue(). 118*9880d681SAndroid Build Coastguard Worker Constant *RetainRV; 119*9880d681SAndroid Build Coastguard Worker /// Declaration for objc_retainAutorelease(). 120*9880d681SAndroid Build Coastguard Worker Constant *RetainAutorelease; 121*9880d681SAndroid Build Coastguard Worker /// Declaration for objc_retainAutoreleaseReturnValue(). 122*9880d681SAndroid Build Coastguard Worker Constant *RetainAutoreleaseRV; 123*9880d681SAndroid Build Coastguard Worker getVoidRetI8XEntryPoint(Constant * & Decl,const char * Name)124*9880d681SAndroid Build Coastguard Worker Constant *getVoidRetI8XEntryPoint(Constant *&Decl, 125*9880d681SAndroid Build Coastguard Worker const char *Name) { 126*9880d681SAndroid Build Coastguard Worker if (Decl) 127*9880d681SAndroid Build Coastguard Worker return Decl; 128*9880d681SAndroid Build Coastguard Worker 129*9880d681SAndroid Build Coastguard Worker LLVMContext &C = TheModule->getContext(); 130*9880d681SAndroid Build Coastguard Worker Type *Params[] = { PointerType::getUnqual(Type::getInt8Ty(C)) }; 131*9880d681SAndroid Build Coastguard Worker AttributeSet Attr = 132*9880d681SAndroid Build Coastguard Worker AttributeSet().addAttribute(C, AttributeSet::FunctionIndex, 133*9880d681SAndroid Build Coastguard Worker Attribute::NoUnwind); 134*9880d681SAndroid Build Coastguard Worker FunctionType *Fty = FunctionType::get(Type::getVoidTy(C), Params, 135*9880d681SAndroid Build Coastguard Worker /*isVarArg=*/false); 136*9880d681SAndroid Build Coastguard Worker return Decl = TheModule->getOrInsertFunction(Name, Fty, Attr); 137*9880d681SAndroid Build Coastguard Worker } 138*9880d681SAndroid Build Coastguard Worker 139*9880d681SAndroid Build Coastguard Worker Constant *getI8XRetI8XEntryPoint(Constant *& Decl, 140*9880d681SAndroid Build Coastguard Worker const char *Name, 141*9880d681SAndroid Build Coastguard Worker bool NoUnwind = false) { 142*9880d681SAndroid Build Coastguard Worker if (Decl) 143*9880d681SAndroid Build Coastguard Worker return Decl; 144*9880d681SAndroid Build Coastguard Worker 145*9880d681SAndroid Build Coastguard Worker LLVMContext &C = TheModule->getContext(); 146*9880d681SAndroid Build Coastguard Worker Type *I8X = PointerType::getUnqual(Type::getInt8Ty(C)); 147*9880d681SAndroid Build Coastguard Worker Type *Params[] = { I8X }; 148*9880d681SAndroid Build Coastguard Worker FunctionType *Fty = FunctionType::get(I8X, Params, /*isVarArg=*/false); 149*9880d681SAndroid Build Coastguard Worker AttributeSet Attr = AttributeSet(); 150*9880d681SAndroid Build Coastguard Worker 151*9880d681SAndroid Build Coastguard Worker if (NoUnwind) 152*9880d681SAndroid Build Coastguard Worker Attr = Attr.addAttribute(C, AttributeSet::FunctionIndex, 153*9880d681SAndroid Build Coastguard Worker Attribute::NoUnwind); 154*9880d681SAndroid Build Coastguard Worker 155*9880d681SAndroid Build Coastguard Worker return Decl = TheModule->getOrInsertFunction(Name, Fty, Attr); 156*9880d681SAndroid Build Coastguard Worker } 157*9880d681SAndroid Build Coastguard Worker getI8XRetI8XXI8XEntryPoint(Constant * & Decl,const char * Name)158*9880d681SAndroid Build Coastguard Worker Constant *getI8XRetI8XXI8XEntryPoint(Constant *&Decl, 159*9880d681SAndroid Build Coastguard Worker const char *Name) { 160*9880d681SAndroid Build Coastguard Worker if (Decl) 161*9880d681SAndroid Build Coastguard Worker return Decl; 162*9880d681SAndroid Build Coastguard Worker 163*9880d681SAndroid Build Coastguard Worker LLVMContext &C = TheModule->getContext(); 164*9880d681SAndroid Build Coastguard Worker Type *I8X = PointerType::getUnqual(Type::getInt8Ty(C)); 165*9880d681SAndroid Build Coastguard Worker Type *I8XX = PointerType::getUnqual(I8X); 166*9880d681SAndroid Build Coastguard Worker Type *Params[] = { I8XX, I8X }; 167*9880d681SAndroid Build Coastguard Worker 168*9880d681SAndroid Build Coastguard Worker AttributeSet Attr = 169*9880d681SAndroid Build Coastguard Worker AttributeSet().addAttribute(C, AttributeSet::FunctionIndex, 170*9880d681SAndroid Build Coastguard Worker Attribute::NoUnwind); 171*9880d681SAndroid Build Coastguard Worker Attr = Attr.addAttribute(C, 1, Attribute::NoCapture); 172*9880d681SAndroid Build Coastguard Worker 173*9880d681SAndroid Build Coastguard Worker FunctionType *Fty = FunctionType::get(Type::getVoidTy(C), Params, 174*9880d681SAndroid Build Coastguard Worker /*isVarArg=*/false); 175*9880d681SAndroid Build Coastguard Worker 176*9880d681SAndroid Build Coastguard Worker return Decl = TheModule->getOrInsertFunction(Name, Fty, Attr); 177*9880d681SAndroid Build Coastguard Worker } 178*9880d681SAndroid Build Coastguard Worker 179*9880d681SAndroid Build Coastguard Worker }; // class ARCRuntimeEntryPoints 180*9880d681SAndroid Build Coastguard Worker 181*9880d681SAndroid Build Coastguard Worker } // namespace objcarc 182*9880d681SAndroid Build Coastguard Worker } // namespace llvm 183*9880d681SAndroid Build Coastguard Worker 184*9880d681SAndroid Build Coastguard Worker #endif 185