[llvm] 1d0676b - [ORC] Break up OrcJIT library, add Orc-RPC based remote TargetProcessControl

Lang Hames via llvm-commits llvm-commits at lists.llvm.org
Fri Nov 13 14:48:36 PST 2020


Thanks for the heads up Arthur. This should be fixed in f2980e8849a.

-- Lang.

On Sat, Nov 14, 2020 at 6:35 AM Arthur Eubanks <aeubanks at google.com> wrote:

> This causes a warning on Windows:
> [326/1881] CXX
> obj/llvm/tools/llvm-jitlink/llvm-jitlink-executor/llvm-jitlink-executor.llvm-jitlink-executor.obj
> ../../llvm/tools/llvm-jitlink/llvm-jitlink-executor/llvm-jitlink-executor.cpp(77,1):
> warning: non-void function does not return a value [-Wreturn-type]
> }
>
> On Thu, Nov 12, 2020 at 10:06 PM Lang Hames via llvm-commits <
> llvm-commits at lists.llvm.org> wrote:
>
>>
>> Author: Lang Hames
>> Date: 2020-11-13T17:05:13+11:00
>> New Revision: 1d0676b54c4e3a517719220def96dfdbc26d8048
>>
>> URL:
>> https://github.com/llvm/llvm-project/commit/1d0676b54c4e3a517719220def96dfdbc26d8048
>> DIFF:
>> https://github.com/llvm/llvm-project/commit/1d0676b54c4e3a517719220def96dfdbc26d8048.diff
>>
>> LOG: [ORC] Break up OrcJIT library, add Orc-RPC based remote
>> TargetProcessControl
>> implementation.
>>
>> This patch aims to improve support for out-of-process JITing using OrcV2.
>> It
>> introduces two new class templates, OrcRPCTargetProcessControlBase and
>> OrcRPCTPCServer, which together implement the TargetProcessControl API by
>> forwarding operations to an execution process via an Orc-RPC Endpoint.
>> These
>> utilities are used to implement out-of-process JITing from llvm-jitlink to
>> a new llvm-jitlink-executor tool.
>>
>> This patch also breaks the OrcJIT library into three parts:
>>   -- OrcTargetProcess: Contains code needed by the JIT execution process.
>>   -- OrcShared: Contains code needed by the JIT execution and compiler
>>      processes
>>   -- OrcJIT: Everything else.
>>
>> This break-up allows JIT executor processes to link against
>> OrcTargetProcess
>> and OrcShared only, without having to link in all of OrcJIT. Clients
>> executing
>> JIT'd code in-process should start linking against OrcTargetProcess as
>> well as
>> OrcJIT.
>>
>> In the near future these changes will enable:
>>   -- Removal of the OrcRemoteTargetClient/OrcRemoteTargetServer class
>> templates
>>      which provided similar functionality in OrcV1.
>>   -- Restoration of Chapter 5 of the Building-A-JIT tutorial series,
>> which will
>>      serve as a simple usage example for these APIs.
>>   -- Implementation of lazy, cross-target compilation in lli's
>> -jit-kind=orc-lazy
>>      mode.
>>
>> Added:
>>     llvm/include/llvm/ExecutionEngine/Orc/OrcRPCTargetProcessControl.h
>>
>> llvm/include/llvm/ExecutionEngine/Orc/Shared/TargetProcessControlTypes.h
>>     llvm/include/llvm/ExecutionEngine/Orc/TPCEHFrameRegistrar.h
>>     llvm/include/llvm/ExecutionEngine/Orc/TargetProcess/OrcRPCTPCServer.h
>>     llvm/include/llvm/ExecutionEngine/Orc/TargetProcess/RegisterEHFrames.h
>>
>> llvm/include/llvm/ExecutionEngine/Orc/TargetProcess/TargetExecutionUtils.h
>>     llvm/lib/ExecutionEngine/Orc/Shared/CMakeLists.txt
>>     llvm/lib/ExecutionEngine/Orc/Shared/LLVMBuild.txt
>>     llvm/lib/ExecutionEngine/Orc/Shared/LLVMBuild.txt.rej
>>     llvm/lib/ExecutionEngine/Orc/Shared/OrcError.cpp
>>     llvm/lib/ExecutionEngine/Orc/Shared/RPCError.cpp
>>     llvm/lib/ExecutionEngine/Orc/Shared/TargetProcessControlTypes.cpp
>>     llvm/lib/ExecutionEngine/Orc/TPCEHFrameRegistrar.cpp
>>     llvm/lib/ExecutionEngine/Orc/TargetProcess/CMakeLists.txt
>>     llvm/lib/ExecutionEngine/Orc/TargetProcess/LLVMBuild.txt
>>     llvm/lib/ExecutionEngine/Orc/TargetProcess/RegisterEHFrames.cpp
>>     llvm/lib/ExecutionEngine/Orc/TargetProcess/TargetExecutionUtils.cpp
>>     llvm/tools/llvm-jitlink/llvm-jitlink-executor/CMakeLists.txt
>>     llvm/tools/llvm-jitlink/llvm-jitlink-executor/LLVMBuild.txt
>>
>> llvm/tools/llvm-jitlink/llvm-jitlink-executor/llvm-jitlink-executor.cpp
>>
>> Modified:
>>
>> llvm/examples/OrcV2Examples/LLJITWithTargetProcessControl/LLJITWithTargetProcessControl.cpp
>>     llvm/include/llvm/ExecutionEngine/JITLink/EHFrameSupport.h
>>     llvm/include/llvm/ExecutionEngine/JITLink/JITLink.h
>>     llvm/include/llvm/ExecutionEngine/Orc/ExecutionUtils.h
>>     llvm/include/llvm/ExecutionEngine/Orc/RPC/FDRawByteChannel.h
>>     llvm/include/llvm/ExecutionEngine/Orc/RPC/RPCSerialization.h
>>
>> llvm/include/llvm/ExecutionEngine/Orc/TPCDynamicLibrarySearchGenerator.h
>>     llvm/include/llvm/ExecutionEngine/Orc/TargetProcessControl.h
>>     llvm/lib/ExecutionEngine/CMakeLists.txt
>>     llvm/lib/ExecutionEngine/JITLink/CMakeLists.txt
>>     llvm/lib/ExecutionEngine/JITLink/EHFrameSupport.cpp
>>     llvm/lib/ExecutionEngine/JITLink/LLVMBuild.txt
>>     llvm/lib/ExecutionEngine/LLVMBuild.txt
>>     llvm/lib/ExecutionEngine/Orc/CMakeLists.txt
>>     llvm/lib/ExecutionEngine/Orc/ExecutionUtils.cpp
>>     llvm/lib/ExecutionEngine/Orc/LLVMBuild.txt
>>     llvm/lib/ExecutionEngine/Orc/TPCDynamicLibrarySearchGenerator.cpp
>>     llvm/lib/ExecutionEngine/Orc/TPCIndirectionUtils.cpp
>>     llvm/lib/ExecutionEngine/Orc/TargetProcessControl.cpp
>>     llvm/tools/lli/CMakeLists.txt
>>     llvm/tools/lli/ChildTarget/CMakeLists.txt
>>     llvm/tools/lli/LLVMBuild.txt
>>     llvm/tools/lli/lli.cpp
>>     llvm/tools/llvm-jitlink/CMakeLists.txt
>>     llvm/tools/llvm-jitlink/LLVMBuild.txt
>>     llvm/tools/llvm-jitlink/llvm-jitlink.cpp
>>     llvm/tools/llvm-jitlink/llvm-jitlink.h
>>     llvm/unittests/ExecutionEngine/JITLink/CMakeLists.txt
>>     llvm/unittests/ExecutionEngine/Orc/CMakeLists.txt
>>
>> Removed:
>>     llvm/lib/ExecutionEngine/OrcError/CMakeLists.txt
>>     llvm/lib/ExecutionEngine/OrcError/LLVMBuild.txt
>>     llvm/lib/ExecutionEngine/OrcError/OrcError.cpp
>>     llvm/lib/ExecutionEngine/OrcError/RPCError.cpp
>>
>>
>>
>> ################################################################################
>> diff  --git
>> a/llvm/examples/OrcV2Examples/LLJITWithTargetProcessControl/LLJITWithTargetProcessControl.cpp
>> b/llvm/examples/OrcV2Examples/LLJITWithTargetProcessControl/LLJITWithTargetProcessControl.cpp
>> index d2ce26bddd72..4e36631ef97d 100644
>> ---
>> a/llvm/examples/OrcV2Examples/LLJITWithTargetProcessControl/LLJITWithTargetProcessControl.cpp
>> +++
>> b/llvm/examples/OrcV2Examples/LLJITWithTargetProcessControl/LLJITWithTargetProcessControl.cpp
>> @@ -134,7 +134,8 @@ int main(int argc, char *argv[]) {
>>    ExitOnErr.setBanner(std::string(argv[0]) + ": ");
>>
>>    // (1) Create LLJIT instance.
>> -  auto TPC = ExitOnErr(SelfTargetProcessControl::Create());
>> +  auto SSP = std::make_shared<SymbolStringPool>();
>> +  auto TPC = ExitOnErr(SelfTargetProcessControl::Create(std::move(SSP)));
>>    auto J =
>> ExitOnErr(LLJITBuilder().setTargetProcessControl(*TPC).create());
>>
>>    // (2) Install transform to print modules as they are compiled:
>>
>> diff  --git a/llvm/include/llvm/ExecutionEngine/JITLink/EHFrameSupport.h
>> b/llvm/include/llvm/ExecutionEngine/JITLink/EHFrameSupport.h
>> index 72394d7c9985..ec78d9db40b6 100644
>> --- a/llvm/include/llvm/ExecutionEngine/JITLink/EHFrameSupport.h
>> +++ b/llvm/include/llvm/ExecutionEngine/JITLink/EHFrameSupport.h
>> @@ -21,14 +21,6 @@
>>  namespace llvm {
>>  namespace jitlink {
>>
>> -/// Registers all FDEs in the given eh-frame section with the current
>> process.
>> -Error registerEHFrameSection(const void *EHFrameSectionAddr,
>> -                             size_t EHFrameSectionSize);
>> -
>> -/// Deregisters all FDEs in the given eh-frame section with the current
>> process.
>> -Error deregisterEHFrameSection(const void *EHFrameSectionAddr,
>> -                               size_t EHFrameSectionSize);
>> -
>>  /// Supports registration/deregistration of EH-frames in a target
>> process.
>>  class EHFrameRegistrar {
>>  public:
>>
>> diff  --git a/llvm/include/llvm/ExecutionEngine/JITLink/JITLink.h
>> b/llvm/include/llvm/ExecutionEngine/JITLink/JITLink.h
>> index 5e22837fa930..f0b4d9bcd49c 100644
>> --- a/llvm/include/llvm/ExecutionEngine/JITLink/JITLink.h
>> +++ b/llvm/include/llvm/ExecutionEngine/JITLink/JITLink.h
>> @@ -801,6 +801,17 @@ class LinkGraph {
>>    /// Returns the endianness of content in this graph.
>>    support::endianness getEndianness() const { return Endianness; }
>>
>> +  /// Allocate a copy of the given String using the LinkGraph's
>> allocator.
>> +  /// This can be useful when renaming symbols or adding new content to
>> the
>> +  /// graph.
>> +  StringRef allocateString(Twine Source) {
>> +    SmallString<256> TmpBuffer;
>> +    auto SourceStr = Source.toStringRef(TmpBuffer);
>> +    auto *AllocatedBuffer = Allocator.Allocate<char>(SourceStr.size());
>> +    llvm::copy(SourceStr, AllocatedBuffer);
>> +    return StringRef(AllocatedBuffer, SourceStr.size());
>> +  }
>> +
>>    /// Create a section with the given name, protection flags, and
>> alignment.
>>    Section &createSection(StringRef Name, sys::Memory::ProtectionFlags
>> Prot) {
>>      std::unique_ptr<Section> Sec(new Section(Name, Prot,
>> Sections.size()));
>>
>> diff  --git a/llvm/include/llvm/ExecutionEngine/Orc/ExecutionUtils.h
>> b/llvm/include/llvm/ExecutionEngine/Orc/ExecutionUtils.h
>> index 0270f8f7d68d..1dc2af49b78e 100644
>> --- a/llvm/include/llvm/ExecutionEngine/Orc/ExecutionUtils.h
>> +++ b/llvm/include/llvm/ExecutionEngine/Orc/ExecutionUtils.h
>> @@ -41,17 +41,6 @@ namespace orc {
>>
>>  class ObjectLayer;
>>
>> -/// Run a main function, returning the result.
>> -///
>> -/// If the optional ProgramName argument is given then it will be
>> inserted
>> -/// before the strings in Args as the first argument to the called
>> function.
>> -///
>> -/// It is legal to have an empty argument list and no program name,
>> however
>> -/// many main functions will expect a name argument at least, and will
>> fail
>> -/// if none is provided.
>> -int runAsMain(int (*Main)(int, char *[]), ArrayRef<std::string> Args,
>> -              Optional<StringRef> ProgramName = None);
>> -
>>  /// This iterator provides a convenient way to iterate over the elements
>>  ///        of an llvm.global_ctors/llvm.global_dtors instance.
>>  ///
>>
>> diff  --git
>> a/llvm/include/llvm/ExecutionEngine/Orc/OrcRPCTargetProcessControl.h
>> b/llvm/include/llvm/ExecutionEngine/Orc/OrcRPCTargetProcessControl.h
>> new file mode 100644
>> index 000000000000..f63dcd0f3471
>> --- /dev/null
>> +++ b/llvm/include/llvm/ExecutionEngine/Orc/OrcRPCTargetProcessControl.h
>> @@ -0,0 +1,411 @@
>> +//===--- OrcRPCTargetProcessControl.h - Remote target control ---*- 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
>> +//
>>
>> +//===----------------------------------------------------------------------===//
>> +//
>> +// Utilities for interacting with target processes.
>> +//
>>
>> +//===----------------------------------------------------------------------===//
>> +
>> +#ifndef LLVM_EXECUTIONENGINE_ORC_ORCRPCTARGETPROCESSCONTROL_H
>> +#define LLVM_EXECUTIONENGINE_ORC_ORCRPCTARGETPROCESSCONTROL_H
>> +
>> +#include "llvm/ExecutionEngine/Orc/RPC/RPCUtils.h"
>> +#include "llvm/ExecutionEngine/Orc/RPC/RawByteChannel.h"
>> +#include "llvm/ExecutionEngine/Orc/TargetProcess/OrcRPCTPCServer.h"
>> +#include "llvm/ExecutionEngine/Orc/TargetProcessControl.h"
>> +#include "llvm/Support/MSVCErrorWorkarounds.h"
>> +
>> +namespace llvm {
>> +namespace orc {
>> +
>> +/// JITLinkMemoryManager implementation for a process connected via an
>> ORC RPC
>> +/// endpoint.
>> +template <typename OrcRPCTPCImplT>
>> +class OrcRPCTPCJITLinkMemoryManager : public
>> jitlink::JITLinkMemoryManager {
>> +private:
>> +  struct HostAlloc {
>> +    std::unique_ptr<char[]> Mem;
>> +    uint64_t Size;
>> +  };
>> +
>> +  struct TargetAlloc {
>> +    JITTargetAddress Address = 0;
>> +    uint64_t AllocatedSize = 0;
>> +  };
>> +
>> +  using HostAllocMap = DenseMap<int, HostAlloc>;
>> +  using TargetAllocMap = DenseMap<int, TargetAlloc>;
>> +
>> +public:
>> +  class OrcRPCAllocation : public Allocation {
>> +  public:
>> +    OrcRPCAllocation(OrcRPCTPCJITLinkMemoryManager<OrcRPCTPCImplT>
>> &Parent,
>> +                     HostAllocMap HostAllocs, TargetAllocMap
>> TargetAllocs)
>> +        : Parent(Parent), HostAllocs(std::move(HostAllocs)),
>> +          TargetAllocs(std::move(TargetAllocs)) {
>> +      assert(HostAllocs.size() == TargetAllocs.size() &&
>> +             "HostAllocs size should match TargetAllocs");
>> +    }
>> +
>> +    ~OrcRPCAllocation() override {
>> +      assert(TargetAllocs.empty() && "failed to deallocate");
>> +    }
>> +
>> +    MutableArrayRef<char> getWorkingMemory(ProtectionFlags Seg) override
>> {
>> +      auto I = HostAllocs.find(Seg);
>> +      assert(I != HostAllocs.end() && "No host allocation for segment");
>> +      auto &HA = I->second;
>> +      return {HA.Mem.get(), HA.Size};
>> +    }
>> +
>> +    JITTargetAddress getTargetMemory(ProtectionFlags Seg) override {
>> +      auto I = TargetAllocs.find(Seg);
>> +      assert(I != TargetAllocs.end() && "No target allocation for
>> segment");
>> +      return I->second.Address;
>> +    }
>> +
>> +    void finalizeAsync(FinalizeContinuation OnFinalize) override {
>> +
>> +      std::vector<tpctypes::BufferWrite> BufferWrites;
>> +      orcrpctpc::ReleaseOrFinalizeMemRequest FMR;
>> +
>> +      for (auto &KV : HostAllocs) {
>> +        assert(TargetAllocs.count(KV.first) &&
>> +               "No target allocation for buffer");
>> +        auto &HA = KV.second;
>> +        auto &TA = TargetAllocs[KV.first];
>> +        BufferWrites.push_back({TA.Address, StringRef(HA.Mem.get(),
>> HA.Size)});
>> +        FMR.push_back({orcrpctpc::toWireProtectionFlags(
>> +
>>  static_cast<sys::Memory::ProtectionFlags>(KV.first)),
>> +                       TA.Address, TA.AllocatedSize});
>> +      }
>> +
>> +      DEBUG_WITH_TYPE("orc", {
>> +        dbgs() << "finalizeAsync " << (void *)this << ":\n";
>> +        auto FMRI = FMR.begin();
>> +        for (auto &B : BufferWrites) {
>> +          auto Prot = FMRI->Prot;
>> +          ++FMRI;
>> +          dbgs() << "  Writing " << formatv("{0:x16}", B.Buffer.size())
>> +                 << " bytes to " << ((Prot & orcrpctpc::WPF_Read) ? 'R'
>> : '-')
>> +                 << ((Prot & orcrpctpc::WPF_Write) ? 'W' : '-')
>> +                 << ((Prot & orcrpctpc::WPF_Exec) ? 'X' : '-')
>> +                 << " segment: local " << (void *)B.Buffer.data()
>> +                 << " -> target " << formatv("{0:x16}", B.Address) <<
>> "\n";
>> +        }
>> +      });
>> +      if (auto Err =
>> +
>> Parent.Parent.getMemoryAccess().writeBuffers(BufferWrites)) {
>> +        OnFinalize(std::move(Err));
>> +        return;
>> +      }
>> +
>> +      DEBUG_WITH_TYPE("orc", dbgs() << " Applying permissions...\n");
>> +      if (auto Err =
>> +              Parent.getEndpoint().template
>> callAsync<orcrpctpc::FinalizeMem>(
>> +                  [OF = std::move(OnFinalize)](Error Err2) {
>> +                    // FIXME: Dispatch to work queue.
>> +                    std::thread([OF = std::move(OF),
>> +                                 Err3 = std::move(Err2)]() mutable {
>> +                      DEBUG_WITH_TYPE(
>> +                          "orc", { dbgs() << "  finalizeAsync
>> complete\n"; });
>> +                      OF(std::move(Err3));
>> +                    }).detach();
>> +                    return Error::success();
>> +                  },
>> +                  FMR)) {
>> +        DEBUG_WITH_TYPE("orc", dbgs() << "    failed.\n");
>> +        Parent.getEndpoint().abandonPendingResponses();
>> +        Parent.reportError(std::move(Err));
>> +      }
>> +      DEBUG_WITH_TYPE("orc", {
>> +        dbgs() << "Leaving finalizeAsync (finalization may continue in "
>> +                  "background)\n";
>> +      });
>> +    }
>> +
>> +    Error deallocate() override {
>> +      orcrpctpc::ReleaseOrFinalizeMemRequest RMR;
>> +      for (auto &KV : TargetAllocs)
>> +        RMR.push_back({orcrpctpc::toWireProtectionFlags(
>> +
>>  static_cast<sys::Memory::ProtectionFlags>(KV.first)),
>> +                       KV.second.Address, KV.second.AllocatedSize});
>> +      TargetAllocs.clear();
>> +
>> +      return Parent.getEndpoint().template
>> callB<orcrpctpc::ReleaseMem>(RMR);
>> +    }
>> +
>> +  private:
>> +    OrcRPCTPCJITLinkMemoryManager<OrcRPCTPCImplT> &Parent;
>> +    HostAllocMap HostAllocs;
>> +    TargetAllocMap TargetAllocs;
>> +  };
>> +
>> +  OrcRPCTPCJITLinkMemoryManager(OrcRPCTPCImplT &Parent) : Parent(Parent)
>> {}
>> +
>> +  Expected<std::unique_ptr<Allocation>>
>> +  allocate(const SegmentsRequestMap &Request) override {
>> +    orcrpctpc::ReserveMemRequest RMR;
>> +    HostAllocMap HostAllocs;
>> +
>> +    for (auto &KV : Request) {
>> +      RMR.push_back({orcrpctpc::toWireProtectionFlags(
>> +
>>  static_cast<sys::Memory::ProtectionFlags>(KV.first)),
>> +                     KV.second.getContentSize() +
>> KV.second.getZeroFillSize(),
>> +                     KV.second.getAlignment()});
>> +      HostAllocs[KV.first] = {
>> +          std::make_unique<char[]>(KV.second.getContentSize()),
>> +          KV.second.getContentSize()};
>> +    }
>> +
>> +    DEBUG_WITH_TYPE("orc", {
>> +      dbgs() << "Orc remote memmgr got request:\n";
>> +      for (auto &KV : Request)
>> +        dbgs() << "  permissions: "
>> +               << ((KV.first & sys::Memory::MF_READ) ? 'R' : '-')
>> +               << ((KV.first & sys::Memory::MF_WRITE) ? 'W' : '-')
>> +               << ((KV.first & sys::Memory::MF_EXEC) ? 'X' : '-')
>> +               << ", content size: "
>> +               << formatv("{0:x16}", KV.second.getContentSize())
>> +               << " + zero-fill-size: "
>> +               << formatv("{0:x16}", KV.second.getZeroFillSize())
>> +               << ", align: " << KV.second.getAlignment() << "\n";
>> +    });
>> +
>> +    // FIXME: LLVM RPC needs to be fixed to support alt
>> +    // serialization/deserialization on return types. For now just
>> +    // translate from std::map to DenseMap manually.
>> +    auto TmpTargetAllocs =
>> +        Parent.getEndpoint().template callB<orcrpctpc::ReserveMem>(RMR);
>> +    if (!TmpTargetAllocs)
>> +      return TmpTargetAllocs.takeError();
>> +
>> +    if (TmpTargetAllocs->size() != RMR.size())
>> +      return make_error<StringError>(
>> +          "Number of target allocations does not match request",
>> +          inconvertibleErrorCode());
>> +
>> +    TargetAllocMap TargetAllocs;
>> +    for (auto &E : *TmpTargetAllocs)
>> +      TargetAllocs[orcrpctpc::fromWireProtectionFlags(E.Prot)] = {
>> +          E.Address, E.AllocatedSize};
>> +
>> +    DEBUG_WITH_TYPE("orc", {
>> +      auto HAI = HostAllocs.begin();
>> +      for (auto &KV : TargetAllocs)
>> +        dbgs() << "  permissions: "
>> +               << ((KV.first & sys::Memory::MF_READ) ? 'R' : '-')
>> +               << ((KV.first & sys::Memory::MF_WRITE) ? 'W' : '-')
>> +               << ((KV.first & sys::Memory::MF_EXEC) ? 'X' : '-')
>> +               << " assigned local " << (void *)HAI->second.Mem.get()
>> +               << ", target " << formatv("{0:x16}", KV.second.Address)
>> << "\n";
>> +    });
>> +
>> +    return std::make_unique<OrcRPCAllocation>(*this,
>> std::move(HostAllocs),
>> +                                              std::move(TargetAllocs));
>> +  }
>> +
>> +private:
>> +  void reportError(Error Err) { Parent.reportError(std::move(Err)); }
>> +
>> +  decltype(std::declval<OrcRPCTPCImplT>().getEndpoint()) getEndpoint() {
>> +    return Parent.getEndpoint();
>> +  }
>> +
>> +  OrcRPCTPCImplT &Parent;
>> +};
>> +
>> +/// TargetProcessControl::MemoryAccess implementation for a process
>> connected
>> +/// via an ORC RPC endpoint.
>> +template <typename OrcRPCTPCImplT>
>> +class OrcRPCTPCMemoryAccess : public TargetProcessControl::MemoryAccess {
>> +public:
>> +  OrcRPCTPCMemoryAccess(OrcRPCTPCImplT &Parent) : Parent(Parent) {}
>> +
>> +  void writeUInt8s(ArrayRef<tpctypes::UInt8Write> Ws,
>> +                   WriteResultFn OnWriteComplete) override {
>> +    writeViaRPC<orcrpctpc::WriteUInt8s>(Ws, std::move(OnWriteComplete));
>> +  }
>> +
>> +  void writeUInt16s(ArrayRef<tpctypes::UInt16Write> Ws,
>> +                    WriteResultFn OnWriteComplete) override {
>> +    writeViaRPC<orcrpctpc::WriteUInt16s>(Ws, std::move(OnWriteComplete));
>> +  }
>> +
>> +  void writeUInt32s(ArrayRef<tpctypes::UInt32Write> Ws,
>> +                    WriteResultFn OnWriteComplete) override {
>> +    writeViaRPC<orcrpctpc::WriteUInt32s>(Ws, std::move(OnWriteComplete));
>> +  }
>> +
>> +  void writeUInt64s(ArrayRef<tpctypes::UInt64Write> Ws,
>> +                    WriteResultFn OnWriteComplete) override {
>> +    writeViaRPC<orcrpctpc::WriteUInt64s>(Ws, std::move(OnWriteComplete));
>> +  }
>> +
>> +  void writeBuffers(ArrayRef<tpctypes::BufferWrite> Ws,
>> +                    WriteResultFn OnWriteComplete) override {
>> +    writeViaRPC<orcrpctpc::WriteBuffers>(Ws, std::move(OnWriteComplete));
>> +  }
>> +
>> +private:
>> +  template <typename WriteRPCFunction, typename WriteElementT>
>> +  void writeViaRPC(ArrayRef<WriteElementT> Ws, WriteResultFn
>> OnWriteComplete) {
>> +    if (auto Err = Parent.getEndpoint().template
>> callAsync<WriteRPCFunction>(
>> +            [OWC = std::move(OnWriteComplete)](Error Err2) mutable ->
>> Error {
>> +              OWC(std::move(Err2));
>> +              return Error::success();
>> +            },
>> +            Ws)) {
>> +      Parent.reportError(std::move(Err));
>> +      Parent.getEndpoint().abandonPendingResponses();
>> +    }
>> +  }
>> +
>> +  OrcRPCTPCImplT &Parent;
>> +};
>> +
>> +// TargetProcessControl for a process connected via an ORC RPC Endpoint.
>> +template <typename RPCEndpointT>
>> +class OrcRPCTargetProcessControlBase : public TargetProcessControl {
>> +public:
>> +  using ErrorReporter = unique_function<void(Error)>;
>> +
>> +  using OnCloseConnectionFunction = unique_function<Error(Error)>;
>> +
>> +  OrcRPCTargetProcessControlBase(std::shared_ptr<SymbolStringPool> SSP,
>> +                                 RPCEndpointT &EP, ErrorReporter
>> ReportError)
>> +      : TargetProcessControl(std::move(SSP)),
>> +        ReportError(std::move(ReportError)), EP(EP) {}
>> +
>> +  void reportError(Error Err) { ReportError(std::move(Err)); }
>> +
>> +  RPCEndpointT &getEndpoint() { return EP; }
>> +
>> +  Expected<tpctypes::DylibHandle> loadDylib(const char *DylibPath)
>> override {
>> +    DEBUG_WITH_TYPE("orc", {
>> +      dbgs() << "Loading dylib \"" << (DylibPath ? DylibPath : "") <<
>> "\" ";
>> +      if (!DylibPath)
>> +        dbgs() << "(process symbols)";
>> +      dbgs() << "\n";
>> +    });
>> +    if (!DylibPath)
>> +      DylibPath = "";
>> +    auto H = EP.template callB<orcrpctpc::LoadDylib>(DylibPath);
>> +    DEBUG_WITH_TYPE("orc", {
>> +      if (H)
>> +        dbgs() << "  got handle " << formatv("{0:x16}", *H) << "\n";
>> +      else
>> +        dbgs() << "  error, unable to load\n";
>> +    });
>> +    return H;
>> +  }
>> +
>> +  Expected<std::vector<tpctypes::LookupResult>>
>> +  lookupSymbols(ArrayRef<tpctypes::LookupRequest> Request) override {
>> +    std::vector<orcrpctpc::RemoteLookupRequest> RR;
>> +    for (auto &E : Request) {
>> +      RR.push_back({});
>> +      RR.back().first = E.Handle;
>> +      for (auto &KV : E.Symbols)
>> +        RR.back().second.push_back(
>> +            {(*KV.first).str(),
>> +             KV.second == SymbolLookupFlags::WeaklyReferencedSymbol});
>> +    }
>> +    DEBUG_WITH_TYPE("orc", {
>> +      dbgs() << "Compound lookup:\n";
>> +      for (auto &R : Request) {
>> +        dbgs() << "  In " << formatv("{0:x16}", R.Handle) << ": {";
>> +        bool First = true;
>> +        for (auto &KV : R.Symbols) {
>> +          dbgs() << (First ? "" : ",") << " " << *KV.first;
>> +          First = false;
>> +        }
>> +        dbgs() << " }\n";
>> +      }
>> +    });
>> +    return EP.template callB<orcrpctpc::LookupSymbols>(RR);
>> +  }
>> +
>> +  Expected<int32_t> runAsMain(JITTargetAddress MainFnAddr,
>> +                              ArrayRef<std::string> Args) override {
>> +    DEBUG_WITH_TYPE("orc", {
>> +      dbgs() << "Running as main: " << formatv("{0:x16}", MainFnAddr)
>> +             << ", args = [";
>> +      for (unsigned I = 0; I != Args.size(); ++I)
>> +        dbgs() << (I ? "," : "") << " \"" << Args[I] << "\"";
>> +      dbgs() << "]\n";
>> +    });
>> +    auto Result = EP.template callB<orcrpctpc::RunMain>(MainFnAddr,
>> Args);
>> +    DEBUG_WITH_TYPE("orc", {
>> +      dbgs() << "  call to " << formatv("{0:x16}", MainFnAddr);
>> +      if (Result)
>> +        dbgs() << " returned result " << *Result << "\n";
>> +      else
>> +        dbgs() << " failed\n";
>> +    });
>> +    return Result;
>> +  }
>> +
>> +  Expected<tpctypes::WrapperFunctionResult>
>> +  runWrapper(JITTargetAddress WrapperFnAddr,
>> +             ArrayRef<uint8_t> ArgBuffer) override {
>> +    DEBUG_WITH_TYPE("orc", {
>> +      dbgs() << "Running as wrapper function "
>> +             << formatv("{0:x16}", WrapperFnAddr) << " with "
>> +             << formatv("{0:x16}", ArgBuffer.size()) << " argument
>> buffer\n";
>> +    });
>> +    auto Result =
>> +        EP.template callB<orcrpctpc::RunWrapper>(WrapperFnAddr,
>> ArgBuffer);
>> +    // dbgs() << "Returned from runWrapper...\n";
>> +    return Result;
>> +  }
>> +
>> +  Error closeConnection(OnCloseConnectionFunction OnCloseConnection) {
>> +    DEBUG_WITH_TYPE("orc", dbgs() << "Closing connection to remote\n");
>> +    return EP.template callAsync<orcrpctpc::CloseConnection>(
>> +        std::move(OnCloseConnection));
>> +  }
>> +
>> +  Error closeConnectionAndWait() {
>> +    std::promise<MSVCPError> P;
>> +    auto F = P.get_future();
>> +    if (auto Err = closeConnection([&](Error Err2) -> Error {
>> +          P.set_value(std::move(Err2));
>> +          return Error::success();
>> +        })) {
>> +      EP.abandonAllPendingResponses();
>> +      return joinErrors(std::move(Err), F.get());
>> +    }
>> +    return F.get();
>> +  }
>> +
>> +protected:
>> +  /// Subclasses must call this during construction to initialize the
>> +  /// TargetTriple and PageSize members.
>> +  Error initializeORCRPCTPCBase() {
>> +    if (auto TripleOrErr = EP.template
>> callB<orcrpctpc::GetTargetTriple>())
>> +      TargetTriple = Triple(*TripleOrErr);
>> +    else
>> +      return TripleOrErr.takeError();
>> +
>> +    if (auto PageSizeOrErr = EP.template callB<orcrpctpc::GetPageSize>())
>> +      PageSize = *PageSizeOrErr;
>> +    else
>> +      return PageSizeOrErr.takeError();
>> +
>> +    return Error::success();
>> +  }
>> +
>> +private:
>> +  ErrorReporter ReportError;
>> +  RPCEndpointT &EP;
>> +};
>> +
>> +} // end namespace orc
>> +} // end namespace llvm
>> +
>> +#endif // LLVM_EXECUTIONENGINE_ORC_ORCRPCTARGETPROCESSCONTROL_H
>>
>> diff  --git
>> a/llvm/include/llvm/ExecutionEngine/Orc/RPC/FDRawByteChannel.h
>> b/llvm/include/llvm/ExecutionEngine/Orc/RPC/FDRawByteChannel.h
>> index 25edb289a5f9..9faa1afe546c 100644
>> --- a/llvm/include/llvm/ExecutionEngine/Orc/RPC/FDRawByteChannel.h
>> +++ b/llvm/include/llvm/ExecutionEngine/Orc/RPC/FDRawByteChannel.h
>> @@ -15,6 +15,9 @@
>>
>>  #include "llvm/ExecutionEngine/Orc/RPC/RawByteChannel.h"
>>
>> +#include "llvm/Support/FormatVariadic.h"
>> +#include "llvm/Support/raw_ostream.h"
>> +
>>  #if !defined(_MSC_VER) && !defined(__MINGW32__)
>>  #include <unistd.h>
>>  #else
>> @@ -31,11 +34,13 @@ class FDRawByteChannel final : public RawByteChannel {
>>    FDRawByteChannel(int InFD, int OutFD) : InFD(InFD), OutFD(OutFD) {}
>>
>>    llvm::Error readBytes(char *Dst, unsigned Size) override {
>> +    // dbgs() << "Reading " << Size << " bytes: [";
>>      assert(Dst && "Attempt to read into null.");
>>      ssize_t Completed = 0;
>>      while (Completed < static_cast<ssize_t>(Size)) {
>>        ssize_t Read = ::read(InFD, Dst + Completed, Size - Completed);
>>        if (Read <= 0) {
>> +        // dbgs() << " <<<\n";
>>          auto ErrNo = errno;
>>          if (ErrNo == EAGAIN || ErrNo == EINTR)
>>            continue;
>> @@ -43,17 +48,22 @@ class FDRawByteChannel final : public RawByteChannel {
>>            return llvm::errorCodeToError(
>>                std::error_code(errno, std::generic_category()));
>>        }
>> +      // for (size_t I = 0; I != Read; ++I)
>> +      //  dbgs() << " " << formatv("{0:x2}", Dst[Completed + I]);
>>        Completed += Read;
>>      }
>> +    // dbgs() << " ]\n";
>>      return llvm::Error::success();
>>    }
>>
>>    llvm::Error appendBytes(const char *Src, unsigned Size) override {
>> +    // dbgs() << "Appending " << Size << " bytes: [";
>>      assert(Src && "Attempt to append from null.");
>>      ssize_t Completed = 0;
>>      while (Completed < static_cast<ssize_t>(Size)) {
>>        ssize_t Written = ::write(OutFD, Src + Completed, Size -
>> Completed);
>>        if (Written < 0) {
>> +        // dbgs() << " <<<\n";
>>          auto ErrNo = errno;
>>          if (ErrNo == EAGAIN || ErrNo == EINTR)
>>            continue;
>> @@ -61,8 +71,11 @@ class FDRawByteChannel final : public RawByteChannel {
>>            return llvm::errorCodeToError(
>>                std::error_code(errno, std::generic_category()));
>>        }
>> +      // for (size_t I = 0; I != Written; ++I)
>> +      //  dbgs() << " " << formatv("{0:x2}", Src[Completed + I]);
>>        Completed += Written;
>>      }
>> +    // dbgs() << " ]\n";
>>      return llvm::Error::success();
>>    }
>>
>>
>> diff  --git
>> a/llvm/include/llvm/ExecutionEngine/Orc/RPC/RPCSerialization.h
>> b/llvm/include/llvm/ExecutionEngine/Orc/RPC/RPCSerialization.h
>> index 948a1b061e3b..0dc05f4d1c17 100644
>> --- a/llvm/include/llvm/ExecutionEngine/Orc/RPC/RPCSerialization.h
>> +++ b/llvm/include/llvm/ExecutionEngine/Orc/RPC/RPCSerialization.h
>> @@ -9,6 +9,8 @@
>>  #ifndef LLVM_EXECUTIONENGINE_ORC_RPC_RPCSERIALIZATION_H
>>  #define LLVM_EXECUTIONENGINE_ORC_RPC_RPCSERIALIZATION_H
>>
>> +#include "llvm/ADT/ArrayRef.h"
>> +#include "llvm/ADT/DenseMap.h"
>>  #include "llvm/ExecutionEngine/Orc/OrcError.h"
>>  #include "llvm/Support/thread.h"
>>  #include <map>
>> @@ -166,6 +168,19 @@ class RPCTypeName<std::tuple<ArgTs...>> {
>>    }
>>  };
>>
>> +template <typename T> class RPCTypeName<Optional<T>> {
>> +public:
>> +  static const char *getName() {
>> +    static std::string Name = [] {
>> +      std::string Name;
>> +      raw_string_ostream(Name)
>> +          << "Optional<" << RPCTypeName<T>::getName() << ">";
>> +      return Name;
>> +    }();
>> +    return Name.data();
>> +  }
>> +};
>> +
>>  template <typename T>
>>  class RPCTypeName<std::vector<T>> {
>>  public:
>> @@ -574,6 +589,31 @@ class SerializationTraits<ChannelT,
>> std::tuple<ArgTs...>> {
>>    }
>>  };
>>
>> +template <typename ChannelT, typename T>
>> +class SerializationTraits<ChannelT, Optional<T>> {
>> +public:
>> +  /// Serialize an Optional<T>.
>> +  static Error serialize(ChannelT &C, const Optional<T> &O) {
>> +    if (auto Err = serializeSeq(C, O != None))
>> +      return Err;
>> +    if (O)
>> +      if (auto Err = serializeSeq(C, *O))
>> +        return Err;
>> +    return Error::success();
>> +  }
>> +
>> +  /// Deserialize an Optional<T>.
>> +  static Error deserialize(ChannelT &C, Optional<T> &O) {
>> +    bool HasValue = false;
>> +    if (auto Err = deserializeSeq(C, HasValue))
>> +      return Err;
>> +    if (HasValue)
>> +      if (auto Err = deserializeSeq(C, *O))
>> +        return Err;
>> +    return Error::success();
>> +  };
>> +};
>> +
>>  /// SerializationTraits default specialization for std::vector.
>>  template <typename ChannelT, typename T>
>>  class SerializationTraits<ChannelT, std::vector<T>> {
>> @@ -609,6 +649,22 @@ class SerializationTraits<ChannelT, std::vector<T>> {
>>    }
>>  };
>>
>> +/// Enable vector serialization from an ArrayRef.
>> +template <typename ChannelT, typename T>
>> +class SerializationTraits<ChannelT, std::vector<T>, ArrayRef<T>> {
>> +public:
>> +  static Error serialize(ChannelT &C, ArrayRef<T> V) {
>> +    if (auto Err = serializeSeq(C, static_cast<uint64_t>(V.size())))
>> +      return Err;
>> +
>> +    for (const auto &E : V)
>> +      if (auto Err = serializeSeq(C, E))
>> +        return Err;
>> +
>> +    return Error::success();
>> +  }
>> +};
>> +
>>  template <typename ChannelT, typename T, typename T2>
>>  class SerializationTraits<ChannelT, std::set<T>, std::set<T2>> {
>>  public:
>> @@ -695,6 +751,55 @@ class SerializationTraits<ChannelT, std::map<K, V>,
>> std::map<K2, V2>> {
>>    }
>>  };
>>
>> +template <typename ChannelT, typename K, typename V, typename K2,
>> typename V2>
>> +class SerializationTraits<ChannelT, std::map<K, V>, DenseMap<K2, V2>> {
>> +public:
>> +  /// Serialize a std::map<K, V> from DenseMap<K2, V2>.
>> +  static Error serialize(ChannelT &C, const DenseMap<K2, V2> &M) {
>> +    if (auto Err = serializeSeq(C, static_cast<uint64_t>(M.size())))
>> +      return Err;
>> +
>> +    for (auto &E : M) {
>> +      if (auto Err =
>> +              SerializationTraits<ChannelT, K, K2>::serialize(C,
>> E.first))
>> +        return Err;
>> +
>> +      if (auto Err =
>> +              SerializationTraits<ChannelT, V, V2>::serialize(C,
>> E.second))
>> +        return Err;
>> +    }
>> +
>> +    return Error::success();
>> +  }
>> +
>> +  /// Serialize a std::map<K, V> from DenseMap<K2, V2>.
>> +  static Error deserialize(ChannelT &C, DenseMap<K2, V2> &M) {
>> +    assert(M.empty() && "Expected default-constructed map to deserialize
>> into");
>> +
>> +    uint64_t Count = 0;
>> +    if (auto Err = deserializeSeq(C, Count))
>> +      return Err;
>> +
>> +    while (Count-- != 0) {
>> +      std::pair<K2, V2> Val;
>> +      if (auto Err =
>> +              SerializationTraits<ChannelT, K, K2>::deserialize(C,
>> Val.first))
>> +        return Err;
>> +
>> +      if (auto Err =
>> +              SerializationTraits<ChannelT, V, V2>::deserialize(C,
>> Val.second))
>> +        return Err;
>> +
>> +      auto Added = M.insert(Val).second;
>> +      if (!Added)
>> +        return make_error<StringError>("Duplicate element in
>> deserialized map",
>> +
>>  orcError(OrcErrorCode::UnknownORCError));
>> +    }
>> +
>> +    return Error::success();
>> +  }
>> +};
>> +
>>  } // end namespace rpc
>>  } // end namespace orc
>>  } // end namespace llvm
>>
>> diff  --git
>> a/llvm/include/llvm/ExecutionEngine/Orc/Shared/TargetProcessControlTypes.h
>> b/llvm/include/llvm/ExecutionEngine/Orc/Shared/TargetProcessControlTypes.h
>> new file mode 100644
>> index 000000000000..9f958989f46d
>> --- /dev/null
>> +++
>> b/llvm/include/llvm/ExecutionEngine/Orc/Shared/TargetProcessControlTypes.h
>> @@ -0,0 +1,174 @@
>> +//===--- TargetProcessControlTypes.h -- Shared Core/TPC types ---*- 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
>> +//
>>
>> +//===----------------------------------------------------------------------===//
>> +//
>> +// TargetProcessControl types that are used by both the Orc and
>> +// OrcTargetProcess libraries.
>> +//
>>
>> +//===----------------------------------------------------------------------===//
>> +
>> +#ifndef LLVM_EXECUTIONENGINE_ORC_SHARED_TARGETPROCESSCONTROLTYPES_H
>> +#define LLVM_EXECUTIONENGINE_ORC_SHARED_TARGETPROCESSCONTROLTYPES_H
>> +
>> +#include "llvm/ADT/ArrayRef.h"
>> +#include "llvm/ADT/StringRef.h"
>> +#include "llvm/ExecutionEngine/JITSymbol.h"
>> +#include "llvm/ExecutionEngine/Orc/Core.h"
>> +
>> +#include <vector>
>> +
>> +namespace llvm {
>> +namespace orc {
>> +namespace tpctypes {
>> +
>> +template <typename T> struct UIntWrite {
>> +  UIntWrite() = default;
>> +  UIntWrite(JITTargetAddress Address, T Value)
>> +      : Address(Address), Value(Value) {}
>> +
>> +  JITTargetAddress Address = 0;
>> +  T Value = 0;
>> +};
>> +
>> +/// Describes a write to a uint8_t.
>> +using UInt8Write = UIntWrite<uint8_t>;
>> +
>> +/// Describes a write to a uint16_t.
>> +using UInt16Write = UIntWrite<uint16_t>;
>> +
>> +/// Describes a write to a uint32_t.
>> +using UInt32Write = UIntWrite<uint32_t>;
>> +
>> +/// Describes a write to a uint64_t.
>> +using UInt64Write = UIntWrite<uint64_t>;
>> +
>> +/// Describes a write to a buffer.
>> +/// For use with TargetProcessControl::MemoryAccess objects.
>> +struct BufferWrite {
>> +  BufferWrite() = default;
>> +  BufferWrite(JITTargetAddress Address, StringRef Buffer)
>> +      : Address(Address), Buffer(Buffer) {}
>> +
>> +  JITTargetAddress Address = 0;
>> +  StringRef Buffer;
>> +};
>> +
>> +/// A handle used to represent a loaded dylib in the target process.
>> +using DylibHandle = JITTargetAddress;
>> +
>> +/// A pair of a dylib and a set of symbols to be looked up.
>> +struct LookupRequest {
>> +  LookupRequest(DylibHandle Handle, const SymbolLookupSet &Symbols)
>> +      : Handle(Handle), Symbols(Symbols) {}
>> +  DylibHandle Handle;
>> +  const SymbolLookupSet &Symbols;
>> +};
>> +
>> +using LookupResult = std::vector<JITTargetAddress>;
>> +
>> +/// Either a uint8_t array or a uint8_t*.
>> +union CWrapperFunctionResultData {
>> +  uint8_t Value[8];
>> +  uint8_t *ValuePtr;
>> +};
>> +
>> +/// C ABI compatible wrapper function result.
>> +///
>> +/// This can be safely returned from extern "C" functions, but should be
>> used
>> +/// to construct a WrapperFunctionResult for safety.
>> +struct CWrapperFunctionResult {
>> +  uint64_t Size;
>> +  CWrapperFunctionResultData Data;
>> +  void (*Destroy)(CWrapperFunctionResultData Data, uint64_t Size);
>> +};
>> +
>> +/// C++ wrapper function result: Same as CWrapperFunctionResult but
>> +/// auto-releases memory.
>> +class WrapperFunctionResult {
>> +public:
>> +  /// Create a default WrapperFunctionResult.
>> +  WrapperFunctionResult() { zeroInit(R); }
>> +
>> +  /// Create a WrapperFunctionResult from a CWrapperFunctionResult. This
>> +  /// instance takes ownership of the result object and will
>> automatically
>> +  /// call the Destroy member upon destruction.
>> +  WrapperFunctionResult(CWrapperFunctionResult R) : R(R) {}
>> +
>> +  WrapperFunctionResult(const WrapperFunctionResult &) = delete;
>> +  WrapperFunctionResult &operator=(const WrapperFunctionResult &) =
>> delete;
>> +
>> +  WrapperFunctionResult(WrapperFunctionResult &&Other) {
>> +    zeroInit(R);
>> +    std::swap(R, Other.R);
>> +  }
>> +
>> +  WrapperFunctionResult &operator=(WrapperFunctionResult &&Other) {
>> +    CWrapperFunctionResult Tmp;
>> +    zeroInit(Tmp);
>> +    std::swap(Tmp, Other.R);
>> +    std::swap(R, Tmp);
>> +    return *this;
>> +  }
>> +
>> +  ~WrapperFunctionResult() {
>> +    if (R.Destroy)
>> +      R.Destroy(R.Data, R.Size);
>> +  }
>> +
>> +  /// Relinquish ownership of and return the CWrapperFunctionResult.
>> +  CWrapperFunctionResult release() {
>> +    CWrapperFunctionResult Tmp;
>> +    zeroInit(Tmp);
>> +    std::swap(R, Tmp);
>> +    return Tmp;
>> +  }
>> +
>> +  /// Get an ArrayRef covering the data in the result.
>> +  ArrayRef<uint8_t> getData() const {
>> +    if (R.Size <= 8)
>> +      return ArrayRef<uint8_t>(R.Data.Value, R.Size);
>> +    return ArrayRef<uint8_t>(R.Data.ValuePtr, R.Size);
>> +  }
>> +
>> +  /// Create a WrapperFunctionResult from the given integer, provided its
>> +  /// size is no greater than 64 bits.
>> +  template <typename T,
>> +            typename _ = std::enable_if_t<std::is_integral<T>::value &&
>> +                                          sizeof(T) <= sizeof(uint64_t)>>
>> +  static WrapperFunctionResult from(T Value) {
>> +    CWrapperFunctionResult R;
>> +    R.Size = sizeof(T);
>> +    memcpy(&R.Data.Value, Value, R.Size);
>> +    R.Destroy = nullptr;
>> +    return R;
>> +  }
>> +
>> +  /// Create a WrapperFunctionResult from the given string.
>> +  static WrapperFunctionResult from(StringRef S);
>> +
>> +  /// Always free Data.ValuePtr by calling free on it.
>> +  static void destroyWithFree(CWrapperFunctionResultData Data, uint64_t
>> Size);
>> +
>> +  /// Always free Data.ValuePtr by calling delete[] on it.
>> +  static void destroyWithDeleteArray(CWrapperFunctionResultData Data,
>> +                                     uint64_t Size);
>> +
>> +private:
>> +  void zeroInit(CWrapperFunctionResult &R) {
>> +    R.Size = 0;
>> +    R.Data.ValuePtr = nullptr;
>> +    R.Destroy = nullptr;
>> +  }
>> +
>> +  CWrapperFunctionResult R;
>> +};
>> +
>> +} // end namespace tpctypes
>> +} // end namespace orc
>> +} // end namespace llvm
>> +
>> +#endif // LLVM_EXECUTIONENGINE_ORC_SHARED_TARGETPROCESSCONTROLTYPES_H
>>
>> diff  --git
>> a/llvm/include/llvm/ExecutionEngine/Orc/TPCDynamicLibrarySearchGenerator.h
>> b/llvm/include/llvm/ExecutionEngine/Orc/TPCDynamicLibrarySearchGenerator.h
>> index 3b5c4b9cf8cd..07720f5c0f33 100644
>> ---
>> a/llvm/include/llvm/ExecutionEngine/Orc/TPCDynamicLibrarySearchGenerator.h
>> +++
>> b/llvm/include/llvm/ExecutionEngine/Orc/TPCDynamicLibrarySearchGenerator.h
>> @@ -31,7 +31,7 @@ class TPCDynamicLibrarySearchGenerator : public
>> DefinitionGenerator {
>>    /// will be searched for. If the predicate is not given then all
>> symbols will
>>    /// be searched for.
>>    TPCDynamicLibrarySearchGenerator(TargetProcessControl &TPC,
>> -                                   TargetProcessControl::DylibHandle H,
>> +                                   tpctypes::DylibHandle H,
>>                                     SymbolPredicate Allow =
>> SymbolPredicate())
>>        : TPC(TPC), H(H), Allow(std::move(Allow)) {}
>>
>> @@ -56,7 +56,7 @@ class TPCDynamicLibrarySearchGenerator : public
>> DefinitionGenerator {
>>
>>  private:
>>    TargetProcessControl &TPC;
>> -  TargetProcessControl::DylibHandle H;
>> +  tpctypes::DylibHandle H;
>>    SymbolPredicate Allow;
>>  };
>>
>>
>> diff  --git a/llvm/include/llvm/ExecutionEngine/Orc/TPCEHFrameRegistrar.h
>> b/llvm/include/llvm/ExecutionEngine/Orc/TPCEHFrameRegistrar.h
>> new file mode 100644
>> index 000000000000..519f818907f9
>> --- /dev/null
>> +++ b/llvm/include/llvm/ExecutionEngine/Orc/TPCEHFrameRegistrar.h
>> @@ -0,0 +1,54 @@
>> +//===-- TPCEHFrameRegistrar.h - TPC based eh-frame registration -*- 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
>> +//
>>
>> +//===----------------------------------------------------------------------===//
>> +//
>> +// TargetProcessControl based eh-frame registration.
>> +//
>>
>> +//===----------------------------------------------------------------------===//
>> +
>> +#ifndef LLVM_EXECUTIONENGINE_ORC_TPCEHFRAMEREGISTRAR_H
>> +#define LLVM_EXECUTIONENGINE_ORC_TPCEHFRAMEREGISTRAR_H
>> +
>> +#include "llvm/ExecutionEngine/JITLink/EHFrameSupport.h"
>> +#include "llvm/ExecutionEngine/Orc/TargetProcessControl.h"
>> +
>> +namespace llvm {
>> +namespace orc {
>> +
>> +/// Register/Deregisters EH frames in a remote process via a
>> +/// TargetProcessControl instance.
>> +class TPCEHFrameRegistrar : public jitlink::EHFrameRegistrar {
>> +public:
>> +  /// Create from a TargetProcessControl instance alone. This will use
>> +  /// the TPC's lookupSymbols method to find the
>> registration/deregistration
>> +  /// funciton addresses by name.
>> +  static Expected<std::unique_ptr<TPCEHFrameRegistrar>>
>> +  Create(TargetProcessControl &TPC);
>> +
>> +  /// Create a TPCEHFrameRegistrar with the given TargetProcessControl
>> +  /// object and registration/deregistration function addresses.
>> +  TPCEHFrameRegistrar(TargetProcessControl &TPC,
>> +                      JITTargetAddress RegisterEHFrameWrapperFnAddr,
>> +                      JITTargetAddress DeregisterEHFRameWrapperFnAddr)
>> +      : TPC(TPC),
>> RegisterEHFrameWrapperFnAddr(RegisterEHFrameWrapperFnAddr),
>> +        DeregisterEHFrameWrapperFnAddr(DeregisterEHFRameWrapperFnAddr) {}
>> +
>> +  Error registerEHFrames(JITTargetAddress EHFrameSectionAddr,
>> +                         size_t EHFrameSectionSize) override;
>> +  Error deregisterEHFrames(JITTargetAddress EHFrameSectionAddr,
>> +                           size_t EHFrameSectionSize) override;
>> +
>> +private:
>> +  TargetProcessControl &TPC;
>> +  JITTargetAddress RegisterEHFrameWrapperFnAddr;
>> +  JITTargetAddress DeregisterEHFrameWrapperFnAddr;
>> +};
>> +
>> +} // end namespace orc
>> +} // end namespace llvm
>> +
>> +#endif // LLVM_EXECUTIONENGINE_ORC_TPCEHFRAMEREGISTRAR_H
>>
>> diff  --git
>> a/llvm/include/llvm/ExecutionEngine/Orc/TargetProcess/OrcRPCTPCServer.h
>> b/llvm/include/llvm/ExecutionEngine/Orc/TargetProcess/OrcRPCTPCServer.h
>> new file mode 100644
>> index 000000000000..2b759dea6333
>> --- /dev/null
>> +++
>> b/llvm/include/llvm/ExecutionEngine/Orc/TargetProcess/OrcRPCTPCServer.h
>> @@ -0,0 +1,614 @@
>> +//===-- OrcRPCTPCServer.h -- OrcRPCTargetProcessControl Server --*- 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
>> +//
>>
>> +//===----------------------------------------------------------------------===//
>> +//
>> +// OrcRPCTargetProcessControl server class.
>> +//
>>
>> +//===----------------------------------------------------------------------===//
>> +
>> +#ifndef LLVM_EXECUTIONENGINE_ORC_TARGETPROCESS_ORCRPCTPCSERVER_H
>> +#define LLVM_EXECUTIONENGINE_ORC_TARGETPROCESS_ORCRPCTPCSERVER_H
>> +
>> +#include "llvm/ADT/BitmaskEnum.h"
>> +#include "llvm/ExecutionEngine/Orc/RPC/RPCUtils.h"
>> +#include "llvm/ExecutionEngine/Orc/RPC/RawByteChannel.h"
>> +#include "llvm/ExecutionEngine/Orc/Shared/TargetProcessControlTypes.h"
>> +#include "llvm/ExecutionEngine/Orc/TargetProcess/TargetExecutionUtils.h"
>> +#include "llvm/ExecutionEngine/Orc/TargetProcessControl.h"
>> +#include "llvm/Support/DynamicLibrary.h"
>> +#include "llvm/Support/FormatVariadic.h"
>> +#include "llvm/Support/Host.h"
>> +#include "llvm/Support/MathExtras.h"
>> +#include "llvm/Support/Memory.h"
>> +#include "llvm/Support/Process.h"
>> +
>> +#include <atomic>
>> +
>> +namespace llvm {
>> +namespace orc {
>> +
>> +namespace orcrpctpc {
>> +
>> +enum WireProtectionFlags : uint8_t {
>> +  WPF_None = 0,
>> +  WPF_Read = 1U << 0,
>> +  WPF_Write = 1U << 1,
>> +  WPF_Exec = 1U << 2,
>> +  LLVM_MARK_AS_BITMASK_ENUM(WPF_Exec)
>> +};
>> +
>> +/// Convert from sys::Memory::ProtectionFlags
>> +inline WireProtectionFlags
>> +toWireProtectionFlags(sys::Memory::ProtectionFlags PF) {
>> +  WireProtectionFlags WPF = WPF_None;
>> +  if (PF & sys::Memory::MF_READ)
>> +    WPF |= WPF_Read;
>> +  if (PF & sys::Memory::MF_WRITE)
>> +    WPF |= WPF_Write;
>> +  if (PF & sys::Memory::MF_EXEC)
>> +    WPF |= WPF_Exec;
>> +  return WPF;
>> +}
>> +
>> +inline sys::Memory::ProtectionFlags
>> +fromWireProtectionFlags(WireProtectionFlags WPF) {
>> +  int PF = 0;
>> +  if (WPF & WPF_Read)
>> +    PF |= sys::Memory::MF_READ;
>> +  if (WPF & WPF_Write)
>> +    PF |= sys::Memory::MF_WRITE;
>> +  if (WPF & WPF_Exec)
>> +    PF |= sys::Memory::MF_EXEC;
>> +  return static_cast<sys::Memory::ProtectionFlags>(PF);
>> +}
>> +
>> +struct ReserveMemRequestElement {
>> +  WireProtectionFlags Prot = WPF_None;
>> +  uint64_t Size = 0;
>> +  uint64_t Alignment = 0;
>> +};
>> +
>> +using ReserveMemRequest = std::vector<ReserveMemRequestElement>;
>> +
>> +struct ReserveMemResultElement {
>> +  WireProtectionFlags Prot = WPF_None;
>> +  JITTargetAddress Address = 0;
>> +  uint64_t AllocatedSize = 0;
>> +};
>> +
>> +using ReserveMemResult = std::vector<ReserveMemResultElement>;
>> +
>> +struct ReleaseOrFinalizeMemRequestElement {
>> +  WireProtectionFlags Prot = WPF_None;
>> +  JITTargetAddress Address = 0;
>> +  uint64_t Size = 0;
>> +};
>> +
>> +using ReleaseOrFinalizeMemRequest =
>> +    std::vector<ReleaseOrFinalizeMemRequestElement>;
>> +
>> +} // end namespace orcrpctpc
>> +
>> +namespace rpc {
>> +
>> +template <> class RPCTypeName<tpctypes::UInt8Write> {
>> +public:
>> +  static const char *getName() { return "UInt8Write"; }
>> +};
>> +
>> +template <> class RPCTypeName<tpctypes::UInt16Write> {
>> +public:
>> +  static const char *getName() { return "UInt16Write"; }
>> +};
>> +
>> +template <> class RPCTypeName<tpctypes::UInt32Write> {
>> +public:
>> +  static const char *getName() { return "UInt32Write"; }
>> +};
>> +
>> +template <> class RPCTypeName<tpctypes::UInt64Write> {
>> +public:
>> +  static const char *getName() { return "UInt64Write"; }
>> +};
>> +
>> +template <> class RPCTypeName<tpctypes::BufferWrite> {
>> +public:
>> +  static const char *getName() { return "BufferWrite"; }
>> +};
>> +
>> +template <> class RPCTypeName<orcrpctpc::ReserveMemRequestElement> {
>> +public:
>> +  static const char *getName() { return "ReserveMemRequestElement"; }
>> +};
>> +
>> +template <> class RPCTypeName<orcrpctpc::ReserveMemResultElement> {
>> +public:
>> +  static const char *getName() { return "ReserveMemResultElement"; }
>> +};
>> +
>> +template <> class
>> RPCTypeName<orcrpctpc::ReleaseOrFinalizeMemRequestElement> {
>> +public:
>> +  static const char *getName() { return
>> "ReleaseOrFinalizeMemRequestElement"; }
>> +};
>> +
>> +template <> class RPCTypeName<tpctypes::WrapperFunctionResult> {
>> +public:
>> +  static const char *getName() { return "WrapperFunctionResult"; }
>> +};
>> +
>> +template <typename ChannelT, typename WriteT>
>> +class SerializationTraits<
>> +    ChannelT, WriteT, WriteT,
>> +    std::enable_if_t<std::is_same<WriteT, tpctypes::UInt8Write>::value ||
>> +                     std::is_same<WriteT, tpctypes::UInt16Write>::value
>> ||
>> +                     std::is_same<WriteT, tpctypes::UInt32Write>::value
>> ||
>> +                     std::is_same<WriteT,
>> tpctypes::UInt64Write>::value>> {
>> +public:
>> +  static Error serialize(ChannelT &C, const WriteT &W) {
>> +    return serializeSeq(C, W.Address, W.Value);
>> +  }
>> +  static Error deserialize(ChannelT &C, WriteT &W) {
>> +    return deserializeSeq(C, W.Address, W.Value);
>> +  }
>> +};
>> +
>> +template <typename ChannelT>
>> +class SerializationTraits<
>> +    ChannelT, tpctypes::BufferWrite, tpctypes::BufferWrite,
>> +    std::enable_if_t<std::is_base_of<RawByteChannel, ChannelT>::value>> {
>> +public:
>> +  static Error serialize(ChannelT &C, const tpctypes::BufferWrite &W) {
>> +    uint64_t Size = W.Buffer.size();
>> +    if (auto Err = serializeSeq(C, W.Address, Size))
>> +      return Err;
>> +
>> +    return C.appendBytes(W.Buffer.data(), Size);
>> +  }
>> +  static Error deserialize(ChannelT &C, tpctypes::BufferWrite &W) {
>> +    JITTargetAddress Address;
>> +    uint64_t Size;
>> +
>> +    if (auto Err = deserializeSeq(C, Address, Size))
>> +      return Err;
>> +
>> +    char *Buffer = jitTargetAddressToPointer<char *>(Address);
>> +
>> +    if (auto Err = C.readBytes(Buffer, Size))
>> +      return Err;
>> +
>> +    W = {Address, StringRef(Buffer, Size)};
>> +    return Error::success();
>> +  }
>> +};
>> +
>> +template <typename ChannelT>
>> +class SerializationTraits<ChannelT, orcrpctpc::ReserveMemRequestElement>
>> {
>> +public:
>> +  static Error serialize(ChannelT &C,
>> +                         const orcrpctpc::ReserveMemRequestElement &E) {
>> +    return serializeSeq(C, static_cast<uint8_t>(E.Prot), E.Size,
>> E.Alignment);
>> +  }
>> +
>> +  static Error deserialize(ChannelT &C,
>> +                           orcrpctpc::ReserveMemRequestElement &E) {
>> +    return deserializeSeq(C, *reinterpret_cast<uint8_t *>(&E.Prot),
>> E.Size,
>> +                          E.Alignment);
>> +  }
>> +};
>> +
>> +template <typename ChannelT>
>> +class SerializationTraits<ChannelT, orcrpctpc::ReserveMemResultElement> {
>> +public:
>> +  static Error serialize(ChannelT &C,
>> +                         const orcrpctpc::ReserveMemResultElement &E) {
>> +    return serializeSeq(C, static_cast<uint8_t>(E.Prot), E.Address,
>> +                        E.AllocatedSize);
>> +  }
>> +
>> +  static Error deserialize(ChannelT &C,
>> orcrpctpc::ReserveMemResultElement &E) {
>> +    return deserializeSeq(C, *reinterpret_cast<uint8_t *>(&E.Prot),
>> E.Address,
>> +                          E.AllocatedSize);
>> +  }
>> +};
>> +
>> +template <typename ChannelT>
>> +class SerializationTraits<ChannelT,
>> +                          orcrpctpc::ReleaseOrFinalizeMemRequestElement>
>> {
>> +public:
>> +  static Error
>> +  serialize(ChannelT &C,
>> +            const orcrpctpc::ReleaseOrFinalizeMemRequestElement &E) {
>> +    return serializeSeq(C, static_cast<uint8_t>(E.Prot), E.Address,
>> E.Size);
>> +  }
>> +
>> +  static Error deserialize(ChannelT &C,
>> +                           orcrpctpc::ReleaseOrFinalizeMemRequestElement
>> &E) {
>> +    return deserializeSeq(C, *reinterpret_cast<uint8_t *>(&E.Prot),
>> E.Address,
>> +                          E.Size);
>> +  }
>> +};
>> +
>> +template <typename ChannelT>
>> +class SerializationTraits<
>> +    ChannelT, tpctypes::WrapperFunctionResult,
>> tpctypes::WrapperFunctionResult,
>> +    std::enable_if_t<std::is_base_of<RawByteChannel, ChannelT>::value>> {
>> +public:
>> +  static Error serialize(ChannelT &C,
>> +                         const tpctypes::WrapperFunctionResult &E) {
>> +    auto Data = E.getData();
>> +    if (auto Err = serializeSeq(C, static_cast<uint64_t>(Data.size())))
>> +      return Err;
>> +    if (Data.size() == 0)
>> +      return Error::success();
>> +    return C.appendBytes(reinterpret_cast<const char *>(Data.data()),
>> +                         Data.size());
>> +  }
>> +
>> +  static Error deserialize(ChannelT &C, tpctypes::WrapperFunctionResult
>> &E) {
>> +    tpctypes::CWrapperFunctionResult R;
>> +
>> +    R.Size = 0;
>> +    R.Data.ValuePtr = nullptr;
>> +    R.Destroy = nullptr;
>> +
>> +    if (auto Err = deserializeSeq(C, R.Size))
>> +      return Err;
>> +    if (R.Size == 0)
>> +      return Error::success();
>> +    R.Data.ValuePtr = new uint8_t[R.Size];
>> +    if (auto Err =
>> +            C.readBytes(reinterpret_cast<char *>(R.Data.ValuePtr),
>> R.Size)) {
>> +      R.Destroy =
>> tpctypes::WrapperFunctionResult::destroyWithDeleteArray;
>> +      return Err;
>> +    }
>> +
>> +    E = tpctypes::WrapperFunctionResult(R);
>> +    return Error::success();
>> +  }
>> +};
>> +
>> +} // end namespace rpc
>> +
>> +namespace orcrpctpc {
>> +
>> +using RemoteSymbolLookupSet = std::vector<std::pair<std::string, bool>>;
>> +using RemoteLookupRequest =
>> +    std::pair<tpctypes::DylibHandle, RemoteSymbolLookupSet>;
>> +
>> +class GetTargetTriple : public rpc::Function<GetTargetTriple,
>> std::string()> {
>> +public:
>> +  static const char *getName() { return "GetTargetTriple"; }
>> +};
>> +
>> +class GetPageSize : public rpc::Function<GetPageSize, uint64_t()> {
>> +public:
>> +  static const char *getName() { return "GetPageSize"; }
>> +};
>> +
>> +class ReserveMem : public rpc::Function<ReserveMem,
>> Expected<ReserveMemResult>(
>> +
>> ReserveMemRequest)> {
>> +public:
>> +  static const char *getName() { return "ReserveMem"; }
>> +};
>> +
>> +class FinalizeMem
>> +    : public rpc::Function<FinalizeMem,
>> Error(ReleaseOrFinalizeMemRequest)> {
>> +public:
>> +  static const char *getName() { return "FinalizeMem"; }
>> +};
>> +
>> +class ReleaseMem
>> +    : public rpc::Function<ReleaseMem,
>> Error(ReleaseOrFinalizeMemRequest)> {
>> +public:
>> +  static const char *getName() { return "ReleaseMem"; }
>> +};
>> +
>> +class WriteUInt8s
>> +    : public rpc::Function<WriteUInt8s,
>> +                           Error(std::vector<tpctypes::UInt8Write>)> {
>> +public:
>> +  static const char *getName() { return "WriteUInt8s"; }
>> +};
>> +
>> +class WriteUInt16s
>> +    : public rpc::Function<WriteUInt16s,
>> +                           Error(std::vector<tpctypes::UInt16Write>)> {
>> +public:
>> +  static const char *getName() { return "WriteUInt16s"; }
>> +};
>> +
>> +class WriteUInt32s
>> +    : public rpc::Function<WriteUInt32s,
>> +                           Error(std::vector<tpctypes::UInt32Write>)> {
>> +public:
>> +  static const char *getName() { return "WriteUInt32s"; }
>> +};
>> +
>> +class WriteUInt64s
>> +    : public rpc::Function<WriteUInt64s,
>> +                           Error(std::vector<tpctypes::UInt64Write>)> {
>> +public:
>> +  static const char *getName() { return "WriteUInt64s"; }
>> +};
>> +
>> +class WriteBuffers
>> +    : public rpc::Function<WriteBuffers,
>> +                           Error(std::vector<tpctypes::BufferWrite>)> {
>> +public:
>> +  static const char *getName() { return "WriteBuffers"; }
>> +};
>> +
>> +class LoadDylib
>> +    : public rpc::Function<LoadDylib, Expected<tpctypes::DylibHandle>(
>> +                                          std::string DylibPath)> {
>> +public:
>> +  static const char *getName() { return "LoadDylib"; }
>> +};
>> +
>> +class LookupSymbols
>> +    : public rpc::Function<LookupSymbols,
>> +                           Expected<std::vector<tpctypes::LookupResult>>(
>> +                               std::vector<RemoteLookupRequest>)> {
>> +public:
>> +  static const char *getName() { return "LookupSymbols"; }
>> +};
>> +
>> +class RunMain
>> +    : public rpc::Function<RunMain, int32_t(JITTargetAddress MainAddr,
>> +                                            std::vector<std::string>
>> Args)> {
>> +public:
>> +  static const char *getName() { return "RunMain"; }
>> +};
>> +
>> +class RunWrapper
>> +    : public rpc::Function<RunWrapper,
>> +                           tpctypes::WrapperFunctionResult(
>> +                               JITTargetAddress, std::vector<uint8_t>)> {
>> +public:
>> +  static const char *getName() { return "RunWrapper"; }
>> +};
>> +
>> +class CloseConnection : public rpc::Function<CloseConnection, void()> {
>> +public:
>> +  static const char *getName() { return "CloseConnection"; }
>> +};
>> +
>> +} // end namespace orcrpctpc
>> +
>> +/// TargetProcessControl for a process connected via an ORC RPC Endpoint.
>> +template <typename RPCEndpointT> class OrcRPCTPCServer {
>> +public:
>> +  /// Create an OrcRPCTPCServer from the given endpoint.
>> +  OrcRPCTPCServer(RPCEndpointT &EP) : EP(EP) {
>> +    using ThisT = OrcRPCTPCServer<RPCEndpointT>;
>> +
>> +    TripleStr = sys::getProcessTriple();
>> +    PageSize = sys::Process::getPageSizeEstimate();
>> +
>> +    EP.template addHandler<orcrpctpc::GetTargetTriple>(*this,
>> +
>>  &ThisT::getTargetTriple);
>> +    EP.template addHandler<orcrpctpc::GetPageSize>(*this,
>> &ThisT::getPageSize);
>> +
>> +    EP.template addHandler<orcrpctpc::ReserveMem>(*this,
>> &ThisT::reserveMemory);
>> +    EP.template addHandler<orcrpctpc::FinalizeMem>(*this,
>> +
>>  &ThisT::finalizeMemory);
>> +    EP.template addHandler<orcrpctpc::ReleaseMem>(*this,
>> &ThisT::releaseMemory);
>> +
>> +    EP.template addHandler<orcrpctpc::WriteUInt8s>(
>> +        handleWriteUInt<tpctypes::UInt8Write>);
>> +    EP.template addHandler<orcrpctpc::WriteUInt16s>(
>> +        handleWriteUInt<tpctypes::UInt16Write>);
>> +    EP.template addHandler<orcrpctpc::WriteUInt32s>(
>> +        handleWriteUInt<tpctypes::UInt32Write>);
>> +    EP.template addHandler<orcrpctpc::WriteUInt64s>(
>> +        handleWriteUInt<tpctypes::UInt64Write>);
>> +    EP.template addHandler<orcrpctpc::WriteBuffers>(handleWriteBuffer);
>> +
>> +    EP.template addHandler<orcrpctpc::LoadDylib>(*this,
>> &ThisT::loadDylib);
>> +    EP.template addHandler<orcrpctpc::LookupSymbols>(*this,
>> +
>>  &ThisT::lookupSymbols);
>> +
>> +    EP.template addHandler<orcrpctpc::RunMain>(*this, &ThisT::runMain);
>> +    EP.template addHandler<orcrpctpc::RunWrapper>(*this,
>> &ThisT::runWrapper);
>> +
>> +    EP.template addHandler<orcrpctpc::CloseConnection>(*this,
>> +
>>  &ThisT::closeConnection);
>> +  }
>> +
>> +  /// Set the ProgramName to be used as the first argv element when
>> running
>> +  /// functions via runAsMain.
>> +  void setProgramName(Optional<std::string> ProgramName = None) {
>> +    this->ProgramName = std::move(ProgramName);
>> +  }
>> +
>> +  /// Get the RPC endpoint for this server.
>> +  RPCEndpointT &getEndpoint() { return EP; }
>> +
>> +  /// Run the server loop.
>> +  Error run() {
>> +    while (!Finished) {
>> +      if (auto Err = EP.handleOne())
>> +        return Err;
>> +    }
>> +    return Error::success();
>> +  }
>> +
>> +private:
>> +  std::string getTargetTriple() { return TripleStr; }
>> +  uint64_t getPageSize() { return PageSize; }
>> +
>> +  template <typename WriteT>
>> +  static void handleWriteUInt(const std::vector<WriteT> &Ws) {
>> +    using ValueT = decltype(std::declval<WriteT>().Value);
>> +    for (auto &W : Ws)
>> +      *jitTargetAddressToPointer<ValueT *>(W.Address) = W.Value;
>> +  }
>> +
>> +  std::string getProtStr(orcrpctpc::WireProtectionFlags WPF) {
>> +    std::string Result;
>> +    Result += (WPF & orcrpctpc::WPF_Read) ? 'R' : '-';
>> +    Result += (WPF & orcrpctpc::WPF_Write) ? 'W' : '-';
>> +    Result += (WPF & orcrpctpc::WPF_Exec) ? 'X' : '-';
>> +    return Result;
>> +  }
>> +
>> +  static void handleWriteBuffer(const std::vector<tpctypes::BufferWrite>
>> &Ws) {
>> +    for (auto &W : Ws) {
>> +      memcpy(jitTargetAddressToPointer<char *>(W.Address),
>> W.Buffer.data(),
>> +             W.Buffer.size());
>> +    }
>> +  }
>> +
>> +  Expected<orcrpctpc::ReserveMemResult>
>> +  reserveMemory(const orcrpctpc::ReserveMemRequest &Request) {
>> +    orcrpctpc::ReserveMemResult Allocs;
>> +    auto PF = sys::Memory::MF_READ | sys::Memory::MF_WRITE;
>> +
>> +    uint64_t TotalSize = 0;
>> +
>> +    for (const auto &E : Request) {
>> +      uint64_t Size = alignTo(E.Size, PageSize);
>> +      uint16_t Align = E.Alignment;
>> +
>> +      if ((Align > PageSize) || (PageSize % Align))
>> +        return make_error<StringError>(
>> +            "Page alignmen does not satisfy requested alignment",
>> +            inconvertibleErrorCode());
>> +
>> +      TotalSize += Size;
>> +    }
>> +
>> +    // Allocate memory slab.
>> +    std::error_code EC;
>> +    auto MB = sys::Memory::allocateMappedMemory(TotalSize, nullptr, PF,
>> EC);
>> +    if (EC)
>> +      return make_error<StringError>("Unable to allocate memory: " +
>> +                                         EC.message(),
>> +                                     inconvertibleErrorCode());
>> +
>> +    // Zero-fill the whole thing.
>> +    memset(MB.base(), 0, MB.allocatedSize());
>> +
>> +    // Carve up sections to return.
>> +    uint64_t SectionBase = 0;
>> +    for (const auto &E : Request) {
>> +      uint64_t SectionSize = alignTo(E.Size, PageSize);
>> +      Allocs.push_back({E.Prot,
>> +                        pointerToJITTargetAddress(MB.base()) +
>> SectionBase,
>> +                        SectionSize});
>> +      SectionBase += SectionSize;
>> +    }
>> +
>> +    return Allocs;
>> +  }
>> +
>> +  Error finalizeMemory(const orcrpctpc::ReleaseOrFinalizeMemRequest
>> &FMR) {
>> +    for (const auto &E : FMR) {
>> +      sys::MemoryBlock MB(jitTargetAddressToPointer<void *>(E.Address),
>> E.Size);
>> +
>> +      auto PF = orcrpctpc::fromWireProtectionFlags(E.Prot);
>> +      if (auto EC =
>> +              sys::Memory::protectMappedMemory(MB,
>> static_cast<unsigned>(PF)))
>> +        return make_error<StringError>("error protecting memory: " +
>> +                                           EC.message(),
>> +                                       inconvertibleErrorCode());
>> +    }
>> +    return Error::success();
>> +  }
>> +
>> +  Error releaseMemory(const orcrpctpc::ReleaseOrFinalizeMemRequest &RMR)
>> {
>> +    for (const auto &E : RMR) {
>> +      sys::MemoryBlock MB(jitTargetAddressToPointer<void *>(E.Address),
>> E.Size);
>> +
>> +      if (auto EC = sys::Memory::releaseMappedMemory(MB))
>> +        return make_error<StringError>("error release memory: " +
>> EC.message(),
>> +                                       inconvertibleErrorCode());
>> +    }
>> +    return Error::success();
>> +  }
>> +
>> +  Expected<tpctypes::DylibHandle> loadDylib(const std::string &Path) {
>> +    std::string ErrMsg;
>> +    const char *DLPath = !Path.empty() ? Path.c_str() : nullptr;
>> +    auto DL = sys::DynamicLibrary::getPermanentLibrary(DLPath, &ErrMsg);
>> +    if (!DL.isValid())
>> +      return make_error<StringError>(std::move(ErrMsg),
>> +                                     inconvertibleErrorCode());
>> +
>> +    tpctypes::DylibHandle H = Dylibs.size();
>> +    Dylibs[H] = std::move(DL);
>> +    return H;
>> +  }
>> +
>> +  Expected<std::vector<tpctypes::LookupResult>>
>> +  lookupSymbols(const std::vector<orcrpctpc::RemoteLookupRequest>
>> &Request) {
>> +    std::vector<tpctypes::LookupResult> Result;
>> +
>> +    for (const auto &E : Request) {
>> +      auto I = Dylibs.find(E.first);
>> +      if (I == Dylibs.end())
>> +        return make_error<StringError>("Unrecognized handle",
>> +                                       inconvertibleErrorCode());
>> +      auto &DL = I->second;
>> +      Result.push_back({});
>> +
>> +      for (const auto &KV : E.second) {
>> +        auto &SymString = KV.first;
>> +        bool WeakReference = KV.second;
>> +
>> +        const char *Sym = SymString.c_str();
>> +#ifdef __APPLE__
>> +        if (*Sym == '_')
>> +          ++Sym;
>> +#endif
>> +
>> +        void *Addr = DL.getAddressOfSymbol(Sym);
>> +        if (!Addr && !WeakReference)
>> +          return make_error<StringError>(Twine("Missing definition for
>> ") + Sym,
>> +                                         inconvertibleErrorCode());
>> +
>> +        Result.back().push_back(pointerToJITTargetAddress(Addr));
>> +      }
>> +    }
>> +
>> +    return Result;
>> +  }
>> +
>> +  int32_t runMain(JITTargetAddress MainFnAddr,
>> +                  const std::vector<std::string> &Args) {
>> +    Optional<StringRef> ProgramNameOverride;
>> +    if (ProgramName)
>> +      ProgramNameOverride = *ProgramName;
>> +
>> +    return runAsMain(
>> +        jitTargetAddressToFunction<int (*)(int, char *[])>(MainFnAddr),
>> Args,
>> +        ProgramNameOverride);
>> +  }
>> +
>> +  tpctypes::WrapperFunctionResult
>> +  runWrapper(JITTargetAddress WrapperFnAddr,
>> +             const std::vector<uint8_t> &ArgBuffer) {
>> +    using WrapperFnTy = tpctypes::CWrapperFunctionResult (*)(
>> +        const uint8_t *Data, uint64_t Size);
>> +    auto *WrapperFn =
>> jitTargetAddressToFunction<WrapperFnTy>(WrapperFnAddr);
>> +    return WrapperFn(ArgBuffer.data(), ArgBuffer.size());
>> +  }
>> +
>> +  void closeConnection() { Finished = true; }
>> +
>> +  std::string TripleStr;
>> +  uint64_t PageSize = 0;
>> +  Optional<std::string> ProgramName;
>> +  RPCEndpointT &EP;
>> +  std::atomic<bool> Finished{false};
>> +  DenseMap<tpctypes::DylibHandle, sys::DynamicLibrary> Dylibs;
>> +};
>> +
>> +} // end namespace orc
>> +} // end namespace llvm
>> +
>> +#endif // LLVM_EXECUTIONENGINE_ORC_TARGETPROCESS_ORCRPCTPCSERVER_H
>>
>> diff  --git
>> a/llvm/include/llvm/ExecutionEngine/Orc/TargetProcess/RegisterEHFrames.h
>> b/llvm/include/llvm/ExecutionEngine/Orc/TargetProcess/RegisterEHFrames.h
>> new file mode 100644
>> index 000000000000..811c50e3ce4d
>> --- /dev/null
>> +++
>> b/llvm/include/llvm/ExecutionEngine/Orc/TargetProcess/RegisterEHFrames.h
>> @@ -0,0 +1,41 @@
>> +//===----- RegisterEHFrames.h -- Register EH frame sections -----*- 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
>> +//
>>
>> +//===----------------------------------------------------------------------===//
>> +//
>> +// Support for dynamically registering and deregistering eh-frame
>> sections
>> +// in-process via libunwind.
>> +//
>>
>> +//===----------------------------------------------------------------------===//
>> +
>> +#ifndef LLVM_EXECUTIONENGINE_ORC_TARGETPROCESS_REGISTEREHFRAMES_H
>> +#define LLVM_EXECUTIONENGINE_ORC_TARGETPROCESS_REGISTEREHFRAMES_H
>> +
>> +#include "llvm/ExecutionEngine/Orc/Shared/TargetProcessControlTypes.h"
>> +#include "llvm/Support/Error.h"
>> +#include <vector>
>> +
>> +namespace llvm {
>> +namespace orc {
>> +
>> +/// Register frames in the given eh-frame section with libunwind.
>> +Error registerEHFrameSection(const void *EHFrameSectionAddr,
>> +                             size_t EHFrameSectionSize);
>> +
>> +/// Unregister frames in the given eh-frame section with libunwind.
>> +Error deregisterEHFrameSection(const void *EHFrameSectionAddr,
>> +                               size_t EHFrameSectionSize);
>> +
>> +} // end namespace orc
>> +} // end namespace llvm
>> +
>> +extern "C" llvm::orc::tpctypes::CWrapperFunctionResult
>> +llvm_orc_registerEHFrameSectionWrapper(uint8_t *Data, uint64_t Size);
>> +
>> +extern "C" llvm::orc::tpctypes::CWrapperFunctionResult
>> +llvm_orc_deregisterEHFrameSectionWrapper(uint8_t *Data, uint64_t Size);
>> +
>> +#endif // LLVM_EXECUTIONENGINE_ORC_TARGETPROCESS_REGISTEREHFRAMES_H
>>
>> diff  --git
>> a/llvm/include/llvm/ExecutionEngine/Orc/TargetProcess/TargetExecutionUtils.h
>> b/llvm/include/llvm/ExecutionEngine/Orc/TargetProcess/TargetExecutionUtils.h
>> new file mode 100644
>> index 000000000000..1d2f6d2be089
>> --- /dev/null
>> +++
>> b/llvm/include/llvm/ExecutionEngine/Orc/TargetProcess/TargetExecutionUtils.h
>> @@ -0,0 +1,38 @@
>> +//===-- TargetExecutionUtils.h - Utils for execution in target --*- 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
>> +//
>>
>> +//===----------------------------------------------------------------------===//
>> +//
>> +// Utilities for execution in the target process.
>> +//
>>
>> +//===----------------------------------------------------------------------===//
>> +
>> +#ifndef LLVM_EXECUTIONENGINE_ORC_TARGETPROCESS_TARGETEXECUTIONUTILS_H
>> +#define LLVM_EXECUTIONENGINE_ORC_TARGETPROCESS_TARGETEXECUTIONUTILS_H
>> +
>> +#include "llvm/ADT/ArrayRef.h"
>> +#include "llvm/ADT/Optional.h"
>> +#include "llvm/ADT/StringRef.h"
>> +#include <string>
>> +
>> +namespace llvm {
>> +namespace orc {
>> +
>> +/// Run a main function, returning the result.
>> +///
>> +/// If the optional ProgramName argument is given then it will be
>> inserted
>> +/// before the strings in Args as the first argument to the called
>> function.
>> +///
>> +/// It is legal to have an empty argument list and no program name,
>> however
>> +/// many main functions will expect a name argument at least, and will
>> fail
>> +/// if none is provided.
>> +int runAsMain(int (*Main)(int, char *[]), ArrayRef<std::string> Args,
>> +              Optional<StringRef> ProgramName = None);
>> +
>> +} // end namespace orc
>> +} // end namespace llvm
>> +
>> +#endif // LLVM_EXECUTIONENGINE_ORC_TARGETPROCESS_TARGETEXECUTIONUTILS_H
>>
>> diff  --git
>> a/llvm/include/llvm/ExecutionEngine/Orc/TargetProcessControl.h
>> b/llvm/include/llvm/ExecutionEngine/Orc/TargetProcessControl.h
>> index d3349753284e..504a5ea0f9e9 100644
>> --- a/llvm/include/llvm/ExecutionEngine/Orc/TargetProcessControl.h
>> +++ b/llvm/include/llvm/ExecutionEngine/Orc/TargetProcessControl.h
>> @@ -18,6 +18,7 @@
>>  #include "llvm/ADT/Triple.h"
>>  #include "llvm/ExecutionEngine/JITLink/JITLinkMemoryManager.h"
>>  #include "llvm/ExecutionEngine/Orc/Core.h"
>> +#include "llvm/ExecutionEngine/Orc/Shared/TargetProcessControlTypes.h"
>>  #include "llvm/Support/DynamicLibrary.h"
>>  #include "llvm/Support/MSVCErrorWorkarounds.h"
>>
>> @@ -33,76 +34,55 @@ class TargetProcessControl {
>>    /// APIs for manipulating memory in the target process.
>>    class MemoryAccess {
>>    public:
>> -    template <typename T> struct UIntWrite {
>> -      UIntWrite() = default;
>> -      UIntWrite(JITTargetAddress Address, T Value)
>> -          : Address(Address), Value(Value) {}
>> -
>> -      JITTargetAddress Address = 0;
>> -      T Value = 0;
>> -    };
>> -
>> -    using UInt8Write = UIntWrite<uint8_t>;
>> -    using UInt16Write = UIntWrite<uint16_t>;
>> -    using UInt32Write = UIntWrite<uint32_t>;
>> -    using UInt64Write = UIntWrite<uint64_t>;
>> -
>> -    struct BufferWrite {
>> -      BufferWrite(JITTargetAddress Address, StringRef Buffer)
>> -          : Address(Address), Buffer(Buffer) {}
>> -
>> -      JITTargetAddress Address = 0;
>> -      StringRef Buffer;
>> -    };
>> -
>> +    /// Callback function for asynchronous writes.
>>      using WriteResultFn = unique_function<void(Error)>;
>>
>>      virtual ~MemoryAccess();
>>
>> -    virtual void writeUInt8s(ArrayRef<UInt8Write> Ws,
>> +    virtual void writeUInt8s(ArrayRef<tpctypes::UInt8Write> Ws,
>>                               WriteResultFn OnWriteComplete) = 0;
>>
>> -    virtual void writeUInt16s(ArrayRef<UInt16Write> Ws,
>> +    virtual void writeUInt16s(ArrayRef<tpctypes::UInt16Write> Ws,
>>                                WriteResultFn OnWriteComplete) = 0;
>>
>> -    virtual void writeUInt32s(ArrayRef<UInt32Write> Ws,
>> +    virtual void writeUInt32s(ArrayRef<tpctypes::UInt32Write> Ws,
>>                                WriteResultFn OnWriteComplete) = 0;
>>
>> -    virtual void writeUInt64s(ArrayRef<UInt64Write> Ws,
>> +    virtual void writeUInt64s(ArrayRef<tpctypes::UInt64Write> Ws,
>>                                WriteResultFn OnWriteComplete) = 0;
>>
>> -    virtual void writeBuffers(ArrayRef<BufferWrite> Ws,
>> +    virtual void writeBuffers(ArrayRef<tpctypes::BufferWrite> Ws,
>>                                WriteResultFn OnWriteComplete) = 0;
>>
>> -    Error writeUInt8s(ArrayRef<UInt8Write> Ws) {
>> +    Error writeUInt8s(ArrayRef<tpctypes::UInt8Write> Ws) {
>>        std::promise<MSVCPError> ResultP;
>>        auto ResultF = ResultP.get_future();
>>        writeUInt8s(Ws, [&](Error Err) {
>> ResultP.set_value(std::move(Err)); });
>>        return ResultF.get();
>>      }
>>
>> -    Error writeUInt16s(ArrayRef<UInt16Write> Ws) {
>> +    Error writeUInt16s(ArrayRef<tpctypes::UInt16Write> Ws) {
>>        std::promise<MSVCPError> ResultP;
>>        auto ResultF = ResultP.get_future();
>>        writeUInt16s(Ws, [&](Error Err) {
>> ResultP.set_value(std::move(Err)); });
>>        return ResultF.get();
>>      }
>>
>> -    Error writeUInt32s(ArrayRef<UInt32Write> Ws) {
>> +    Error writeUInt32s(ArrayRef<tpctypes::UInt32Write> Ws) {
>>        std::promise<MSVCPError> ResultP;
>>        auto ResultF = ResultP.get_future();
>>        writeUInt32s(Ws, [&](Error Err) {
>> ResultP.set_value(std::move(Err)); });
>>        return ResultF.get();
>>      }
>>
>> -    Error writeUInt64s(ArrayRef<UInt64Write> Ws) {
>> +    Error writeUInt64s(ArrayRef<tpctypes::UInt64Write> Ws) {
>>        std::promise<MSVCPError> ResultP;
>>        auto ResultF = ResultP.get_future();
>>        writeUInt64s(Ws, [&](Error Err) {
>> ResultP.set_value(std::move(Err)); });
>>        return ResultF.get();
>>      }
>>
>> -    Error writeBuffers(ArrayRef<BufferWrite> Ws) {
>> +    Error writeBuffers(ArrayRef<tpctypes::BufferWrite> Ws) {
>>        std::promise<MSVCPError> ResultP;
>>        auto ResultF = ResultP.get_future();
>>        writeBuffers(Ws, [&](Error Err) {
>> ResultP.set_value(std::move(Err)); });
>> @@ -110,43 +90,30 @@ class TargetProcessControl {
>>      }
>>    };
>>
>> -  /// A handle for a library opened via loadDylib.
>> -  ///
>> -  /// Note that this handle does not necessarily represent a JITDylib:
>> it may
>> -  /// be a regular dynamic library or shared object (e.g. one opened via
>> a
>> -  /// dlopen in the target process).
>> -  using DylibHandle = JITTargetAddress;
>> -
>> -  /// Request lookup within the given DylibHandle.
>> -  struct LookupRequestElement {
>> -    LookupRequestElement(DylibHandle Handle, const SymbolLookupSet
>> &Symbols)
>> -        : Handle(Handle), Symbols(Symbols) {}
>> -    DylibHandle Handle;
>> -    const SymbolLookupSet &Symbols;
>> -  };
>> -
>> -  using LookupRequest = ArrayRef<LookupRequestElement>;
>> +  virtual ~TargetProcessControl();
>>
>> -  using LookupResult = std::vector<std::vector<JITTargetAddress>>;
>> +  /// Intern a symbol name in the SymbolStringPool.
>> +  SymbolStringPtr intern(StringRef SymName) { return
>> SSP->intern(SymName); }
>>
>> -  virtual ~TargetProcessControl();
>> +  /// Return a shared pointer to the SymbolStringPool for this instance.
>> +  std::shared_ptr<SymbolStringPool> getSymbolStringPool() const { return
>> SSP; }
>>
>>    /// Return the Triple for the target process.
>> -  const Triple &getTargetTriple() const { return TT; }
>> +  const Triple &getTargetTriple() const { return TargetTriple; }
>>
>>    /// Get the page size for the target process.
>>    unsigned getPageSize() const { return PageSize; }
>>
>> -  /// Return a JITLinkMemoryManager for the target process.
>> -  jitlink::JITLinkMemoryManager &getMemMgr() const { return *MemMgr; }
>> -
>>    /// Return a MemoryAccess object for the target process.
>>    MemoryAccess &getMemoryAccess() const { return *MemAccess; }
>>
>> +  /// Return a JITLinkMemoryManager for the target process.
>> +  jitlink::JITLinkMemoryManager &getMemMgr() const { return *MemMgr; }
>> +
>>    /// Load the dynamic library at the given path and return a handle to
>> it.
>>    /// If LibraryPath is null this function will return the global handle
>> for
>>    /// the target process.
>> -  virtual Expected<DylibHandle> loadDylib(const char *DylibPath) = 0;
>> +  virtual Expected<tpctypes::DylibHandle> loadDylib(const char
>> *DylibPath) = 0;
>>
>>    /// Search for symbols in the target process.
>>    ///
>> @@ -154,14 +121,37 @@ class TargetProcessControl {
>>    /// that correspond to the lookup order. If a required symbol is not
>>    /// found then this method will return an error. If a weakly referenced
>>    /// symbol is not found then it be assigned a '0' value in the result.
>> -  virtual Expected<LookupResult> lookupSymbols(LookupRequest Request) =
>> 0;
>> +  /// that correspond to the lookup order.
>> +  virtual Expected<std::vector<tpctypes::LookupResult>>
>> +  lookupSymbols(ArrayRef<tpctypes::LookupRequest> Request) = 0;
>> +
>> +  /// Run function with a main-like signature.
>> +  virtual Expected<int32_t> runAsMain(JITTargetAddress MainFnAddr,
>> +                                      ArrayRef<std::string> Args) = 0;
>> +
>> +  /// Run a wrapper function with signature:
>> +  ///
>> +  /// \code{.cpp}
>> +  ///   CWrapperFunctionResult fn(uint8_t *Data, uint64_t Size);
>> +  /// \endcode{.cpp}
>> +  ///
>> +  virtual Expected<tpctypes::WrapperFunctionResult>
>> +  runWrapper(JITTargetAddress WrapperFnAddr, ArrayRef<uint8_t>
>> ArgBuffer) = 0;
>> +
>> +  /// Disconnect from the target process.
>> +  ///
>> +  /// This should be called after the JIT session is shut down.
>> +  virtual Error disconnect() = 0;
>>
>>  protected:
>> +  TargetProcessControl(std::shared_ptr<SymbolStringPool> SSP)
>> +      : SSP(std::move(SSP)) {}
>>
>> -  Triple TT;
>> +  std::shared_ptr<SymbolStringPool> SSP;
>> +  Triple TargetTriple;
>>    unsigned PageSize = 0;
>> -  jitlink::JITLinkMemoryManager *MemMgr = nullptr;
>>    MemoryAccess *MemAccess = nullptr;
>> +  jitlink::JITLinkMemoryManager *MemMgr = nullptr;
>>  };
>>
>>  /// A TargetProcessControl implementation targeting the current process.
>> @@ -169,33 +159,44 @@ class SelfTargetProcessControl : public
>> TargetProcessControl,
>>                                   private
>> TargetProcessControl::MemoryAccess {
>>  public:
>>    SelfTargetProcessControl(
>> -      Triple TT, unsigned PageSize,
>> -      std::unique_ptr<jitlink::JITLinkMemoryManager> MemMgr);
>> +      std::shared_ptr<SymbolStringPool> SSP, Triple TargetTriple,
>> +      unsigned PageSize, std::unique_ptr<jitlink::JITLinkMemoryManager>
>> MemMgr);
>>
>>    /// Create a SelfTargetProcessControl with the given memory manager.
>>    /// If no memory manager is given a jitlink::InProcessMemoryManager
>> will
>>    /// be used by default.
>>    static Expected<std::unique_ptr<SelfTargetProcessControl>>
>> -  Create(std::unique_ptr<jitlink::JITLinkMemoryManager> MemMgr =
>> nullptr);
>> +  Create(std::shared_ptr<SymbolStringPool> SSP,
>> +         std::unique_ptr<jitlink::JITLinkMemoryManager> MemMgr =
>> nullptr);
>> +
>> +  Expected<tpctypes::DylibHandle> loadDylib(const char *DylibPath)
>> override;
>> +
>> +  Expected<std::vector<tpctypes::LookupResult>>
>> +  lookupSymbols(ArrayRef<tpctypes::LookupRequest> Request) override;
>> +
>> +  Expected<int32_t> runAsMain(JITTargetAddress MainFnAddr,
>> +                              ArrayRef<std::string> Args) override;
>>
>> -  Expected<DylibHandle> loadDylib(const char *DylibPath) override;
>> +  Expected<tpctypes::WrapperFunctionResult>
>> +  runWrapper(JITTargetAddress WrapperFnAddr,
>> +             ArrayRef<uint8_t> ArgBuffer) override;
>>
>> -  Expected<LookupResult> lookupSymbols(LookupRequest Request) override;
>> +  Error disconnect() override;
>>
>>  private:
>> -  void writeUInt8s(ArrayRef<UInt8Write> Ws,
>> +  void writeUInt8s(ArrayRef<tpctypes::UInt8Write> Ws,
>>                     WriteResultFn OnWriteComplete) override;
>>
>> -  void writeUInt16s(ArrayRef<UInt16Write> Ws,
>> +  void writeUInt16s(ArrayRef<tpctypes::UInt16Write> Ws,
>>                      WriteResultFn OnWriteComplete) override;
>>
>> -  void writeUInt32s(ArrayRef<UInt32Write> Ws,
>> +  void writeUInt32s(ArrayRef<tpctypes::UInt32Write> Ws,
>>                      WriteResultFn OnWriteComplete) override;
>>
>> -  void writeUInt64s(ArrayRef<UInt64Write> Ws,
>> +  void writeUInt64s(ArrayRef<tpctypes::UInt64Write> Ws,
>>                      WriteResultFn OnWriteComplete) override;
>>
>> -  void writeBuffers(ArrayRef<BufferWrite> Ws,
>> +  void writeBuffers(ArrayRef<tpctypes::BufferWrite> Ws,
>>                      WriteResultFn OnWriteComplete) override;
>>
>>    std::unique_ptr<jitlink::JITLinkMemoryManager> OwnedMemMgr;
>>
>> diff  --git a/llvm/lib/ExecutionEngine/CMakeLists.txt
>> b/llvm/lib/ExecutionEngine/CMakeLists.txt
>> index 9b5dd44e079e..a13fcc784e4b 100644
>> --- a/llvm/lib/ExecutionEngine/CMakeLists.txt
>> +++ b/llvm/lib/ExecutionEngine/CMakeLists.txt
>> @@ -21,7 +21,6 @@ endif()
>>  add_subdirectory(Interpreter)
>>  add_subdirectory(JITLink)
>>  add_subdirectory(MCJIT)
>> -add_subdirectory(OrcError)
>>  add_subdirectory(Orc)
>>  add_subdirectory(RuntimeDyld)
>>
>>
>> diff  --git a/llvm/lib/ExecutionEngine/JITLink/CMakeLists.txt
>> b/llvm/lib/ExecutionEngine/JITLink/CMakeLists.txt
>> index 86836e54f20e..20c53980b512 100644
>> --- a/llvm/lib/ExecutionEngine/JITLink/CMakeLists.txt
>> +++ b/llvm/lib/ExecutionEngine/JITLink/CMakeLists.txt
>> @@ -22,4 +22,6 @@ add_llvm_component_library(LLVMJITLink
>>  target_link_libraries(LLVMJITLink
>>    PRIVATE
>>    LLVMObject
>> +  LLVMOrcTargetProcess
>> +  LLVMSupport
>>  )
>>
>> diff  --git a/llvm/lib/ExecutionEngine/JITLink/EHFrameSupport.cpp
>> b/llvm/lib/ExecutionEngine/JITLink/EHFrameSupport.cpp
>> index b94a2b36b5f1..7a89476687d2 100644
>> --- a/llvm/lib/ExecutionEngine/JITLink/EHFrameSupport.cpp
>> +++ b/llvm/lib/ExecutionEngine/JITLink/EHFrameSupport.cpp
>> @@ -11,6 +11,7 @@
>>
>>  #include "llvm/BinaryFormat/Dwarf.h"
>>  #include "llvm/Config/config.h"
>> +#include "llvm/ExecutionEngine/Orc/TargetProcess/RegisterEHFrames.h"
>>  #include "llvm/Support/DynamicLibrary.h"
>>
>>  #define DEBUG_TYPE "jitlink"
>> @@ -630,142 +631,18 @@ Expected<Symbol &>
>> EHFrameEdgeFixer::getOrCreateSymbol(ParseContext &PC,
>>    return PC.G.addAnonymousSymbol(*B, Addr - B->getAddress(), 0, false,
>> false);
>>  }
>>
>> -#if defined(HAVE_REGISTER_FRAME) && defined(HAVE_DEREGISTER_FRAME) &&
>>       \
>> -    !defined(__SEH__) && !defined(__USING_SJLJ_EXCEPTIONS__)
>> -extern "C" void __register_frame(const void *);
>> -extern "C" void __deregister_frame(const void *);
>> -
>> -Error registerFrameWrapper(const void *P) {
>> -  __register_frame(P);
>> -  return Error::success();
>> -}
>> -
>> -Error deregisterFrameWrapper(const void *P) {
>> -  __deregister_frame(P);
>> -  return Error::success();
>> -}
>> -
>> -#else
>> -
>> -// The building compiler does not have __(de)register_frame but
>> -// it may be found at runtime in a dynamically-loaded library.
>> -// For example, this happens when building LLVM with Visual C++
>> -// but using the MingW runtime.
>> -static Error registerFrameWrapper(const void *P) {
>> -  static void((*RegisterFrame)(const void *)) = 0;
>> -
>> -  if (!RegisterFrame)
>> -    *(void **)&RegisterFrame =
>> -
>> llvm::sys::DynamicLibrary::SearchForAddressOfSymbol("__register_frame");
>> -
>> -  if (RegisterFrame) {
>> -    RegisterFrame(P);
>> -    return Error::success();
>> -  }
>> -
>> -  return make_error<JITLinkError>("could not register eh-frame: "
>> -                                  "__register_frame function not found");
>> -}
>> -
>> -static Error deregisterFrameWrapper(const void *P) {
>> -  static void((*DeregisterFrame)(const void *)) = 0;
>> -
>> -  if (!DeregisterFrame)
>> -    *(void **)&DeregisterFrame =
>> -        llvm::sys::DynamicLibrary::SearchForAddressOfSymbol(
>> -            "__deregister_frame");
>> -
>> -  if (DeregisterFrame) {
>> -    DeregisterFrame(P);
>> -    return Error::success();
>> -  }
>> -
>> -  return make_error<JITLinkError>("could not deregister eh-frame: "
>> -                                  "__deregister_frame function not
>> found");
>> -}
>> -#endif
>> -
>> -#ifdef __APPLE__
>> -
>> -template <typename HandleFDEFn>
>> -Error walkAppleEHFrameSection(const char *const SectionStart,
>> -                              size_t SectionSize,
>> -                              HandleFDEFn HandleFDE) {
>> -  const char *CurCFIRecord = SectionStart;
>> -  const char *End = SectionStart + SectionSize;
>> -  uint64_t Size = *reinterpret_cast<const uint32_t *>(CurCFIRecord);
>> -
>> -  while (CurCFIRecord != End && Size != 0) {
>> -    const char *OffsetField = CurCFIRecord + (Size == 0xffffffff ? 12 :
>> 4);
>> -    if (Size == 0xffffffff)
>> -      Size = *reinterpret_cast<const uint64_t *>(CurCFIRecord + 4) + 12;
>> -    else
>> -      Size += 4;
>> -    uint32_t Offset = *reinterpret_cast<const uint32_t *>(OffsetField);
>> -
>> -    LLVM_DEBUG({
>> -      dbgs() << "Registering eh-frame section:\n";
>> -      dbgs() << "Processing " << (Offset ? "FDE" : "CIE") << " @"
>> -             << (void *)CurCFIRecord << ": [";
>> -      for (unsigned I = 0; I < Size; ++I)
>> -        dbgs() << format(" 0x%02" PRIx8, *(CurCFIRecord + I));
>> -      dbgs() << " ]\n";
>> -    });
>> -
>> -    if (Offset != 0)
>> -      if (auto Err = HandleFDE(CurCFIRecord))
>> -        return Err;
>> -
>> -    CurCFIRecord += Size;
>> -
>> -    Size = *reinterpret_cast<const uint32_t *>(CurCFIRecord);
>> -  }
>> -
>> -  return Error::success();
>> -}
>> -
>> -#endif // __APPLE__
>> -
>> -Error registerEHFrameSection(const void *EHFrameSectionAddr,
>> -                             size_t EHFrameSectionSize) {
>> -#ifdef __APPLE__
>> -  // On Darwin __register_frame has to be called for each FDE entry.
>> -  return walkAppleEHFrameSection(static_cast<const char
>> *>(EHFrameSectionAddr),
>> -                                 EHFrameSectionSize,
>> -                                 registerFrameWrapper);
>> -#else
>> -  // On Linux __register_frame takes a single argument:
>> -  // a pointer to the start of the .eh_frame section.
>> -
>> -  // How can it find the end? Because crtendS.o is linked
>> -  // in and it has an .eh_frame section with four zero chars.
>> -  return registerFrameWrapper(EHFrameSectionAddr);
>> -#endif
>> -}
>> -
>> -Error deregisterEHFrameSection(const void *EHFrameSectionAddr,
>> -                               size_t EHFrameSectionSize) {
>> -#ifdef __APPLE__
>> -  return walkAppleEHFrameSection(static_cast<const char
>> *>(EHFrameSectionAddr),
>> -                                 EHFrameSectionSize,
>> -                                 deregisterFrameWrapper);
>> -#else
>> -  return deregisterFrameWrapper(EHFrameSectionAddr);
>> -#endif
>> -}
>> -
>>  EHFrameRegistrar::~EHFrameRegistrar() {}
>>
>>  Error InProcessEHFrameRegistrar::registerEHFrames(
>>      JITTargetAddress EHFrameSectionAddr, size_t EHFrameSectionSize) {
>> -  return registerEHFrameSection(
>> +  return orc::registerEHFrameSection(
>>        jitTargetAddressToPointer<void *>(EHFrameSectionAddr),
>>        EHFrameSectionSize);
>>  }
>>
>>  Error InProcessEHFrameRegistrar::deregisterEHFrames(
>>      JITTargetAddress EHFrameSectionAddr, size_t EHFrameSectionSize) {
>> -  return deregisterEHFrameSection(
>> +  return orc::deregisterEHFrameSection(
>>        jitTargetAddressToPointer<void *>(EHFrameSectionAddr),
>>        EHFrameSectionSize);
>>  }
>>
>> diff  --git a/llvm/lib/ExecutionEngine/JITLink/LLVMBuild.txt
>> b/llvm/lib/ExecutionEngine/JITLink/LLVMBuild.txt
>> index e7721a184b98..f73246beb224 100644
>> --- a/llvm/lib/ExecutionEngine/JITLink/LLVMBuild.txt
>> +++ b/llvm/lib/ExecutionEngine/JITLink/LLVMBuild.txt
>> @@ -18,4 +18,4 @@
>>  type = Library
>>  name = JITLink
>>  parent = ExecutionEngine
>> -required_libraries = BinaryFormat Object Support
>> +required_libraries = BinaryFormat Object OrcTargetProcess Support
>>
>> diff  --git a/llvm/lib/ExecutionEngine/LLVMBuild.txt
>> b/llvm/lib/ExecutionEngine/LLVMBuild.txt
>> index 9bc6775f78a0..13872da4a564 100644
>> --- a/llvm/lib/ExecutionEngine/LLVMBuild.txt
>> +++ b/llvm/lib/ExecutionEngine/LLVMBuild.txt
>> @@ -16,7 +16,7 @@
>>
>>  [common]
>>  subdirectories = Interpreter MCJIT JITLink RuntimeDyld IntelJITEvents
>> -                 OProfileJIT Orc OrcError PerfJITEvents
>> +                 OProfileJIT Orc PerfJITEvents
>>
>>  [component_0]
>>  type = Library
>>
>> diff  --git a/llvm/lib/ExecutionEngine/Orc/CMakeLists.txt
>> b/llvm/lib/ExecutionEngine/Orc/CMakeLists.txt
>> index 6396fb5d1187..2ab410dbf578 100644
>> --- a/llvm/lib/ExecutionEngine/Orc/CMakeLists.txt
>> +++ b/llvm/lib/ExecutionEngine/Orc/CMakeLists.txt
>> @@ -23,6 +23,7 @@ add_llvm_component_library(LLVMOrcJIT
>>    TargetProcessControl.cpp
>>    ThreadSafeModule.cpp
>>    TPCDynamicLibrarySearchGenerator.cpp
>> +  TPCEHFrameRegistrar.cpp
>>    TPCIndirectionUtils.cpp
>>    ADDITIONAL_HEADER_DIRS
>>    ${LLVM_MAIN_INCLUDE_DIR}/llvm/ExecutionEngine/Orc
>> @@ -31,6 +32,9 @@ add_llvm_component_library(LLVMOrcJIT
>>    intrinsics_gen
>>    )
>>
>> +add_subdirectory(Shared)
>> +add_subdirectory(TargetProcess)
>> +
>>  target_link_libraries(LLVMOrcJIT
>>    PRIVATE
>>    LLVMAnalysis
>>
>> diff  --git a/llvm/lib/ExecutionEngine/Orc/ExecutionUtils.cpp
>> b/llvm/lib/ExecutionEngine/Orc/ExecutionUtils.cpp
>> index 5f9faf693c82..6a1a41a13a1b 100644
>> --- a/llvm/lib/ExecutionEngine/Orc/ExecutionUtils.cpp
>> +++ b/llvm/lib/ExecutionEngine/Orc/ExecutionUtils.cpp
>> @@ -21,32 +21,6 @@
>>  namespace llvm {
>>  namespace orc {
>>
>> -int runAsMain(int (*Main)(int, char *[]), ArrayRef<std::string> Args,
>> -              Optional<StringRef> ProgramName) {
>> -  std::vector<std::unique_ptr<char[]>> ArgVStorage;
>> -  std::vector<char *> ArgV;
>> -
>> -  ArgVStorage.reserve(Args.size() + (ProgramName ? 1 : 0));
>> -  ArgV.reserve(Args.size() + 1 + (ProgramName ? 1 : 0));
>> -
>> -  if (ProgramName) {
>> -    ArgVStorage.push_back(std::make_unique<char[]>(ProgramName->size() +
>> 1));
>> -    llvm::copy(*ProgramName, &ArgVStorage.back()[0]);
>> -    ArgVStorage.back()[ProgramName->size()] = '\0';
>> -    ArgV.push_back(ArgVStorage.back().get());
>> -  }
>> -
>> -  for (auto &Arg : Args) {
>> -    ArgVStorage.push_back(std::make_unique<char[]>(Arg.size() + 1));
>> -    llvm::copy(Arg, &ArgVStorage.back()[0]);
>> -    ArgVStorage.back()[Arg.size()] = '\0';
>> -    ArgV.push_back(ArgVStorage.back().get());
>> -  }
>> -  ArgV.push_back(nullptr);
>> -
>> -  return Main(Args.size() + !!ProgramName, ArgV.data());
>> -}
>> -
>>  CtorDtorIterator::CtorDtorIterator(const GlobalVariable *GV, bool End)
>>    : InitList(
>>        GV ? dyn_cast_or_null<ConstantArray>(GV->getInitializer()) :
>> nullptr),
>>
>> diff  --git a/llvm/lib/ExecutionEngine/Orc/LLVMBuild.txt
>> b/llvm/lib/ExecutionEngine/Orc/LLVMBuild.txt
>> index 4a78243551ca..5d580d8fb40d 100644
>> --- a/llvm/lib/ExecutionEngine/Orc/LLVMBuild.txt
>> +++ b/llvm/lib/ExecutionEngine/Orc/LLVMBuild.txt
>> @@ -14,9 +14,12 @@
>>  ;
>>
>>  ;===------------------------------------------------------------------------===;
>>
>> +[common]
>> +subdirectories = Shared TargetProcess
>> +
>>  [component_0]
>>  type = Library
>>  name = OrcJIT
>>  parent = ExecutionEngine
>> -required_libraries = Core ExecutionEngine JITLink Object OrcError MC
>> Passes
>> +required_libraries = Core ExecutionEngine JITLink Object OrcShared MC
>> Passes
>>                       RuntimeDyld Support Target TransformUtils
>>
>> diff  --git a/llvm/lib/ExecutionEngine/OrcError/CMakeLists.txt
>> b/llvm/lib/ExecutionEngine/Orc/Shared/CMakeLists.txt
>> similarity index 60%
>> rename from llvm/lib/ExecutionEngine/OrcError/CMakeLists.txt
>> rename to llvm/lib/ExecutionEngine/Orc/Shared/CMakeLists.txt
>> index bd968d55e670..57c06d739ec7 100644
>> --- a/llvm/lib/ExecutionEngine/OrcError/CMakeLists.txt
>> +++ b/llvm/lib/ExecutionEngine/Orc/Shared/CMakeLists.txt
>> @@ -1,6 +1,7 @@
>> -add_llvm_component_library(LLVMOrcError
>> +add_llvm_component_library(LLVMOrcShared
>>    OrcError.cpp
>>    RPCError.cpp
>> +  TargetProcessControlTypes.cpp
>>    ADDITIONAL_HEADER_DIRS
>>    ${LLVM_MAIN_INCLUDE_DIR}/llvm/ExecutionEngine/Orc
>>    )
>>
>> diff  --git a/llvm/lib/ExecutionEngine/OrcError/LLVMBuild.txt
>> b/llvm/lib/ExecutionEngine/Orc/Shared/LLVMBuild.txt
>> similarity index 83%
>> rename from llvm/lib/ExecutionEngine/OrcError/LLVMBuild.txt
>> rename to llvm/lib/ExecutionEngine/Orc/Shared/LLVMBuild.txt
>> index 65e7916916f3..68f2ab08c9ca 100644
>> --- a/llvm/lib/ExecutionEngine/OrcError/LLVMBuild.txt
>> +++ b/llvm/lib/ExecutionEngine/Orc/Shared/LLVMBuild.txt
>> @@ -1,4 +1,4 @@
>> -;===- ./lib/ExecutionEngine/OrcError/LLVMBuild.txt -------------*- Conf
>> -*--===;
>> +;===- ./lib/ExecutionEngine/Orc/Shared/LLVMBuild.txt ------------*- Conf
>> -*--===;
>>  ;
>>  ; Part of the LLVM Project, under the Apache License v2.0 with LLVM
>> Exceptions.
>>  ; See https://llvm.org/LICENSE.txt for license information.
>> @@ -16,6 +16,6 @@
>>
>>  [component_0]
>>  type = Library
>> -name = OrcError
>> -parent = ExecutionEngine
>> +name = OrcShared
>> +parent = OrcJIT
>>  required_libraries = Support
>>
>> diff  --git a/llvm/lib/ExecutionEngine/Orc/Shared/LLVMBuild.txt.rej
>> b/llvm/lib/ExecutionEngine/Orc/Shared/LLVMBuild.txt.rej
>> new file mode 100644
>> index 000000000000..49d4038c2bf5
>> --- /dev/null
>> +++ b/llvm/lib/ExecutionEngine/Orc/Shared/LLVMBuild.txt.rej
>> @@ -0,0 +1,27 @@
>> +***************
>> +*** 1,4 ****
>> +- ;===- ./lib/ExecutionEngine/OrcError/LLVMBuild.txt -------------*-
>> Conf -*--===;
>> +  ;
>> +  ; Part of the LLVM Project, under the Apache License v2.0 with LLVM
>> Exceptions.
>> +  ; See https://llvm.org/LICENSE.txt for license information.
>> +--- 1,4 ----
>> ++ ;===- ./tools/llvm-jitlink/llvm-jitlink-executor/LLVMBuild.txt -*-
>> Conf -*--===;
>> +  ;
>> +  ; Part of the LLVM Project, under the Apache License v2.0 with LLVM
>> Exceptions.
>> +  ; See https://llvm.org/LICENSE.txt for license information.
>> +***************
>> +*** 15,21 ****
>> +
>> ;===------------------------------------------------------------------------===;
>> +
>> +  [component_0]
>> +- type = Library
>> +- name = OrcError
>> +- parent = ExecutionEngine
>> +- required_libraries = Support
>> +--- 15,20 ----
>> +
>> ;===------------------------------------------------------------------------===;
>> +
>> +  [component_0]
>> ++ type = Tool
>> ++ name = llvm-jitlink-executor
>> ++ parent = llvm-jitlink
>>
>> diff  --git a/llvm/lib/ExecutionEngine/OrcError/OrcError.cpp
>> b/llvm/lib/ExecutionEngine/Orc/Shared/OrcError.cpp
>> similarity index 96%
>> rename from llvm/lib/ExecutionEngine/OrcError/OrcError.cpp
>> rename to llvm/lib/ExecutionEngine/Orc/Shared/OrcError.cpp
>> index cc99e154fbec..9b1c028d7047 100644
>> --- a/llvm/lib/ExecutionEngine/OrcError/OrcError.cpp
>> +++ b/llvm/lib/ExecutionEngine/Orc/Shared/OrcError.cpp
>> @@ -71,7 +71,7 @@ class OrcErrorCategory : public std::error_category {
>>  };
>>
>>  static ManagedStatic<OrcErrorCategory> OrcErrCat;
>> -}
>> +} // namespace
>>
>>  namespace llvm {
>>  namespace orc {
>> @@ -84,9 +84,8 @@ std::error_code orcError(OrcErrorCode ErrCode) {
>>    return std::error_code(static_cast<UT>(ErrCode), *OrcErrCat);
>>  }
>>
>> -
>>  DuplicateDefinition::DuplicateDefinition(std::string SymbolName)
>> -  : SymbolName(std::move(SymbolName)) {}
>> +    : SymbolName(std::move(SymbolName)) {}
>>
>>  std::error_code DuplicateDefinition::convertToErrorCode() const {
>>    return orcError(OrcErrorCode::DuplicateDefinition);
>> @@ -101,7 +100,7 @@ const std::string
>> &DuplicateDefinition::getSymbolName() const {
>>  }
>>
>>  JITSymbolNotFound::JITSymbolNotFound(std::string SymbolName)
>> -  : SymbolName(std::move(SymbolName)) {}
>> +    : SymbolName(std::move(SymbolName)) {}
>>
>>  std::error_code JITSymbolNotFound::convertToErrorCode() const {
>>    typedef std::underlying_type<OrcErrorCode>::type UT;
>> @@ -117,5 +116,5 @@ const std::string &JITSymbolNotFound::getSymbolName()
>> const {
>>    return SymbolName;
>>  }
>>
>> -}
>> -}
>> +} // namespace orc
>> +} // namespace llvm
>>
>> diff  --git a/llvm/lib/ExecutionEngine/OrcError/RPCError.cpp
>> b/llvm/lib/ExecutionEngine/Orc/Shared/RPCError.cpp
>> similarity index 99%
>> rename from llvm/lib/ExecutionEngine/OrcError/RPCError.cpp
>> rename to llvm/lib/ExecutionEngine/Orc/Shared/RPCError.cpp
>> index 3cf78fd9f7ba..a13db4863953 100644
>> --- a/llvm/lib/ExecutionEngine/OrcError/RPCError.cpp
>> +++ b/llvm/lib/ExecutionEngine/Orc/Shared/RPCError.cpp
>> @@ -14,8 +14,8 @@
>>  #include "llvm/Support/Error.h"
>>  #include "llvm/Support/raw_ostream.h"
>>
>> -#include <system_error>
>>  #include <string>
>> +#include <system_error>
>>
>>  char llvm::orc::rpc::RPCFatalError::ID = 0;
>>  char llvm::orc::rpc::ConnectionClosed::ID = 0;
>> @@ -53,7 +53,6 @@ void CouldNotNegotiate::log(raw_ostream &OS) const {
>>    OS << "Could not negotiate RPC function " << Signature;
>>  }
>>
>> -
>>  } // end namespace rpc
>>  } // end namespace orc
>>  } // end namespace llvm
>>
>> diff  --git
>> a/llvm/lib/ExecutionEngine/Orc/Shared/TargetProcessControlTypes.cpp
>> b/llvm/lib/ExecutionEngine/Orc/Shared/TargetProcessControlTypes.cpp
>> new file mode 100644
>> index 000000000000..0b77eac8b4a6
>> --- /dev/null
>> +++ b/llvm/lib/ExecutionEngine/Orc/Shared/TargetProcessControlTypes.cpp
>> @@ -0,0 +1,43 @@
>> +//===---------- TargetProcessControlTypes.cpp - Shared TPC types
>> ----------===//
>> +//
>> +// 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
>> +//
>>
>> +//===----------------------------------------------------------------------===//
>> +//
>> +// TargetProcessControl types.
>> +//
>>
>> +//===----------------------------------------------------------------------===//
>> +
>> +#include "llvm/ExecutionEngine/Orc/Shared/TargetProcessControlTypes.h"
>> +
>> +namespace llvm {
>> +namespace orc {
>> +namespace tpctypes {
>> +
>> +WrapperFunctionResult WrapperFunctionResult::from(StringRef S) {
>> +  CWrapperFunctionResult R = {0, {.ValuePtr = nullptr}, nullptr};
>> +  R.Size = S.size();
>> +  if (R.Size > sizeof(uint64_t)) {
>> +    R.Data.ValuePtr = new uint8_t[R.Size];
>> +    memcpy(R.Data.ValuePtr, S.data(), R.Size);
>> +    R.Destroy = destroyWithDeleteArray;
>> +  } else
>> +    memcpy(R.Data.Value, S.data(), R.Size);
>> +  return R;
>> +}
>> +
>> +void WrapperFunctionResult::destroyWithFree(CWrapperFunctionResultData
>> Data,
>> +                                            uint64_t Size) {
>> +  free(Data.ValuePtr);
>> +}
>> +
>> +void WrapperFunctionResult::destroyWithDeleteArray(
>> +    CWrapperFunctionResultData Data, uint64_t Size) {
>> +  delete[] Data.ValuePtr;
>> +}
>> +
>> +} // end namespace tpctypes
>> +} // end namespace orc
>> +} // end namespace llvm
>>
>> diff  --git
>> a/llvm/lib/ExecutionEngine/Orc/TPCDynamicLibrarySearchGenerator.cpp
>> b/llvm/lib/ExecutionEngine/Orc/TPCDynamicLibrarySearchGenerator.cpp
>> index ab58641b3478..f275c634a6d5 100644
>> --- a/llvm/lib/ExecutionEngine/Orc/TPCDynamicLibrarySearchGenerator.cpp
>> +++ b/llvm/lib/ExecutionEngine/Orc/TPCDynamicLibrarySearchGenerator.cpp
>> @@ -41,7 +41,7 @@ Error TPCDynamicLibrarySearchGenerator::tryToGenerate(
>>
>>    SymbolMap NewSymbols;
>>
>> -  TargetProcessControl::LookupRequestElement Request(H, LookupSymbols);
>> +  tpctypes::LookupRequest Request(H, LookupSymbols);
>>    auto Result = TPC.lookupSymbols(Request);
>>    if (!Result)
>>      return Result.takeError();
>>
>> diff  --git a/llvm/lib/ExecutionEngine/Orc/TPCEHFrameRegistrar.cpp
>> b/llvm/lib/ExecutionEngine/Orc/TPCEHFrameRegistrar.cpp
>> new file mode 100644
>> index 000000000000..4f901ce6d445
>> --- /dev/null
>> +++ b/llvm/lib/ExecutionEngine/Orc/TPCEHFrameRegistrar.cpp
>> @@ -0,0 +1,80 @@
>> +//===------ TPCEHFrameRegistrar.cpp - TPC-based eh-frame registration
>> -----===//
>> +//
>> +// 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/TPCEHFrameRegistrar.h"
>> +#include "llvm/Support/BinaryStreamWriter.h"
>> +
>> +namespace llvm {
>> +namespace orc {
>> +
>> +Expected<std::unique_ptr<TPCEHFrameRegistrar>>
>> +TPCEHFrameRegistrar::Create(TargetProcessControl &TPC) {
>> +  // FIXME: Proper mangling here -- we really need to decouple linker
>> mangling
>> +  // from DataLayout.
>> +
>> +  // Find the addresses of the registration/deregistration functions in
>> the
>> +  // target process.
>> +  auto ProcessHandle = TPC.loadDylib(nullptr);
>> +  if (!ProcessHandle)
>> +    return ProcessHandle.takeError();
>> +
>> +  std::string RegisterWrapperName, DeregisterWrapperName;
>> +  if (TPC.getTargetTriple().isOSBinFormatMachO()) {
>> +    RegisterWrapperName += '_';
>> +    DeregisterWrapperName += '_';
>> +  }
>> +  RegisterWrapperName += "llvm_orc_registerEHFrameSectionWrapper";
>> +  DeregisterWrapperName += "llvm_orc_deregisterEHFrameSectionWrapper";
>> +
>> +  SymbolLookupSet RegistrationSymbols;
>> +  RegistrationSymbols.add(TPC.intern(RegisterWrapperName));
>> +  RegistrationSymbols.add(TPC.intern(DeregisterWrapperName));
>> +
>> +  auto Result = TPC.lookupSymbols({{*ProcessHandle,
>> RegistrationSymbols}});
>> +  if (!Result)
>> +    return Result.takeError();
>> +
>> +  assert(Result->size() == 1 && "Unexpected number of dylibs in result");
>> +  assert((*Result)[0].size() == 2 &&
>> +         "Unexpected number of addresses in result");
>> +
>> +  auto RegisterEHFrameWrapperFnAddr = (*Result)[0][0];
>> +  auto DeregisterEHFrameWrapperFnAddr = (*Result)[0][1];
>> +
>> +  return std::make_unique<TPCEHFrameRegistrar>(
>> +      TPC, RegisterEHFrameWrapperFnAddr, DeregisterEHFrameWrapperFnAddr);
>> +}
>> +
>> +Error TPCEHFrameRegistrar::registerEHFrames(JITTargetAddress
>> EHFrameSectionAddr,
>> +                                            size_t EHFrameSectionSize) {
>> +  constexpr size_t ArgBufferSize = sizeof(uint64_t) + sizeof(uint64_t);
>> +  uint8_t ArgBuffer[ArgBufferSize];
>> +  BinaryStreamWriter ArgWriter(
>> +      MutableArrayRef<uint8_t>(ArgBuffer, ArgBufferSize),
>> +      support::endianness::big);
>> +
>> cantFail(ArgWriter.writeInteger(static_cast<uint64_t>(EHFrameSectionAddr)));
>> +
>> cantFail(ArgWriter.writeInteger(static_cast<uint64_t>(EHFrameSectionSize)));
>> +
>> +  return TPC.runWrapper(RegisterEHFrameWrapperFnAddr,
>> ArgBuffer).takeError();
>> +}
>> +
>> +Error TPCEHFrameRegistrar::deregisterEHFrames(
>> +    JITTargetAddress EHFrameSectionAddr, size_t EHFrameSectionSize) {
>> +  constexpr size_t ArgBufferSize = sizeof(uint64_t) + sizeof(uint64_t);
>> +  uint8_t ArgBuffer[ArgBufferSize];
>> +  BinaryStreamWriter ArgWriter(
>> +      MutableArrayRef<uint8_t>(ArgBuffer, ArgBufferSize),
>> +      support::endianness::big);
>> +
>> cantFail(ArgWriter.writeInteger(static_cast<uint64_t>(EHFrameSectionAddr)));
>> +
>> cantFail(ArgWriter.writeInteger(static_cast<uint64_t>(EHFrameSectionSize)));
>> +
>> +  return TPC.runWrapper(DeregisterEHFrameWrapperFnAddr,
>> ArgBuffer).takeError();
>> +}
>> +
>> +} // end namespace orc
>> +} // end namespace llvm
>>
>> diff  --git a/llvm/lib/ExecutionEngine/Orc/TPCIndirectionUtils.cpp
>> b/llvm/lib/ExecutionEngine/Orc/TPCIndirectionUtils.cpp
>> index de13f064189a..d827cf7b273b 100644
>> --- a/llvm/lib/ExecutionEngine/Orc/TPCIndirectionUtils.cpp
>> +++ b/llvm/lib/ExecutionEngine/Orc/TPCIndirectionUtils.cpp
>> @@ -160,7 +160,7 @@ Error TPCIndirectStubsManager::createStubs(const
>> StubInitsMap &StubInits) {
>>    switch (TPCIU.getABISupport().getPointerSize()) {
>>    case 4: {
>>      unsigned ASIdx = 0;
>> -    std::vector<TargetProcessControl::MemoryAccess::UInt32Write>
>> PtrUpdates;
>> +    std::vector<tpctypes::UInt32Write> PtrUpdates;
>>      for (auto &SI : StubInits)
>>
>>  PtrUpdates.push_back({(*AvailableStubInfos)[ASIdx++].PointerAddress,
>>                              static_cast<uint32_t>(SI.second.first)});
>> @@ -168,7 +168,7 @@ Error TPCIndirectStubsManager::createStubs(const
>> StubInitsMap &StubInits) {
>>    }
>>    case 8: {
>>      unsigned ASIdx = 0;
>> -    std::vector<TargetProcessControl::MemoryAccess::UInt64Write>
>> PtrUpdates;
>> +    std::vector<tpctypes::UInt64Write> PtrUpdates;
>>      for (auto &SI : StubInits)
>>
>>  PtrUpdates.push_back({(*AvailableStubInfos)[ASIdx++].PointerAddress,
>>                              static_cast<uint64_t>(SI.second.first)});
>> @@ -213,11 +213,11 @@ Error
>> TPCIndirectStubsManager::updatePointer(StringRef Name,
>>    auto &MemAccess = TPCIU.getTargetProcessControl().getMemoryAccess();
>>    switch (TPCIU.getABISupport().getPointerSize()) {
>>    case 4: {
>> -    TargetProcessControl::MemoryAccess::UInt32Write PUpdate(PtrAddr,
>> NewAddr);
>> +    tpctypes::UInt32Write PUpdate(PtrAddr, NewAddr);
>>      return MemAccess.writeUInt32s(PUpdate);
>>    }
>>    case 8: {
>> -    TargetProcessControl::MemoryAccess::UInt64Write PUpdate(PtrAddr,
>> NewAddr);
>> +    tpctypes::UInt64Write PUpdate(PtrAddr, NewAddr);
>>      return MemAccess.writeUInt64s(PUpdate);
>>    }
>>    default:
>>
>> diff  --git a/llvm/lib/ExecutionEngine/Orc/TargetProcess/CMakeLists.txt
>> b/llvm/lib/ExecutionEngine/Orc/TargetProcess/CMakeLists.txt
>> new file mode 100644
>> index 000000000000..b561ce232ce4
>> --- /dev/null
>> +++ b/llvm/lib/ExecutionEngine/Orc/TargetProcess/CMakeLists.txt
>> @@ -0,0 +1,6 @@
>> +add_llvm_component_library(LLVMOrcTargetProcess
>> +  RegisterEHFrames.cpp
>> +  TargetExecutionUtils.cpp
>> +  ADDITIONAL_HEADER_DIRS
>> +  ${LLVM_MAIN_INCLUDE_DIR}/llvm/ExecutionEngine/Orc
>> +  )
>>
>> diff  --git a/llvm/lib/ExecutionEngine/Orc/TargetProcess/LLVMBuild.txt
>> b/llvm/lib/ExecutionEngine/Orc/TargetProcess/LLVMBuild.txt
>> new file mode 100644
>> index 000000000000..781e6188a702
>> --- /dev/null
>> +++ b/llvm/lib/ExecutionEngine/Orc/TargetProcess/LLVMBuild.txt
>> @@ -0,0 +1,21 @@
>> +;===- ./lib/ExecutionEngine/OrcTargetProcess/LLVMBuild.txt -----*- Conf
>> -*--===;
>> +;
>> +; 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
>> +;
>>
>> +;===------------------------------------------------------------------------===;
>> +;
>> +; This is an LLVMBuild description file for the components in this
>> subdirectory.
>> +;
>> +; For more information on the LLVMBuild system, please see:
>> +;
>> +;   http://llvm.org/docs/LLVMBuild.html
>> +;
>>
>> +;===------------------------------------------------------------------------===;
>> +
>> +[component_0]
>> +type = Library
>> +name = OrcTargetProcess
>> +parent = OrcJIT
>> +required_libraries = OrcShared Support
>>
>> diff  --git
>> a/llvm/lib/ExecutionEngine/Orc/TargetProcess/RegisterEHFrames.cpp
>> b/llvm/lib/ExecutionEngine/Orc/TargetProcess/RegisterEHFrames.cpp
>> new file mode 100644
>> index 000000000000..e32916dfcd96
>> --- /dev/null
>> +++ b/llvm/lib/ExecutionEngine/Orc/TargetProcess/RegisterEHFrames.cpp
>> @@ -0,0 +1,207 @@
>> +//===--------- RegisterEHFrames.cpp - Register EH frame sections
>> ----------===//
>> +//
>> +//                     The LLVM Compiler Infrastructure
>> +//
>> +// This file is distributed under the University of Illinois Open Source
>> +// License. See LICENSE.TXT for details.
>> +//
>>
>> +//===----------------------------------------------------------------------===//
>> +
>> +#include "llvm/ExecutionEngine/Orc/TargetProcess/RegisterEHFrames.h"
>> +
>> +#include "llvm/ExecutionEngine/JITSymbol.h"
>> +#include "llvm/Support/BinaryStreamReader.h"
>> +#include "llvm/Support/Compiler.h"
>> +#include "llvm/Support/Debug.h"
>> +#include "llvm/Support/DynamicLibrary.h"
>> +#include "llvm/Support/raw_ostream.h"
>> +
>> +#include "llvm/Support/FormatVariadic.h"
>> +
>> +#define DEBUG_TYPE "orc"
>> +
>> +using namespace llvm;
>> +using namespace llvm::orc;
>> +using namespace llvm::orc::tpctypes;
>> +
>> +namespace llvm {
>> +namespace orc {
>> +
>> +#if defined(HAVE_REGISTER_FRAME) && defined(HAVE_DEREGISTER_FRAME) &&
>>       \
>> +    !defined(__SEH__) && !defined(__USING_SJLJ_EXCEPTIONS__)
>> +
>> +extern "C" void __register_frame(const void *);
>> +extern "C" void __deregister_frame(const void *);
>> +
>> +Error registerFrameWrapper(const void *P) {
>> +  __register_frame(P);
>> +  return Error::success();
>> +}
>> +
>> +Error deregisterFrameWrapper(const void *P) {
>> +  __deregister_frame(P);
>> +  return Error::success();
>> +}
>> +
>> +#else
>> +
>> +// The building compiler does not have __(de)register_frame but
>> +// it may be found at runtime in a dynamically-loaded library.
>> +// For example, this happens when building LLVM with Visual C++
>> +// but using the MingW runtime.
>> +static Error registerFrameWrapper(const void *P) {
>> +  static void((*RegisterFrame)(const void *)) = 0;
>> +
>> +  if (!RegisterFrame)
>> +    *(void **)&RegisterFrame =
>> +
>> llvm::sys::DynamicLibrary::SearchForAddressOfSymbol("__register_frame");
>> +
>> +  if (RegisterFrame) {
>> +    RegisterFrame(P);
>> +    return Error::success();
>> +  }
>> +
>> +  return make_error<StringError>("could not register eh-frame: "
>> +                                 "__register_frame function not found",
>> +                                 inconvertibleErrorCode());
>> +}
>> +
>> +static Error deregisterFrameWrapper(const void *P) {
>> +  static void((*DeregisterFrame)(const void *)) = 0;
>> +
>> +  if (!DeregisterFrame)
>> +    *(void **)&DeregisterFrame =
>> +        llvm::sys::DynamicLibrary::SearchForAddressOfSymbol(
>> +            "__deregister_frame");
>> +
>> +  if (DeregisterFrame) {
>> +    DeregisterFrame(P);
>> +    return Error::success();
>> +  }
>> +
>> +  return make_error<StringError>("could not deregister eh-frame: "
>> +                                 "__deregister_frame function not found",
>> +                                 inconvertibleErrorCode());
>> +}
>> +#endif
>> +
>> +#ifdef __APPLE__
>> +
>> +template <typename HandleFDEFn>
>> +Error walkAppleEHFrameSection(const char *const SectionStart,
>> +                              size_t SectionSize, HandleFDEFn HandleFDE)
>> {
>> +  const char *CurCFIRecord = SectionStart;
>> +  const char *End = SectionStart + SectionSize;
>> +  uint64_t Size = *reinterpret_cast<const uint32_t *>(CurCFIRecord);
>> +
>> +  while (CurCFIRecord != End && Size != 0) {
>> +    const char *OffsetField = CurCFIRecord + (Size == 0xffffffff ? 12 :
>> 4);
>> +    if (Size == 0xffffffff)
>> +      Size = *reinterpret_cast<const uint64_t *>(CurCFIRecord + 4) + 12;
>> +    else
>> +      Size += 4;
>> +    uint32_t Offset = *reinterpret_cast<const uint32_t *>(OffsetField);
>> +
>> +    LLVM_DEBUG({
>> +      dbgs() << "Registering eh-frame section:\n";
>> +      dbgs() << "Processing " << (Offset ? "FDE" : "CIE") << " @"
>> +             << (void *)CurCFIRecord << ": [";
>> +      for (unsigned I = 0; I < Size; ++I)
>> +        dbgs() << format(" 0x%02" PRIx8, *(CurCFIRecord + I));
>> +      dbgs() << " ]\n";
>> +    });
>> +
>> +    if (Offset != 0)
>> +      if (auto Err = HandleFDE(CurCFIRecord))
>> +        return Err;
>> +
>> +    CurCFIRecord += Size;
>> +
>> +    Size = *reinterpret_cast<const uint32_t *>(CurCFIRecord);
>> +  }
>> +
>> +  return Error::success();
>> +}
>> +
>> +#endif // __APPLE__
>> +
>> +Error registerEHFrameSection(const void *EHFrameSectionAddr,
>> +                             size_t EHFrameSectionSize) {
>> +#ifdef __APPLE__
>> +  // On Darwin __register_frame has to be called for each FDE entry.
>> +  return walkAppleEHFrameSection(static_cast<const char
>> *>(EHFrameSectionAddr),
>> +                                 EHFrameSectionSize,
>> registerFrameWrapper);
>> +#else
>> +  // On Linux __register_frame takes a single argument:
>> +  // a pointer to the start of the .eh_frame section.
>> +
>> +  // How can it find the end? Because crtendS.o is linked
>> +  // in and it has an .eh_frame section with four zero chars.
>> +  return registerFrameWrapper(EHFrameSectionAddr);
>> +#endif
>> +}
>> +
>> +Error deregisterEHFrameSection(const void *EHFrameSectionAddr,
>> +                               size_t EHFrameSectionSize) {
>> +#ifdef __APPLE__
>> +  return walkAppleEHFrameSection(static_cast<const char
>> *>(EHFrameSectionAddr),
>> +                                 EHFrameSectionSize,
>> deregisterFrameWrapper);
>> +#else
>> +  return deregisterFrameWrapper(EHFrameSectionAddr);
>> +#endif
>> +}
>> +
>> +} // end namespace orc
>> +} // end namespace llvm
>> +
>> +extern "C" CWrapperFunctionResult
>> +llvm_orc_registerEHFrameSectionWrapper(uint8_t *Data, uint64_t Size) {
>> +  if (Size != sizeof(uint64_t) + sizeof(uint64_t))
>> +    return WrapperFunctionResult::from(
>> +               "Invalid arguments to
>> llvm_orc_registerEHFrameSectionWrapper")
>> +        .release();
>> +
>> +  uint64_t EHFrameSectionAddr;
>> +  uint64_t EHFrameSectionSize;
>> +
>> +  {
>> +    BinaryStreamReader ArgReader(ArrayRef<uint8_t>(Data, Size),
>> +                                 support::endianness::big);
>> +    cantFail(ArgReader.readInteger(EHFrameSectionAddr));
>> +    cantFail(ArgReader.readInteger(EHFrameSectionSize));
>> +  }
>> +
>> +  if (auto Err = registerEHFrameSection(
>> +          jitTargetAddressToPointer<void *>(EHFrameSectionAddr),
>> +          EHFrameSectionSize)) {
>> +    auto ErrMsg = toString(std::move(Err));
>> +    return WrapperFunctionResult::from(ErrMsg).release();
>> +  }
>> +  return WrapperFunctionResult().release();
>> +}
>> +
>> +extern "C" CWrapperFunctionResult
>> +llvm_orc_deregisterEHFrameSectionWrapper(uint8_t *Data, uint64_t Size) {
>> +  if (Size != sizeof(uint64_t) + sizeof(uint64_t))
>> +    return WrapperFunctionResult::from(
>> +               "Invalid arguments to
>> llvm_orc_registerEHFrameSectionWrapper")
>> +        .release();
>> +
>> +  uint64_t EHFrameSectionAddr;
>> +  uint64_t EHFrameSectionSize;
>> +
>> +  {
>> +    BinaryStreamReader ArgReader(ArrayRef<uint8_t>(Data, Size),
>> +                                 support::endianness::big);
>> +    cantFail(ArgReader.readInteger(EHFrameSectionAddr));
>> +    cantFail(ArgReader.readInteger(EHFrameSectionSize));
>> +  }
>> +
>> +  if (auto Err = deregisterEHFrameSection(
>> +          jitTargetAddressToPointer<void *>(EHFrameSectionAddr),
>> +          EHFrameSectionSize)) {
>> +    auto ErrMsg = toString(std::move(Err));
>> +    return WrapperFunctionResult::from(ErrMsg).release();
>> +  }
>> +  return WrapperFunctionResult().release();
>> +}
>>
>> diff  --git
>> a/llvm/lib/ExecutionEngine/Orc/TargetProcess/TargetExecutionUtils.cpp
>> b/llvm/lib/ExecutionEngine/Orc/TargetProcess/TargetExecutionUtils.cpp
>> new file mode 100644
>> index 000000000000..a8e6c049cf4b
>> --- /dev/null
>> +++ b/llvm/lib/ExecutionEngine/Orc/TargetProcess/TargetExecutionUtils.cpp
>> @@ -0,0 +1,43 @@
>> +//===--- TargetExecutionUtils.cpp - Execution utils for target processes
>> --===//
>> +//
>> +// 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/TargetProcess/TargetExecutionUtils.h"
>> +
>> +#include <vector>
>> +
>> +namespace llvm {
>> +namespace orc {
>> +
>> +int runAsMain(int (*Main)(int, char *[]), ArrayRef<std::string> Args,
>> +              Optional<StringRef> ProgramName) {
>> +  std::vector<std::unique_ptr<char[]>> ArgVStorage;
>> +  std::vector<char *> ArgV;
>> +
>> +  ArgVStorage.reserve(Args.size() + (ProgramName ? 1 : 0));
>> +  ArgV.reserve(Args.size() + 1 + (ProgramName ? 1 : 0));
>> +
>> +  if (ProgramName) {
>> +    ArgVStorage.push_back(std::make_unique<char[]>(ProgramName->size() +
>> 1));
>> +    llvm::copy(*ProgramName, &ArgVStorage.back()[0]);
>> +    ArgVStorage.back()[ProgramName->size()] = '\0';
>> +    ArgV.push_back(ArgVStorage.back().get());
>> +  }
>> +
>> +  for (const auto &Arg : Args) {
>> +    ArgVStorage.push_back(std::make_unique<char[]>(Arg.size() + 1));
>> +    llvm::copy(Arg, &ArgVStorage.back()[0]);
>> +    ArgVStorage.back()[Arg.size()] = '\0';
>> +    ArgV.push_back(ArgVStorage.back().get());
>> +  }
>> +  ArgV.push_back(nullptr);
>> +
>> +  return Main(Args.size() + !!ProgramName, ArgV.data());
>> +}
>> +
>> +} // End namespace orc.
>> +} // End namespace llvm.
>>
>> diff  --git a/llvm/lib/ExecutionEngine/Orc/TargetProcessControl.cpp
>> b/llvm/lib/ExecutionEngine/Orc/TargetProcessControl.cpp
>> index 1e7736d1f40d..bbbc2d60d936 100644
>> --- a/llvm/lib/ExecutionEngine/Orc/TargetProcessControl.cpp
>> +++ b/llvm/lib/ExecutionEngine/Orc/TargetProcessControl.cpp
>> @@ -9,6 +9,7 @@
>>  #include "llvm/ExecutionEngine/Orc/TargetProcessControl.h"
>>
>>  #include "llvm/ExecutionEngine/Orc/Core.h"
>> +#include "llvm/ExecutionEngine/Orc/TargetProcess/TargetExecutionUtils.h"
>>  #include "llvm/Support/Host.h"
>>  #include "llvm/Support/Process.h"
>>
>> @@ -22,23 +23,25 @@ TargetProcessControl::MemoryAccess::~MemoryAccess() {}
>>  TargetProcessControl::~TargetProcessControl() {}
>>
>>  SelfTargetProcessControl::SelfTargetProcessControl(
>> -    Triple TT, unsigned PageSize,
>> -    std::unique_ptr<jitlink::JITLinkMemoryManager> MemMgr) {
>> +    std::shared_ptr<SymbolStringPool> SSP, Triple TargetTriple,
>> +    unsigned PageSize, std::unique_ptr<jitlink::JITLinkMemoryManager>
>> MemMgr)
>> +    : TargetProcessControl(std::move(SSP)) {
>>
>>    OwnedMemMgr = std::move(MemMgr);
>>    if (!OwnedMemMgr)
>>      OwnedMemMgr = std::make_unique<jitlink::InProcessMemoryManager>();
>>
>> -  this->TT = std::move(TT);
>> +  this->TargetTriple = std::move(TargetTriple);
>>    this->PageSize = PageSize;
>>    this->MemMgr = OwnedMemMgr.get();
>>    this->MemAccess = this;
>> -  if (this->TT.isOSBinFormatMachO())
>> +  if (this->TargetTriple.isOSBinFormatMachO())
>>      GlobalManglingPrefix = '_';
>>  }
>>
>>  Expected<std::unique_ptr<SelfTargetProcessControl>>
>>  SelfTargetProcessControl::Create(
>> +    std::shared_ptr<SymbolStringPool> SSP,
>>      std::unique_ptr<jitlink::JITLinkMemoryManager> MemMgr) {
>>    auto PageSize = sys::Process::getPageSize();
>>    if (!PageSize)
>> @@ -46,11 +49,11 @@ SelfTargetProcessControl::Create(
>>
>>    Triple TT(sys::getProcessTriple());
>>
>> -  return std::make_unique<SelfTargetProcessControl>(std::move(TT),
>> *PageSize,
>> -                                                    std::move(MemMgr));
>> +  return std::make_unique<SelfTargetProcessControl>(
>> +      std::move(SSP), std::move(TT), *PageSize, std::move(MemMgr));
>>  }
>>
>> -Expected<TargetProcessControl::DylibHandle>
>> +Expected<tpctypes::DylibHandle>
>>  SelfTargetProcessControl::loadDylib(const char *DylibPath) {
>>    std::string ErrMsg;
>>    auto Dylib = std::make_unique<sys::DynamicLibrary>(
>> @@ -61,9 +64,10 @@ SelfTargetProcessControl::loadDylib(const char
>> *DylibPath) {
>>    return pointerToJITTargetAddress(DynamicLibraries.back().get());
>>  }
>>
>> -Expected<TargetProcessControl::LookupResult>
>> -SelfTargetProcessControl::lookupSymbols(LookupRequest Request) {
>> -  LookupResult R;
>> +Expected<std::vector<tpctypes::LookupResult>>
>> +SelfTargetProcessControl::lookupSymbols(
>> +    ArrayRef<tpctypes::LookupRequest> Request) {
>> +  std::vector<tpctypes::LookupResult> R;
>>
>>    for (auto &Elem : Request) {
>>      auto *Dylib = jitTargetAddressToPointer<sys::DynamicLibrary
>> *>(Elem.Handle);
>> @@ -92,35 +96,53 @@ SelfTargetProcessControl::lookupSymbols(LookupRequest
>> Request) {
>>    return R;
>>  }
>>
>> -void SelfTargetProcessControl::writeUInt8s(ArrayRef<UInt8Write> Ws,
>> +Expected<int32_t>
>> +SelfTargetProcessControl::runAsMain(JITTargetAddress MainFnAddr,
>> +                                    ArrayRef<std::string> Args) {
>> +  using MainTy = int (*)(int, char *[]);
>> +  return orc::runAsMain(jitTargetAddressToFunction<MainTy>(MainFnAddr),
>> Args);
>> +}
>> +
>> +Expected<tpctypes::WrapperFunctionResult>
>> +SelfTargetProcessControl::runWrapper(JITTargetAddress WrapperFnAddr,
>> +                                     ArrayRef<uint8_t> ArgBuffer) {
>> +  using WrapperFnTy =
>> +      tpctypes::CWrapperFunctionResult (*)(const uint8_t *Data, uint64_t
>> Size);
>> +  auto *WrapperFn =
>> jitTargetAddressToFunction<WrapperFnTy>(WrapperFnAddr);
>> +  return WrapperFn(ArgBuffer.data(), ArgBuffer.size());
>> +};
>> +
>> +Error SelfTargetProcessControl::disconnect() { return Error::success(); }
>> +
>> +void
>> SelfTargetProcessControl::writeUInt8s(ArrayRef<tpctypes::UInt8Write> Ws,
>>                                             WriteResultFn
>> OnWriteComplete) {
>>    for (auto &W : Ws)
>>      *jitTargetAddressToPointer<uint8_t *>(W.Address) = W.Value;
>>    OnWriteComplete(Error::success());
>>  }
>>
>> -void SelfTargetProcessControl::writeUInt16s(ArrayRef<UInt16Write> Ws,
>> +void
>> SelfTargetProcessControl::writeUInt16s(ArrayRef<tpctypes::UInt16Write> Ws,
>>                                              WriteResultFn
>> OnWriteComplete) {
>>    for (auto &W : Ws)
>>      *jitTargetAddressToPointer<uint16_t *>(W.Address) = W.Value;
>>    OnWriteComplete(Error::success());
>>  }
>>
>> -void SelfTargetProcessControl::writeUInt32s(ArrayRef<UInt32Write> Ws,
>> +void
>> SelfTargetProcessControl::writeUInt32s(ArrayRef<tpctypes::UInt32Write> Ws,
>>                                              WriteResultFn
>> OnWriteComplete) {
>>    for (auto &W : Ws)
>>      *jitTargetAddressToPointer<uint32_t *>(W.Address) = W.Value;
>>    OnWriteComplete(Error::success());
>>  }
>>
>> -void SelfTargetProcessControl::writeUInt64s(ArrayRef<UInt64Write> Ws,
>> +void
>> SelfTargetProcessControl::writeUInt64s(ArrayRef<tpctypes::UInt64Write> Ws,
>>                                              WriteResultFn
>> OnWriteComplete) {
>>    for (auto &W : Ws)
>>      *jitTargetAddressToPointer<uint64_t *>(W.Address) = W.Value;
>>    OnWriteComplete(Error::success());
>>  }
>>
>> -void SelfTargetProcessControl::writeBuffers(ArrayRef<BufferWrite> Ws,
>> +void
>> SelfTargetProcessControl::writeBuffers(ArrayRef<tpctypes::BufferWrite> Ws,
>>                                              WriteResultFn
>> OnWriteComplete) {
>>    for (auto &W : Ws)
>>      memcpy(jitTargetAddressToPointer<char *>(W.Address), W.Buffer.data(),
>>
>> diff  --git a/llvm/tools/lli/CMakeLists.txt
>> b/llvm/tools/lli/CMakeLists.txt
>> index bc6ef213b8fd..098e9dd3e743 100644
>> --- a/llvm/tools/lli/CMakeLists.txt
>> +++ b/llvm/tools/lli/CMakeLists.txt
>> @@ -11,8 +11,9 @@ set(LLVM_LINK_COMPONENTS
>>    MC
>>    MCJIT
>>    Object
>> -  OrcError
>> +  OrcShared
>>    OrcJIT
>> +  OrcTargetProcess
>>    Passes
>>    RuntimeDyld
>>    SelectionDAG
>>
>> diff  --git a/llvm/tools/lli/ChildTarget/CMakeLists.txt
>> b/llvm/tools/lli/ChildTarget/CMakeLists.txt
>> index d3d15bef6c5b..c5795eebd71a 100644
>> --- a/llvm/tools/lli/ChildTarget/CMakeLists.txt
>> +++ b/llvm/tools/lli/ChildTarget/CMakeLists.txt
>> @@ -1,5 +1,5 @@
>>  set(LLVM_LINK_COMPONENTS
>> -  OrcError
>> +  OrcShared
>>    OrcJIT
>>    RuntimeDyld
>>    Support
>>
>> diff  --git a/llvm/tools/lli/LLVMBuild.txt b/llvm/tools/lli/LLVMBuild.txt
>> index 133543a26fce..0d473cbe9238 100644
>> --- a/llvm/tools/lli/LLVMBuild.txt
>> +++ b/llvm/tools/lli/LLVMBuild.txt
>> @@ -28,6 +28,9 @@ required_libraries =
>>   Instrumentation
>>   Interpreter
>>   MCJIT
>> + OrcJIT
>> + OrcShared
>> + OrcTargetProcess
>>   Native
>>   NativeCodeGen
>>   SelectionDAG
>>
>> diff  --git a/llvm/tools/lli/lli.cpp b/llvm/tools/lli/lli.cpp
>> index 1ebd1435f2f3..e9b48a8542ec 100644
>> --- a/llvm/tools/lli/lli.cpp
>> +++ b/llvm/tools/lli/lli.cpp
>> @@ -31,6 +31,7 @@
>>  #include "llvm/ExecutionEngine/Orc/MachOPlatform.h"
>>  #include "llvm/ExecutionEngine/Orc/OrcRemoteTargetClient.h"
>>  #include "llvm/ExecutionEngine/Orc/RTDyldObjectLinkingLayer.h"
>> +#include "llvm/ExecutionEngine/Orc/TargetProcess/TargetExecutionUtils.h"
>>  #include "llvm/ExecutionEngine/SectionMemoryManager.h"
>>  #include "llvm/IR/IRBuilder.h"
>>  #include "llvm/IR/LLVMContext.h"
>>
>> diff  --git a/llvm/tools/llvm-jitlink/CMakeLists.txt
>> b/llvm/tools/llvm-jitlink/CMakeLists.txt
>> index bfe691d976ba..8d511b17fca2 100644
>> --- a/llvm/tools/llvm-jitlink/CMakeLists.txt
>> +++ b/llvm/tools/llvm-jitlink/CMakeLists.txt
>> @@ -1,3 +1,7 @@
>> +if ( LLVM_INCLUDE_UTILS )
>> +  add_subdirectory(llvm-jitlink-executor)
>> +endif()
>> +
>>  set(LLVM_LINK_COMPONENTS
>>    AllTargetsDescs
>>    AllTargetsDisassemblers
>> @@ -8,6 +12,8 @@ set(LLVM_LINK_COMPONENTS
>>    MC
>>    Object
>>    OrcJIT
>> +  OrcShared
>> +  OrcTargetProcess
>>    RuntimeDyld
>>    Support
>>    )
>>
>> diff  --git a/llvm/tools/llvm-jitlink/LLVMBuild.txt
>> b/llvm/tools/llvm-jitlink/LLVMBuild.txt
>> index 224bab58c215..8aa0ef8161e6 100644
>> --- a/llvm/tools/llvm-jitlink/LLVMBuild.txt
>> +++ b/llvm/tools/llvm-jitlink/LLVMBuild.txt
>> @@ -18,5 +18,5 @@
>>  type = Tool
>>  name = llvm-jitlink
>>  parent = Tools
>> -required_libraries = JITLink BinaryFormat MC Object RuntimeDyld Support
>> -                     all-targets
>> +required_libraries = JITLink BinaryFormat MC Object OrcJIT
>> OrcTargetProcess
>> +                     Support all-targets
>>
>> diff  --git
>> a/llvm/tools/llvm-jitlink/llvm-jitlink-executor/CMakeLists.txt
>> b/llvm/tools/llvm-jitlink/llvm-jitlink-executor/CMakeLists.txt
>> new file mode 100644
>> index 000000000000..f6d882d1a8f0
>> --- /dev/null
>> +++ b/llvm/tools/llvm-jitlink/llvm-jitlink-executor/CMakeLists.txt
>> @@ -0,0 +1,14 @@
>> +set(LLVM_LINK_COMPONENTS
>> +  OrcShared
>> +  OrcTargetProcess
>> +  Support
>> +  )
>> +
>> +add_llvm_utility(llvm-jitlink-executor
>> +  llvm-jitlink-executor.cpp
>> +
>> +  DEPENDS
>> +  intrinsics_gen
>> +)
>> +
>> +export_executable_symbols(llvm-jitlink-executor)
>>
>> diff  --git a/llvm/tools/llvm-jitlink/llvm-jitlink-executor/LLVMBuild.txt
>> b/llvm/tools/llvm-jitlink/llvm-jitlink-executor/LLVMBuild.txt
>> new file mode 100644
>> index 000000000000..0d96143673dd
>> --- /dev/null
>> +++ b/llvm/tools/llvm-jitlink/llvm-jitlink-executor/LLVMBuild.txt
>> @@ -0,0 +1,21 @@
>> +;===- ./tools/llvm-jitlink/llvm-jitlink-executor/LLVMBuild.txt -*- Conf
>> -*--===;
>> +;
>> +; 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
>> +;
>>
>> +;===------------------------------------------------------------------------===;
>> +;
>> +; This is an LLVMBuild description file for the components in this
>> subdirectory.
>> +;
>> +; For more information on the LLVMBuild system, please see:
>> +;
>> +;   http://llvm.org/docs/LLVMBuild.html
>> +;
>>
>> +;===------------------------------------------------------------------------===;
>> +
>> +[component_0]
>> +type = Tool
>> +name = llvm-jitlink-executor
>> +parent = llvm-jitlink
>> +required_libraries = OrcTargetProcess Support
>>
>> diff  --git
>> a/llvm/tools/llvm-jitlink/llvm-jitlink-executor/llvm-jitlink-executor.cpp
>> b/llvm/tools/llvm-jitlink/llvm-jitlink-executor/llvm-jitlink-executor.cpp
>> new file mode 100644
>> index 000000000000..78227f3f423b
>> --- /dev/null
>> +++
>> b/llvm/tools/llvm-jitlink/llvm-jitlink-executor/llvm-jitlink-executor.cpp
>> @@ -0,0 +1,127 @@
>> +//===- llvm-jitlink-executor.cpp - Out-of-proc executor for llvm-jitlink
>> -===//
>> +//
>> +// 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
>> +//
>>
>> +//===----------------------------------------------------------------------===//
>> +//
>> +// Simple out-of-process executor for llvm-jitlink.
>> +//
>>
>> +//===----------------------------------------------------------------------===//
>> +
>> +#include "llvm/ADT/StringRef.h"
>> +#include "llvm/ExecutionEngine/Orc/RPC/FDRawByteChannel.h"
>> +#include "llvm/ExecutionEngine/Orc/TargetProcess/OrcRPCTPCServer.h"
>> +#include "llvm/ExecutionEngine/Orc/TargetProcess/RegisterEHFrames.h"
>> +#include "llvm/Support/DynamicLibrary.h"
>> +#include "llvm/Support/Error.h"
>> +#include "llvm/Support/raw_ostream.h"
>> +#include <sstream>
>> +
>> +#ifdef LLVM_ON_UNIX
>> +
>> +#include <netinet/in.h>
>> +#include <sys/socket.h>
>> +
>> +#endif
>> +
>> +using namespace llvm;
>> +using namespace llvm::orc;
>> +
>> +ExitOnError ExitOnErr;
>> +
>> +LLVM_ATTRIBUTE_USED void linkComponents() {
>> +  errs() << (void *)&llvm_orc_registerEHFrameSectionWrapper
>> +         << (void *)&llvm_orc_deregisterEHFrameSectionWrapper;
>> +}
>> +
>> +void printErrorAndExit(Twine ErrMsg) {
>> +  errs() << "error: " << ErrMsg.str() << "\n\n"
>> +         << "Usage:\n"
>> +         << "  llvm-jitlink-executor filedescs=<infd>,<outfd>
>> [args...]\n"
>> +         << "  llvm-jitlink-executor listen=<host>:<port> [args...]\n";
>> +  exit(1);
>> +}
>> +
>> +int openListener(std::string Host, int Port) {
>> +#ifndef LLVM_ON_UNIX
>> +  // FIXME: Add TCP support for Windows.
>> +  printErrorAndExit("listen option not supported");
>> +#else
>> +  int SockFD = socket(PF_INET, SOCK_STREAM, 0);
>> +  struct sockaddr_in ServerAddr, ClientAddr;
>> +  socklen_t ClientAddrLen = sizeof(ClientAddr);
>> +  memset(&ServerAddr, 0, sizeof(ServerAddr));
>> +  ServerAddr.sin_family = PF_INET;
>> +  ServerAddr.sin_family = INADDR_ANY;
>> +  ServerAddr.sin_port = htons(Port);
>> +
>> +  {
>> +    // lose the "Address already in use" error message
>> +    int Yes = 1;
>> +    if (setsockopt(SockFD, SOL_SOCKET, SO_REUSEADDR, &Yes, sizeof(int))
>> == -1) {
>> +      errs() << "Error calling setsockopt.\n";
>> +      exit(1);
>> +    }
>> +  }
>> +
>> +  if (bind(SockFD, (struct sockaddr *)&ServerAddr, sizeof(ServerAddr)) <
>> 0) {
>> +    errs() << "Error on binding.\n";
>> +    exit(1);
>> +  }
>> +
>> +  listen(SockFD, 1);
>> +  return accept(SockFD, (struct sockaddr *)&ClientAddr, &ClientAddrLen);
>> +#endif
>> +}
>> +
>> +int main(int argc, char *argv[]) {
>> +
>> +  ExitOnErr.setBanner(std::string(argv[0]) + ": ");
>> +
>> +  int InFD = 0;
>> +  int OutFD = 0;
>> +
>> +  if (argc < 2)
>> +    printErrorAndExit("insufficient arguments");
>> +  else {
>> +    StringRef Arg1 = argv[1];
>> +    StringRef SpecifierType, Specifier;
>> +    std::tie(SpecifierType, Specifier) = Arg1.split('=');
>> +    if (SpecifierType == "filedescs") {
>> +      StringRef FD1Str, FD2Str;
>> +      std::tie(FD1Str, FD2Str) = Specifier.split(',');
>> +      if (FD1Str.getAsInteger(10, InFD))
>> +        printErrorAndExit(FD1Str + " is not a valid file descriptor");
>> +      if (FD2Str.getAsInteger(10, OutFD))
>> +        printErrorAndExit(FD2Str + " is not a valid file descriptor");
>> +    } else if (SpecifierType == "listen") {
>> +      StringRef Host, PortStr;
>> +      std::tie(Host, PortStr) = Specifier.split(':');
>> +
>> +      int Port = 0;
>> +      if (PortStr.getAsInteger(10, Port))
>> +        printErrorAndExit("port" + PortStr + " is not a valid integer");
>> +
>> +      InFD = OutFD = openListener(Host.str(), Port);
>> +    } else
>> +      printErrorAndExit("invalid specifier type \"" + SpecifierType +
>> "\"");
>> +  }
>> +
>> +  ExitOnErr.setBanner(std::string(argv[0]) + ":");
>> +
>> +  using JITLinkExecutorEndpoint =
>> +      rpc::MultiThreadedRPCEndpoint<rpc::FDRawByteChannel>;
>> +
>> +  rpc::registerStringError<rpc::FDRawByteChannel>();
>> +
>> +  rpc::FDRawByteChannel C(InFD, OutFD);
>> +  JITLinkExecutorEndpoint EP(C, true);
>> +  OrcRPCTPCServer<JITLinkExecutorEndpoint> Server(EP);
>> +  Server.setProgramName(std::string("llvm-jitlink-executor"));
>> +
>> +  ExitOnErr(Server.run());
>> +
>> +  return 0;
>> +}
>>
>> diff  --git a/llvm/tools/llvm-jitlink/llvm-jitlink.cpp
>> b/llvm/tools/llvm-jitlink/llvm-jitlink.cpp
>> index 8c3b99824fe3..4e899cf2d156 100644
>> --- a/llvm/tools/llvm-jitlink/llvm-jitlink.cpp
>> +++ b/llvm/tools/llvm-jitlink/llvm-jitlink.cpp
>> @@ -15,9 +15,9 @@
>>  #include "llvm-jitlink.h"
>>
>>  #include "llvm/BinaryFormat/Magic.h"
>> -#include "llvm/ExecutionEngine/JITLink/EHFrameSupport.h"
>>  #include "llvm/ExecutionEngine/Orc/ExecutionUtils.h"
>>  #include "llvm/ExecutionEngine/Orc/TPCDynamicLibrarySearchGenerator.h"
>> +#include "llvm/ExecutionEngine/Orc/TPCEHFrameRegistrar.h"
>>  #include "llvm/MC/MCAsmInfo.h"
>>  #include "llvm/MC/MCContext.h"
>>  #include "llvm/MC/MCDisassembler/MCDisassembler.h"
>> @@ -41,6 +41,13 @@
>>  #include <list>
>>  #include <string>
>>
>> +#ifdef LLVM_ON_UNIX
>> +#include <netdb.h>
>> +#include <netinet/in.h>
>> +#include <sys/socket.h>
>> +#include <unistd.h>
>> +#endif // LLVM_ON_UNIX
>> +
>>  #define DEBUG_TYPE "llvm_jitlink"
>>
>>  using namespace llvm;
>> @@ -138,6 +145,14 @@ static cl::opt<bool> PhonyExternals(
>>      cl::desc("resolve all otherwise unresolved externals to null"),
>>      cl::init(false));
>>
>> +static cl::opt<std::string> OutOfProcessExecutor(
>> +    "oop-executor", cl::desc("Launch an out-of-process executor to run
>> code"),
>> +    cl::ValueOptional);
>> +
>> +static cl::opt<std::string> OutOfProcessExecutorConnect(
>> +    "oop-executor-connect",
>> +    cl::desc("Connect to an out-of-process executor via TCP"));
>> +
>>  ExitOnError ExitOnErr;
>>
>>  namespace llvm {
>> @@ -561,6 +576,165 @@ Error
>> LLVMJITLinkObjectLinkingLayer::add(ResourceTrackerSP RT,
>>    return JD.define(std::move(MU), std::move(RT));
>>  }
>>
>> +Expected<std::unique_ptr<TargetProcessControl>>
>> +LLVMJITLinkRemoteTargetProcessControl::LaunchExecutor() {
>> +#ifndef LLVM_ON_UNIX
>> +  // FIXME: Add support for Windows.
>> +  return make_error<StringError>("-" + OutOfProcessExecutor.ArgStr +
>> +                                     " not supported on non-unix
>> platforms",
>> +                                 inconvertibleErrorCode());
>> +#else
>> +
>> +  rpc::registerStringError<LLVMJITLinkChannel>();
>> +
>> +  constexpr int ReadEnd = 0;
>> +  constexpr int WriteEnd = 1;
>> +
>> +  // Pipe FDs.
>> +  int ToExecutor[2];
>> +  int FromExecutor[2];
>> +
>> +  pid_t ChildPID;
>> +
>> +  // Create pipes to/from the executor..
>> +  if (pipe(ToExecutor) != 0 || pipe(FromExecutor) != 0)
>> +    return make_error<StringError>("Unable to create pipe for executor",
>> +                                   inconvertibleErrorCode());
>> +
>> +  ChildPID = fork();
>> +
>> +  if (ChildPID == 0) {
>> +    // In the child...
>> +
>> +    // Close the parent ends of the pipes
>> +    close(ToExecutor[WriteEnd]);
>> +    close(FromExecutor[ReadEnd]);
>> +
>> +    // Execute the child process.
>> +    std::unique_ptr<char[]> ExecutorPath, FDSpecifier;
>> +    {
>> +      ExecutorPath =
>> std::make_unique<char[]>(OutOfProcessExecutor.size() + 1);
>> +      strcpy(ExecutorPath.get(), OutOfProcessExecutor.data());
>> +
>> +      std::string FDSpecifierStr("filedescs=");
>> +      FDSpecifierStr += utostr(ToExecutor[ReadEnd]);
>> +      FDSpecifierStr += ',';
>> +      FDSpecifierStr += utostr(FromExecutor[WriteEnd]);
>> +      FDSpecifier = std::make_unique<char[]>(FDSpecifierStr.size() + 1);
>> +      strcpy(FDSpecifier.get(), FDSpecifierStr.c_str());
>> +    }
>> +
>> +    char *const Args[] = {ExecutorPath.get(), FDSpecifier.get(),
>> nullptr};
>> +    int RC = execvp(ExecutorPath.get(), Args);
>> +    if (RC != 0) {
>> +      errs() << "unable to launch out-of-process executor \""
>> +             << ExecutorPath.get() << "\"\n";
>> +      exit(1);
>> +    }
>> +  }
>> +  // else we're the parent...
>> +
>> +  // Close the child ends of the pipes
>> +  close(ToExecutor[ReadEnd]);
>> +  close(FromExecutor[WriteEnd]);
>> +
>> +  // Return an RPC channel connected to our end of the pipes.
>> +  auto SSP = std::make_shared<SymbolStringPool>();
>> +  auto Channel =
>> std::make_unique<rpc::FDRawByteChannel>(FromExecutor[ReadEnd],
>> +
>>  ToExecutor[WriteEnd]);
>> +  auto Endpoint = std::make_unique<LLVMJITLinkRPCEndpoint>(*Channel,
>> true);
>> +
>> +  auto ReportError = [](Error Err) {
>> +    logAllUnhandledErrors(std::move(Err), errs(), "");
>> +  };
>> +
>> +  Error Err = Error::success();
>> +  std::unique_ptr<LLVMJITLinkRemoteTargetProcessControl> RTPC(
>> +      new LLVMJITLinkRemoteTargetProcessControl(
>> +          std::move(SSP), std::move(Channel), std::move(Endpoint),
>> +          std::move(ReportError), Err));
>> +  if (Err)
>> +    return std::move(Err);
>> +  return std::move(RTPC);
>> +#endif
>> +}
>> +
>> +Expected<std::unique_ptr<TargetProcessControl>>
>> +LLVMJITLinkRemoteTargetProcessControl::ConnectToExecutor() {
>> +#ifndef LLVM_ON_UNIX
>> +  // FIXME: Add TCP support for Windows.
>> +  return make_error<StringError>("-" +
>> OutOfProcessExecutorConnect.ArgStr +
>> +                                     " not supported on non-unix
>> platforms",
>> +                                 inconvertibleErrorCode());
>> +#else
>> +
>> +  rpc::registerStringError<LLVMJITLinkChannel>();
>> +
>> +  StringRef HostNameStr, PortStr;
>> +  std::tie(HostNameStr, PortStr) =
>> +      StringRef(OutOfProcessExecutorConnect).split(':');
>> +
>> +  if (HostNameStr.empty())
>> +    return make_error<StringError>("host name for -" +
>> +
>>  OutOfProcessExecutorConnect.ArgStr +
>> +                                       " can not be empty",
>> +                                   inconvertibleErrorCode());
>> +  if (PortStr.empty())
>> +    return make_error<StringError>(
>> +        "port for -" + OutOfProcessExecutorConnect.ArgStr + " can not be
>> empty",
>> +        inconvertibleErrorCode());
>> +
>> +  std::string HostName = HostNameStr.str();
>> +  int Port = 0;
>> +  if (PortStr.getAsInteger(10, Port))
>> +    return make_error<StringError>("port number " + PortStr +
>> +                                       " is not a valid integer",
>> +                                   inconvertibleErrorCode());
>> +
>> +  int SockFD = socket(PF_INET, SOCK_STREAM, 0);
>> +  hostent *Server = gethostbyname(HostName.c_str());
>> +  sockaddr_in ServAddr;
>> +  memset(&ServAddr, 0, sizeof(ServAddr));
>> +  ServAddr.sin_family = PF_INET;
>> +  memmove(&Server->h_addr, &ServAddr.sin_addr.s_addr, Server->h_length);
>> +  ServAddr.sin_port = htons(Port);
>> +  if (connect(SockFD, reinterpret_cast<sockaddr *>(&ServAddr),
>> +              sizeof(ServAddr)) < 0)
>> +    return make_error<StringError>("Failed to connect to " + HostName +
>> ":" +
>> +                                       Twine(Port),
>> +                                   inconvertibleErrorCode());
>> +
>> +  auto SSP = std::make_shared<SymbolStringPool>();
>> +  auto Channel = std::make_unique<rpc::FDRawByteChannel>(SockFD, SockFD);
>> +  auto Endpoint = std::make_unique<LLVMJITLinkRPCEndpoint>(*Channel,
>> true);
>> +
>> +  auto ReportError = [](Error Err) {
>> +    logAllUnhandledErrors(std::move(Err), errs(), "");
>> +  };
>> +
>> +  Error Err = Error::success();
>> +  std::unique_ptr<LLVMJITLinkRemoteTargetProcessControl> RTPC(
>> +      new LLVMJITLinkRemoteTargetProcessControl(
>> +          std::move(SSP), std::move(Channel), std::move(Endpoint),
>> +          std::move(ReportError), Err));
>> +  if (Err)
>> +    return std::move(Err);
>> +  return std::move(RTPC);
>> +#endif
>> +}
>> +
>> +Error LLVMJITLinkRemoteTargetProcessControl::disconnect() {
>> +  std::promise<MSVCPError> P;
>> +  auto F = P.get_future();
>> +  auto Err = closeConnection([&](Error Err) -> Error {
>> +    P.set_value(std::move(Err));
>> +    Finished = true;
>> +    return Error::success();
>> +  });
>> +  ListenerThread.join();
>> +  return joinErrors(std::move(Err), F.get());
>> +};
>> +
>>  class PhonyExternalsGenerator : public DefinitionGenerator {
>>  public:
>>    Error tryToGenerate(LookupState &LS, LookupKind K, JITDylib &JD,
>> @@ -574,13 +748,30 @@ class PhonyExternalsGenerator : public
>> DefinitionGenerator {
>>  };
>>
>>  Expected<std::unique_ptr<Session>> Session::Create(Triple TT) {
>> -  Error Err = Error::success();
>>
>>    auto PageSize = sys::Process::getPageSize();
>>    if (!PageSize)
>>      return PageSize.takeError();
>>
>> -  std::unique_ptr<Session> S(new Session(std::move(TT), *PageSize, Err));
>> +  /// If -oop-executor is passed then launch the executor.
>> +  std::unique_ptr<TargetProcessControl> TPC;
>> +  if (OutOfProcessExecutor.getNumOccurrences()) {
>> +    if (auto RTPC =
>> LLVMJITLinkRemoteTargetProcessControl::LaunchExecutor())
>> +      TPC = std::move(*RTPC);
>> +    else
>> +      return RTPC.takeError();
>> +  } else if (OutOfProcessExecutorConnect.getNumOccurrences()) {
>> +    if (auto RTPC =
>> LLVMJITLinkRemoteTargetProcessControl::ConnectToExecutor())
>> +      TPC = std::move(*RTPC);
>> +    else
>> +      return RTPC.takeError();
>> +  } else
>> +    TPC = std::make_unique<SelfTargetProcessControl>(
>> +        std::make_shared<SymbolStringPool>(), std::move(TT), *PageSize,
>> +        createMemoryManager());
>> +
>> +  Error Err = Error::success();
>> +  std::unique_ptr<Session> S(new Session(std::move(TPC), Err));
>>    if (Err)
>>      return std::move(Err);
>>    return std::move(S);
>> @@ -593,10 +784,8 @@ Session::~Session() {
>>
>>  // FIXME: Move to createJITDylib if/when we start using Platform support
>> in
>>  // llvm-jitlink.
>> -Session::Session(Triple TT, uint64_t PageSize, Error &Err)
>> -    : TPC(std::make_unique<SelfTargetProcessControl>(std::move(TT),
>> PageSize,
>> -
>>  createMemoryManager())),
>> -      ObjLayer(*this, TPC->getMemMgr()) {
>> +Session::Session(std::unique_ptr<TargetProcessControl> TPC, Error &Err)
>> +    : TPC(std::move(TPC)), ObjLayer(*this, this->TPC->getMemMgr()) {
>>
>>    /// Local ObjectLinkingLayer::Plugin class to forward modifyPassConfig
>> to the
>>    /// Session.
>> @@ -630,9 +819,9 @@ Session::Session(Triple TT, uint64_t PageSize, Error
>> &Err)
>>      return;
>>    }
>>
>> -  if (!NoExec && !TT.isOSWindows())
>> +  if (!NoExec && !this->TPC->getTargetTriple().isOSWindows())
>>      ObjLayer.addPlugin(std::make_unique<EHFrameRegistrationPlugin>(
>> -        ES, std::make_unique<InProcessEHFrameRegistrar>()));
>> +        ES, ExitOnErr(TPCEHFrameRegistrar::Create(*this->TPC))));
>>
>>    ObjLayer.addPlugin(std::make_unique<JITLinkSessionPlugin>(*this));
>>
>> @@ -785,22 +974,28 @@ Session::findSymbolInfo(StringRef SymbolName, Twine
>> ErrorMsgStem) {
>>  } // end namespace llvm
>>
>>  static Triple getFirstFileTriple() {
>> -  assert(!InputFiles.empty() && "InputFiles can not be empty");
>> -  auto ObjBuffer =
>> -
>> ExitOnErr(errorOrToExpected(MemoryBuffer::getFile(InputFiles.front())));
>> -  auto Obj = ExitOnErr(
>> -
>> object::ObjectFile::createObjectFile(ObjBuffer->getMemBufferRef()));
>> -  return Obj->makeTriple();
>> +  static Triple FirstTT = []() {
>> +    assert(!InputFiles.empty() && "InputFiles can not be empty");
>> +    auto ObjBuffer =
>> +
>> ExitOnErr(errorOrToExpected(MemoryBuffer::getFile(InputFiles.front())));
>> +    auto Obj = ExitOnErr(
>> +
>> object::ObjectFile::createObjectFile(ObjBuffer->getMemBufferRef()));
>> +    return Obj->makeTriple();
>> +  }();
>> +
>> +  return FirstTT;
>>  }
>>
>> -static Error sanitizeArguments(const Session &S) {
>> +static Error sanitizeArguments(const Triple &TT, const char *ArgV0) {
>> +  // Set the entry point name if not specified.
>>    if (EntryPointName.empty()) {
>> -    if (S.TPC->getTargetTriple().getObjectFormat() == Triple::MachO)
>> +    if (TT.getObjectFormat() == Triple::MachO)
>>        EntryPointName = "_main";
>>      else
>>        EntryPointName = "main";
>>    }
>>
>> +  // -noexec and --args should not be used together.
>>    if (NoExec && !InputArgv.empty())
>>      outs() << "Warning: --args passed to -noexec run will be ignored.\n";
>>
>> @@ -812,14 +1007,35 @@ static Error sanitizeArguments(const Session &S) {
>>            inconvertibleErrorCode());
>>    }
>>
>> +  // Only one of -oop-executor and -oop-executor-connect can be used.
>> +  if (!!OutOfProcessExecutor.getNumOccurrences() &&
>> +      !!OutOfProcessExecutorConnect.getNumOccurrences())
>> +    return make_error<StringError>(
>> +        "Only one of -" + OutOfProcessExecutor.ArgStr + " and -" +
>> +            OutOfProcessExecutorConnect.ArgStr + " can be specified",
>> +        inconvertibleErrorCode());
>> +
>> +  // If -oop-executor was used but no value was specified then use a
>> sensible
>> +  // default.
>> +  if (!!OutOfProcessExecutor.getNumOccurrences() &&
>> +      OutOfProcessExecutor.empty()) {
>> +    SmallString<256> OOPExecutorPath(sys::fs::getMainExecutable(
>> +        ArgV0, reinterpret_cast<void *>(&sanitizeArguments)));
>> +    sys::path::remove_filename(OOPExecutorPath);
>> +    if (OOPExecutorPath.back() != '/')
>> +      OOPExecutorPath += '/';
>> +    OOPExecutorPath += "llvm-jitlink-executor";
>> +    OutOfProcessExecutor = OOPExecutorPath.str().str();
>> +  }
>> +
>>    return Error::success();
>>  }
>>
>>  static Error loadProcessSymbols(Session &S) {
>> -  auto InternedEntryPointName = S.ES.intern(EntryPointName);
>> -  auto FilterMainEntryPoint = [InternedEntryPointName](SymbolStringPtr
>> Name) {
>> -    return Name != InternedEntryPointName;
>> -  };
>> +  auto FilterMainEntryPoint =
>> +      [EPName = S.ES.intern(EntryPointName)](SymbolStringPtr Name) {
>> +        return Name != EPName;
>> +      };
>>    S.MainJD->addGenerator(
>>
>>  ExitOnErr(orc::TPCDynamicLibrarySearchGenerator::GetForTargetProcess(
>>            *S.TPC, std::move(FilterMainEntryPoint))));
>> @@ -827,15 +1043,12 @@ static Error loadProcessSymbols(Session &S) {
>>    return Error::success();
>>  }
>>
>> -static Error loadDylibs() {
>> -  // FIXME: This should all be handled inside DynamicLibrary.
>> +static Error loadDylibs(Session &S) {
>>    for (const auto &Dylib : Dylibs) {
>> -    if (!sys::fs::is_regular_file(Dylib))
>> -      return make_error<StringError>("\"" + Dylib + "\" is not a regular
>> file",
>> -                                     inconvertibleErrorCode());
>> -    std::string ErrMsg;
>> -    if (sys::DynamicLibrary::LoadLibraryPermanently(Dylib.c_str(),
>> &ErrMsg))
>> -      return make_error<StringError>(ErrMsg, inconvertibleErrorCode());
>> +    auto G = orc::TPCDynamicLibrarySearchGenerator::Load(*S.TPC,
>> Dylib.c_str());
>> +    if (!G)
>> +      return G.takeError();
>> +    S.MainJD->addGenerator(std::move(*G));
>>    }
>>
>>    return Error::success();
>> @@ -1072,9 +1285,9 @@ int main(int argc, char *argv[]) {
>>    std::unique_ptr<JITLinkTimers> Timers =
>>        ShowTimes ? std::make_unique<JITLinkTimers>() : nullptr;
>>
>> -  auto S = ExitOnErr(Session::Create(getFirstFileTriple()));
>> +  ExitOnErr(sanitizeArguments(getFirstFileTriple(), argv[0]));
>>
>> -  ExitOnErr(sanitizeArguments(*S));
>> +  auto S = ExitOnErr(Session::Create(getFirstFileTriple()));
>>
>>    {
>>      TimeRegion TR(Timers ? &Timers->LoadObjectsTimer : nullptr);
>> @@ -1083,7 +1296,7 @@ int main(int argc, char *argv[]) {
>>
>>    if (!NoProcessSymbols)
>>      ExitOnErr(loadProcessSymbols(*S));
>> -  ExitOnErr(loadDylibs());
>> +  ExitOnErr(loadDylibs(*S));
>>
>>    if (PhonyExternals)
>>      addPhonyExternalsGenerator(*S);
>> @@ -1110,11 +1323,12 @@ int main(int argc, char *argv[]) {
>>
>>    int Result = 0;
>>    {
>> -    using MainTy = int (*)(int, char *[]);
>> -    auto EntryFn =
>> jitTargetAddressToFunction<MainTy>(EntryPoint.getAddress());
>>      TimeRegion TR(Timers ? &Timers->RunTimer : nullptr);
>> -    Result = runAsMain(EntryFn, InputArgv,
>> StringRef(InputFiles.front()));
>> +    Result = ExitOnErr(S->TPC->runAsMain(EntryPoint.getAddress(),
>> InputArgv));
>>    }
>>
>> +  ExitOnErr(S->ES.endSession());
>> +  ExitOnErr(S->TPC->disconnect());
>> +
>>    return Result;
>>  }
>>
>> diff  --git a/llvm/tools/llvm-jitlink/llvm-jitlink.h
>> b/llvm/tools/llvm-jitlink/llvm-jitlink.h
>> index f0ede14050fd..5132eb204be1 100644
>> --- a/llvm/tools/llvm-jitlink/llvm-jitlink.h
>> +++ b/llvm/tools/llvm-jitlink/llvm-jitlink.h
>> @@ -18,6 +18,9 @@
>>  #include "llvm/ADT/Triple.h"
>>  #include "llvm/ExecutionEngine/Orc/Core.h"
>>  #include "llvm/ExecutionEngine/Orc/ObjectLinkingLayer.h"
>> +#include "llvm/ExecutionEngine/Orc/OrcRPCTargetProcessControl.h"
>> +#include "llvm/ExecutionEngine/Orc/RPC/FDRawByteChannel.h"
>> +#include "llvm/ExecutionEngine/Orc/RPC/RPCUtils.h"
>>  #include "llvm/ExecutionEngine/Orc/TargetProcessControl.h"
>>  #include "llvm/ExecutionEngine/RuntimeDyldChecker.h"
>>  #include "llvm/Support/Error.h"
>> @@ -45,9 +48,71 @@ class LLVMJITLinkObjectLinkingLayer : public
>> orc::ObjectLinkingLayer {
>>    Session &S;
>>  };
>>
>> +using LLVMJITLinkChannel = orc::rpc::FDRawByteChannel;
>> +using LLVMJITLinkRPCEndpoint =
>> +    orc::rpc::MultiThreadedRPCEndpoint<LLVMJITLinkChannel>;
>> +using LLVMJITLinkRemoteMemoryManager =
>> +    orc::OrcRPCTPCJITLinkMemoryManager<LLVMJITLinkRPCEndpoint>;
>> +using LLVMJITLinkRemoteMemoryAccess =
>> +    orc::OrcRPCTPCMemoryAccess<LLVMJITLinkRPCEndpoint>;
>> +
>> +class LLVMJITLinkRemoteTargetProcessControl
>> +    : public orc::OrcRPCTargetProcessControlBase<LLVMJITLinkRPCEndpoint>
>> {
>> +public:
>> +  using BaseT =
>> orc::OrcRPCTargetProcessControlBase<LLVMJITLinkRPCEndpoint>;
>> +  static Expected<std::unique_ptr<TargetProcessControl>>
>> LaunchExecutor();
>> +
>> +  static Expected<std::unique_ptr<TargetProcessControl>>
>> ConnectToExecutor();
>> +
>> +  Error disconnect() override;
>> +
>> +private:
>> +  using LLVMJITLinkRemoteMemoryAccess =
>> +      orc::OrcRPCTPCMemoryAccess<LLVMJITLinkRemoteTargetProcessControl>;
>> +
>> +  using LLVMJITLinkRemoteMemoryManager =
>> +
>> orc::OrcRPCTPCJITLinkMemoryManager<LLVMJITLinkRemoteTargetProcessControl>;
>> +
>> +  LLVMJITLinkRemoteTargetProcessControl(
>> +      std::shared_ptr<orc::SymbolStringPool> SSP,
>> +      std::unique_ptr<LLVMJITLinkChannel> Channel,
>> +      std::unique_ptr<LLVMJITLinkRPCEndpoint> Endpoint,
>> +      ErrorReporter ReportError, Error &Err)
>> +      : BaseT(std::move(SSP), *Endpoint, std::move(ReportError)),
>> +        Channel(std::move(Channel)), Endpoint(std::move(Endpoint)) {
>> +    ErrorAsOutParameter _(&Err);
>> +
>> +    ListenerThread = std::thread([&]() {
>> +      while (!Finished) {
>> +        if (auto Err = this->Endpoint->handleOne()) {
>> +          reportError(std::move(Err));
>> +          return;
>> +        }
>> +      }
>> +    });
>> +
>> +    if (auto Err2 = initializeORCRPCTPCBase()) {
>> +      Err = joinErrors(std::move(Err2), disconnect());
>> +      return;
>> +    }
>> +
>> +    OwnedMemAccess =
>> std::make_unique<LLVMJITLinkRemoteMemoryAccess>(*this);
>> +    MemAccess = OwnedMemAccess.get();
>> +    OwnedMemMgr =
>> std::make_unique<LLVMJITLinkRemoteMemoryManager>(*this);
>> +    MemMgr = OwnedMemMgr.get();
>> +  }
>> +
>> +  std::unique_ptr<LLVMJITLinkChannel> Channel;
>> +  std::unique_ptr<LLVMJITLinkRPCEndpoint> Endpoint;
>> +  std::unique_ptr<TargetProcessControl::MemoryAccess> OwnedMemAccess;
>> +  std::unique_ptr<jitlink::JITLinkMemoryManager> OwnedMemMgr;
>> +  std::atomic<bool> Finished{false};
>> +  std::thread ListenerThread;
>> +};
>> +
>>  struct Session {
>> -  orc::ExecutionSession ES;
>>    std::unique_ptr<orc::TargetProcessControl> TPC;
>> +  orc::ExecutionSession ES;
>>    orc::JITDylib *MainJD;
>>    LLVMJITLinkObjectLinkingLayer ObjLayer;
>>    std::vector<orc::JITDylib *> JDSearchOrder;
>> @@ -93,7 +158,7 @@ struct Session {
>>    DenseMap<StringRef, StringRef> CanonicalWeakDefs;
>>
>>  private:
>> -  Session(Triple TT, uint64_t PageSize, Error &Err);
>> +  Session(std::unique_ptr<orc::TargetProcessControl> TPC, Error &Err);
>>  };
>>
>>  /// Record symbols, GOT entries, stubs, and sections for ELF file.
>>
>> diff  --git a/llvm/unittests/ExecutionEngine/JITLink/CMakeLists.txt
>> b/llvm/unittests/ExecutionEngine/JITLink/CMakeLists.txt
>> index 28eb128ac55d..58aacfc25bf3 100644
>> --- a/llvm/unittests/ExecutionEngine/JITLink/CMakeLists.txt
>> +++ b/llvm/unittests/ExecutionEngine/JITLink/CMakeLists.txt
>> @@ -2,6 +2,8 @@ set(LLVM_LINK_COMPONENTS
>>    ${LLVM_TARGETS_TO_BUILD}
>>    JITLink
>>    Object
>> +  OrcShared
>> +  OrcTargetProcess
>>    RuntimeDyld
>>    Support
>>    )
>>
>> diff  --git a/llvm/unittests/ExecutionEngine/Orc/CMakeLists.txt
>> b/llvm/unittests/ExecutionEngine/Orc/CMakeLists.txt
>> index b382e4c4d731..48d6888fad11 100644
>> --- a/llvm/unittests/ExecutionEngine/Orc/CMakeLists.txt
>> +++ b/llvm/unittests/ExecutionEngine/Orc/CMakeLists.txt
>> @@ -3,8 +3,8 @@ set(LLVM_LINK_COMPONENTS
>>    Core
>>    ExecutionEngine
>>    Object
>> -  OrcError
>>    OrcJIT
>> +  OrcShared
>>    Passes
>>    RuntimeDyld
>>    Support
>>
>>
>>
>> _______________________________________________
>> llvm-commits mailing list
>> llvm-commits at lists.llvm.org
>> https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-commits
>>
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/llvm-commits/attachments/20201114/e094d4be/attachment-0001.html>


More information about the llvm-commits mailing list