//===------ RemoteObjectLayer.h - Forwards objs to a remote -----*- C++ -*-===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// Forwards objects to a remote object layer via RPC.
//
//===----------------------------------------------------------------------===//

#ifndef LLVM_EXECUTIONENGINE_ORC_REMOTEOBJECTLAYER_H
#define LLVM_EXECUTIONENGINE_ORC_REMOTEOBJECTLAYER_H

#include "llvm/ExecutionEngine/Orc/OrcRemoteTargetRPCAPI.h"
#include "llvm/Object/ObjectFile.h"
#include "llvm/ExecutionEngine/Orc/LambdaResolver.h"
#include <map>

namespace llvm {
namespace orc {

/// RPC API needed by RemoteObjectClientLayer and RemoteObjectServerLayer.
class RemoteObjectLayerAPI {
public:

  using ObjHandleT = remote::ResourceIdMgr::ResourceId;

protected:

  using RemoteSymbolId = remote::ResourceIdMgr::ResourceId;
  using RemoteSymbol = std::pair<RemoteSymbolId, JITSymbolFlags>;

public:

  using BadSymbolHandleError = remote::ResourceNotFound<RemoteSymbolId>;
  using BadObjectHandleError = remote::ResourceNotFound<ObjHandleT>;

protected:

  static const ObjHandleT InvalidObjectHandleId = 0;
  static const RemoteSymbolId NullSymbolId = 0;

  class AddObject
    : public rpc::Function<AddObject, Expected<ObjHandleT>(std::string)> {
  public:
    static const char *getName() { return "AddObject"; }
  };

  class RemoveObject
    : public rpc::Function<RemoveObject, Error(ObjHandleT)> {
  public:
    static const char *getName() { return "RemoveObject"; }
  };

  class FindSymbol
    : public rpc::Function<FindSymbol, Expected<RemoteSymbol>(std::string,
                                                              bool)> {
  public:
    static const char *getName() { return "FindSymbol"; }
  };

  class FindSymbolIn
    : public rpc::Function<FindSymbolIn,
                           Expected<RemoteSymbol>(ObjHandleT, std::string,
                                                  bool)> {
  public:
    static const char *getName() { return "FindSymbolIn"; }
  };

  class EmitAndFinalize
    : public rpc::Function<EmitAndFinalize,
                           Error(ObjHandleT)> {
  public:
    static const char *getName() { return "EmitAndFinalize"; }
  };

  class Lookup
    : public rpc::Function<Lookup,
                           Expected<RemoteSymbol>(ObjHandleT, std::string)> {
  public:
    static const char *getName() { return "Lookup"; }
  };

  class LookupInLogicalDylib
    : public rpc::Function<LookupInLogicalDylib,
                           Expected<RemoteSymbol>(ObjHandleT, std::string)> {
  public:
    static const char *getName() { return "LookupInLogicalDylib"; }
  };

  class ReleaseRemoteSymbol
    : public rpc::Function<ReleaseRemoteSymbol, Error(RemoteSymbolId)> {
  public:
    static const char *getName() { return "ReleaseRemoteSymbol"; }
  };

  class MaterializeRemoteSymbol
    : public rpc::Function<MaterializeRemoteSymbol,
                           Expected<JITTargetAddress>(RemoteSymbolId)> {
  public:
    static const char *getName() { return "MaterializeRemoteSymbol"; }
  };
};

/// Base class containing common utilities for RemoteObjectClientLayer and
/// RemoteObjectServerLayer.
template <typename RPCEndpoint>
class RemoteObjectLayer : public RemoteObjectLayerAPI {
public:

  RemoteObjectLayer(RPCEndpoint &Remote,
                    std::function<void(Error)> ReportError)
      : Remote(Remote), ReportError(std::move(ReportError)),
        SymbolIdMgr(NullSymbolId + 1) {
    using ThisT = RemoteObjectLayer<RPCEndpoint>;
    Remote.template addHandler<ReleaseRemoteSymbol>(
             *this, &ThisT::handleReleaseRemoteSymbol);
    Remote.template addHandler<MaterializeRemoteSymbol>(
             *this, &ThisT::handleMaterializeRemoteSymbol);
  }

protected:

