//===- OrcCBindingsStack.h - Orc JIT stack for C bindings -----*- C++ -*---===//
//
// 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
//
//===----------------------------------------------------------------------===//

#ifndef LLVM_LIB_EXECUTIONENGINE_ORC_ORCCBINDINGSSTACK_H
#define LLVM_LIB_EXECUTIONENGINE_ORC_ORCCBINDINGSSTACK_H

#include "llvm-c/OrcBindings.h"
#include "llvm-c/TargetMachine.h"
#include "llvm/ADT/STLExtras.h"
#include "llvm/ADT/StringRef.h"
#include "llvm/ExecutionEngine/JITSymbol.h"
#include "llvm/ExecutionEngine/JITEventListener.h"
#include "llvm/ExecutionEngine/Orc/CompileOnDemandLayer.h"
#include "llvm/ExecutionEngine/Orc/CompileUtils.h"
#include "llvm/ExecutionEngine/Orc/ExecutionUtils.h"
#include "llvm/ExecutionEngine/Orc/IRCompileLayer.h"
#include "llvm/ExecutionEngine/Orc/LambdaResolver.h"
#include "llvm/ExecutionEngine/Orc/RTDyldObjectLinkingLayer.h"
#include "llvm/ExecutionEngine/RuntimeDyld.h"
#include "llvm/ExecutionEngine/SectionMemoryManager.h"
#include "llvm/IR/DataLayout.h"
#include "llvm/IR/Mangler.h"
#include "llvm/IR/Module.h"
#include "llvm/Support/CBindingWrapping.h"
#include "llvm/Support/Error.h"
#include "llvm/Support/raw_ostream.h"
#include "llvm/Target/TargetMachine.h"
#include <algorithm>
#include <cstdint>
#include <functional>
#include <map>
#include <memory>
#include <set>
#include <string>
#include <vector>

namespace llvm {

class OrcCBindingsStack;

DEFINE_SIMPLE_CONVERSION_FUNCTIONS(OrcCBindingsStack, LLVMOrcJITStackRef)
DEFINE_SIMPLE_CONVERSION_FUNCTIONS(TargetMachine, LLVMTargetMachineRef)

namespace detail {

// FIXME: Kill this off once the Layer concept becomes an interface.
class GenericLayer {
public:
  virtual ~GenericLayer() = default;

  virtual JITSymbol findSymbolIn(orc::VModuleKey K, const std::string &Name,
                                 bool ExportedSymbolsOnly) = 0;
  virtual Error removeModule(orc::VModuleKey K) = 0;
  };

  template <typename LayerT> class GenericLayerImpl : public GenericLayer {
  public:
    GenericLayerImpl(LayerT &Layer) : Layer(Layer) {}

    JITSymbol findSymbolIn(orc::VModuleKey K, const std::string &Name,
                           bool ExportedSymbolsOnly) override {
      return Layer.findSymbolIn(K, Name, ExportedSymbolsOnly);
    }

    Error removeModule(orc::VModuleKey K) override {
      return Layer.removeModule(K);
    }

  private:
    LayerT &Layer;
  };

  template <>
  class GenericLayerImpl<orc::LegacyRTDyldObjectLinkingLayer> : public GenericLayer {
  private:
    using LayerT = orc::LegacyRTDyldObjectLinkingLayer;
  public:
    GenericLayerImpl(LayerT &Layer) : Layer(Layer) {}

    JITSymbol findSymbolIn(orc::VModuleKey K, const std::string &Name,
                           bool ExportedSymbolsOnly) override {
      return Layer.findSymbolIn(K, Name, ExportedSymbolsOnly);
    }

    Error removeModule(orc::VModuleKey K) override {
      return Layer.removeObject(K);
    }

  private:
    LayerT &Layer;
  };

  template <typename LayerT>
  std::unique_ptr<GenericLayerImpl<LayerT>> createGenericLayer(LayerT &Layer) {
    return std::make_unique<GenericLayerImpl<LayerT>>(Layer);
  }

} // end namespace detail

class OrcCBindingsStack {
public:

