|  | //===- 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/ADT/iterator_range.h" | 
|  | #include "llvm/ExecutionEngine/ExecutionEngine.h" | 
|  | #include "llvm/ExecutionEngine/JITSymbol.h" | 
|  | #include "llvm/ExecutionEngine/Orc/CompileUtils.h" | 
|  | #include "llvm/ExecutionEngine/Orc/IRCompileLayer.h" | 
|  | #include "llvm/ExecutionEngine/Orc/LambdaResolver.h" | 
|  | #include "llvm/ExecutionEngine/Orc/RTDyldObjectLinkingLayer.h" | 
|  | #include "llvm/ExecutionEngine/RTDyldMemoryManager.h" | 
|  | #include "llvm/ExecutionEngine/SectionMemoryManager.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 <map> | 
|  | #include <memory> | 
|  | #include <string> | 
|  | #include <vector> | 
|  |  | 
|  | namespace llvm { | 
|  | namespace orc { | 
|  |  | 
|  | class KaleidoscopeJIT { | 
|  | public: | 
|  | using ObjLayerT = RTDyldObjectLinkingLayer; | 
|  | using CompileLayerT = IRCompileLayer<ObjLayerT, SimpleCompiler>; | 
|  |  | 
|  | KaleidoscopeJIT() | 
|  | : Resolver(createLegacyLookupResolver( | 
|  | ES, | 
|  | [this](const std::string &Name) { | 
|  | return ObjectLayer.findSymbol(Name, true); | 
|  | }, | 
|  | [](Error Err) { cantFail(std::move(Err), "lookupFlags failed"); })), | 
|  | TM(EngineBuilder().selectTarget()), DL(TM->createDataLayout()), | 
|  | ObjectLayer(ES, | 
|  | [this](VModuleKey) { | 
|  | return ObjLayerT::Resources{ | 
|  | std::make_shared<SectionMemoryManager>(), Resolver}; | 
|  | }), | 
|  | CompileLayer(ObjectLayer, SimpleCompiler(*TM)) { | 
|  | llvm::sys::DynamicLibrary::LoadLibraryPermanently(nullptr); | 
|  | } | 
|  |  | 
|  | TargetMachine &getTargetMachine() { return *TM; } | 
|  |  | 
|  | VModuleKey addModule(std::unique_ptr<Module> M) { | 
|  | auto K = ES.allocateVModule(); | 
|  | cantFail(CompileLayer.addModule(K, std::move(M))); | 
|  | ModuleKeys.push_back(K); | 
|  | return K; | 
|  | } | 
|  |  | 
|  | void removeModule(VModuleKey K) { | 
|  | ModuleKeys.erase(find(ModuleKeys, K)); | 
|  | cantFail(CompileLayer.removeModule(K)); | 
|  | } | 
|  |  | 
|  | 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; | 
|  | } | 
|  |  | 
|  | JITSymbol findMangledSymbol(const std::string &Name) { | 
|  | #ifdef _WIN32 | 
|  | // The symbol lookup of ObjectLinkingLayer uses the SymbolRef::SF_Exported | 
|  | // flag to decide whether a symbol will be visible or not, when we call | 
|  | // IRCompileLayer::findSymbolIn with ExportedSymbolsOnly set to true. | 
|  | // | 
|  | // But for Windows COFF objects, this flag is currently never set. | 
|  | // For a potential solution see: https://reviews.llvm.org/rL258665 | 
|  | // For now, we allow non-exported symbols on Windows as a workaround. | 
|  | const bool ExportedSymbolsOnly = false; | 
|  | #else | 
|  | const bool ExportedSymbolsOnly = true; | 
|  | #endif | 
|  |  | 
|  | // 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(ModuleKeys.rbegin(), ModuleKeys.rend())) | 
|  | if (auto Sym = CompileLayer.findSymbolIn(H, Name, ExportedSymbolsOnly)) | 
|  | 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); | 
|  |  | 
|  | #ifdef _WIN32 | 
|  | // For Windows retry without "_" at beginning, as RTDyldMemoryManager uses | 
|  | // GetProcAddress and standard libraries like msvcrt.dll use names | 
|  | // with and without "_" (for example "_itoa" but "sin"). | 
|  | if (Name.length() > 2 && Name[0] == '_') | 
|  | if (auto SymAddr = | 
|  | RTDyldMemoryManager::getSymbolAddressInProcess(Name.substr(1))) | 
|  | return JITSymbol(SymAddr, JITSymbolFlags::Exported); | 
|  | #endif | 
|  |  | 
|  | return nullptr; | 
|  | } | 
|  |  | 
|  | ExecutionSession ES; | 
|  | std::shared_ptr<SymbolResolver> Resolver; | 
|  | std::unique_ptr<TargetMachine> TM; | 
|  | const DataLayout DL; | 
|  | ObjLayerT ObjectLayer; | 
|  | CompileLayerT CompileLayer; | 
|  | std::vector<VModuleKey> ModuleKeys; | 
|  | }; | 
|  |  | 
|  | } // end namespace orc | 
|  | } // end namespace llvm | 
|  |  | 
|  | #endif // LLVM_EXECUTIONENGINE_ORC_KALEIDOSCOPEJIT_H |