  /// This class is used as the symbol materializer for JITSymbols returned by
  /// RemoteObjectLayerClient/RemoteObjectLayerServer -- the materializer knows
  /// how to call back to the other RPC endpoint to get the address when
  /// requested.
  class RemoteSymbolMaterializer {
  public:

    /// Construct a RemoteSymbolMaterializer for the given RemoteObjectLayer
    /// with the given Id.
    RemoteSymbolMaterializer(RemoteObjectLayer &C,
                             RemoteSymbolId Id)
      : C(C), Id(Id) {}

    RemoteSymbolMaterializer(const RemoteSymbolMaterializer &Other)
      : C(Other.C), Id(Other.Id) {
      // FIXME: This is a horrible, auto_ptr-style, copy-as-move operation.
      //        It should be removed as soon as LLVM has C++14's generalized
      //        lambda capture (at which point the materializer can be moved
      //        into the lambda in remoteToJITSymbol below).
      const_cast<RemoteSymbolMaterializer&>(Other).Id = 0;
    }

    RemoteSymbolMaterializer&
    operator=(const RemoteSymbolMaterializer&) = delete;

    /// Release the remote symbol.
    ~RemoteSymbolMaterializer() {
      if (Id)
        C.releaseRemoteSymbol(Id);
    }

    /// Materialize the symbol on the remote and get its address.
    Expected<JITTargetAddress> materialize() {
      auto Addr = C.materializeRemoteSymbol(Id);
      Id = 0;
      return Addr;
    }

  private:
    RemoteObjectLayer &C;
    RemoteSymbolId Id;
  };

  /// Convenience function for getting a null remote symbol value.
  RemoteSymbol nullRemoteSymbol() {
    return RemoteSymbol(0, JITSymbolFlags());
  }

  /// Creates a StringError that contains a copy of Err's log message, then
  /// sends that StringError to ReportError.
  ///
  /// This allows us to locally log error messages for errors that will actually
  /// be delivered to the remote.
  Error teeLog(Error Err) {
    return handleErrors(std::move(Err),
                        [this](std::unique_ptr<ErrorInfoBase> EIB) {
                          ReportError(make_error<StringError>(
                                        EIB->message(),
                                        EIB->convertToErrorCode()));
                          return Error(std::move(EIB));
                        });
  }

  Error badRemoteSymbolIdError(RemoteSymbolId Id) {
    return make_error<BadSymbolHandleError>(Id, "Remote JIT Symbol");
  }

  Error badObjectHandleError(ObjHandleT H) {
    return make_error<RemoteObjectLayerAPI::BadObjectHandleError>(
             H, "Bad object handle");
  }

  /// Create a RemoteSymbol wrapping the given JITSymbol.
  Expected<RemoteSymbol> jitSymbolToRemote(JITSymbol Sym) {
    if (Sym) {
      auto Id = SymbolIdMgr.getNext();
      auto Flags = Sym.getFlags();
      assert(!InUseSymbols.count(Id) && "Symbol id already in use");
      InUseSymbols.insert(std::make_pair(Id, std::move(Sym)));
      return RemoteSymbol(Id, Flags);
    } else if (auto Err = Sym.takeError())
      return teeLog(std::move(Err));
    // else...
    return nullRemoteSymbol();
  }

  /// Convert an Expected<RemoteSymbol> to a JITSymbol.
  JITSymbol remoteToJITSymbol(Expected<RemoteSymbol> RemoteSymOrErr) {
    if (RemoteSymOrErr) {
      auto &RemoteSym = *RemoteSymOrErr;
      if (RemoteSym == nullRemoteSymbol())
        return nullptr;
      // else...
      RemoteSymbolMaterializer RSM(*this, RemoteSym.first);
      auto Sym =
        JITSymbol([RSM]() mutable { return RSM.materialize(); },
                  RemoteSym.second);
      return Sym;
    } else
      return RemoteSymOrErr.takeError();
  }

  RPCEndpoint &Remote;
  std::function<void(Error)> ReportError;

private:

  /// Notify the remote to release the given JITSymbol.
  void releaseRemoteSymbol(RemoteSymbolId Id) {
    if (auto Err = Remote.template callB<ReleaseRemoteSymbol>(Id))
      ReportError(std::move(Err));
  }