  using CompileCallbackMgr = orc::JITCompileCallbackManager;
  using ObjLayerT = orc::LegacyRTDyldObjectLinkingLayer;
  using CompileLayerT = orc::LegacyIRCompileLayer<ObjLayerT, orc::SimpleCompiler>;
  using CODLayerT =
        orc::LegacyCompileOnDemandLayer<CompileLayerT, CompileCallbackMgr>;

  using CallbackManagerBuilder =
      std::function<std::unique_ptr<CompileCallbackMgr>()>;

  using IndirectStubsManagerBuilder = CODLayerT::IndirectStubsManagerBuilderT;

private:

  using OwningObject = object::OwningBinary<object::ObjectFile>;

  class CBindingsResolver : public orc::SymbolResolver {
  public:
    CBindingsResolver(OrcCBindingsStack &Stack,
                      LLVMOrcSymbolResolverFn ExternalResolver,
                      void *ExternalResolverCtx)
        : Stack(Stack), ExternalResolver(std::move(ExternalResolver)),
          ExternalResolverCtx(std::move(ExternalResolverCtx)) {}

    orc::SymbolNameSet
    getResponsibilitySet(const orc::SymbolNameSet &Symbols) override {
      orc::SymbolNameSet Result;

      for (auto &S : Symbols) {
        if (auto Sym = findSymbol(std::string(*S))) {
          if (!Sym.getFlags().isStrong())
            Result.insert(S);
        } else if (auto Err = Sym.takeError()) {
          Stack.reportError(std::move(Err));
          return orc::SymbolNameSet();
        }
      }

      return Result;
    }

    orc::SymbolNameSet
    lookup(std::shared_ptr<orc::AsynchronousSymbolQuery> Query,
           orc::SymbolNameSet Symbols) override {
      orc::SymbolNameSet UnresolvedSymbols;

      for (auto &S : Symbols) {
        if (auto Sym = findSymbol(std::string(*S))) {
          if (auto Addr = Sym.getAddress()) {
            Query->notifySymbolMetRequiredState(
                S, JITEvaluatedSymbol(*Addr, Sym.getFlags()));
          } else {
            Stack.ES.legacyFailQuery(*Query, Addr.takeError());
            return orc::SymbolNameSet();
          }
        } else if (auto Err = Sym.takeError()) {
          Stack.ES.legacyFailQuery(*Query, std::move(Err));
          return orc::SymbolNameSet();
        } else
          UnresolvedSymbols.insert(S);
      }

      if (Query->isComplete())
        Query->handleComplete();

      return UnresolvedSymbols;
    }

  private:
    JITSymbol findSymbol(const std::string &Name) {
      // Search order:
      // 1. JIT'd symbols.
      // 2. Runtime overrides.
      // 3. External resolver (if present).

      if (Stack.CODLayer) {
        if (auto Sym = Stack.CODLayer->findSymbol(Name, true))
          return Sym;
        else if (auto Err = Sym.takeError())
          return Sym.takeError();
      } else {
        if (auto Sym = Stack.CompileLayer.findSymbol(Name, true))
          return Sym;
        else if (auto Err = Sym.takeError())
          return Sym.takeError();
      }

      if (auto Sym = Stack.CXXRuntimeOverrides.searchOverrides(Name))
        return Sym;

      if (ExternalResolver)
        return JITSymbol(ExternalResolver(Name.c_str(), ExternalResolverCtx),
                         JITSymbolFlags::Exported);

      return JITSymbol(nullptr);
    }

