text: //===----- 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/CompileUtils.h"
  #include "llvm/ExecutionEngine/Orc/JITSymbol.h"
  #include "llvm/ExecutionEngine/Orc/IRCompileLayer.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;
    ObjectLinkingLayer<> ObjectLayer;
    IRCompileLayer<decltype(ObjectLayer)> CompileLayer;
  
  public:
    typedef decltype(CompileLayer)::ModuleSetHandleT ModuleHandle;
  
    KaleidoscopeJIT()
        : TM(EngineBuilder().selectTarget()), DL(TM->createDataLayout()),
          CompileLayer(ObjectLayer, SimpleCompiler(*TM)) {
      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 = CompileLayer.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 CompileLayer.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 CompileLayer.findSymbol(MangledNameStream.str(), true);
    }
  
    void removeModule(ModuleHandle H) {
      CompileLayer.removeModuleSet(H);
    }
  
  };
  
  } // end namespace orc
  } // end namespace llvm
  
  #endif // LLVM_EXECUTIONENGINE_ORC_KALEIDOSCOPEJIT_H
  