  /// Notify the remote to materialize the JITSymbol with the given Id and
  /// return its address.
  Expected<JITTargetAddress> materializeRemoteSymbol(RemoteSymbolId Id) {
    return Remote.template callB<MaterializeRemoteSymbol>(Id);
  }

  /// Release the JITSymbol with the given Id.
  Error handleReleaseRemoteSymbol(RemoteSymbolId Id) {
    auto SI = InUseSymbols.find(Id);
    if (SI != InUseSymbols.end()) {
      InUseSymbols.erase(SI);
      return Error::success();
    } else
      return teeLog(badRemoteSymbolIdError(Id));
  }

  /// Run the materializer for the JITSymbol with the given Id and return its
  /// address.
  Expected<JITTargetAddress> handleMaterializeRemoteSymbol(RemoteSymbolId Id) {
    auto SI = InUseSymbols.find(Id);
    if (SI != InUseSymbols.end()) {
      auto AddrOrErr = SI->second.getAddress();
      InUseSymbols.erase(SI);
      SymbolIdMgr.release(Id);
      if (AddrOrErr)
        return *AddrOrErr;
      else
        return teeLog(AddrOrErr.takeError());
    } else {
      return teeLog(badRemoteSymbolIdError(Id));
    }
  }

  remote::ResourceIdMgr SymbolIdMgr;
  std::map<RemoteSymbolId, JITSymbol> InUseSymbols;
};

/// RemoteObjectClientLayer forwards the ORC Object Layer API over an RPC
/// connection.
///
/// This class can be used as the base layer of a JIT stack on the client and
/// will forward operations to a corresponding RemoteObjectServerLayer on the
/// server (which can be composed on top of a "real" object layer like
/// RTDyldObjectLinkingLayer to actually carry out the operations).
///
/// Sending relocatable objects to the server (rather than fully relocated
/// bits) allows JIT'd code to be cached on the server side and re-used in
/// subsequent JIT sessions.
template <typename RPCEndpoint>
class RemoteObjectClientLayer : public RemoteObjectLayer<RPCEndpoint> {
private:

  using AddObject = RemoteObjectLayerAPI::AddObject;
  using RemoveObject = RemoteObjectLayerAPI::RemoveObject;
  using FindSymbol = RemoteObjectLayerAPI::FindSymbol;
  using FindSymbolIn = RemoteObjectLayerAPI::FindSymbolIn;
  using EmitAndFinalize = RemoteObjectLayerAPI::EmitAndFinalize;
  using Lookup = RemoteObjectLayerAPI::Lookup;
  using LookupInLogicalDylib = RemoteObjectLayerAPI::LookupInLogicalDylib;

  using RemoteObjectLayer<RPCEndpoint>::teeLog;
  using RemoteObjectLayer<RPCEndpoint>::badObjectHandleError;
  using RemoteObjectLayer<RPCEndpoint>::remoteToJITSymbol;

public:

  using ObjHandleT = RemoteObjectLayerAPI::ObjHandleT;
  using RemoteSymbol = RemoteObjectLayerAPI::RemoteSymbol;

  using ObjectPtr = std::unique_ptr<MemoryBuffer>;

  /// Create a RemoteObjectClientLayer that communicates with a
  /// RemoteObjectServerLayer instance via the given RPCEndpoint.
  ///
  /// The ReportError functor can be used locally log errors that are intended
  /// to be sent  sent
  RemoteObjectClientLayer(RPCEndpoint &Remote,
                          std::function<void(Error)> ReportError)
      : RemoteObjectLayer<RPCEndpoint>(Remote, std::move(ReportError)) {
    using ThisT = RemoteObjectClientLayer<RPCEndpoint>;
    Remote.template addHandler<Lookup>(*this, &ThisT::lookup);
    Remote.template addHandler<LookupInLogicalDylib>(
            *this, &ThisT::lookupInLogicalDylib);
  }

