| //===----- 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/ExecutionEngine/ExecutionEngine.h" |
| #include "llvm/ExecutionEngine/RTDyldMemoryManager.h" |
| #include "llvm/ExecutionEngine/Orc/CompileUtils.h" |
| #include "llvm/ExecutionEngine/Orc/IRCompileLayer.h" |
| #include "llvm/ExecutionEngine/Orc/LambdaResolver.h" |
| #include "llvm/ExecutionEngine/Orc/ObjectLinkingLayer.h" |
| #include "llvm/IR/Mangler.h" |
| #include "llvm/Support/DynamicLibrary.h" |
| |
| namespace llvm { |
| namespace orc { |
| |
| class KaleidoscopeJIT { |
| public: |
| typedef ObjectLinkingLayer<> ObjLayerT; |
| typedef IRCompileLayer<ObjLayerT> CompileLayerT; |
| typedef CompileLayerT::ModuleSetHandleT ModuleHandleT; |
| |
| KaleidoscopeJIT() |
| : TM(EngineBuilder().selectTarget()), DL(TM->createDataLayout()), |
| CompileLayer(ObjectLayer, SimpleCompiler(*TM)) { |
| llvm::sys::DynamicLibrary::LoadLibraryPermanently(nullptr); |
| } |
| |
| TargetMachine &getTargetMachine() { return *TM; } |
| |
| ModuleHandleT addModule(std::unique_ptr<Module> M) { |
| // We need a memory manager to allocate memory and resolve symbols for this |
| // new module. Create one that resolves symbols by looking back into the |
| // JIT. |
| auto Resolver = createLambdaResolver( |
| [&](const std::string &Name) { |
| if (auto Sym = findMangledSymbol(Name)) |
| return RuntimeDyld::SymbolInfo(Sym.getAddress(), Sym.getFlags()); |
| return RuntimeDyld::SymbolInfo(nullptr); |
| }, |
| [](const std::string &S) { return nullptr; }); |
| auto H = CompileLayer.addModuleSet(singletonSet(std::move(M)), |
| make_unique<SectionMemoryManager>(), |
| std::move(Resolver)); |
| |
| ModuleHandles.push_back(H); |
| return H; |
| } |
| |
| void removeModule(ModuleHandleT H) { |
| ModuleHandles.erase( |
| std::find(ModuleHandles.begin(), ModuleHandles.end(), H)); |
| CompileLayer.removeModuleSet(H); |
| } |
| |
| JITSymbol findSymbol(const std::string Name) { |
| return findMangledSymbol(mangle(Name)); |
| } |
| |
| private: |
| |
| std::string mangle(const std::string &Name) { |
| std::string MangledName; |
| { |
| raw_string_ostream MangledNameStream(MangledName); |
| Mangler::getNameWithPrefix(MangledNameStream, Name, DL); |
| } |
| return MangledName; |
| } |
| |
| template <typename T> static std::vector<T> singletonSet(T t) { |
| std::vector<T> Vec; |
| Vec.push_back(std::move(t)); |
| return Vec; |
| } |
| |
| JITSymbol findMangledSymbol(const std::string &Name) { |
| // Search modules in reverse order: from last added to first added. |
| // This is the opposite of the usual search order for dlsym, but makes more |
| // sense in a REPL where we want to bind to the newest available definition. |
| for (auto H : make_range(ModuleHandles.rbegin(), ModuleHandles.rend())) |
| if (auto Sym = CompileLayer.findSymbolIn(H, Name, true)) |
| return Sym; |
| |
| // If we can't find the symbol in the JIT, try looking in the host process. |
| if (auto SymAddr = RTDyldMemoryManager::getSymbolAddressInProcess(Name)) |
| return JITSymbol(SymAddr, JITSymbolFlags::Exported); |
| |
| return nullptr; |
| } |
| |
| std::unique_ptr<TargetMachine> TM; |
| const DataLayout DL; |
| ObjLayerT ObjectLayer; |
| CompileLayerT CompileLayer; |
| std::vector<ModuleHandleT> ModuleHandles; |
| }; |
| |
| } // End namespace orc. |
| } // End namespace llvm |
| |
| #endif // LLVM_EXECUTIONENGINE_ORC_KALEIDOSCOPEJIT_H |