Home | History | Annotate | Download | only in ObjCARC
      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