  /// @brief Add an object to the JIT.
  ///
  /// @return A handle that can be used to refer to the loaded object (for
  ///         symbol searching, finalization, freeing memory, etc.).
  Expected<ObjHandleT>
  addObject(ObjectPtr ObjBuffer,
            std::shared_ptr<LegacyJITSymbolResolver> Resolver) {
    if (auto HandleOrErr =
            this->Remote.template callB<AddObject>(ObjBuffer->getBuffer())) {
      auto &Handle = *HandleOrErr;
      // FIXME: Return an error for this:
      assert(!Resolvers.count(Handle) && "Handle already in use?");
      Resolvers[Handle] = std::move(Resolver);
      return Handle;
    } else
      return HandleOrErr.takeError();
  }

  /// @brief Remove the given object from the JIT.
  Error removeObject(ObjHandleT H) {
    return this->Remote.template callB<RemoveObject>(H);
  }

  /// @brief Search for the given named symbol.
  JITSymbol findSymbol(StringRef Name, bool ExportedSymbolsOnly) {
    return remoteToJITSymbol(
             this->Remote.template callB<FindSymbol>(Name,
                                                     ExportedSymbolsOnly));
  }

  /// @brief Search for the given named symbol within the given context.
  JITSymbol findSymbolIn(ObjHandleT H, StringRef Name, bool ExportedSymbolsOnly) {
    return remoteToJITSymbol(
             this->Remote.template callB<FindSymbolIn>(H, Name,
                                                       ExportedSymbolsOnly));
  }

  /// @brief Immediately emit and finalize the object with the given handle.
  Error emitAndFinalize(ObjHandleT H) {
    return this->Remote.template callB<EmitAndFinalize>(H);
  }

private:

  Expected<RemoteSymbol> lookup(ObjHandleT H, const std::string &Name) {
    auto RI = Resolvers.find(H);
    if (RI != Resolvers.end()) {
      return this->jitSymbolToRemote(RI->second->findSymbol(Name));
    } else
      return teeLog(badObjectHandleError(H));
  }

  Expected<RemoteSymbol> lookupInLogicalDylib(ObjHandleT H,
                                              const std::string &Name) {
    auto RI = Resolvers.find(H);
    if (RI != Resolvers.end())
      return this->jitSymbolToRemote(
               RI->second->findSymbolInLogicalDylib(Name));
    else
      return teeLog(badObjectHandleError(H));
  }

  std::map<remote::ResourceIdMgr::ResourceId,
           std::shared_ptr<LegacyJITSymbolResolver>>
      Resolvers;
};

/// RemoteObjectServerLayer acts as a server and handling RPC calls for the
/// object layer API from the given RPC connection.
///
/// This class can be composed on top of a 'real' object layer (e.g.
/// RTDyldObjectLinkingLayer) to do the actual work of relocating objects
/// and making them executable.
template <typename BaseLayerT, typename RPCEndpoint>
class RemoteObjectServerLayer : public RemoteObjectLayer<RPCEndpoint> {
private:

  using ObjHandleT = RemoteObjectLayerAPI::ObjHandleT;
  using RemoteSymbol = RemoteObjectLayerAPI::RemoteSymbol;

  using AddObject = RemoteObjectLayerAPI::AddObject;
  using RemoveObject = RemoteObjectLayerAPI::RemoveObject;
  using FindSymbol = RemoteObjectLayerAPI::FindSymbol;
  using FindSymbolIn = RemoteObjectLayerAPI::FindSymbolIn;
  using EmitAndFinalize = RemoteObjectLayerAPI::EmitAndFinalize;
  using Lookup = RemoteObjectLayerAPI::Lookup;
  using LookupInLogicalDylib = RemoteObjectLayerAPI::LookupInLogicalDylib;

  using RemoteObjectLayer<RPCEndpoint>::teeLog;
  using RemoteObjectLayer<RPCEndpoint>::badObjectHandleError;
  using RemoteObjectLayer<RPCEndpoint>::remoteToJITSymbol;

public:

  /// Create a RemoteObjectServerLayer with the given base layer (which must be
  /// an object layer), RPC endpoint, and error reporter function.
  RemoteObjectServerLayer(BaseLayerT &BaseLayer,
                          RPCEndpoint &Remote,
                          std::function<void(Error)> ReportError)
    : RemoteObjectLayer<RPCEndpoint>(Remote, std::move(ReportError)),
      BaseLayer(BaseLayer), HandleIdMgr(1) {
    using ThisT = RemoteObjectServerLayer<BaseLayerT, RPCEndpoint>;

    Remote.template addHandler<AddObject>(*this, &ThisT::addObject);
    Remote.template addHandler<RemoveObject>(*this, &ThisT::removeObject);
    Remote.template addHandler<FindSymbol>(*this, &ThisT::findSymbol);
    Remote.template addHandler<FindSymbolIn>(*this, &ThisT::findSymbolIn);
    Remote.template addHandler<EmitAndFinalize>(*this, &ThisT::emitAndFinalize);
  }

private:

