1023d2bbbbedc6ed991b11381a987673133be2c81Michael Gottesman//===- ARCRuntimeEntryPoints.h - ObjC ARC Optimization --*- C++ -*---------===//
27ec67156b060ee4e0aac35eed24088ebcbe40aeeMichael Gottesman//
37ec67156b060ee4e0aac35eed24088ebcbe40aeeMichael Gottesman//                     The LLVM Compiler Infrastructure
47ec67156b060ee4e0aac35eed24088ebcbe40aeeMichael Gottesman//
57ec67156b060ee4e0aac35eed24088ebcbe40aeeMichael Gottesman// This file is distributed under the University of Illinois Open Source
67ec67156b060ee4e0aac35eed24088ebcbe40aeeMichael Gottesman// License. See LICENSE.TXT for details.
77ec67156b060ee4e0aac35eed24088ebcbe40aeeMichael Gottesman//
87ec67156b060ee4e0aac35eed24088ebcbe40aeeMichael Gottesman//===----------------------------------------------------------------------===//
97ec67156b060ee4e0aac35eed24088ebcbe40aeeMichael Gottesman/// \file
107ec67156b060ee4e0aac35eed24088ebcbe40aeeMichael Gottesman/// This file contains a class ARCRuntimeEntryPoints for use in
117ec67156b060ee4e0aac35eed24088ebcbe40aeeMichael Gottesman/// creating/managing references to entry points to the arc objective c runtime.
127ec67156b060ee4e0aac35eed24088ebcbe40aeeMichael Gottesman///
137ec67156b060ee4e0aac35eed24088ebcbe40aeeMichael Gottesman/// WARNING: This file knows about certain library functions. It recognizes them
147ec67156b060ee4e0aac35eed24088ebcbe40aeeMichael Gottesman/// by name, and hardwires knowledge of their semantics.
157ec67156b060ee4e0aac35eed24088ebcbe40aeeMichael Gottesman///
167ec67156b060ee4e0aac35eed24088ebcbe40aeeMichael Gottesman/// WARNING: This file knows about how certain Objective-C library functions are
177ec67156b060ee4e0aac35eed24088ebcbe40aeeMichael Gottesman/// used. Naive LLVM IR transformations which would otherwise be
187ec67156b060ee4e0aac35eed24088ebcbe40aeeMichael Gottesman/// behavior-preserving may break these assumptions.
197ec67156b060ee4e0aac35eed24088ebcbe40aeeMichael Gottesman///
207ec67156b060ee4e0aac35eed24088ebcbe40aeeMichael Gottesman//===----------------------------------------------------------------------===//
217ec67156b060ee4e0aac35eed24088ebcbe40aeeMichael Gottesman
227ec67156b060ee4e0aac35eed24088ebcbe40aeeMichael Gottesman#ifndef LLVM_TRANSFORMS_SCALAR_ARCRUNTIMEENTRYPOINTS_H
237ec67156b060ee4e0aac35eed24088ebcbe40aeeMichael Gottesman#define LLVM_TRANSFORMS_SCALAR_ARCRUNTIMEENTRYPOINTS_H
247ec67156b060ee4e0aac35eed24088ebcbe40aeeMichael Gottesman
257ec67156b060ee4e0aac35eed24088ebcbe40aeeMichael Gottesman#include "ObjCARC.h"
267ec67156b060ee4e0aac35eed24088ebcbe40aeeMichael Gottesman
277ec67156b060ee4e0aac35eed24088ebcbe40aeeMichael Gottesmannamespace llvm {
287ec67156b060ee4e0aac35eed24088ebcbe40aeeMichael Gottesmannamespace objcarc {
297ec67156b060ee4e0aac35eed24088ebcbe40aeeMichael Gottesman
307ec67156b060ee4e0aac35eed24088ebcbe40aeeMichael Gottesman/// Declarations for ObjC runtime functions and constants. These are initialized
317ec67156b060ee4e0aac35eed24088ebcbe40aeeMichael Gottesman/// lazily to avoid cluttering up the Module with unused declarations.
327ec67156b060ee4e0aac35eed24088ebcbe40aeeMichael Gottesmanclass ARCRuntimeEntryPoints {
337ec67156b060ee4e0aac35eed24088ebcbe40aeeMichael Gottesmanpublic:
347ec67156b060ee4e0aac35eed24088ebcbe40aeeMichael Gottesman  enum EntryPointType {
357ec67156b060ee4e0aac35eed24088ebcbe40aeeMichael Gottesman    EPT_AutoreleaseRV,
367ec67156b060ee4e0aac35eed24088ebcbe40aeeMichael Gottesman    EPT_Release,
377ec67156b060ee4e0aac35eed24088ebcbe40aeeMichael Gottesman    EPT_Retain,
387ec67156b060ee4e0aac35eed24088ebcbe40aeeMichael Gottesman    EPT_RetainBlock,
397ec67156b060ee4e0aac35eed24088ebcbe40aeeMichael Gottesman    EPT_Autorelease,
407ec67156b060ee4e0aac35eed24088ebcbe40aeeMichael Gottesman    EPT_StoreStrong,
417ec67156b060ee4e0aac35eed24088ebcbe40aeeMichael Gottesman    EPT_RetainRV,
427ec67156b060ee4e0aac35eed24088ebcbe40aeeMichael Gottesman    EPT_RetainAutorelease,
437ec67156b060ee4e0aac35eed24088ebcbe40aeeMichael Gottesman    EPT_RetainAutoreleaseRV
447ec67156b060ee4e0aac35eed24088ebcbe40aeeMichael Gottesman  };
457ec67156b060ee4e0aac35eed24088ebcbe40aeeMichael Gottesman
46dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines  ARCRuntimeEntryPoints() : TheModule(nullptr),
47dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines                            AutoreleaseRV(nullptr),
48dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines                            Release(nullptr),
49dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines                            Retain(nullptr),
50dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines                            RetainBlock(nullptr),
51dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines                            Autorelease(nullptr),
52dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines                            StoreStrong(nullptr),
53dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines                            RetainRV(nullptr),
54dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines                            RetainAutorelease(nullptr),
55dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines                            RetainAutoreleaseRV(nullptr) { }
567ec67156b060ee4e0aac35eed24088ebcbe40aeeMichael Gottesman
577ec67156b060ee4e0aac35eed24088ebcbe40aeeMichael Gottesman  ~ARCRuntimeEntryPoints() { }
587ec67156b060ee4e0aac35eed24088ebcbe40aeeMichael Gottesman
597ec67156b060ee4e0aac35eed24088ebcbe40aeeMichael Gottesman  void Initialize(Module *M) {
60c3e6edba384e023da4e974faca4e28b2276d575fMichael Gottesman    TheModule = M;
61dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines    AutoreleaseRV = nullptr;
62dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines    Release = nullptr;
63dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines    Retain = nullptr;
64dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines    RetainBlock = nullptr;
65dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines    Autorelease = nullptr;
66dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines    StoreStrong = nullptr;
67dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines    RetainRV = nullptr;
68dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines    RetainAutorelease = nullptr;
69dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines    RetainAutoreleaseRV = nullptr;
707ec67156b060ee4e0aac35eed24088ebcbe40aeeMichael Gottesman  }
717ec67156b060ee4e0aac35eed24088ebcbe40aeeMichael Gottesman
727ec67156b060ee4e0aac35eed24088ebcbe40aeeMichael Gottesman  Constant *get(const EntryPointType entry) {
73dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines    assert(TheModule != nullptr && "Not initialized.");
747ec67156b060ee4e0aac35eed24088ebcbe40aeeMichael Gottesman
757ec67156b060ee4e0aac35eed24088ebcbe40aeeMichael Gottesman    switch (entry) {
767ec67156b060ee4e0aac35eed24088ebcbe40aeeMichael Gottesman    case EPT_AutoreleaseRV:
777ec67156b060ee4e0aac35eed24088ebcbe40aeeMichael Gottesman      return getI8XRetI8XEntryPoint(AutoreleaseRV,
787ec67156b060ee4e0aac35eed24088ebcbe40aeeMichael Gottesman                                    "objc_autoreleaseReturnValue", true);
797ec67156b060ee4e0aac35eed24088ebcbe40aeeMichael Gottesman    case EPT_Release:
807ec67156b060ee4e0aac35eed24088ebcbe40aeeMichael Gottesman      return getVoidRetI8XEntryPoint(Release, "objc_release");
817ec67156b060ee4e0aac35eed24088ebcbe40aeeMichael Gottesman    case EPT_Retain:
827ec67156b060ee4e0aac35eed24088ebcbe40aeeMichael Gottesman      return getI8XRetI8XEntryPoint(Retain, "objc_retain", true);
837ec67156b060ee4e0aac35eed24088ebcbe40aeeMichael Gottesman    case EPT_RetainBlock:
847ec67156b060ee4e0aac35eed24088ebcbe40aeeMichael Gottesman      return getI8XRetI8XEntryPoint(RetainBlock, "objc_retainBlock", false);
857ec67156b060ee4e0aac35eed24088ebcbe40aeeMichael Gottesman    case EPT_Autorelease:
867ec67156b060ee4e0aac35eed24088ebcbe40aeeMichael Gottesman      return getI8XRetI8XEntryPoint(Autorelease, "objc_autorelease", true);
877ec67156b060ee4e0aac35eed24088ebcbe40aeeMichael Gottesman    case EPT_StoreStrong:
887ec67156b060ee4e0aac35eed24088ebcbe40aeeMichael Gottesman      return getI8XRetI8XXI8XEntryPoint(StoreStrong, "objc_storeStrong");
89462e998f076b625507d134c8c341f8cf960d1eb0Michael Gottesman    case EPT_RetainRV:
90462e998f076b625507d134c8c341f8cf960d1eb0Michael Gottesman      return getI8XRetI8XEntryPoint(RetainRV,
91462e998f076b625507d134c8c341f8cf960d1eb0Michael Gottesman                                    "objc_retainAutoreleasedReturnValue", true);
927ec67156b060ee4e0aac35eed24088ebcbe40aeeMichael Gottesman    case EPT_RetainAutorelease:
937ec67156b060ee4e0aac35eed24088ebcbe40aeeMichael Gottesman      return getI8XRetI8XEntryPoint(RetainAutorelease, "objc_retainAutorelease",
947ec67156b060ee4e0aac35eed24088ebcbe40aeeMichael Gottesman                                    true);
957ec67156b060ee4e0aac35eed24088ebcbe40aeeMichael Gottesman    case EPT_RetainAutoreleaseRV:
967ec67156b060ee4e0aac35eed24088ebcbe40aeeMichael Gottesman      return getI8XRetI8XEntryPoint(RetainAutoreleaseRV,
977ec67156b060ee4e0aac35eed24088ebcbe40aeeMichael Gottesman                                    "objc_retainAutoreleaseReturnValue", true);
987ec67156b060ee4e0aac35eed24088ebcbe40aeeMichael Gottesman    }
99462e998f076b625507d134c8c341f8cf960d1eb0Michael Gottesman
100462e998f076b625507d134c8c341f8cf960d1eb0Michael Gottesman    llvm_unreachable("Switch should be a covered switch.");
1017ec67156b060ee4e0aac35eed24088ebcbe40aeeMichael Gottesman  }
1027ec67156b060ee4e0aac35eed24088ebcbe40aeeMichael Gottesman
1037ec67156b060ee4e0aac35eed24088ebcbe40aeeMichael Gottesmanprivate:
1047ec67156b060ee4e0aac35eed24088ebcbe40aeeMichael Gottesman  /// Cached reference to the module which we will insert declarations into.
105c3e6edba384e023da4e974faca4e28b2276d575fMichael Gottesman  Module *TheModule;
1067ec67156b060ee4e0aac35eed24088ebcbe40aeeMichael Gottesman
1077ec67156b060ee4e0aac35eed24088ebcbe40aeeMichael Gottesman  /// Declaration for ObjC runtime function objc_autoreleaseReturnValue.
1087ec67156b060ee4e0aac35eed24088ebcbe40aeeMichael Gottesman  Constant *AutoreleaseRV;
1097ec67156b060ee4e0aac35eed24088ebcbe40aeeMichael Gottesman  /// Declaration for ObjC runtime function objc_release.
1107ec67156b060ee4e0aac35eed24088ebcbe40aeeMichael Gottesman  Constant *Release;
1117ec67156b060ee4e0aac35eed24088ebcbe40aeeMichael Gottesman  /// Declaration for ObjC runtime function objc_retain.
1127ec67156b060ee4e0aac35eed24088ebcbe40aeeMichael Gottesman  Constant *Retain;
1137ec67156b060ee4e0aac35eed24088ebcbe40aeeMichael Gottesman  /// Declaration for ObjC runtime function objc_retainBlock.
1147ec67156b060ee4e0aac35eed24088ebcbe40aeeMichael Gottesman  Constant *RetainBlock;
1157ec67156b060ee4e0aac35eed24088ebcbe40aeeMichael Gottesman  /// Declaration for ObjC runtime function objc_autorelease.
1167ec67156b060ee4e0aac35eed24088ebcbe40aeeMichael Gottesman  Constant *Autorelease;
1177ec67156b060ee4e0aac35eed24088ebcbe40aeeMichael Gottesman  /// Declaration for objc_storeStrong().
1187ec67156b060ee4e0aac35eed24088ebcbe40aeeMichael Gottesman  Constant *StoreStrong;
1197ec67156b060ee4e0aac35eed24088ebcbe40aeeMichael Gottesman  /// Declaration for objc_retainAutoreleasedReturnValue().
1207ec67156b060ee4e0aac35eed24088ebcbe40aeeMichael Gottesman  Constant *RetainRV;
1217ec67156b060ee4e0aac35eed24088ebcbe40aeeMichael Gottesman  /// Declaration for objc_retainAutorelease().
1227ec67156b060ee4e0aac35eed24088ebcbe40aeeMichael Gottesman  Constant *RetainAutorelease;
1237ec67156b060ee4e0aac35eed24088ebcbe40aeeMichael Gottesman  /// Declaration for objc_retainAutoreleaseReturnValue().
1247ec67156b060ee4e0aac35eed24088ebcbe40aeeMichael Gottesman  Constant *RetainAutoreleaseRV;
1257ec67156b060ee4e0aac35eed24088ebcbe40aeeMichael Gottesman
1267ec67156b060ee4e0aac35eed24088ebcbe40aeeMichael Gottesman  Constant *getVoidRetI8XEntryPoint(Constant *&Decl,
1277ec67156b060ee4e0aac35eed24088ebcbe40aeeMichael Gottesman                                    const char *Name) {
1287ec67156b060ee4e0aac35eed24088ebcbe40aeeMichael Gottesman    if (Decl)
1297ec67156b060ee4e0aac35eed24088ebcbe40aeeMichael Gottesman      return Decl;
1307ec67156b060ee4e0aac35eed24088ebcbe40aeeMichael Gottesman
131c3e6edba384e023da4e974faca4e28b2276d575fMichael Gottesman    LLVMContext &C = TheModule->getContext();
1327ec67156b060ee4e0aac35eed24088ebcbe40aeeMichael Gottesman    Type *Params[] = { PointerType::getUnqual(Type::getInt8Ty(C)) };
1337ec67156b060ee4e0aac35eed24088ebcbe40aeeMichael Gottesman    AttributeSet Attr =
134c3e6edba384e023da4e974faca4e28b2276d575fMichael Gottesman      AttributeSet().addAttribute(C, AttributeSet::FunctionIndex,
1357ec67156b060ee4e0aac35eed24088ebcbe40aeeMichael Gottesman                                  Attribute::NoUnwind);
1367ec67156b060ee4e0aac35eed24088ebcbe40aeeMichael Gottesman    FunctionType *Fty = FunctionType::get(Type::getVoidTy(C), Params,
1377ec67156b060ee4e0aac35eed24088ebcbe40aeeMichael Gottesman                                          /*isVarArg=*/false);
138c3e6edba384e023da4e974faca4e28b2276d575fMichael Gottesman    return Decl = TheModule->getOrInsertFunction(Name, Fty, Attr);
1397ec67156b060ee4e0aac35eed24088ebcbe40aeeMichael Gottesman  }
1407ec67156b060ee4e0aac35eed24088ebcbe40aeeMichael Gottesman
1417ec67156b060ee4e0aac35eed24088ebcbe40aeeMichael Gottesman  Constant *getI8XRetI8XEntryPoint(Constant *& Decl,
1427ec67156b060ee4e0aac35eed24088ebcbe40aeeMichael Gottesman                                   const char *Name,
1437ec67156b060ee4e0aac35eed24088ebcbe40aeeMichael Gottesman                                   bool NoUnwind = false) {
1447ec67156b060ee4e0aac35eed24088ebcbe40aeeMichael Gottesman    if (Decl)
1457ec67156b060ee4e0aac35eed24088ebcbe40aeeMichael Gottesman      return Decl;
1467ec67156b060ee4e0aac35eed24088ebcbe40aeeMichael Gottesman
147c3e6edba384e023da4e974faca4e28b2276d575fMichael Gottesman    LLVMContext &C = TheModule->getContext();
1487ec67156b060ee4e0aac35eed24088ebcbe40aeeMichael Gottesman    Type *I8X = PointerType::getUnqual(Type::getInt8Ty(C));
1497ec67156b060ee4e0aac35eed24088ebcbe40aeeMichael Gottesman    Type *Params[] = { I8X };
1507ec67156b060ee4e0aac35eed24088ebcbe40aeeMichael Gottesman    FunctionType *Fty = FunctionType::get(I8X, Params, /*isVarArg=*/false);
1517ec67156b060ee4e0aac35eed24088ebcbe40aeeMichael Gottesman    AttributeSet Attr = AttributeSet();
1527ec67156b060ee4e0aac35eed24088ebcbe40aeeMichael Gottesman
1537ec67156b060ee4e0aac35eed24088ebcbe40aeeMichael Gottesman    if (NoUnwind)
154c3e6edba384e023da4e974faca4e28b2276d575fMichael Gottesman      Attr = Attr.addAttribute(C, AttributeSet::FunctionIndex,
1557ec67156b060ee4e0aac35eed24088ebcbe40aeeMichael Gottesman                               Attribute::NoUnwind);
1567ec67156b060ee4e0aac35eed24088ebcbe40aeeMichael Gottesman
157c3e6edba384e023da4e974faca4e28b2276d575fMichael Gottesman    return Decl = TheModule->getOrInsertFunction(Name, Fty, Attr);
1587ec67156b060ee4e0aac35eed24088ebcbe40aeeMichael Gottesman  }
1597ec67156b060ee4e0aac35eed24088ebcbe40aeeMichael Gottesman
1607ec67156b060ee4e0aac35eed24088ebcbe40aeeMichael Gottesman  Constant *getI8XRetI8XXI8XEntryPoint(Constant *&Decl,
1617ec67156b060ee4e0aac35eed24088ebcbe40aeeMichael Gottesman                                       const char *Name) {
1627ec67156b060ee4e0aac35eed24088ebcbe40aeeMichael Gottesman    if (Decl)
1637ec67156b060ee4e0aac35eed24088ebcbe40aeeMichael Gottesman      return Decl;
1647ec67156b060ee4e0aac35eed24088ebcbe40aeeMichael Gottesman
165c3e6edba384e023da4e974faca4e28b2276d575fMichael Gottesman    LLVMContext &C = TheModule->getContext();
1667ec67156b060ee4e0aac35eed24088ebcbe40aeeMichael Gottesman    Type *I8X = PointerType::getUnqual(Type::getInt8Ty(C));
1677ec67156b060ee4e0aac35eed24088ebcbe40aeeMichael Gottesman    Type *I8XX = PointerType::getUnqual(I8X);
1687ec67156b060ee4e0aac35eed24088ebcbe40aeeMichael Gottesman    Type *Params[] = { I8XX, I8X };
1697ec67156b060ee4e0aac35eed24088ebcbe40aeeMichael Gottesman
1707ec67156b060ee4e0aac35eed24088ebcbe40aeeMichael Gottesman    AttributeSet Attr =
171c3e6edba384e023da4e974faca4e28b2276d575fMichael Gottesman      AttributeSet().addAttribute(C, AttributeSet::FunctionIndex,
1727ec67156b060ee4e0aac35eed24088ebcbe40aeeMichael Gottesman                                  Attribute::NoUnwind);
173c3e6edba384e023da4e974faca4e28b2276d575fMichael Gottesman    Attr = Attr.addAttribute(C, 1, Attribute::NoCapture);
1747ec67156b060ee4e0aac35eed24088ebcbe40aeeMichael Gottesman
1757ec67156b060ee4e0aac35eed24088ebcbe40aeeMichael Gottesman    FunctionType *Fty = FunctionType::get(Type::getVoidTy(C), Params,
1767ec67156b060ee4e0aac35eed24088ebcbe40aeeMichael Gottesman                                          /*isVarArg=*/false);
1777ec67156b060ee4e0aac35eed24088ebcbe40aeeMichael Gottesman
178c3e6edba384e023da4e974faca4e28b2276d575fMichael Gottesman    return Decl = TheModule->getOrInsertFunction(Name, Fty, Attr);
1797ec67156b060ee4e0aac35eed24088ebcbe40aeeMichael Gottesman  }
1807ec67156b060ee4e0aac35eed24088ebcbe40aeeMichael Gottesman
1817ec67156b060ee4e0aac35eed24088ebcbe40aeeMichael Gottesman}; // class ARCRuntimeEntryPoints
1827ec67156b060ee4e0aac35eed24088ebcbe40aeeMichael Gottesman
1837ec67156b060ee4e0aac35eed24088ebcbe40aeeMichael Gottesman} // namespace objcarc
1847ec67156b060ee4e0aac35eed24088ebcbe40aeeMichael Gottesman} // namespace llvm
1857ec67156b060ee4e0aac35eed24088ebcbe40aeeMichael Gottesman
1867ec67156b060ee4e0aac35eed24088ebcbe40aeeMichael Gottesman#endif // LLVM_TRANSFORMS_SCALAR_ARCRUNTIMEENTRYPOINTS_H
187