//===----- KaleidoscopeJIT.h - A simple JIT for Kaleidoscope ----*- C++ -*-===// // // The LLVM Compiler Infrastructure // // This file is distributed under the University of Illinois Open Source // License. See LICENSE.TXT for details. // //===----------------------------------------------------------------------===// // // Contains a simple JIT definition for use in the kaleidoscope tutorials. // //===----------------------------------------------------------------------===// #ifndef LLVM_EXECUTIONENGINE_ORC_KALEIDOSCOPEJIT_H #define LLVM_EXECUTIONENGINE_ORC_KALEIDOSCOPEJIT_H #include "llvm/ADT/STLExtras.h" #include "llvm/ExecutionEngine/ExecutionEngine.h" #include "llvm/ExecutionEngine/RuntimeDyld.h" #include "llvm/ExecutionEngine/SectionMemoryManager.h" #include "llvm/ExecutionEngine/Orc/CompileOnDemandLayer.h" #include "llvm/ExecutionEngine/Orc/CompileUtils.h" #include "llvm/ExecutionEngine/Orc/JITSymbol.h" #include "llvm/ExecutionEngine/Orc/IRCompileLayer.h" #include "llvm/ExecutionEngine/Orc/IRTransformLayer.h" #include "llvm/ExecutionEngine/Orc/LambdaResolver.h" #include "llvm/ExecutionEngine/Orc/ObjectLinkingLayer.h" #include "llvm/IR/DataLayout.h" #include "llvm/IR/Mangler.h" #include "llvm/Support/DynamicLibrary.h" #include "llvm/Support/raw_ostream.h" #include "llvm/Target/TargetMachine.h" #include <algorithm> #include <memory> #include <string> #include <vector> namespace llvm { namespace orc { class KaleidoscopeJIT { private: std::unique_ptr<TargetMachine> TM; const DataLayout DL; std::unique_ptr<JITCompileCallbackManager> CompileCallbackManager; ObjectLinkingLayer<> ObjectLayer; IRCompileLayer<decltype(ObjectLayer)> CompileLayer; typedef std::function<std::unique_ptr<Module>(std::unique_ptr<Module>)> OptimizeFunction; IRTransformLayer<decltype(CompileLayer), OptimizeFunction> OptimizeLayer; CompileOnDemandLayer<decltype(OptimizeLayer)> CODLayer; public: typedef decltype(CODLayer)::ModuleSetHandleT ModuleHandle; KaleidoscopeJIT() : TM(EngineBuilder().selectTarget()), DL(TM->createDataLayout()), CompileCallbackManager( orc::createLocalCompileCallbackManager(TM->getTargetTriple(), 0)), CompileLayer(ObjectLayer, SimpleCompiler(*TM)), OptimizeLayer(CompileLayer, [this](std::unique_ptr<Module> M) { return optimizeModule(std::move(M)); }), CODLayer(OptimizeLayer, [this](Function &F) { return std::set<Function*>({&F}); }, *CompileCallbackManager, orc::createLocalIndirectStubsManagerBuilder( TM->getTargetTriple())) { llvm::sys::DynamicLibrary::LoadLibraryPermanently(nullptr); } TargetMachine &getTargetMachine() { return *TM; } ModuleHandle addModule(std::unique_ptr<Module> M) { // Build our symbol resolver: // Lambda 1: Look back into the JIT itself to find symbols that are part of // the same "logical dylib". // Lambda 2: Search for external symbols in the host process. auto Resolver = createLambdaResolver( [&](const std::string &Name) { if (auto Sym = CODLayer.findSymbol(Name, false)) return Sym.toRuntimeDyldSymbol(); return RuntimeDyld::SymbolInfo(nullptr); }, [](const std::string &Name) { if (auto SymAddr = RTDyldMemoryManager::getSymbolAddressInProcess(Name)) return RuntimeDyld::SymbolInfo(SymAddr, JITSymbolFlags::Exported); return RuntimeDyld::SymbolInfo(nullptr); }); // Build a singlton module set to hold our module. std::vector<std::unique_ptr<Module>> Ms; Ms.push_back(std::move(M)); // Add the set to the JIT with the resolver we created above and a newly // created SectionMemoryManager. return CODLayer.addModuleSet(std::move(Ms), make_unique<SectionMemoryManager>(), std::move(Resolver)); } JITSymbol findSymbol(const std::string Name) { std::string MangledName; raw_string_ostream MangledNameStream(MangledName); Mangler::getNameWithPrefix(MangledNameStream, Name, DL); return CODLayer.findSymbol(MangledNameStream.str(), true); } void removeModule(ModuleHandle H) { CODLayer.removeModuleSet(H); } private: std::unique_ptr<Module> optimizeModule(std::unique_ptr<Module> M) { // Create a function pass manager. auto FPM = llvm::make_unique<legacy::FunctionPassManager>(M.get()); // Add some optimizations. FPM->add(createInstructionCombiningPass()); FPM->add(createReassociatePass()); FPM->add(createGVNPass()); FPM->add(createCFGSimplificationPass()); FPM->doInitialization(); // Run the optimizations over all functions in the module being added to // the JIT. for (auto &F : *M) FPM->run(F); return M; } }; } // end namespace orc } // end namespace llvm #endif // LLVM_EXECUTIONENGINE_ORC_KALEIDOSCOPEJIT_H