1 //===-- OrcTargetSupport.h - Code to support specific targets --*- C++ -*-===// 2 // 3 // The LLVM Compiler Infrastructure 4 // 5 // This file is distributed under the University of Illinois Open Source 6 // License. See LICENSE.TXT for details. 7 // 8 //===----------------------------------------------------------------------===// 9 // 10 // Target specific code for Orc, e.g. callback assembly. 11 // 12 // Target classes should be part of the JIT *target* process, not the host 13 // process (except where you're doing hosted JITing and the two are one and the 14 // same). 15 // 16 //===----------------------------------------------------------------------===// 17 18 #ifndef LLVM_EXECUTIONENGINE_ORC_ORCTARGETSUPPORT_H 19 #define LLVM_EXECUTIONENGINE_ORC_ORCTARGETSUPPORT_H 20 21 #include "IndirectionUtils.h" 22 #include "llvm/Support/Memory.h" 23 24 namespace llvm { 25 namespace orc { 26 27 class OrcX86_64 { 28 public: 29 static const unsigned PageSize = 4096; 30 static const unsigned PointerSize = 8; 31 static const unsigned TrampolineSize = 8; 32 static const unsigned ResolverCodeSize = 0x78; 33 34 typedef TargetAddress (*JITReentryFn)(void *CallbackMgr, 35 void *TrampolineId); 36 37 /// @brief Write the resolver code into the given memory. The user is be 38 /// responsible for allocating the memory and setting permissions. 39 static void writeResolverCode(uint8_t *ResolveMem, JITReentryFn Reentry, 40 void *CallbackMgr); 41 42 /// @brief Write the requsted number of trampolines into the given memory, 43 /// which must be big enough to hold 1 pointer, plus NumTrampolines 44 /// trampolines. 45 static void writeTrampolines(uint8_t *TrampolineMem, void *ResolverAddr, 46 unsigned NumTrampolines); 47 48 /// @brief Provide information about stub blocks generated by the 49 /// makeIndirectStubsBlock function. 50 class IndirectStubsInfo { 51 friend class OrcX86_64; 52 public: 53 const static unsigned StubSize = 8; 54 const static unsigned PtrSize = 8; 55 IndirectStubsInfo()56 IndirectStubsInfo() : NumStubs(0) {} IndirectStubsInfo(IndirectStubsInfo && Other)57 IndirectStubsInfo(IndirectStubsInfo &&Other) 58 : NumStubs(Other.NumStubs), StubsMem(std::move(Other.StubsMem)) { 59 Other.NumStubs = 0; 60 } 61 IndirectStubsInfo& operator=(IndirectStubsInfo &&Other) { 62 NumStubs = Other.NumStubs; 63 Other.NumStubs = 0; 64 StubsMem = std::move(Other.StubsMem); 65 return *this; 66 } 67 68 /// @brief Number of stubs in this block. getNumStubs()69 unsigned getNumStubs() const { return NumStubs; } 70 71 /// @brief Get a pointer to the stub at the given index, which must be in 72 /// the range 0 .. getNumStubs() - 1. getStub(unsigned Idx)73 void* getStub(unsigned Idx) const { 74 return static_cast<uint64_t*>(StubsMem.base()) + Idx; 75 } 76 77 /// @brief Get a pointer to the implementation-pointer at the given index, 78 /// which must be in the range 0 .. getNumStubs() - 1. getPtr(unsigned Idx)79 void** getPtr(unsigned Idx) const { 80 char *PtrsBase = 81 static_cast<char*>(StubsMem.base()) + NumStubs * StubSize; 82 return reinterpret_cast<void**>(PtrsBase) + Idx; 83 } 84 private: 85 unsigned NumStubs; 86 sys::OwningMemoryBlock StubsMem; 87 }; 88 89 /// @brief Emit at least MinStubs worth of indirect call stubs, rounded out to 90 /// the nearest page size. 91 /// 92 /// E.g. Asking for 4 stubs on x86-64, where stubs are 8-bytes, with 4k 93 /// pages will return a block of 512 stubs (4096 / 8 = 512). Asking for 513 94 /// will return a block of 1024 (2-pages worth). 95 static std::error_code emitIndirectStubsBlock(IndirectStubsInfo &StubsInfo, 96 unsigned MinStubs, 97 void *InitialPtrVal); 98 }; 99 100 } // End namespace orc. 101 } // End namespace llvm. 102 103 #endif // LLVM_EXECUTIONENGINE_ORC_ORCTARGETSUPPORT_H 104