#include "llvm/ExecutionEngine/Orc/CompileOnDemandLayer.h" #include "llvm/ExecutionEngine/Orc/CompileUtils.h" #include "llvm/ExecutionEngine/Orc/Core.h" #include "llvm/ExecutionEngine/Orc/ExecutionUtils.h" #include "llvm/ExecutionEngine/Orc/IRCompileLayer.h" #include "llvm/ExecutionEngine/Orc/IndirectionUtils.h" #include "llvm/ExecutionEngine/Orc/JITTargetMachineBuilder.h" #include "llvm/ExecutionEngine/Orc/RTDyldObjectLinkingLayer.h" #include "llvm/ExecutionEngine/Orc/SpeculateAnalyses.h" #include "llvm/ExecutionEngine/Orc/Speculation.h" #include "llvm/ExecutionEngine/Orc/TargetProcess/TargetExecutionUtils.h" #include "llvm/ExecutionEngine/SectionMemoryManager.h" #include "llvm/IRReader/IRReader.h" #include "llvm/Support/CommandLine.h" #include "llvm/Support/Debug.h" #include "llvm/Support/InitLLVM.h" #include "llvm/Support/SourceMgr.h" #include "llvm/Support/TargetSelect.h" #include "llvm/Support/ThreadPool.h" #include #include using namespace llvm; using namespace llvm::orc; static cl::list InputFiles(cl::Positional, cl::OneOrMore, cl::desc("input files")); static cl::list InputArgv("args", cl::Positional, cl::desc("..."), cl::ZeroOrMore, cl::PositionalEatsArgs); static cl::opt NumThreads("num-threads", cl::Optional, cl::desc("Number of compile threads"), cl::init(4)); ExitOnError ExitOnErr; // Add Layers class SpeculativeJIT { public: static Expected> Create() { auto JTMB = orc::JITTargetMachineBuilder::detectHost(); if (!JTMB) return JTMB.takeError(); auto DL = JTMB->getDefaultDataLayoutForTarget(); if (!DL) return DL.takeError(); auto ES = std::make_unique(); auto LCTMgr = createLocalLazyCallThroughManager( JTMB->getTargetTriple(), *ES, pointerToJITTargetAddress(explodeOnLazyCompileFailure)); if (!LCTMgr) return LCTMgr.takeError(); auto ISMBuilder = createLocalIndirectStubsManagerBuilder(JTMB->getTargetTriple()); if (!ISMBuilder) return make_error("No indirect stubs manager for target", inconvertibleErrorCode()); auto ProcessSymbolsSearchGenerator = DynamicLibrarySearchGenerator::GetForCurrentProcess( DL->getGlobalPrefix()); if (!ProcessSymbolsSearchGenerator) return ProcessSymbolsSearchGenerator.takeError(); std::unique_ptr SJ(new SpeculativeJIT( std::move(ES), std::move(*DL), std::move(*JTMB), std::move(*LCTMgr), std::move(ISMBuilder), std::move(*ProcessSymbolsSearchGenerator))); return std::move(SJ); } ExecutionSession &getES() { return *ES; } Error addModule(ThreadSafeModule TSM) { return CODLayer.add(MainJD, std::move(TSM)); } Expected lookup(StringRef UnmangledName) { return ES->lookup({&MainJD}, Mangle(UnmangledName)); } ~SpeculativeJIT() { CompileThreads.wait(); } private: using IndirectStubsManagerBuilderFunction = std::function()>; static void explodeOnLazyCompileFailure() { errs() << "Lazy compilation failed, Symbol Implmentation not found!\n"; exit(1); } SpeculativeJIT( std::unique_ptr ES, DataLayout DL, orc::JITTargetMachineBuilder JTMB, std::unique_ptr LCTMgr, IndirectStubsManagerBuilderFunction ISMBuilder, std::unique_ptr ProcessSymbolsGenerator) : ES(std::move(ES)), DL(std::move(DL)), MainJD(this->ES->createBareJITDylib("
")), LCTMgr(std::move(LCTMgr)), CompileLayer(*this->ES, ObjLayer, std::make_unique(std::move(JTMB))), S(Imps, *this->ES), SpeculateLayer(*this->ES, CompileLayer, S, Mangle, BlockFreqQuery()), CODLayer(*this->ES, SpeculateLayer, *this->LCTMgr, std::move(ISMBuilder)) { MainJD.addGenerator(std::move(ProcessSymbolsGenerator)); this->CODLayer.setImplMap(&Imps); this->ES->setDispatchMaterialization( [this](std::unique_ptr MU, std::unique_ptr MR) { CompileThreads.async( [UnownedMU = MU.release(), UnownedMR = MR.release()]() { std::unique_ptr MU(UnownedMU); std::unique_ptr MR(UnownedMR); MU->materialize(std::move(MR)); }); }); ExitOnErr(S.addSpeculationRuntime(MainJD, Mangle)); LocalCXXRuntimeOverrides CXXRuntimeoverrides; ExitOnErr(CXXRuntimeoverrides.enable(MainJD, Mangle)); } static std::unique_ptr createMemMgr() { return std::make_unique(); } std::unique_ptr ES; DataLayout DL; MangleAndInterner Mangle{*ES, DL}; ThreadPool CompileThreads{llvm::hardware_concurrency(NumThreads)}; JITDylib &MainJD; Triple TT; std::unique_ptr LCTMgr; IRCompileLayer CompileLayer; ImplSymbolMap Imps; Speculator S; RTDyldObjectLinkingLayer ObjLayer{*ES, createMemMgr}; IRSpeculationLayer SpeculateLayer; CompileOnDemandLayer CODLayer; }; int main(int argc, char *argv[]) { // Initialize LLVM. InitLLVM X(argc, argv); InitializeNativeTarget(); InitializeNativeTargetAsmPrinter(); cl::ParseCommandLineOptions(argc, argv, "SpeculativeJIT"); ExitOnErr.setBanner(std::string(argv[0]) + ": "); if (NumThreads < 1) { errs() << "Speculative compilation requires one or more dedicated compile " "threads\n"; return 1; } // Create a JIT instance. auto SJ = ExitOnErr(SpeculativeJIT::Create()); // Load the IR inputs. for (const auto &InputFile : InputFiles) { SMDiagnostic Err; auto Ctx = std::make_unique(); auto M = parseIRFile(InputFile, Err, *Ctx); if (!M) { Err.print(argv[0], errs()); return 1; } ExitOnErr(SJ->addModule(ThreadSafeModule(std::move(M), std::move(Ctx)))); } auto MainSym = ExitOnErr(SJ->lookup("main")); auto Main = jitTargetAddressToFunction(MainSym.getAddress()); return runAsMain(Main, InputArgv, StringRef(InputFiles.front())); return 0; }