  class StringMemoryBuffer : public MemoryBuffer {
  public:
    StringMemoryBuffer(std::string Buffer)
      : Buffer(std::move(Buffer)) {
      init(this->Buffer.data(), this->Buffer.data() + this->Buffer.size(),
           false);
    }

    BufferKind getBufferKind() const override { return MemoryBuffer_Malloc; }
  private:
    std::string Buffer;
  };

  JITSymbol lookup(ObjHandleT Id, const std::string &Name) {
    return remoteToJITSymbol(
             this->Remote.template callB<Lookup>(Id, Name));
  }

  JITSymbol lookupInLogicalDylib(ObjHandleT Id, const std::string &Name) {
    return remoteToJITSymbol(
             this->Remote.template callB<LookupInLogicalDylib>(Id, Name));
  }

  Expected<ObjHandleT> addObject(std::string ObjBuffer) {
    auto Buffer = llvm::make_unique<StringMemoryBuffer>(std::move(ObjBuffer));
    auto Id = HandleIdMgr.getNext();
    assert(!BaseLayerHandles.count(Id) && "Id already in use?");

    auto Resolver = createLambdaResolver(
        [this, Id](const std::string &Name) { return lookup(Id, Name); },
        [this, Id](const std::string &Name) {
          return lookupInLogicalDylib(Id, Name);
        });

    if (auto HandleOrErr =
            BaseLayer.addObject(std::move(Buffer), std::move(Resolver))) {
      BaseLayerHandles[Id] = std::move(*HandleOrErr);
      return Id;
    } else
      return teeLog(HandleOrErr.takeError());
  }

  Error removeObject(ObjHandleT H) {
    auto HI = BaseLayerHandles.find(H);
    if (HI != BaseLayerHandles.end()) {
      if (auto Err = BaseLayer.removeObject(HI->second))
        return teeLog(std::move(Err));
      return Error::success();
    } else
      return teeLog(badObjectHandleError(H));
  }

  Expected<RemoteSymbol> findSymbol(const std::string &Name,
                                    bool ExportedSymbolsOnly) {
    if (auto Sym = BaseLayer.findSymbol(Name, ExportedSymbolsOnly))
      return this->jitSymbolToRemote(std::move(Sym));
    else if (auto Err = Sym.takeError())
      return teeLog(std::move(Err));
    return this->nullRemoteSymbol();
  }

  Expected<RemoteSymbol> findSymbolIn(ObjHandleT H, const std::string &Name,
                                      bool ExportedSymbolsOnly) {
    auto HI = BaseLayerHandles.find(H);
    if (HI != BaseLayerHandles.end()) {
      if (auto Sym = BaseLayer.findSymbolIn(HI->second, Name, ExportedSymbolsOnly))
        return this->jitSymbolToRemote(std::move(Sym));
      else if (auto Err = Sym.takeError())
        return teeLog(std::move(Err));
      return this->nullRemoteSymbol();
    } else
      return teeLog(badObjectHandleError(H));
  }

  Error emitAndFinalize(ObjHandleT H) {
    auto HI = BaseLayerHandles.find(H);
    if (HI != BaseLayerHandles.end()) {
      if (auto Err = BaseLayer.emitAndFinalize(HI->second))
        return teeLog(std::move(Err));
      return Error::success();
    } else
      return teeLog(badObjectHandleError(H));
  }

  BaseLayerT &BaseLayer;
  remote::ResourceIdMgr HandleIdMgr;
  std::map<ObjHandleT, typename BaseLayerT::ObjHandleT> BaseLayerHandles;
};

} // end namespace orc
} // end namespace llvm

#endif // LLVM_EXECUTIONENGINE_ORC_REMOTEOBJECTLAYER_H
