1
0
mirror of https://github.com/RPCS3/llvm-mirror.git synced 2024-10-20 19:42:54 +02:00
llvm-mirror/include/llvm/ExecutionEngine/Orc/OrcABISupport.h
Lang Hames 9a3ce89b6d [ExecutionEngine][MCJIT][Orc] Replace RuntimeDyld::SymbolInfo with JITSymbol.
This patch replaces RuntimeDyld::SymbolInfo with JITSymbol: A symbol class
that is capable of lazy materialization (i.e. the symbol definition needn't be
emitted until the address is requested). This can be used to support common
and weak symbols in the JIT (though this is not implemented in this patch).

For consistency, RuntimeDyld::SymbolResolver is renamed to JITSymbolResolver.

For space efficiency a new class, JITEvaluatedSymbol, is introduced that
behaves like the old RuntimeDyld::SymbolInfo - i.e. it is just a pair of an
address and symbol flags. Instances of JITEvaluatedSymbol can be used in
symbol-tables to avoid paying the space cost of the materializer.

llvm-svn: 277386
2016-08-01 20:49:11 +00:00

238 lines
9.1 KiB
C++

//===-------------- OrcABISupport.h - ABI support code ---------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// ABI specific code for Orc, e.g. callback assembly.
//
// ABI classes should be part of the JIT *target* process, not the host
// process (except where you're doing hosted JITing and the two are one and the
// same).
//
//===----------------------------------------------------------------------===//
#ifndef LLVM_EXECUTIONENGINE_ORC_ORCABISUPPORT_H
#define LLVM_EXECUTIONENGINE_ORC_ORCABISUPPORT_H
#include "IndirectionUtils.h"
#include "llvm/Support/Memory.h"
#include "llvm/Support/Process.h"
namespace llvm {
namespace orc {
/// Generic ORC ABI support.
///
/// This class can be substituted as the target architecure support class for
/// ORC templates that require one (e.g. IndirectStubsManagers). It does not
/// support lazy JITing however, and any attempt to use that functionality
/// will result in execution of an llvm_unreachable.
class OrcGenericABI {
public:
static const unsigned PointerSize = sizeof(uintptr_t);
static const unsigned TrampolineSize = 1;
static const unsigned ResolverCodeSize = 1;
typedef JITTargetAddress (*JITReentryFn)(void *CallbackMgr,
void *TrampolineId);
static void writeResolverCode(uint8_t *ResolveMem, JITReentryFn Reentry,
void *CallbackMgr) {
llvm_unreachable("writeResolverCode is not supported by the generic host "
"support class");
}
static void writeTrampolines(uint8_t *TrampolineMem, void *ResolverAddr,
unsigned NumTrampolines) {
llvm_unreachable("writeTrampolines is not supported by the generic host "
"support class");
}
class IndirectStubsInfo {
public:
const static unsigned StubSize = 1;
unsigned getNumStubs() const { llvm_unreachable("Not supported"); }
void *getStub(unsigned Idx) const { llvm_unreachable("Not supported"); }
void **getPtr(unsigned Idx) const { llvm_unreachable("Not supported"); }
};
static Error emitIndirectStubsBlock(IndirectStubsInfo &StubsInfo,
unsigned MinStubs, void *InitialPtrVal) {
llvm_unreachable("emitIndirectStubsBlock is not supported by the generic "
"host support class");
}
};
/// @brief Provide information about stub blocks generated by the
/// makeIndirectStubsBlock function.
template <unsigned StubSizeVal> class GenericIndirectStubsInfo {
public:
const static unsigned StubSize = StubSizeVal;
GenericIndirectStubsInfo() : NumStubs(0) {}
GenericIndirectStubsInfo(unsigned NumStubs, sys::OwningMemoryBlock StubsMem)
: NumStubs(NumStubs), StubsMem(std::move(StubsMem)) {}
GenericIndirectStubsInfo(GenericIndirectStubsInfo &&Other)
: NumStubs(Other.NumStubs), StubsMem(std::move(Other.StubsMem)) {
Other.NumStubs = 0;
}
GenericIndirectStubsInfo &operator=(GenericIndirectStubsInfo &&Other) {
NumStubs = Other.NumStubs;
Other.NumStubs = 0;
StubsMem = std::move(Other.StubsMem);
return *this;
}
/// @brief Number of stubs in this block.
unsigned getNumStubs() const { return NumStubs; }
/// @brief Get a pointer to the stub at the given index, which must be in
/// the range 0 .. getNumStubs() - 1.
void *getStub(unsigned Idx) const {
return static_cast<char *>(StubsMem.base()) + Idx * StubSize;
}
/// @brief Get a pointer to the implementation-pointer at the given index,
/// which must be in the range 0 .. getNumStubs() - 1.
void **getPtr(unsigned Idx) const {
char *PtrsBase = static_cast<char *>(StubsMem.base()) + NumStubs * StubSize;
return reinterpret_cast<void **>(PtrsBase) + Idx;
}
private:
unsigned NumStubs;
sys::OwningMemoryBlock StubsMem;
};
class OrcAArch64 {
public:
static const unsigned PointerSize = 8;
static const unsigned TrampolineSize = 12;
static const unsigned ResolverCodeSize = 0x120;
typedef GenericIndirectStubsInfo<8> IndirectStubsInfo;
typedef JITTargetAddress (*JITReentryFn)(void *CallbackMgr,
void *TrampolineId);
/// @brief Write the resolver code into the given memory. The user is be
/// responsible for allocating the memory and setting permissions.
static void writeResolverCode(uint8_t *ResolveMem, JITReentryFn Reentry,
void *CallbackMgr);
/// @brief Write the requsted number of trampolines into the given memory,
/// which must be big enough to hold 1 pointer, plus NumTrampolines
/// trampolines.
static void writeTrampolines(uint8_t *TrampolineMem, void *ResolverAddr,
unsigned NumTrampolines);
/// @brief Emit at least MinStubs worth of indirect call stubs, rounded out to
/// the nearest page size.
///
/// E.g. Asking for 4 stubs on x86-64, where stubs are 8-bytes, with 4k
/// pages will return a block of 512 stubs (4096 / 8 = 512). Asking for 513
/// will return a block of 1024 (2-pages worth).
static Error emitIndirectStubsBlock(IndirectStubsInfo &StubsInfo,
unsigned MinStubs, void *InitialPtrVal);
};
/// @brief X86_64 code that's common to all ABIs.
///
/// X86_64 supports lazy JITing.
class OrcX86_64_Base {
public:
static const unsigned PointerSize = 8;
static const unsigned TrampolineSize = 8;
typedef GenericIndirectStubsInfo<8> IndirectStubsInfo;
/// @brief Write the requsted number of trampolines into the given memory,
/// which must be big enough to hold 1 pointer, plus NumTrampolines
/// trampolines.
static void writeTrampolines(uint8_t *TrampolineMem, void *ResolverAddr,
unsigned NumTrampolines);
/// @brief Emit at least MinStubs worth of indirect call stubs, rounded out to
/// the nearest page size.
///
/// E.g. Asking for 4 stubs on x86-64, where stubs are 8-bytes, with 4k
/// pages will return a block of 512 stubs (4096 / 8 = 512). Asking for 513
/// will return a block of 1024 (2-pages worth).
static Error emitIndirectStubsBlock(IndirectStubsInfo &StubsInfo,
unsigned MinStubs, void *InitialPtrVal);
};
/// @brief X86_64 support for SysV ABI (Linux, MacOSX).
///
/// X86_64_SysV supports lazy JITing.
class OrcX86_64_SysV : public OrcX86_64_Base {
public:
static const unsigned ResolverCodeSize = 0x6C;
typedef JITTargetAddress (*JITReentryFn)(void *CallbackMgr,
void *TrampolineId);
/// @brief Write the resolver code into the given memory. The user is be
/// responsible for allocating the memory and setting permissions.
static void writeResolverCode(uint8_t *ResolveMem, JITReentryFn Reentry,
void *CallbackMgr);
};
/// @brief X86_64 support for Win32.
///
/// X86_64_Win32 supports lazy JITing.
class OrcX86_64_Win32 : public OrcX86_64_Base {
public:
static const unsigned ResolverCodeSize = 0x74;
typedef JITTargetAddress (*JITReentryFn)(void *CallbackMgr,
void *TrampolineId);
/// @brief Write the resolver code into the given memory. The user is be
/// responsible for allocating the memory and setting permissions.
static void writeResolverCode(uint8_t *ResolveMem, JITReentryFn Reentry,
void *CallbackMgr);
};
/// @brief I386 support.
///
/// I386 supports lazy JITing.
class OrcI386 {
public:
static const unsigned PointerSize = 4;
static const unsigned TrampolineSize = 8;
static const unsigned ResolverCodeSize = 0x4a;
typedef GenericIndirectStubsInfo<8> IndirectStubsInfo;
typedef JITTargetAddress (*JITReentryFn)(void *CallbackMgr,
void *TrampolineId);
/// @brief Write the resolver code into the given memory. The user is be
/// responsible for allocating the memory and setting permissions.
static void writeResolverCode(uint8_t *ResolveMem, JITReentryFn Reentry,
void *CallbackMgr);
/// @brief Write the requsted number of trampolines into the given memory,
/// which must be big enough to hold 1 pointer, plus NumTrampolines
/// trampolines.
static void writeTrampolines(uint8_t *TrampolineMem, void *ResolverAddr,
unsigned NumTrampolines);
/// @brief Emit at least MinStubs worth of indirect call stubs, rounded out to
/// the nearest page size.
///
/// E.g. Asking for 4 stubs on i386, where stubs are 8-bytes, with 4k
/// pages will return a block of 512 stubs (4096 / 8 = 512). Asking for 513
/// will return a block of 1024 (2-pages worth).
static Error emitIndirectStubsBlock(IndirectStubsInfo &StubsInfo,
unsigned MinStubs, void *InitialPtrVal);
};
} // End namespace orc.
} // End namespace llvm.
#endif // LLVM_EXECUTIONENGINE_ORC_ORCABISUPPORT_H