//===- 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/IR/Attributes.h" #include "llvm/IR/Intrinsics.h" #include "llvm/Support/ErrorHandling.h" #include namespace llvm { class Function; class Module; 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