LLVM API Documentation

ARCRuntimeEntryPoints.h
Go to the documentation of this file.
00001 //===- ARCRuntimeEntryPoints.h - ObjC ARC Optimization --*- C++ -*---------===//
00002 //
00003 //                     The LLVM Compiler Infrastructure
00004 //
00005 // This file is distributed under the University of Illinois Open Source
00006 // License. See LICENSE.TXT for details.
00007 //
00008 //===----------------------------------------------------------------------===//
00009 /// \file
00010 /// This file contains a class ARCRuntimeEntryPoints for use in
00011 /// creating/managing references to entry points to the arc objective c runtime.
00012 ///
00013 /// WARNING: This file knows about certain library functions. It recognizes them
00014 /// by name, and hardwires knowledge of their semantics.
00015 ///
00016 /// WARNING: This file knows about how certain Objective-C library functions are
00017 /// used. Naive LLVM IR transformations which would otherwise be
00018 /// behavior-preserving may break these assumptions.
00019 ///
00020 //===----------------------------------------------------------------------===//
00021 
00022 #ifndef LLVM_LIB_TRANSFORMS_OBJCARC_ARCRUNTIMEENTRYPOINTS_H
00023 #define LLVM_LIB_TRANSFORMS_OBJCARC_ARCRUNTIMEENTRYPOINTS_H
00024 
00025 #include "ObjCARC.h"
00026 
00027 namespace llvm {
00028 namespace objcarc {
00029 
00030 /// Declarations for ObjC runtime functions and constants. These are initialized
00031 /// lazily to avoid cluttering up the Module with unused declarations.
00032 class ARCRuntimeEntryPoints {
00033 public:
00034   enum EntryPointType {
00035     EPT_AutoreleaseRV,
00036     EPT_Release,
00037     EPT_Retain,
00038     EPT_RetainBlock,
00039     EPT_Autorelease,
00040     EPT_StoreStrong,
00041     EPT_RetainRV,
00042     EPT_RetainAutorelease,
00043     EPT_RetainAutoreleaseRV
00044   };
00045 
00046   ARCRuntimeEntryPoints() : TheModule(nullptr),
00047                             AutoreleaseRV(nullptr),
00048                             Release(nullptr),
00049                             Retain(nullptr),
00050                             RetainBlock(nullptr),
00051                             Autorelease(nullptr),
00052                             StoreStrong(nullptr),
00053                             RetainRV(nullptr),
00054                             RetainAutorelease(nullptr),
00055                             RetainAutoreleaseRV(nullptr) { }
00056 
00057   ~ARCRuntimeEntryPoints() { }
00058 
00059   void Initialize(Module *M) {
00060     TheModule = M;
00061     AutoreleaseRV = nullptr;
00062     Release = nullptr;
00063     Retain = nullptr;
00064     RetainBlock = nullptr;
00065     Autorelease = nullptr;
00066     StoreStrong = nullptr;
00067     RetainRV = nullptr;
00068     RetainAutorelease = nullptr;
00069     RetainAutoreleaseRV = nullptr;
00070   }
00071 
00072   Constant *get(const EntryPointType entry) {
00073     assert(TheModule != nullptr && "Not initialized.");
00074 
00075     switch (entry) {
00076     case EPT_AutoreleaseRV:
00077       return getI8XRetI8XEntryPoint(AutoreleaseRV,
00078                                     "objc_autoreleaseReturnValue", true);
00079     case EPT_Release:
00080       return getVoidRetI8XEntryPoint(Release, "objc_release");
00081     case EPT_Retain:
00082       return getI8XRetI8XEntryPoint(Retain, "objc_retain", true);
00083     case EPT_RetainBlock:
00084       return getI8XRetI8XEntryPoint(RetainBlock, "objc_retainBlock", false);
00085     case EPT_Autorelease:
00086       return getI8XRetI8XEntryPoint(Autorelease, "objc_autorelease", true);
00087     case EPT_StoreStrong:
00088       return getI8XRetI8XXI8XEntryPoint(StoreStrong, "objc_storeStrong");
00089     case EPT_RetainRV:
00090       return getI8XRetI8XEntryPoint(RetainRV,
00091                                     "objc_retainAutoreleasedReturnValue", true);
00092     case EPT_RetainAutorelease:
00093       return getI8XRetI8XEntryPoint(RetainAutorelease, "objc_retainAutorelease",
00094                                     true);
00095     case EPT_RetainAutoreleaseRV:
00096       return getI8XRetI8XEntryPoint(RetainAutoreleaseRV,
00097                                     "objc_retainAutoreleaseReturnValue", true);
00098     }
00099 
00100     llvm_unreachable("Switch should be a covered switch.");
00101   }
00102 
00103 private:
00104   /// Cached reference to the module which we will insert declarations into.
00105   Module *TheModule;
00106 
00107   /// Declaration for ObjC runtime function objc_autoreleaseReturnValue.
00108   Constant *AutoreleaseRV;
00109   /// Declaration for ObjC runtime function objc_release.
00110   Constant *Release;
00111   /// Declaration for ObjC runtime function objc_retain.
00112   Constant *Retain;
00113   /// Declaration for ObjC runtime function objc_retainBlock.
00114   Constant *RetainBlock;
00115   /// Declaration for ObjC runtime function objc_autorelease.
00116   Constant *Autorelease;
00117   /// Declaration for objc_storeStrong().
00118   Constant *StoreStrong;
00119   /// Declaration for objc_retainAutoreleasedReturnValue().
00120   Constant *RetainRV;
00121   /// Declaration for objc_retainAutorelease().
00122   Constant *RetainAutorelease;
00123   /// Declaration for objc_retainAutoreleaseReturnValue().
00124   Constant *RetainAutoreleaseRV;
00125 
00126   Constant *getVoidRetI8XEntryPoint(Constant *&Decl,
00127                                     const char *Name) {
00128     if (Decl)
00129       return Decl;
00130 
00131     LLVMContext &C = TheModule->getContext();
00132     Type *Params[] = { PointerType::getUnqual(Type::getInt8Ty(C)) };
00133     AttributeSet Attr =
00134       AttributeSet().addAttribute(C, AttributeSet::FunctionIndex,
00135                                   Attribute::NoUnwind);
00136     FunctionType *Fty = FunctionType::get(Type::getVoidTy(C), Params,
00137                                           /*isVarArg=*/false);
00138     return Decl = TheModule->getOrInsertFunction(Name, Fty, Attr);
00139   }
00140 
00141   Constant *getI8XRetI8XEntryPoint(Constant *& Decl,
00142                                    const char *Name,
00143                                    bool NoUnwind = false) {
00144     if (Decl)
00145       return Decl;
00146 
00147     LLVMContext &C = TheModule->getContext();
00148     Type *I8X = PointerType::getUnqual(Type::getInt8Ty(C));
00149     Type *Params[] = { I8X };
00150     FunctionType *Fty = FunctionType::get(I8X, Params, /*isVarArg=*/false);
00151     AttributeSet Attr = AttributeSet();
00152 
00153     if (NoUnwind)
00154       Attr = Attr.addAttribute(C, AttributeSet::FunctionIndex,
00155                                Attribute::NoUnwind);
00156 
00157     return Decl = TheModule->getOrInsertFunction(Name, Fty, Attr);
00158   }
00159 
00160   Constant *getI8XRetI8XXI8XEntryPoint(Constant *&Decl,
00161                                        const char *Name) {
00162     if (Decl)
00163       return Decl;
00164 
00165     LLVMContext &C = TheModule->getContext();
00166     Type *I8X = PointerType::getUnqual(Type::getInt8Ty(C));
00167     Type *I8XX = PointerType::getUnqual(I8X);
00168     Type *Params[] = { I8XX, I8X };
00169 
00170     AttributeSet Attr =
00171       AttributeSet().addAttribute(C, AttributeSet::FunctionIndex,
00172                                   Attribute::NoUnwind);
00173     Attr = Attr.addAttribute(C, 1, Attribute::NoCapture);
00174 
00175     FunctionType *Fty = FunctionType::get(Type::getVoidTy(C), Params,
00176                                           /*isVarArg=*/false);
00177 
00178     return Decl = TheModule->getOrInsertFunction(Name, Fty, Attr);
00179   }
00180 
00181 }; // class ARCRuntimeEntryPoints
00182 
00183 } // namespace objcarc
00184 } // namespace llvm
00185 
00186 #endif