    OrcCBindingsStack &Stack;
    LLVMOrcSymbolResolverFn ExternalResolver;
    void *ExternalResolverCtx = nullptr;
  };

public:
  OrcCBindingsStack(TargetMachine &TM,
                    IndirectStubsManagerBuilder IndirectStubsMgrBuilder)
      : CCMgr(createCompileCallbackManager(TM, ES)), DL(TM.createDataLayout()),
        IndirectStubsMgr(IndirectStubsMgrBuilder()),
        ObjectLayer(
            AcknowledgeORCv1Deprecation, ES,
            [this](orc::VModuleKey K) {
              auto ResolverI = Resolvers.find(K);
              assert(ResolverI != Resolvers.end() &&
                     "No resolver for module K");
              auto Resolver = std::move(ResolverI->second);
              Resolvers.erase(ResolverI);
              return ObjLayerT::Resources{
                  std::make_shared<SectionMemoryManager>(), Resolver};
            },
            nullptr,
            [this](orc::VModuleKey K, const object::ObjectFile &Obj,
                   const RuntimeDyld::LoadedObjectInfo &LoadedObjInfo) {
              this->notifyFinalized(K, Obj, LoadedObjInfo);
            },
            [this](orc::VModuleKey K, const object::ObjectFile &Obj) {
              this->notifyFreed(K, Obj);
            }),
        CompileLayer(AcknowledgeORCv1Deprecation, ObjectLayer,
                     orc::SimpleCompiler(TM)),
        CODLayer(createCODLayer(ES, CompileLayer, CCMgr.get(),
                                std::move(IndirectStubsMgrBuilder), Resolvers)),
        CXXRuntimeOverrides(
            AcknowledgeORCv1Deprecation,
            [this](const std::string &S) { return mangle(S); }) {}

  Error shutdown() {
    // Run any destructors registered with __cxa_atexit.
    CXXRuntimeOverrides.runDestructors();
    // Run any IR destructors.
    for (auto &DtorRunner : IRStaticDestructorRunners)
      if (auto Err = DtorRunner.runViaLayer(*this))
        return Err;
    return Error::success();
  }

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

  template <typename PtrTy>
  static PtrTy fromTargetAddress(JITTargetAddress Addr) {
    return reinterpret_cast<PtrTy>(static_cast<uintptr_t>(Addr));
  }

  Expected<JITTargetAddress>
  createLazyCompileCallback(LLVMOrcLazyCompileCallbackFn Callback,
                            void *CallbackCtx) {
    auto WrappedCallback = [=]() -> JITTargetAddress {
      return Callback(wrap(this), CallbackCtx);
    };

    return CCMgr->getCompileCallback(std::move(WrappedCallback));
  }

  Error createIndirectStub(StringRef StubName, JITTargetAddress Addr) {
    return IndirectStubsMgr->createStub(StubName, Addr,
                                        JITSymbolFlags::Exported);
  }

  Error setIndirectStubPointer(StringRef Name, JITTargetAddress Addr) {
    return IndirectStubsMgr->updatePointer(Name, Addr);
  }

  template <typename LayerT>
  Expected<orc::VModuleKey>
  addIRModule(LayerT &Layer, std::unique_ptr<Module> M,
              std::unique_ptr<RuntimeDyld::MemoryManager> MemMgr,
              LLVMOrcSymbolResolverFn ExternalResolver,
              void *ExternalResolverCtx) {

    // Attach a data-layout if one isn't already present.
    if (M->getDataLayout().isDefault())
      M->setDataLayout(DL);

    // Record the static constructors and destructors. We have to do this before
    // we hand over ownership of the module to the JIT.
    std::vector<std::string> CtorNames, DtorNames;
    for (auto Ctor : orc::getConstructors(*M))
      CtorNames.push_back(mangle(Ctor.Func->getName()));
    for (auto Dtor : orc::getDestructors(*M))
      DtorNames.push_back(mangle(Dtor.Func->getName()));

    // Add the module to the JIT.
    auto K = ES.allocateVModule();
    Resolvers[K] = std::make_shared<CBindingsResolver>(*this, ExternalResolver,
                                                       ExternalResolverCtx);
    if (auto Err = Layer.addModule(K, std::move(M)))
      return std::move(Err);

    KeyLayers[K] = detail::createGenericLayer(Layer);

    // Run the static constructors, and save the static destructor runner for
    // execution when the JIT is torn down.
    orc::LegacyCtorDtorRunner<OrcCBindingsStack> CtorRunner(
        AcknowledgeORCv1Deprecation, std::move(CtorNames), K);
    if (auto Err = CtorRunner.runViaLayer(*this))
      return std::move(Err);

    IRStaticDestructorRunners.emplace_back(AcknowledgeORCv1Deprecation,
                                           std::move(DtorNames), K);

    return K;
  }

