|  | //===- ARCRuntimeEntryPoints.h - ObjC ARC Optimization ----------*- C++ -*-===// | 
|  | // | 
|  | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. | 
|  | // See https://llvm.org/LICENSE.txt for license information. | 
|  | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception | 
|  | // | 
|  | //===----------------------------------------------------------------------===// | 
|  | // | 
|  | /// \file | 
|  | /// This file contains a class ARCRuntimeEntryPoints for use in | 
|  | /// creating/managing references to entry points to the arc objective c runtime. | 
|  | /// | 
|  | /// WARNING: This file knows about certain library functions. It recognizes them | 
|  | /// by name, and hardwires knowledge of their semantics. | 
|  | /// | 
|  | /// WARNING: This file knows about how certain Objective-C library functions are | 
|  | /// used. Naive LLVM IR transformations which would otherwise be | 
|  | /// behavior-preserving may break these assumptions. | 
|  | // | 
|  | //===----------------------------------------------------------------------===// | 
|  |  | 
|  | #ifndef LLVM_LIB_TRANSFORMS_OBJCARC_ARCRUNTIMEENTRYPOINTS_H | 
|  | #define LLVM_LIB_TRANSFORMS_OBJCARC_ARCRUNTIMEENTRYPOINTS_H | 
|  |  | 
|  | #include "llvm/ADT/StringRef.h" | 
|  | #include "llvm/IR/Attributes.h" | 
|  | #include "llvm/IR/DerivedTypes.h" | 
|  | #include "llvm/IR/Intrinsics.h" | 
|  | #include "llvm/IR/Module.h" | 
|  | #include "llvm/IR/Type.h" | 
|  | #include "llvm/Support/ErrorHandling.h" | 
|  | #include <cassert> | 
|  |  | 
|  | namespace llvm { | 
|  |  | 
|  | class Function; | 
|  | class LLVMContext; | 
|  |  | 
|  | namespace objcarc { | 
|  |  | 
|  | enum class ARCRuntimeEntryPointKind { | 
|  | AutoreleaseRV, | 
|  | Release, | 
|  | Retain, | 
|  | RetainBlock, | 
|  | Autorelease, | 
|  | StoreStrong, | 
|  | RetainRV, | 
|  | RetainAutorelease, | 
|  | RetainAutoreleaseRV, | 
|  | }; | 
|  |  | 
|  | /// Declarations for ObjC runtime functions and constants. These are initialized | 
|  | /// lazily to avoid cluttering up the Module with unused declarations. | 
|  | class ARCRuntimeEntryPoints { | 
|  | public: | 
|  | ARCRuntimeEntryPoints() = default; | 
|  |  | 
|  | void init(Module *M) { | 
|  | TheModule = M; | 
|  | AutoreleaseRV = nullptr; | 
|  | Release = nullptr; | 
|  | Retain = nullptr; | 
|  | RetainBlock = nullptr; | 
|  | Autorelease = nullptr; | 
|  | StoreStrong = nullptr; | 
|  | RetainRV = nullptr; | 
|  | RetainAutorelease = nullptr; | 
|  | RetainAutoreleaseRV = nullptr; | 
|  | } | 
|  |  | 
|  | Function *get(ARCRuntimeEntryPointKind kind) { | 
|  | assert(TheModule != nullptr && "Not initialized."); | 
|  |  | 
|  | switch (kind) { | 
|  | case ARCRuntimeEntryPointKind::AutoreleaseRV: | 
|  | return getIntrinsicEntryPoint(AutoreleaseRV, | 
|  | Intrinsic::objc_autoreleaseReturnValue); | 
|  | case ARCRuntimeEntryPointKind::Release: | 
|  | return getIntrinsicEntryPoint(Release, Intrinsic::objc_release); | 
|  | case ARCRuntimeEntryPointKind::Retain: | 
|  | return getIntrinsicEntryPoint(Retain, Intrinsic::objc_retain); | 
|  | case ARCRuntimeEntryPointKind::RetainBlock: | 
|  | return getIntrinsicEntryPoint(RetainBlock, Intrinsic::objc_retainBlock); | 
|  | case ARCRuntimeEntryPointKind::Autorelease: | 
|  | return getIntrinsicEntryPoint(Autorelease, Intrinsic::objc_autorelease); | 
|  | case ARCRuntimeEntryPointKind::StoreStrong: | 
|  | return getIntrinsicEntryPoint(StoreStrong, Intrinsic::objc_storeStrong); | 
|  | case ARCRuntimeEntryPointKind::RetainRV: | 
|  | return getIntrinsicEntryPoint(RetainRV, | 
|  | Intrinsic::objc_retainAutoreleasedReturnValue); | 
|  | case ARCRuntimeEntryPointKind::RetainAutorelease: | 
|  | return getIntrinsicEntryPoint(RetainAutorelease, | 
|  | Intrinsic::objc_retainAutorelease); | 
|  | case ARCRuntimeEntryPointKind::RetainAutoreleaseRV: | 
|  | return getIntrinsicEntryPoint(RetainAutoreleaseRV, | 
|  | Intrinsic::objc_retainAutoreleaseReturnValue); | 
|  | } | 
|  |  | 
|  | llvm_unreachable("Switch should be a covered switch."); | 
|  | } | 
|  |  | 
|  | private: | 
|  | /// Cached reference to the module which we will insert declarations into. | 
|  | Module *TheModule = nullptr; | 
|  |  | 
|  | /// Declaration for ObjC runtime function objc_autoreleaseReturnValue. | 
|  | Function *AutoreleaseRV = nullptr; | 
|  |  | 
|  | /// Declaration for ObjC runtime function objc_release. | 
|  | Function *Release = nullptr; | 
|  |  | 
|  | /// Declaration for ObjC runtime function objc_retain. | 
|  | Function *Retain = nullptr; | 
|  |  | 
|  | /// Declaration for ObjC runtime function objc_retainBlock. | 
|  | Function *RetainBlock = nullptr; | 
|  |  | 
|  | /// Declaration for ObjC runtime function objc_autorelease. | 
|  | Function *Autorelease = nullptr; | 
|  |  | 
|  | /// Declaration for objc_storeStrong(). | 
|  | Function *StoreStrong = nullptr; | 
|  |  | 
|  | /// Declaration for objc_retainAutoreleasedReturnValue(). | 
|  | Function *RetainRV = nullptr; | 
|  |  | 
|  | /// Declaration for objc_retainAutorelease(). | 
|  | Function *RetainAutorelease = nullptr; | 
|  |  | 
|  | /// Declaration for objc_retainAutoreleaseReturnValue(). | 
|  | Function *RetainAutoreleaseRV = nullptr; | 
|  |  | 
|  | Function *getIntrinsicEntryPoint(Function *&Decl, Intrinsic::ID IntID) { | 
|  | if (Decl) | 
|  | return Decl; | 
|  |  | 
|  | return Decl = Intrinsic::getDeclaration(TheModule, IntID); | 
|  | } | 
|  | }; | 
|  |  | 
|  | } // end namespace objcarc | 
|  |  | 
|  | } // end namespace llvm | 
|  |  | 
|  | #endif // LLVM_LIB_TRANSFORMS_OBJCARC_ARCRUNTIMEENTRYPOINTS_H |