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_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:
     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 
     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 
     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 
    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 
    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