  Expected<orc::VModuleKey>
  addIRModuleEager(std::unique_ptr<Module> M,
                   LLVMOrcSymbolResolverFn ExternalResolver,
                   void *ExternalResolverCtx) {
    return addIRModule(CompileLayer, std::move(M),
                       std::make_unique<SectionMemoryManager>(),
                       std::move(ExternalResolver), ExternalResolverCtx);
  }

  Expected<orc::VModuleKey>
  addIRModuleLazy(std::unique_ptr<Module> M,
                  LLVMOrcSymbolResolverFn ExternalResolver,
                  void *ExternalResolverCtx) {
    if (!CODLayer)
      return make_error<StringError>("Can not add lazy module: No compile "
                                     "callback manager available",
                                     inconvertibleErrorCode());

    return addIRModule(*CODLayer, std::move(M),
                       std::make_unique<SectionMemoryManager>(),
                       std::move(ExternalResolver), ExternalResolverCtx);
  }

  Error removeModule(orc::VModuleKey K) {
    // FIXME: Should error release the module key?
    if (auto Err = KeyLayers[K]->removeModule(K))
      return Err;
    ES.releaseVModule(K);
    KeyLayers.erase(K);
    return Error::success();
  }

  Expected<orc::VModuleKey> addObject(std::unique_ptr<MemoryBuffer> ObjBuffer,
                                      LLVMOrcSymbolResolverFn ExternalResolver,
                                      void *ExternalResolverCtx) {
    if (auto Obj = object::ObjectFile::createObjectFile(
            ObjBuffer->getMemBufferRef())) {

      auto K = ES.allocateVModule();
      Resolvers[K] = std::make_shared<CBindingsResolver>(
          *this, ExternalResolver, ExternalResolverCtx);

      if (auto Err = ObjectLayer.addObject(K, std::move(ObjBuffer)))
        return std::move(Err);

      KeyLayers[K] = detail::createGenericLayer(ObjectLayer);

      return K;
    } else
      return Obj.takeError();
  }

  JITSymbol findSymbol(const std::string &Name,
                                 bool ExportedSymbolsOnly) {
    if (auto Sym = IndirectStubsMgr->findStub(Name, ExportedSymbolsOnly))
      return Sym;
    if (CODLayer)
      return CODLayer->findSymbol(mangle(Name), ExportedSymbolsOnly);
    return CompileLayer.findSymbol(mangle(Name), ExportedSymbolsOnly);
  }

  JITSymbol findSymbolIn(orc::VModuleKey K, const std::string &Name,
                         bool ExportedSymbolsOnly) {
    assert(KeyLayers.count(K) && "looking up symbol in unknown module");
    return KeyLayers[K]->findSymbolIn(K, mangle(Name), ExportedSymbolsOnly);
  }

  Expected<JITTargetAddress> findSymbolAddress(const std::string &Name,
                                               bool ExportedSymbolsOnly) {
    if (auto Sym = findSymbol(Name, ExportedSymbolsOnly)) {
      // Successful lookup, non-null symbol:
      if (auto AddrOrErr = Sym.getAddress())
        return *AddrOrErr;
      else
        return AddrOrErr.takeError();
    } else if (auto Err = Sym.takeError()) {
      // Lookup failure - report error.
      return std::move(Err);
    }

    // No symbol not found. Return 0.
    return 0;
  }

  Expected<JITTargetAddress> findSymbolAddressIn(orc::VModuleKey K,
                                                 const std::string &Name,
                                                 bool ExportedSymbolsOnly) {
    if (auto Sym = findSymbolIn(K, Name, ExportedSymbolsOnly)) {
      // Successful lookup, non-null symbol:
      if (auto AddrOrErr = Sym.getAddress())
        return *AddrOrErr;
      else
        return AddrOrErr.takeError();
    } else if (auto Err = Sym.takeError()) {
      // Lookup failure - report error.
      return std::move(Err);
    }

    // Symbol not found. Return 0.
    return 0;
  }

  const std::string &getErrorMessage() const { return ErrMsg; }

  void RegisterJITEventListener(JITEventListener *L) {
    if (!L)
      return;
    EventListeners.push_back(L);
  }

