2013-07-11 02:49:00 +08:00
|
|
|
//===- ARCRuntimeEntryPoints.h - ObjC ARC Optimization --*- C++ -*---------===//
|
2013-07-06 09:39:18 +08:00
|
|
|
//
|
|
|
|
// 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_TRANSFORMS_SCALAR_ARCRUNTIMEENTRYPOINTS_H
|
|
|
|
#define LLVM_TRANSFORMS_SCALAR_ARCRUNTIMEENTRYPOINTS_H
|
|
|
|
|
|
|
|
#include "ObjCARC.h"
|
|
|
|
|
|
|
|
namespace llvm {
|
|
|
|
namespace objcarc {
|
|
|
|
|
|
|
|
/// Declarations for ObjC runtime functions and constants. These are initialized
|
|
|
|
/// lazily to avoid cluttering up the Module with unused declarations.
|
2013-09-12 02:05:11 +08:00
|
|
|
class ARCRuntimeEntryPoints {
|
2013-07-06 09:39:18 +08:00
|
|
|
public:
|
|
|
|
enum EntryPointType {
|
|
|
|
EPT_AutoreleaseRV,
|
|
|
|
EPT_Release,
|
|
|
|
EPT_Retain,
|
|
|
|
EPT_RetainBlock,
|
|
|
|
EPT_Autorelease,
|
|
|
|
EPT_StoreStrong,
|
|
|
|
EPT_RetainRV,
|
|
|
|
EPT_RetainAutorelease,
|
|
|
|
EPT_RetainAutoreleaseRV
|
|
|
|
};
|
|
|
|
|
2013-07-06 09:57:32 +08:00
|
|
|
ARCRuntimeEntryPoints() : TheModule(0),
|
2013-07-06 09:39:18 +08:00
|
|
|
AutoreleaseRV(0),
|
|
|
|
Release(0),
|
|
|
|
Retain(0),
|
|
|
|
RetainBlock(0),
|
|
|
|
Autorelease(0),
|
|
|
|
StoreStrong(0),
|
|
|
|
RetainRV(0),
|
|
|
|
RetainAutorelease(0),
|
|
|
|
RetainAutoreleaseRV(0) { }
|
|
|
|
|
|
|
|
~ARCRuntimeEntryPoints() { }
|
|
|
|
|
|
|
|
void Initialize(Module *M) {
|
2013-07-06 09:57:32 +08:00
|
|
|
TheModule = M;
|
2013-07-07 02:43:05 +08:00
|
|
|
AutoreleaseRV = 0;
|
|
|
|
Release = 0;
|
|
|
|
Retain = 0;
|
|
|
|
RetainBlock = 0;
|
|
|
|
Autorelease = 0;
|
|
|
|
StoreStrong = 0;
|
|
|
|
RetainRV = 0;
|
|
|
|
RetainAutorelease = 0;
|
|
|
|
RetainAutoreleaseRV = 0;
|
2013-07-06 09:39:18 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
Constant *get(const EntryPointType entry) {
|
2013-07-06 09:57:32 +08:00
|
|
|
assert(TheModule != 0 && "Not initialized.");
|
2013-07-06 09:39:18 +08:00
|
|
|
|
|
|
|
switch (entry) {
|
|
|
|
case EPT_AutoreleaseRV:
|
|
|
|
return getI8XRetI8XEntryPoint(AutoreleaseRV,
|
|
|
|
"objc_autoreleaseReturnValue", true);
|
|
|
|
case EPT_Release:
|
|
|
|
return getVoidRetI8XEntryPoint(Release, "objc_release");
|
|
|
|
case EPT_Retain:
|
|
|
|
return getI8XRetI8XEntryPoint(Retain, "objc_retain", true);
|
|
|
|
case EPT_RetainBlock:
|
|
|
|
return getI8XRetI8XEntryPoint(RetainBlock, "objc_retainBlock", false);
|
|
|
|
case EPT_Autorelease:
|
|
|
|
return getI8XRetI8XEntryPoint(Autorelease, "objc_autorelease", true);
|
|
|
|
case EPT_StoreStrong:
|
|
|
|
return getI8XRetI8XXI8XEntryPoint(StoreStrong, "objc_storeStrong");
|
2013-07-06 10:18:56 +08:00
|
|
|
case EPT_RetainRV:
|
|
|
|
return getI8XRetI8XEntryPoint(RetainRV,
|
|
|
|
"objc_retainAutoreleasedReturnValue", true);
|
2013-07-06 09:39:18 +08:00
|
|
|
case EPT_RetainAutorelease:
|
|
|
|
return getI8XRetI8XEntryPoint(RetainAutorelease, "objc_retainAutorelease",
|
|
|
|
true);
|
|
|
|
case EPT_RetainAutoreleaseRV:
|
|
|
|
return getI8XRetI8XEntryPoint(RetainAutoreleaseRV,
|
|
|
|
"objc_retainAutoreleaseReturnValue", true);
|
|
|
|
}
|
2013-07-06 10:18:56 +08:00
|
|
|
|
|
|
|
llvm_unreachable("Switch should be a covered switch.");
|
2013-07-06 09:39:18 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
private:
|
|
|
|
/// Cached reference to the module which we will insert declarations into.
|
2013-07-06 09:57:32 +08:00
|
|
|
Module *TheModule;
|
2013-07-06 09:39:18 +08:00
|
|
|
|
|
|
|
/// Declaration for ObjC runtime function objc_autoreleaseReturnValue.
|
|
|
|
Constant *AutoreleaseRV;
|
|
|
|
/// Declaration for ObjC runtime function objc_release.
|
|
|
|
Constant *Release;
|
|
|
|
/// Declaration for ObjC runtime function objc_retain.
|
|
|
|
Constant *Retain;
|
|
|
|
/// Declaration for ObjC runtime function objc_retainBlock.
|
|
|
|
Constant *RetainBlock;
|
|
|
|
/// Declaration for ObjC runtime function objc_autorelease.
|
|
|
|
Constant *Autorelease;
|
|
|
|
/// Declaration for objc_storeStrong().
|
|
|
|
Constant *StoreStrong;
|
|
|
|
/// Declaration for objc_retainAutoreleasedReturnValue().
|
|
|
|
Constant *RetainRV;
|
|
|
|
/// Declaration for objc_retainAutorelease().
|
|
|
|
Constant *RetainAutorelease;
|
|
|
|
/// Declaration for objc_retainAutoreleaseReturnValue().
|
|
|
|
Constant *RetainAutoreleaseRV;
|
|
|
|
|
|
|
|
Constant *getVoidRetI8XEntryPoint(Constant *&Decl,
|
|
|
|
const char *Name) {
|
|
|
|
if (Decl)
|
|
|
|
return Decl;
|
|
|
|
|
2013-07-06 09:57:32 +08:00
|
|
|
LLVMContext &C = TheModule->getContext();
|
2013-07-06 09:39:18 +08:00
|
|
|
Type *Params[] = { PointerType::getUnqual(Type::getInt8Ty(C)) };
|
|
|
|
AttributeSet Attr =
|
2013-07-06 09:57:32 +08:00
|
|
|
AttributeSet().addAttribute(C, AttributeSet::FunctionIndex,
|
2013-07-06 09:39:18 +08:00
|
|
|
Attribute::NoUnwind);
|
|
|
|
FunctionType *Fty = FunctionType::get(Type::getVoidTy(C), Params,
|
|
|
|
/*isVarArg=*/false);
|
2013-07-06 09:57:32 +08:00
|
|
|
return Decl = TheModule->getOrInsertFunction(Name, Fty, Attr);
|
2013-07-06 09:39:18 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
Constant *getI8XRetI8XEntryPoint(Constant *& Decl,
|
|
|
|
const char *Name,
|
|
|
|
bool NoUnwind = false) {
|
|
|
|
if (Decl)
|
|
|
|
return Decl;
|
|
|
|
|
2013-07-06 09:57:32 +08:00
|
|
|
LLVMContext &C = TheModule->getContext();
|
2013-07-06 09:39:18 +08:00
|
|
|
Type *I8X = PointerType::getUnqual(Type::getInt8Ty(C));
|
|
|
|
Type *Params[] = { I8X };
|
|
|
|
FunctionType *Fty = FunctionType::get(I8X, Params, /*isVarArg=*/false);
|
|
|
|
AttributeSet Attr = AttributeSet();
|
|
|
|
|
|
|
|
if (NoUnwind)
|
2013-07-06 09:57:32 +08:00
|
|
|
Attr = Attr.addAttribute(C, AttributeSet::FunctionIndex,
|
2013-07-06 09:39:18 +08:00
|
|
|
Attribute::NoUnwind);
|
|
|
|
|
2013-07-06 09:57:32 +08:00
|
|
|
return Decl = TheModule->getOrInsertFunction(Name, Fty, Attr);
|
2013-07-06 09:39:18 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
Constant *getI8XRetI8XXI8XEntryPoint(Constant *&Decl,
|
|
|
|
const char *Name) {
|
|
|
|
if (Decl)
|
|
|
|
return Decl;
|
|
|
|
|
2013-07-06 09:57:32 +08:00
|
|
|
LLVMContext &C = TheModule->getContext();
|
2013-07-06 09:39:18 +08:00
|
|
|
Type *I8X = PointerType::getUnqual(Type::getInt8Ty(C));
|
|
|
|
Type *I8XX = PointerType::getUnqual(I8X);
|
|
|
|
Type *Params[] = { I8XX, I8X };
|
|
|
|
|
|
|
|
AttributeSet Attr =
|
2013-07-06 09:57:32 +08:00
|
|
|
AttributeSet().addAttribute(C, AttributeSet::FunctionIndex,
|
2013-07-06 09:39:18 +08:00
|
|
|
Attribute::NoUnwind);
|
2013-07-06 09:57:32 +08:00
|
|
|
Attr = Attr.addAttribute(C, 1, Attribute::NoCapture);
|
2013-07-06 09:39:18 +08:00
|
|
|
|
|
|
|
FunctionType *Fty = FunctionType::get(Type::getVoidTy(C), Params,
|
|
|
|
/*isVarArg=*/false);
|
|
|
|
|
2013-07-06 09:57:32 +08:00
|
|
|
return Decl = TheModule->getOrInsertFunction(Name, Fty, Attr);
|
2013-07-06 09:39:18 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
}; // class ARCRuntimeEntryPoints
|
|
|
|
|
|
|
|
} // namespace objcarc
|
|
|
|
} // namespace llvm
|
|
|
|
|
|
|
|
#endif // LLVM_TRANSFORMS_SCALAR_ARCRUNTIMEENTRYPOINTS_H
|