diff options
Diffstat (limited to 'llvm/include')
4 files changed, 83 insertions, 105 deletions
diff --git a/llvm/include/llvm-c/OrcBindings.h b/llvm/include/llvm-c/OrcBindings.h index 78a7bc146ee..f6aff916999 100644 --- a/llvm/include/llvm-c/OrcBindings.h +++ b/llvm/include/llvm-c/OrcBindings.h @@ -47,8 +47,7 @@ typedef uint64_t (*LLVMOrcLazyCompileCallbackFn)(LLVMOrcJITStackRef JITStack, * client should not attempt to dispose of the Target Machine, or it will result * in a double-free. */ -LLVMOrcJITStackRef LLVMOrcCreateInstance(LLVMTargetMachineRef TM, - LLVMContextRef Context); +LLVMOrcJITStackRef LLVMOrcCreateInstance(LLVMTargetMachineRef TM); /** * Mangle the given symbol. diff --git a/llvm/include/llvm/ExecutionEngine/Orc/CompileOnDemandLayer.h b/llvm/include/llvm/ExecutionEngine/Orc/CompileOnDemandLayer.h index 9c37aa01681..8f4e844032c 100644 --- a/llvm/include/llvm/ExecutionEngine/Orc/CompileOnDemandLayer.h +++ b/llvm/include/llvm/ExecutionEngine/Orc/CompileOnDemandLayer.h @@ -242,7 +242,7 @@ private: // Create a callback, associate it with the stub for the function, // and set the compile action to compile the partition containing the // function. - auto CCInfo = CompileCallbackMgr.getCompileCallback(SrcM.getContext()); + auto CCInfo = CompileCallbackMgr.getCompileCallback(); StubInits[mangle(F.getName(), DL)] = std::make_pair(CCInfo.getAddress(), JITSymbolBase::flagsFromGlobalValue(F)); diff --git a/llvm/include/llvm/ExecutionEngine/Orc/IndirectionUtils.h b/llvm/include/llvm/ExecutionEngine/Orc/IndirectionUtils.h index 5ed8935980f..cabc95543d8 100644 --- a/llvm/include/llvm/ExecutionEngine/Orc/IndirectionUtils.h +++ b/llvm/include/llvm/ExecutionEngine/Orc/IndirectionUtils.h @@ -27,8 +27,7 @@ namespace llvm { namespace orc { -/// @brief Base class for JITLayer independent aspects of -/// JITCompileCallbackManager. +/// @brief Target-independent base class JITCompileCallbackManager. class JITCompileCallbackManagerBase { public: @@ -54,13 +53,8 @@ public: /// @brief Construct a JITCompileCallbackManagerBase. /// @param ErrorHandlerAddress The address of an error handler in the target /// process to be used if a compile callback fails. - /// @param NumTrampolinesPerBlock Number of trampolines to emit if there is no - /// available trampoline when getCompileCallback is - /// called. - JITCompileCallbackManagerBase(TargetAddress ErrorHandlerAddress, - unsigned NumTrampolinesPerBlock) - : ErrorHandlerAddress(ErrorHandlerAddress), - NumTrampolinesPerBlock(NumTrampolinesPerBlock) {} + JITCompileCallbackManagerBase(TargetAddress ErrorHandlerAddress) + : ErrorHandlerAddress(ErrorHandlerAddress) {} virtual ~JITCompileCallbackManagerBase() {} @@ -90,7 +84,7 @@ public: } /// @brief Reserve a compile callback. - virtual CompileCallbackInfo getCompileCallback(LLVMContext &Context) = 0; + virtual CompileCallbackInfo getCompileCallback() = 0; /// @brief Get a CompileCallbackInfo for an existing callback. CompileCallbackInfo getCompileCallbackInfo(TargetAddress TrampolineAddr) { @@ -113,7 +107,6 @@ public: protected: TargetAddress ErrorHandlerAddress; - unsigned NumTrampolinesPerBlock; typedef std::map<TargetAddress, CompileFtor> TrampolineMapT; TrampolineMapT ActiveTrampolines; @@ -124,69 +117,54 @@ private: }; /// @brief Manage compile callbacks. -template <typename JITLayerT, typename TargetT> +template <typename TargetT> class JITCompileCallbackManager : public JITCompileCallbackManagerBase { public: /// @brief Construct a JITCompileCallbackManager. - /// @param JIT JIT layer to emit callback trampolines, etc. into. - /// @param Context LLVMContext to use for trampoline & resolve block modules. /// @param ErrorHandlerAddress The address of an error handler in the target /// process to be used if a compile callback fails. - /// @param NumTrampolinesPerBlock Number of trampolines to allocate whenever - /// there is no existing callback trampoline. - /// (Trampolines are allocated in blocks for - /// efficiency.) - JITCompileCallbackManager(JITLayerT &JIT, RuntimeDyld::MemoryManager &MemMgr, - LLVMContext &Context, - TargetAddress ErrorHandlerAddress, - unsigned NumTrampolinesPerBlock) - : JITCompileCallbackManagerBase(ErrorHandlerAddress, - NumTrampolinesPerBlock), - JIT(JIT), MemMgr(MemMgr) { - emitResolverBlock(Context); + JITCompileCallbackManager(TargetAddress ErrorHandlerAddress) + : JITCompileCallbackManagerBase(ErrorHandlerAddress) { + + /// Set up the resolver block. + std::error_code EC; + ResolverBlock = + sys::OwningMemoryBlock( + sys::Memory::allocateMappedMemory(TargetT::ResolverCodeSize, nullptr, + sys::Memory::MF_READ | + sys::Memory::MF_WRITE, EC)); + assert(!EC && "Failed to allocate resolver block"); + + TargetT::writeResolverCode(static_cast<uint8_t*>(ResolverBlock.base()), + &reenter, this); + + EC = sys::Memory::protectMappedMemory(ResolverBlock.getMemoryBlock(), + sys::Memory::MF_READ | + sys::Memory::MF_EXEC); + assert(!EC && "Failed to mprotect resolver block"); } /// @brief Get/create a compile callback with the given signature. - CompileCallbackInfo getCompileCallback(LLVMContext &Context) final { - TargetAddress TrampolineAddr = getAvailableTrampolineAddr(Context); + CompileCallbackInfo getCompileCallback() final { + TargetAddress TrampolineAddr = getAvailableTrampolineAddr(); auto &Compile = this->ActiveTrampolines[TrampolineAddr]; return CompileCallbackInfo(TrampolineAddr, Compile); } private: - std::vector<std::unique_ptr<Module>> - SingletonSet(std::unique_ptr<Module> M) { - std::vector<std::unique_ptr<Module>> Ms; - Ms.push_back(std::move(M)); - return Ms; - } - - void emitResolverBlock(LLVMContext &Context) { - std::unique_ptr<Module> M(new Module("resolver_block_module", - Context)); - TargetT::insertResolverBlock(*M, *this); - auto NonResolver = - createLambdaResolver( - [](const std::string &Name) -> RuntimeDyld::SymbolInfo { - llvm_unreachable("External symbols in resolver block?"); - }, - [](const std::string &Name) -> RuntimeDyld::SymbolInfo { - llvm_unreachable("Dylib symbols in resolver block?"); - }); - auto H = JIT.addModuleSet(SingletonSet(std::move(M)), &MemMgr, - std::move(NonResolver)); - JIT.emitAndFinalize(H); - auto ResolverBlockSymbol = - JIT.findSymbolIn(H, TargetT::ResolverBlockName, false); - assert(ResolverBlockSymbol && "Failed to insert resolver block"); - ResolverBlockAddr = ResolverBlockSymbol.getAddress(); + static TargetAddress reenter(void *CCMgr, void *TrampolineId) { + JITCompileCallbackManager *Mgr = + static_cast<JITCompileCallbackManager*>(CCMgr); + return Mgr->executeCompileCallback( + static_cast<TargetAddress>( + reinterpret_cast<uintptr_t>(TrampolineId))); } - TargetAddress getAvailableTrampolineAddr(LLVMContext &Context) { + TargetAddress getAvailableTrampolineAddr() { if (this->AvailableTrampolines.empty()) - grow(Context); + grow(); assert(!this->AvailableTrampolines.empty() && "Failed to grow available trampolines."); TargetAddress TrampolineAddr = this->AvailableTrampolines.back(); @@ -194,35 +172,41 @@ private: return TrampolineAddr; } - void grow(LLVMContext &Context) { + void grow() { assert(this->AvailableTrampolines.empty() && "Growing prematurely?"); - std::unique_ptr<Module> M(new Module("trampoline_block", Context)); - auto GetLabelName = - TargetT::insertCompileCallbackTrampolines(*M, ResolverBlockAddr, - this->NumTrampolinesPerBlock, - this->ActiveTrampolines.size()); - auto NonResolver = - createLambdaResolver( - [](const std::string &Name) -> RuntimeDyld::SymbolInfo { - llvm_unreachable("External symbols in trampoline block?"); - }, - [](const std::string &Name) -> RuntimeDyld::SymbolInfo { - llvm_unreachable("Dylib symbols in trampoline block?"); - }); - auto H = JIT.addModuleSet(SingletonSet(std::move(M)), &MemMgr, - std::move(NonResolver)); - JIT.emitAndFinalize(H); - for (unsigned I = 0; I < this->NumTrampolinesPerBlock; ++I) { - std::string Name = GetLabelName(I); - auto TrampolineSymbol = JIT.findSymbolIn(H, Name, false); - assert(TrampolineSymbol && "Failed to emit trampoline."); - this->AvailableTrampolines.push_back(TrampolineSymbol.getAddress()); - } + + std::error_code EC; + auto TrampolineBlock = + sys::OwningMemoryBlock( + sys::Memory::allocateMappedMemory(TargetT::PageSize, nullptr, + sys::Memory::MF_READ | + sys::Memory::MF_WRITE, EC)); + assert(!EC && "Failed to allocate trampoline block"); + + + unsigned NumTrampolines = + (TargetT::PageSize - TargetT::PointerSize) / TargetT::TrampolineSize; + + uint8_t *TrampolineMem = static_cast<uint8_t*>(TrampolineBlock.base()); + TargetT::writeTrampolines(TrampolineMem, ResolverBlock.base(), + NumTrampolines); + + for (unsigned I = 0; I < NumTrampolines; ++I) + this->AvailableTrampolines.push_back( + static_cast<TargetAddress>( + reinterpret_cast<uintptr_t>( + TrampolineMem + (I * TargetT::TrampolineSize)))); + + EC = sys::Memory::protectMappedMemory(TrampolineBlock.getMemoryBlock(), + sys::Memory::MF_READ | + sys::Memory::MF_EXEC); + assert(!EC && "Failed to mprotect trampoline block"); + + TrampolineBlocks.push_back(std::move(TrampolineBlock)); } - JITLayerT &JIT; - RuntimeDyld::MemoryManager &MemMgr; - TargetAddress ResolverBlockAddr; + sys::OwningMemoryBlock ResolverBlock; + std::vector<sys::OwningMemoryBlock> TrampolineBlocks; }; /// @brief Base class for managing collections of named indirect stubs. diff --git a/llvm/include/llvm/ExecutionEngine/Orc/OrcTargetSupport.h b/llvm/include/llvm/ExecutionEngine/Orc/OrcTargetSupport.h index 58273ae4616..3e57314ba2d 100644 --- a/llvm/include/llvm/ExecutionEngine/Orc/OrcTargetSupport.h +++ b/llvm/include/llvm/ExecutionEngine/Orc/OrcTargetSupport.h @@ -26,29 +26,24 @@ namespace orc { class OrcX86_64 { public: - static const char *ResolverBlockName; + static const unsigned PageSize = 4096; + static const unsigned PointerSize = 8; + static const unsigned TrampolineSize = 8; + static const unsigned ResolverCodeSize = 0x78; - /// @brief Insert module-level inline callback asm into module M for the - /// symbols managed by JITResolveCallbackHandler J. - static void insertResolverBlock(Module &M, - JITCompileCallbackManagerBase &JCBM); + typedef TargetAddress (*JITReentryFn)(void *CallbackMgr, + void *TrampolineId); - /// @brief Get a label name from the given index. - typedef std::function<std::string(unsigned)> LabelNameFtor; + /// @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 Insert the requested number of trampolines into the given module. - /// @param M Module to insert the call block into. - /// @param NumCalls Number of calls to create in the call block. - /// @param StartIndex Optional argument specifying the index suffix to start - /// with. - /// @return A functor that provides the symbol name for each entry in the call - /// block. - /// - static LabelNameFtor insertCompileCallbackTrampolines( - Module &M, - TargetAddress TrampolineAddr, - unsigned NumCalls, - unsigned StartIndex = 0); + /// @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. |