  void UnregisterJITEventListener(JITEventListener *L) {
    if (!L)
      return;

    auto I = find(reverse(EventListeners), L);
    if (I != EventListeners.rend()) {
      std::swap(*I, EventListeners.back());
      EventListeners.pop_back();
    }
  }

private:
  using ResolverMap =
      std::map<orc::VModuleKey, std::shared_ptr<orc::SymbolResolver>>;

  static std::unique_ptr<CompileCallbackMgr>
  createCompileCallbackManager(TargetMachine &TM, orc::ExecutionSession &ES) {
    auto CCMgr = createLocalCompileCallbackManager(TM.getTargetTriple(), ES, 0);
    if (!CCMgr) {
      // FIXME: It would be good if we could report this somewhere, but we do
      //        have an instance yet.
      logAllUnhandledErrors(CCMgr.takeError(), errs(), "ORC error: ");
      return nullptr;
    }
    return std::move(*CCMgr);
  }

  static std::unique_ptr<CODLayerT>
  createCODLayer(orc::ExecutionSession &ES, CompileLayerT &CompileLayer,
                 CompileCallbackMgr *CCMgr,
                 IndirectStubsManagerBuilder IndirectStubsMgrBuilder,
                 ResolverMap &Resolvers) {
    // If there is no compile callback manager available we can not create a
    // compile on demand layer.
    if (!CCMgr)
      return nullptr;

    return std::make_unique<CODLayerT>(
        AcknowledgeORCv1Deprecation, ES, CompileLayer,
        [&Resolvers](orc::VModuleKey K) {
          auto ResolverI = Resolvers.find(K);
          assert(ResolverI != Resolvers.end() && "No resolver for module K");
          return ResolverI->second;
        },
        [&Resolvers](orc::VModuleKey K,
                     std::shared_ptr<orc::SymbolResolver> Resolver) {
          assert(!Resolvers.count(K) && "Resolver already present");
          Resolvers[K] = std::move(Resolver);
        },
        [](Function &F) { return std::set<Function *>({&F}); }, *CCMgr,
        std::move(IndirectStubsMgrBuilder), false);
  }

  void reportError(Error Err) {
    // FIXME: Report errors on the execution session.
    logAllUnhandledErrors(std::move(Err), errs(), "ORC error: ");
  };

  void notifyFinalized(orc::VModuleKey K,
		       const object::ObjectFile &Obj,
		       const RuntimeDyld::LoadedObjectInfo &LoadedObjInfo) {
    uint64_t Key = static_cast<uint64_t>(
        reinterpret_cast<uintptr_t>(Obj.getData().data()));
    for (auto &Listener : EventListeners)
      Listener->notifyObjectLoaded(Key, Obj, LoadedObjInfo);
  }

  void notifyFreed(orc::VModuleKey K, const object::ObjectFile &Obj) {
    uint64_t Key = static_cast<uint64_t>(
        reinterpret_cast<uintptr_t>(Obj.getData().data()));
    for (auto &Listener : EventListeners)
      Listener->notifyFreeingObject(Key);
  }

  orc::ExecutionSession ES;
  std::unique_ptr<CompileCallbackMgr> CCMgr;

  std::vector<JITEventListener *> EventListeners;

  DataLayout DL;
  SectionMemoryManager CCMgrMemMgr;

  std::unique_ptr<orc::IndirectStubsManager> IndirectStubsMgr;

  ObjLayerT ObjectLayer;
  CompileLayerT CompileLayer;
  std::unique_ptr<CODLayerT> CODLayer;

  std::map<orc::VModuleKey, std::unique_ptr<detail::GenericLayer>> KeyLayers;

  orc::LegacyLocalCXXRuntimeOverrides CXXRuntimeOverrides;
  std::vector<orc::LegacyCtorDtorRunner<OrcCBindingsStack>> IRStaticDestructorRunners;
  std::string ErrMsg;

  ResolverMap Resolvers;
};

} // end namespace llvm

#endif // LLVM_LIB_EXECUTIONENGINE_ORC_ORCCBINDINGSSTACK_H
