| //===- ARCRuntimeEntryPoints.h - ObjC ARC Optimization ----------*- C++ -*-===// |
| // |
| // The LLVM Compiler Infrastructure |
| // |
| // This file is distributed under the University of Illinois Open Source |
| // License. See LICENSE.TXT for details. |
| // |
| //===----------------------------------------------------------------------===// |
| // |
| /// \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/Module.h" |
| #include "llvm/IR/Type.h" |
| #include "llvm/Support/ErrorHandling.h" |
| #include <cassert> |
| |
| namespace llvm { |
| |
| class Constant; |
| 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; |
| } |
| |
| Constant *get(ARCRuntimeEntryPointKind kind) { |
| assert(TheModule != nullptr && "Not initialized."); |
| |
| switch (kind) { |
| case ARCRuntimeEntryPointKind::AutoreleaseRV: |
| return getI8XRetI8XEntryPoint(AutoreleaseRV, |
| "objc_autoreleaseReturnValue", true); |
| case ARCRuntimeEntryPointKind::Release: |
| return getVoidRetI8XEntryPoint(Release, "objc_release"); |
| case ARCRuntimeEntryPointKind::Retain: |
| return getI8XRetI8XEntryPoint(Retain, "objc_retain", true); |
| case ARCRuntimeEntryPointKind::RetainBlock: |
| return getI8XRetI8XEntryPoint(RetainBlock, "objc_retainBlock", false); |
| case ARCRuntimeEntryPointKind::Autorelease: |
| return getI8XRetI8XEntryPoint(Autorelease, "objc_autorelease", true); |
| case ARCRuntimeEntryPointKind::StoreStrong: |
| return getI8XRetI8XXI8XEntryPoint(StoreStrong, "objc_storeStrong"); |
| case ARCRuntimeEntryPointKind::RetainRV: |
| return getI8XRetI8XEntryPoint(RetainRV, |
| "objc_retainAutoreleasedReturnValue", true); |
| case ARCRuntimeEntryPointKind::RetainAutorelease: |
| return getI8XRetI8XEntryPoint(RetainAutorelease, "objc_retainAutorelease", |
| true); |
| case ARCRuntimeEntryPointKind::RetainAutoreleaseRV: |
| return getI8XRetI8XEntryPoint(RetainAutoreleaseRV, |
| "objc_retainAutoreleaseReturnValue", true); |
| } |
| |
| 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. |
| Constant *AutoreleaseRV = nullptr; |
| |
| /// Declaration for ObjC runtime function objc_release. |
| Constant *Release = nullptr; |
| |
| /// Declaration for ObjC runtime function objc_retain. |
| Constant *Retain = nullptr; |
| |
| /// Declaration for ObjC runtime function objc_retainBlock. |
| Constant *RetainBlock = nullptr; |
| |
| /// Declaration for ObjC runtime function objc_autorelease. |
| Constant *Autorelease = nullptr; |
| |
| /// Declaration for objc_storeStrong(). |
| Constant *StoreStrong = nullptr; |
| |
| /// Declaration for objc_retainAutoreleasedReturnValue(). |
| Constant *RetainRV = nullptr; |
| |
| /// Declaration for objc_retainAutorelease(). |
| Constant *RetainAutorelease = nullptr; |
| |
| /// Declaration for objc_retainAutoreleaseReturnValue(). |
| Constant *RetainAutoreleaseRV = nullptr; |
| |
| Constant *getVoidRetI8XEntryPoint(Constant *&Decl, StringRef Name) { |
| if (Decl) |
| return Decl; |
| |
| LLVMContext &C = TheModule->getContext(); |
| Type *Params[] = { PointerType::getUnqual(Type::getInt8Ty(C)) }; |
| AttributeList Attr = AttributeList().addAttribute( |
| C, AttributeList::FunctionIndex, Attribute::NoUnwind); |
| FunctionType *Fty = FunctionType::get(Type::getVoidTy(C), Params, |
| /*isVarArg=*/false); |
| return Decl = TheModule->getOrInsertFunction(Name, Fty, Attr); |
| } |
| |
| Constant *getI8XRetI8XEntryPoint(Constant *&Decl, StringRef Name, |
| bool NoUnwind = false) { |
| if (Decl) |
| return Decl; |
| |
| LLVMContext &C = TheModule->getContext(); |
| Type *I8X = PointerType::getUnqual(Type::getInt8Ty(C)); |
| Type *Params[] = { I8X }; |
| FunctionType *Fty = FunctionType::get(I8X, Params, /*isVarArg=*/false); |
| AttributeList Attr = AttributeList(); |
| |
| if (NoUnwind) |
| Attr = Attr.addAttribute(C, AttributeList::FunctionIndex, |
| Attribute::NoUnwind); |
| |
| return Decl = TheModule->getOrInsertFunction(Name, Fty, Attr); |
| } |
| |
| Constant *getI8XRetI8XXI8XEntryPoint(Constant *&Decl, StringRef Name) { |
| if (Decl) |
| return Decl; |
| |
| LLVMContext &C = TheModule->getContext(); |
| Type *I8X = PointerType::getUnqual(Type::getInt8Ty(C)); |
| Type *I8XX = PointerType::getUnqual(I8X); |
| Type *Params[] = { I8XX, I8X }; |
| |
| AttributeList Attr = AttributeList().addAttribute( |
| C, AttributeList::FunctionIndex, Attribute::NoUnwind); |
| Attr = Attr.addParamAttribute(C, 0, Attribute::NoCapture); |
| |
| FunctionType *Fty = FunctionType::get(Type::getVoidTy(C), Params, |
| /*isVarArg=*/false); |
| |
| return Decl = TheModule->getOrInsertFunction(Name, Fty, Attr); |
| } |
| }; |
| |
| } // end namespace objcarc |
| |
| } // end namespace llvm |
| |
| #endif // LLVM_LIB_TRANSFORMS_OBJCARC_ARCRUNTIMEENTRYPOINTS_H |