summaryrefslogtreecommitdiffstats
path: root/include/llvm/ExecutionEngine/Orc/OrcArchitectureSupport.h
diff options
context:
space:
mode:
Diffstat (limited to 'include/llvm/ExecutionEngine/Orc/OrcArchitectureSupport.h')
-rw-r--r--include/llvm/ExecutionEngine/Orc/OrcArchitectureSupport.h148
1 files changed, 148 insertions, 0 deletions
diff --git a/include/llvm/ExecutionEngine/Orc/OrcArchitectureSupport.h b/include/llvm/ExecutionEngine/Orc/OrcArchitectureSupport.h
new file mode 100644
index 0000000..1b0488b
--- /dev/null
+++ b/include/llvm/ExecutionEngine/Orc/OrcArchitectureSupport.h
@@ -0,0 +1,148 @@
+//===-- OrcArchitectureSupport.h - Architecture support code ---*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// Architecture specific code for Orc, e.g. callback assembly.
+//
+// Architecture 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_ORCARCHITECTURESUPPORT_H
+#define LLVM_EXECUTIONENGINE_ORC_ORCARCHITECTURESUPPORT_H
+
+#include "IndirectionUtils.h"
+#include "llvm/Support/Memory.h"
+#include "llvm/Support/Process.h"
+
+namespace llvm {
+namespace orc {
+
+/// Generic ORC Architecture 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 OrcGenericArchitecture {
+public:
+ static const unsigned PointerSize = sizeof(uintptr_t);
+ static const unsigned TrampolineSize = 1;
+ static const unsigned ResolverCodeSize = 1;
+
+ typedef TargetAddress (*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 std::error_code emitIndirectStubsBlock(IndirectStubsInfo &StubsInfo,
+ unsigned MinStubs,
+ void *InitialPtrVal) {
+ llvm_unreachable("emitIndirectStubsBlock is not supported by the generic "
+ "host support class");
+ }
+};
+
+/// @brief X86_64 support.
+///
+/// X86_64 supports lazy JITing.
+class OrcX86_64 {
+public:
+ static const unsigned PointerSize = 8;
+ static const unsigned TrampolineSize = 8;
+ static const unsigned ResolverCodeSize = 0x78;
+
+ typedef TargetAddress (*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 Provide information about stub blocks generated by the
+ /// makeIndirectStubsBlock function.
+ class IndirectStubsInfo {
+ friend class OrcX86_64;
+
+ public:
+ const static unsigned StubSize = 8;
+
+ IndirectStubsInfo() : NumStubs(0) {}
+ IndirectStubsInfo(IndirectStubsInfo &&Other)
+ : NumStubs(Other.NumStubs), StubsMem(std::move(Other.StubsMem)) {
+ Other.NumStubs = 0;
+ }
+ IndirectStubsInfo &operator=(IndirectStubsInfo &&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<uint64_t *>(StubsMem.base()) + Idx;
+ }
+
+ /// @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;
+ };
+
+ /// @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 std::error_code emitIndirectStubsBlock(IndirectStubsInfo &StubsInfo,
+ unsigned MinStubs,
+ void *InitialPtrVal);
+};
+
+} // End namespace orc.
+} // End namespace llvm.
+
+#endif // LLVM_EXECUTIONENGINE_ORC_ORCARCHITECTURESUPPORT_H
OpenPOWER on IntegriCloud