//===--------- LLJIT.cpp - An ORC-based JIT for compiling LLVM IR ---------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//

#include "llvm/ExecutionEngine/Orc/LLJIT.h"
#include "llvm/ExecutionEngine/Orc/OrcError.h"
#include "llvm/ExecutionEngine/SectionMemoryManager.h"
#include "llvm/IR/Mangler.h"

namespace {

  // A SimpleCompiler that owns its TargetMachine.
  class TMOwningSimpleCompiler : public llvm::orc::SimpleCompiler {
  public:
    TMOwningSimpleCompiler(std::unique_ptr<llvm::TargetMachine> TM)
      : llvm::orc::SimpleCompiler(*TM), TM(std::move(TM)) {}
  private:
    // FIXME: shared because std::functions (and thus
    // IRCompileLayer::CompileFunction) are not moveable.
    std::shared_ptr<llvm::TargetMachine> TM;
  };

} // end anonymous namespace

namespace llvm {
namespace orc {

LLJIT::~LLJIT() {
  if (CompileThreads)
    CompileThreads->wait();
}

Expected<std::unique_ptr<LLJIT>>
LLJIT::Create(JITTargetMachineBuilder JTMB, DataLayout DL,
              unsigned NumCompileThreads) {

  if (NumCompileThreads == 0) {
    // If NumCompileThreads == 0 then create a single-threaded LLJIT instance.
    auto TM = JTMB.createTargetMachine();
    if (!TM)
      return TM.takeError();
    return std::unique_ptr<LLJIT>(new LLJIT(llvm::make_unique<ExecutionSession>(),
                                            std::move(*TM), std::move(DL)));
  }

  return std::unique_ptr<LLJIT>(new LLJIT(llvm::make_unique<ExecutionSession>(),
                                          std::move(JTMB), std::move(DL),
                                          NumCompileThreads));
}

Error LLJIT::defineAbsolute(StringRef Name, JITEvaluatedSymbol Sym) {
  auto InternedName = ES->intern(Name);
  SymbolMap Symbols({{InternedName, Sym}});
  return Main.define(absoluteSymbols(std::move(Symbols)));
}

Error LLJIT::addIRModule(JITDylib &JD, ThreadSafeModule TSM) {
  assert(TSM && "Can not add null module");

  if (auto Err = applyDataLayout(*TSM.getModule()))
    return Err;

  return CompileLayer.add(JD, std::move(TSM), ES->allocateVModule());
}

Error LLJIT::addObjectFile(JITDylib &JD, std::unique_ptr<MemoryBuffer> Obj) {
  assert(Obj && "Can not add null object");

  return ObjLinkingLayer.add(JD, std::move(Obj), ES->allocateVModule());
}

Expected<JITEvaluatedSymbol> LLJIT::lookupLinkerMangled(JITDylib &JD,
                                                        StringRef Name) {
  return ES->lookup(JITDylibSearchList({{&JD, true}}), ES->intern(Name));
}

LLJIT::LLJIT(std::unique_ptr<ExecutionSession> ES,
             std::unique_ptr<TargetMachine> TM, DataLayout DL)
    : ES(std::move(ES)), Main(this->ES->getMainJITDylib()), DL(std::move(DL)),
      ObjLinkingLayer(
          *this->ES,
          []() { return llvm::make_unique<SectionMemoryManager>(); }),
      CompileLayer(*this->ES, ObjLinkingLayer,
                   TMOwningSimpleCompiler(std::move(TM))),
      CtorRunner(Main), DtorRunner(Main) {}

LLJIT::LLJIT(std::unique_ptr<ExecutionSession> ES, JITTargetMachineBuilder JTMB,
             DataLayout DL, unsigned NumCompileThreads)
    : ES(std::move(ES)), Main(this->ES->getMainJITDylib()), DL(std::move(DL)),
      ObjLinkingLayer(
          *this->ES,
          []() { return llvm::make_unique<SectionMemoryManager>(); }),
      CompileLayer(*this->ES, ObjLinkingLayer,
                   ConcurrentIRCompiler(std::move(JTMB))),
      CtorRunner(Main), DtorRunner(Main) {
  assert(NumCompileThreads != 0 &&
         "Multithreaded LLJIT instance can not be created with 0 threads");

  // Move modules to new contexts when they're emitted so that we can compile
  // them in parallel.
  CompileLayer.setCloneToNewContextOnEmit(true);

  // Create a thread pool to compile on and set the execution session
  // dispatcher to use the thread pool.
  CompileThreads = llvm::make_unique<ThreadPool>(NumCompileThreads);
  this->ES->setDispatchMaterialization(
      [this](JITDylib &JD, std::unique_ptr<MaterializationUnit> MU) {
        // FIXME: Switch to move capture once we have c++14.
        auto SharedMU = std::shared_ptr<MaterializationUnit>(std::move(MU));
        auto Work = [SharedMU, &JD]() { SharedMU->doMaterialize(JD); };
        CompileThreads->async(std::move(Work));
      });
}

std::string LLJIT::mangle(StringRef UnmangledName) {
  std::string MangledName;
  {
    raw_string_ostream MangledNameStream(MangledName);
    Mangler::getNameWithPrefix(MangledNameStream, UnmangledName, DL);
  }
  return MangledName;
}

Error LLJIT::applyDataLayout(Module &M) {
  if (M.getDataLayout().isDefault())
    M.setDataLayout(DL);

  if (M.getDataLayout() != DL)
    return make_error<StringError>(
        "Added modules have incompatible data layouts",
        inconvertibleErrorCode());

  return Error::success();
}

void LLJIT::recordCtorDtors(Module &M) {
  CtorRunner.add(getConstructors(M));
  DtorRunner.add(getDestructors(M));
}

Expected<std::unique_ptr<LLLazyJIT>>
LLLazyJIT::Create(JITTargetMachineBuilder JTMB, DataLayout DL,
                  JITTargetAddress ErrorAddr, unsigned NumCompileThreads) {
  auto ES = llvm::make_unique<ExecutionSession>();

  const Triple &TT = JTMB.getTargetTriple();

  auto LCTMgr = createLocalLazyCallThroughManager(TT, *ES, ErrorAddr);
  if (!LCTMgr)
    return LCTMgr.takeError();

  auto ISMBuilder = createLocalIndirectStubsManagerBuilder(TT);
  if (!ISMBuilder)
    return make_error<StringError>(
        std::string("No indirect stubs manager builder for ") + TT.str(),
        inconvertibleErrorCode());

  if (NumCompileThreads == 0) {
    auto TM = JTMB.createTargetMachine();
    if (!TM)
      return TM.takeError();
    return std::unique_ptr<LLLazyJIT>(
        new LLLazyJIT(std::move(ES), std::move(*TM), std::move(DL),
                      std::move(*LCTMgr), std::move(ISMBuilder)));
  }

  return std::unique_ptr<LLLazyJIT>(new LLLazyJIT(
      std::move(ES), std::move(JTMB), std::move(DL), NumCompileThreads,
      std::move(*LCTMgr), std::move(ISMBuilder)));
}

Error LLLazyJIT::addLazyIRModule(JITDylib &JD, ThreadSafeModule TSM) {
  assert(TSM && "Can not add null module");

  if (auto Err = applyDataLayout(*TSM.getModule()))
    return Err;

  recordCtorDtors(*TSM.getModule());

  return CODLayer.add(JD, std::move(TSM), ES->allocateVModule());
}

LLLazyJIT::LLLazyJIT(
    std::unique_ptr<ExecutionSession> ES, std::unique_ptr<TargetMachine> TM,
    DataLayout DL, std::unique_ptr<LazyCallThroughManager> LCTMgr,
    std::function<std::unique_ptr<IndirectStubsManager>()> ISMBuilder)
    : LLJIT(std::move(ES), std::move(TM), std::move(DL)),
      LCTMgr(std::move(LCTMgr)), TransformLayer(*this->ES, CompileLayer),
      CODLayer(*this->ES, TransformLayer, *this->LCTMgr,
               std::move(ISMBuilder)) {}

LLLazyJIT::LLLazyJIT(
    std::unique_ptr<ExecutionSession> ES, JITTargetMachineBuilder JTMB,
    DataLayout DL, unsigned NumCompileThreads,
    std::unique_ptr<LazyCallThroughManager> LCTMgr,
    std::function<std::unique_ptr<IndirectStubsManager>()> ISMBuilder)
    : LLJIT(std::move(ES), std::move(JTMB), std::move(DL), NumCompileThreads),
      LCTMgr(std::move(LCTMgr)), TransformLayer(*this->ES, CompileLayer),
      CODLayer(*this->ES, TransformLayer, *this->LCTMgr,
               std::move(ISMBuilder)) {
  CODLayer.setCloneToNewContextOnEmit(true);
}

} // End namespace orc.
} // End namespace llvm.
