/** @file Jit.hpp **/ /** Adapted from LLVM KaleidoscopeJIT.h **/ #pragma once #pragma GCC diagnostic push #pragma GCC diagnostic ignored "-Wunused-parameter" #pragma GCC diagnostic ignored "-Wredundant-move" # include "llvm/ADT/StringRef.h" # include "llvm/ExecutionEngine/JITSymbol.h" # include "llvm/ExecutionEngine/Orc/CompileUtils.h" # include "llvm/ExecutionEngine/Orc/Core.h" # include "llvm/ExecutionEngine/Orc/ExecutionUtils.h" # include "llvm/ExecutionEngine/Orc/ExecutorProcessControl.h" # include "llvm/ExecutionEngine/Orc/IRCompileLayer.h" # include "llvm/ExecutionEngine/Orc/JITTargetMachineBuilder.h" # include "llvm/ExecutionEngine/Orc/RTDyldObjectLinkingLayer.h" # include "llvm/ExecutionEngine/Orc/Shared/ExecutorSymbolDef.h" // need llvm18 # include "llvm/ExecutionEngine/SectionMemoryManager.h" # include "llvm/IR/DataLayout.h" # include "llvm/IR/LLVMContext.h" #pragma GCC diagnostic pop #include namespace xo { namespace jit { class Jit { private: using StringRef = llvm::StringRef; using SectionMemoryManager = llvm::SectionMemoryManager; using DynamicLibrarySearchGenerator = llvm::orc::DynamicLibrarySearchGenerator; using ConcurrentIRCompiler = llvm::orc::ConcurrentIRCompiler; using ExecutionSession = llvm::orc::ExecutionSession; using DataLayout = llvm::DataLayout; using MangleAndInterner = llvm::orc::MangleAndInterner; using RTDyldObjectLinkingLayer = llvm::orc::RTDyldObjectLinkingLayer; using IRCompileLayer = llvm::orc::IRCompileLayer; using JITDylib = llvm::orc::JITDylib; using JITTargetMachineBuilder = llvm::orc::JITTargetMachineBuilder; using ThreadSafeModule = llvm::orc::ThreadSafeModule; using ResourceTrackerSP = llvm::orc::ResourceTrackerSP; using ExecutorSymbolDef = llvm::orc::ExecutorSymbolDef; using SelfExecutorProcessControl = llvm::orc::SelfExecutorProcessControl; private: /** execution session - represents a currently-running jit program **/ std::unique_ptr xsession_; /** (?) needed for name mangling (?) **/ DataLayout data_layout_; /** symbol mangling and unique-ifying */ MangleAndInterner mangler_; /** in-process linking layer * (? specialized for jit in running process ?) **/ RTDyldObjectLinkingLayer object_layer_; /** compilation layer (sits above linking layer) **/ IRCompileLayer compile_layer_; /** destination library **/ JITDylib & dest_dynamic_lib_; //MainJD; public: Jit(std::unique_ptr xsession, JITTargetMachineBuilder jtmb, DataLayout data_layout) : xsession_{std::move(xsession)}, data_layout_(std::move(data_layout)), mangler_(*this->xsession_, this->data_layout_), object_layer_(*this->xsession_, []() { return std::make_unique(); }), compile_layer_(*this->xsession_, object_layer_, std::make_unique(std::move(jtmb))), dest_dynamic_lib_(this->xsession_->createBareJITDylib("
")) { dest_dynamic_lib_.addGenerator (cantFail(DynamicLibrarySearchGenerator::GetForCurrentProcess (data_layout_.getGlobalPrefix()))); if (jtmb.getTargetTriple().isOSBinFormatCOFF()) { object_layer_.setOverrideObjectFlagsWithResponsibilityFlags(true); object_layer_.setAutoClaimResponsibilityForObjectSymbols(true); } } ~Jit() { if (auto Err = this->xsession_->endSession()) this->xsession_->reportError(std::move(Err)); } static llvm::Expected> Create() { auto EPC = SelfExecutorProcessControl::Create(); if (!EPC) return EPC.takeError(); auto xsession = std::make_unique(std::move(*EPC)); JITTargetMachineBuilder jtmb (xsession->getExecutorProcessControl().getTargetTriple()); auto data_layout = jtmb.getDefaultDataLayoutForTarget(); if (!data_layout) return data_layout.takeError(); return std::make_unique(std::move(xsession), std::move(jtmb), std::move(*data_layout)); } /* exposing this for printing */ const ExecutionSession * xsession() const { return xsession_.get(); } const DataLayout & data_layout() const { return data_layout_; } JITDylib & dest_dynamic_lib_ref() { return dest_dynamic_lib_; } const std::string & target_triple() const { return xsession_->getTargetTriple().getTriple(); } /** compile module to machine code that's runnable from this process; * incorporate into @ref dest_dynamic_lib_ **/ llvm::Error add_llvm_module(ThreadSafeModule ts_module, ResourceTrackerSP rtracker = nullptr) { if (!rtracker) rtracker = dest_dynamic_lib_.getDefaultResourceTracker(); return compile_layer_.add(rtracker, std::move(ts_module)); } /** intern @p symbol, binding it to address @p dest **/ template llvm::Error intern_symbol(const std::string & symbol, T * dest) { auto mangled_sym = mangler_(symbol); llvm::orc::SymbolMap symbol_map; symbol_map[mangled_sym] = llvm::orc::ExecutorSymbolDef(llvm::orc::ExecutorAddr::fromPtr(dest), llvm::JITSymbolFlags()); auto materializer = llvm::orc::absoluteSymbols(symbol_map); return dest_dynamic_lib_.define(materializer); } /*intern_symbol*/ /** report mangled symbol name **/ std::string_view mangle(StringRef name) { auto tmp = *(this->mangler_(name.str())); return std::string_view(tmp.data(), tmp.size()); } llvm::Expected lookup(StringRef name) { return this->xsession_->lookup({&dest_dynamic_lib_}, this->mangle(name)); } /* dump */ void dump_execution_session() { this->xsession_->dump(llvm::errs()); } }; /*Jit*/ } /*namespace jit*/ } /*namespace xo*/ /** end Jit.hpp **/