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