Author: Abhinav Kumar
Date: 2025-09-07T18:35:29+03:00
New Revision: 645dd324d1b7d028745c2a4045b69e745df2ae6a

URL: 
https://github.com/llvm/llvm-project/commit/645dd324d1b7d028745c2a4045b69e745df2ae6a
DIFF: 
https://github.com/llvm/llvm-project/commit/645dd324d1b7d028745c2a4045b69e745df2ae6a.diff

LOG: [clang-repl] Sink RemoteJITUtils into Interpreter class. NFC (#155140)

This is a refactoring PR. It sinks RemoteJITUtils into Interpreter and 
IncrementalExecutor classes.

---------

Co-authored-by: kr-2003 <kumar.kr.abhi...@gmail.com>

Added: 
    

Modified: 
    clang/include/clang/Interpreter/Interpreter.h
    clang/lib/Interpreter/CMakeLists.txt
    clang/lib/Interpreter/IncrementalExecutor.cpp
    clang/lib/Interpreter/IncrementalExecutor.h
    clang/lib/Interpreter/Interpreter.cpp
    clang/tools/clang-repl/ClangRepl.cpp

Removed: 
    clang/include/clang/Interpreter/RemoteJITUtils.h
    clang/lib/Interpreter/RemoteJITUtils.cpp


################################################################################
diff  --git a/clang/include/clang/Interpreter/Interpreter.h 
b/clang/include/clang/Interpreter/Interpreter.h
index 8c124aadf1005..61af7bf762d5e 100644
--- a/clang/include/clang/Interpreter/Interpreter.h
+++ b/clang/include/clang/Interpreter/Interpreter.h
@@ -23,6 +23,7 @@
 #include "llvm/ExecutionEngine/Orc/ExecutorProcessControl.h"
 #include "llvm/ExecutionEngine/Orc/Shared/ExecutorAddress.h"
 #include "llvm/Support/Error.h"
+#include <cstdint>
 #include <memory>
 #include <vector>
 
@@ -36,6 +37,10 @@ class ThreadSafeContext;
 
 namespace clang {
 
+namespace driver {
+class ToolChain;
+} // namespace driver
+
 class CompilerInstance;
 class CXXRecordDecl;
 class Decl;
@@ -115,15 +120,38 @@ class Interpreter {
   /// An optional compiler instance for CUDA offloading
   std::unique_ptr<CompilerInstance> DeviceCI;
 
+public:
+  struct JITConfig {
+    /// Indicates whether out-of-process JIT execution is enabled.
+    bool IsOutOfProcess = false;
+    /// Path to the out-of-process JIT executor.
+    std::string OOPExecutor = "";
+    std::string OOPExecutorConnect = "";
+    /// Indicates whether to use shared memory for communication.
+    bool UseSharedMemory = false;
+    /// Representing the slab allocation size for memory management in kb.
+    unsigned SlabAllocateSize = 0;
+    /// Path to the ORC runtime library.
+    std::string OrcRuntimePath = "";
+    /// PID of the out-of-process JIT executor.
+    uint32_t ExecutorPID = 0;
+
+    JITConfig()
+        : IsOutOfProcess(false), OOPExecutor(""), OOPExecutorConnect(""),
+          UseSharedMemory(false), SlabAllocateSize(0), OrcRuntimePath(""),
+          ExecutorPID(0) {}
+  };
+
 protected:
   // Derived classes can use an extended interface of the Interpreter.
   Interpreter(std::unique_ptr<CompilerInstance> Instance, llvm::Error &Err,
               std::unique_ptr<llvm::orc::LLJITBuilder> JITBuilder = nullptr,
-              std::unique_ptr<clang::ASTConsumer> Consumer = nullptr);
+              std::unique_ptr<clang::ASTConsumer> Consumer = nullptr,
+              JITConfig Config = JITConfig());
 
   // Create the internal IncrementalExecutor, or re-create it after calling
   // ResetExecutor().
-  llvm::Error CreateExecutor();
+  llvm::Error CreateExecutor(JITConfig Config = JITConfig());
 
   // Delete the internal IncrementalExecutor. This causes a hard shutdown of 
the
   // JIT engine. In particular, it doesn't run cleanup or destructors.
@@ -132,14 +160,19 @@ class Interpreter {
 public:
   virtual ~Interpreter();
   static llvm::Expected<std::unique_ptr<Interpreter>>
-  create(std::unique_ptr<CompilerInstance> CI,
-         std::unique_ptr<llvm::orc::LLJITBuilder> JITBuilder = nullptr);
+  create(std::unique_ptr<CompilerInstance> CI, JITConfig Config = {});
   static llvm::Expected<std::unique_ptr<Interpreter>>
   createWithCUDA(std::unique_ptr<CompilerInstance> CI,
                  std::unique_ptr<CompilerInstance> DCI);
   static llvm::Expected<std::unique_ptr<llvm::orc::LLJITBuilder>>
   createLLJITBuilder(std::unique_ptr<llvm::orc::ExecutorProcessControl> EPC,
                      llvm::StringRef OrcRuntimePath);
+  static llvm::Expected<
+      std::pair<std::unique_ptr<llvm::orc::LLJITBuilder>, uint32_t>>
+  outOfProcessJITBuilder(JITConfig Config);
+  static llvm::Expected<std::string>
+  getOrcRuntimePath(const driver::ToolChain &TC);
+
   const ASTContext &getASTContext() const;
   ASTContext &getASTContext();
   const CompilerInstance *getCompilerInstance() const;
@@ -170,6 +203,8 @@ class Interpreter {
   llvm::Expected<llvm::orc::ExecutorAddr>
   getSymbolAddressFromLinkerName(llvm::StringRef LinkerName) const;
 
+  uint32_t getOutOfProcessExecutorPID() const;
+
 private:
   size_t getEffectivePTUSize() const;
   void markUserCodeStart();

diff  --git a/clang/include/clang/Interpreter/RemoteJITUtils.h 
b/clang/include/clang/Interpreter/RemoteJITUtils.h
deleted file mode 100644
index 8705a3b1f669d..0000000000000
--- a/clang/include/clang/Interpreter/RemoteJITUtils.h
+++ /dev/null
@@ -1,38 +0,0 @@
-//===-- RemoteJITUtils.h - Utilities for remote-JITing ----------*- C++ 
-*-===//
-//
-// Part of the LLVM Project, under the Apache License v2.0 with LLVM 
Exceptions.
-// See https://llvm.org/LICENSE.txt for license information.
-// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
-//
-//===----------------------------------------------------------------------===//
-//
-// Utilities for ExecutorProcessControl-based remote JITing with Orc and
-// JITLink.
-//
-//===----------------------------------------------------------------------===//
-
-#ifndef LLVM_CLANG_INTERPRETER_REMOTEJITUTILS_H
-#define LLVM_CLANG_INTERPRETER_REMOTEJITUTILS_H
-
-#include "llvm/ADT/StringRef.h"
-#include "llvm/ExecutionEngine/Orc/Core.h"
-#include "llvm/ExecutionEngine/Orc/Layer.h"
-#include "llvm/ExecutionEngine/Orc/SimpleRemoteEPC.h"
-#include "llvm/Support/Error.h"
-
-#include <cstdint>
-#include <memory>
-#include <string>
-
-llvm::Expected<std::unique_ptr<llvm::orc::SimpleRemoteEPC>>
-launchExecutor(llvm::StringRef ExecutablePath, bool UseSharedMemory,
-               llvm::StringRef SlabAllocateSizeString);
-
-/// Create a JITLinkExecutor that connects to the given network address
-/// through a TCP socket. A valid NetworkAddress provides hostname and port,
-/// e.g. localhost:20000.
-llvm::Expected<std::unique_ptr<llvm::orc::SimpleRemoteEPC>>
-connectTCPSocket(llvm::StringRef NetworkAddress, bool UseSharedMemory,
-                 llvm::StringRef SlabAllocateSizeString);
-
-#endif // LLVM_CLANG_INTERPRETER_REMOTEJITUTILS_H

diff  --git a/clang/lib/Interpreter/CMakeLists.txt 
b/clang/lib/Interpreter/CMakeLists.txt
index d8dda45644668..37faa0302caaa 100644
--- a/clang/lib/Interpreter/CMakeLists.txt
+++ b/clang/lib/Interpreter/CMakeLists.txt
@@ -28,7 +28,6 @@ add_clang_library(clangInterpreter
   Interpreter.cpp
   InterpreterValuePrinter.cpp
   InterpreterUtils.cpp
-  RemoteJITUtils.cpp
   Value.cpp
   InterpreterValuePrinter.cpp
   ${WASM_SRC}

diff  --git a/clang/lib/Interpreter/IncrementalExecutor.cpp 
b/clang/lib/Interpreter/IncrementalExecutor.cpp
index 4d2adecaafce7..b0eb7d0e9f072 100644
--- a/clang/lib/Interpreter/IncrementalExecutor.cpp
+++ b/clang/lib/Interpreter/IncrementalExecutor.cpp
@@ -15,19 +15,36 @@
 #include "clang/Basic/TargetInfo.h"
 #include "clang/Basic/TargetOptions.h"
 #include "clang/Interpreter/PartialTranslationUnit.h"
+#include "llvm/ADT/StringExtras.h"
 #include "llvm/ExecutionEngine/ExecutionEngine.h"
 #include "llvm/ExecutionEngine/Orc/CompileUtils.h"
+#include "llvm/ExecutionEngine/Orc/DebugObjectManagerPlugin.h"
 #include "llvm/ExecutionEngine/Orc/Debugging/DebuggerSupport.h"
+#include "llvm/ExecutionEngine/Orc/EPCDebugObjectRegistrar.h"
+#include "llvm/ExecutionEngine/Orc/EPCDynamicLibrarySearchGenerator.h"
 #include "llvm/ExecutionEngine/Orc/ExecutionUtils.h"
 #include "llvm/ExecutionEngine/Orc/IRCompileLayer.h"
 #include "llvm/ExecutionEngine/Orc/JITTargetMachineBuilder.h"
 #include "llvm/ExecutionEngine/Orc/LLJIT.h"
+#include "llvm/ExecutionEngine/Orc/MapperJITLinkMemoryManager.h"
 #include "llvm/ExecutionEngine/Orc/RTDyldObjectLinkingLayer.h"
+#include "llvm/ExecutionEngine/Orc/Shared/OrcRTBridge.h"
+#include "llvm/ExecutionEngine/Orc/Shared/SimpleRemoteEPCUtils.h"
 #include "llvm/ExecutionEngine/Orc/TargetProcess/JITLoaderGDB.h"
 #include "llvm/ExecutionEngine/SectionMemoryManager.h"
 #include "llvm/IR/Module.h"
+#include "llvm/Support/FileSystem.h"
 #include "llvm/Support/ManagedStatic.h"
+#include "llvm/Support/Path.h"
 #include "llvm/Support/TargetSelect.h"
+#include "llvm/TargetParser/Host.h"
+
+#ifdef LLVM_ON_UNIX
+#include <netdb.h>
+#include <netinet/in.h>
+#include <sys/socket.h>
+#include <unistd.h>
+#endif // LLVM_ON_UNIX
 
 // Force linking some of the runtimes that helps attaching to a debugger.
 LLVM_ATTRIBUTE_USED void linkComponents() {
@@ -55,8 +72,9 @@ IncrementalExecutor::createDefaultJITBuilder(
 
 IncrementalExecutor::IncrementalExecutor(llvm::orc::ThreadSafeContext &TSC,
                                          llvm::orc::LLJITBuilder &JITBuilder,
+                                         Interpreter::JITConfig Config,
                                          llvm::Error &Err)
-    : TSCtx(TSC) {
+    : TSCtx(TSC), OutOfProcessChildPid(Config.ExecutorPID) {
   using namespace llvm::orc;
   llvm::ErrorAsOutParameter EAO(&Err);
 
@@ -118,4 +136,225 @@ IncrementalExecutor::getSymbolAddress(llvm::StringRef 
Name,
   return SymOrErr->getAddress();
 }
 
+Expected<std::unique_ptr<llvm::jitlink::JITLinkMemoryManager>>
+createSharedMemoryManager(llvm::orc::SimpleRemoteEPC &SREPC,
+                          unsigned SlabAllocateSize) {
+  llvm::orc::SharedMemoryMapper::SymbolAddrs SAs;
+  if (auto Err = SREPC.getBootstrapSymbols(
+          {{SAs.Instance,
+            llvm::orc::rt::ExecutorSharedMemoryMapperServiceInstanceName},
+           {SAs.Reserve,
+            
llvm::orc::rt::ExecutorSharedMemoryMapperServiceReserveWrapperName},
+           {SAs.Initialize,
+            llvm::orc::rt::
+                ExecutorSharedMemoryMapperServiceInitializeWrapperName},
+           {SAs.Deinitialize,
+            llvm::orc::rt::
+                ExecutorSharedMemoryMapperServiceDeinitializeWrapperName},
+           {SAs.Release,
+            llvm::orc::rt::
+                ExecutorSharedMemoryMapperServiceReleaseWrapperName}}))
+    return std::move(Err);
+
+  size_t SlabSize;
+  if (llvm::Triple(llvm::sys::getProcessTriple()).isOSWindows())
+    SlabSize = 1024 * 1024;
+  else
+    SlabSize = 1024 * 1024 * 1024;
+
+  if (SlabAllocateSize > 0)
+    SlabSize = SlabAllocateSize;
+
+  return llvm::orc::MapperJITLinkMemoryManager::CreateWithMapper<
+      llvm::orc::SharedMemoryMapper>(SlabSize, SREPC, SAs);
+}
+
+llvm::Expected<std::pair<std::unique_ptr<llvm::orc::SimpleRemoteEPC>, 
uint32_t>>
+IncrementalExecutor::launchExecutor(llvm::StringRef ExecutablePath,
+                                    bool UseSharedMemory,
+                                    unsigned SlabAllocateSize) {
+#ifndef LLVM_ON_UNIX
+  // FIXME: Add support for Windows.
+  return llvm::make_error<llvm::StringError>(
+      "-" + ExecutablePath + " not supported on non-unix platforms",
+      llvm::inconvertibleErrorCode());
+#elif !LLVM_ENABLE_THREADS
+  // Out of process mode using SimpleRemoteEPC depends on threads.
+  return llvm::make_error<llvm::StringError>(
+      "-" + ExecutablePath +
+          " requires threads, but LLVM was built with "
+          "LLVM_ENABLE_THREADS=Off",
+      llvm::inconvertibleErrorCode());
+#else
+
+  if (!llvm::sys::fs::can_execute(ExecutablePath))
+    return llvm::make_error<llvm::StringError>(
+        llvm::formatv("Specified executor invalid: {0}", ExecutablePath),
+        llvm::inconvertibleErrorCode());
+
+  constexpr int ReadEnd = 0;
+  constexpr int WriteEnd = 1;
+
+  // Pipe FDs.
+  int ToExecutor[2];
+  int FromExecutor[2];
+
+  uint32_t ChildPID;
+
+  // Create pipes to/from the executor..
+  if (pipe(ToExecutor) != 0 || pipe(FromExecutor) != 0)
+    return llvm::make_error<llvm::StringError>(
+        "Unable to create pipe for executor", llvm::inconvertibleErrorCode());
+
+  ChildPID = fork();
+
+  if (ChildPID == 0) {
+    // In the child...
+
+    // Close the parent ends of the pipes
+    close(ToExecutor[WriteEnd]);
+    close(FromExecutor[ReadEnd]);
+
+    // Execute the child process.
+    std::unique_ptr<char[]> ExecutorPath, FDSpecifier;
+    {
+      ExecutorPath = std::make_unique<char[]>(ExecutablePath.size() + 1);
+      strcpy(ExecutorPath.get(), ExecutablePath.data());
+
+      std::string FDSpecifierStr("filedescs=");
+      FDSpecifierStr += llvm::utostr(ToExecutor[ReadEnd]);
+      FDSpecifierStr += ',';
+      FDSpecifierStr += llvm::utostr(FromExecutor[WriteEnd]);
+      FDSpecifier = std::make_unique<char[]>(FDSpecifierStr.size() + 1);
+      strcpy(FDSpecifier.get(), FDSpecifierStr.c_str());
+    }
+
+    char *const Args[] = {ExecutorPath.get(), FDSpecifier.get(), nullptr};
+    int RC = execvp(ExecutorPath.get(), Args);
+    if (RC != 0) {
+      llvm::errs() << "unable to launch out-of-process executor \""
+                   << ExecutorPath.get() << "\"\n";
+      exit(1);
+    }
+  }
+  // else we're the parent...
+
+  // Close the child ends of the pipes
+  close(ToExecutor[ReadEnd]);
+  close(FromExecutor[WriteEnd]);
+
+  llvm::orc::SimpleRemoteEPC::Setup S = llvm::orc::SimpleRemoteEPC::Setup();
+  if (UseSharedMemory)
+    S.CreateMemoryManager =
+        [SlabAllocateSize](llvm::orc::SimpleRemoteEPC &EPC) {
+          return createSharedMemoryManager(EPC, SlabAllocateSize);
+        };
+
+  auto EPCOrErr =
+      
llvm::orc::SimpleRemoteEPC::Create<llvm::orc::FDSimpleRemoteEPCTransport>(
+          std::make_unique<llvm::orc::DynamicThreadPoolTaskDispatcher>(
+              std::nullopt),
+          std::move(S), FromExecutor[ReadEnd], ToExecutor[WriteEnd]);
+  if (!EPCOrErr)
+    return EPCOrErr.takeError();
+  return std::make_pair(std::move(*EPCOrErr), ChildPID);
+#endif
+}
+
+#if LLVM_ON_UNIX && LLVM_ENABLE_THREADS
+
+static Expected<int> connectTCPSocketImpl(std::string Host,
+                                          std::string PortStr) {
+  addrinfo *AI;
+  addrinfo Hints{};
+  Hints.ai_family = AF_INET;
+  Hints.ai_socktype = SOCK_STREAM;
+  Hints.ai_flags = AI_NUMERICSERV;
+
+  if (int EC = getaddrinfo(Host.c_str(), PortStr.c_str(), &Hints, &AI))
+    return llvm::make_error<llvm::StringError>(
+        llvm::formatv("address resolution failed ({0})", strerror(EC)),
+        llvm::inconvertibleErrorCode());
+  // Cycle through the returned addrinfo structures and connect to the first
+  // reachable endpoint.
+  int SockFD;
+  addrinfo *Server;
+  for (Server = AI; Server != nullptr; Server = Server->ai_next) {
+    // socket might fail, e.g. if the address family is not supported. Skip to
+    // the next addrinfo structure in such a case.
+    if ((SockFD = socket(AI->ai_family, AI->ai_socktype, AI->ai_protocol)) < 0)
+      continue;
+
+    // If connect returns null, we exit the loop with a working socket.
+    if (connect(SockFD, Server->ai_addr, Server->ai_addrlen) == 0)
+      break;
+
+    close(SockFD);
+  }
+  freeaddrinfo(AI);
+
+  // If we reached the end of the loop without connecting to a valid endpoint,
+  // dump the last error that was logged in socket() or connect().
+  if (Server == nullptr)
+    return llvm::make_error<llvm::StringError>("invalid hostname",
+                                               llvm::inconvertibleErrorCode());
+
+  return SockFD;
+}
+
+llvm::Expected<std::unique_ptr<llvm::orc::SimpleRemoteEPC>>
+IncrementalExecutor::connectTCPSocket(llvm::StringRef NetworkAddress,
+                                      bool UseSharedMemory,
+                                      unsigned SlabAllocateSize) {
+#ifndef LLVM_ON_UNIX
+  // FIXME: Add TCP support for Windows.
+  return llvm::make_error<llvm::StringError>(
+      "-" + NetworkAddress + " not supported on non-unix platforms",
+      llvm::inconvertibleErrorCode());
+#elif !LLVM_ENABLE_THREADS
+  // Out of process mode using SimpleRemoteEPC depends on threads.
+  return llvm::make_error<llvm::StringError>(
+      "-" + NetworkAddress +
+          " requires threads, but LLVM was built with "
+          "LLVM_ENABLE_THREADS=Off",
+      llvm::inconvertibleErrorCode());
+#else
+
+  auto CreateErr = [NetworkAddress](Twine Details) {
+    return llvm::make_error<llvm::StringError>(
+        formatv("Failed to connect TCP socket '{0}': {1}", NetworkAddress,
+                Details),
+        llvm::inconvertibleErrorCode());
+  };
+
+  StringRef Host, PortStr;
+  std::tie(Host, PortStr) = NetworkAddress.split(':');
+  if (Host.empty())
+    return CreateErr("Host name for -" + NetworkAddress + " can not be empty");
+  if (PortStr.empty())
+    return CreateErr("Port number in -" + NetworkAddress + " can not be 
empty");
+  int Port = 0;
+  if (PortStr.getAsInteger(10, Port))
+    return CreateErr("Port number '" + PortStr + "' is not a valid integer");
+
+  Expected<int> SockFD = connectTCPSocketImpl(Host.str(), PortStr.str());
+  if (!SockFD)
+    return SockFD.takeError();
+
+  llvm::orc::SimpleRemoteEPC::Setup S = llvm::orc::SimpleRemoteEPC::Setup();
+  if (UseSharedMemory)
+    S.CreateMemoryManager =
+        [SlabAllocateSize](llvm::orc::SimpleRemoteEPC &EPC) {
+          return createSharedMemoryManager(EPC, SlabAllocateSize);
+        };
+
+  return llvm::orc::SimpleRemoteEPC::Create<
+      llvm::orc::FDSimpleRemoteEPCTransport>(
+      std::make_unique<llvm::orc::DynamicThreadPoolTaskDispatcher>(
+          std::nullopt),
+      std::move(S), *SockFD, *SockFD);
+#endif
+}
+#endif // _WIN32
+
 } // namespace clang

diff  --git a/clang/lib/Interpreter/IncrementalExecutor.h 
b/clang/lib/Interpreter/IncrementalExecutor.h
index 71d71bc3883e2..d091535166770 100644
--- a/clang/lib/Interpreter/IncrementalExecutor.h
+++ b/clang/lib/Interpreter/IncrementalExecutor.h
@@ -13,12 +13,19 @@
 #ifndef LLVM_CLANG_LIB_INTERPRETER_INCREMENTALEXECUTOR_H
 #define LLVM_CLANG_LIB_INTERPRETER_INCREMENTALEXECUTOR_H
 
+#include "clang/Interpreter/Interpreter.h"
 #include "llvm/ADT/DenseMap.h"
 #include "llvm/ADT/StringRef.h"
+#include "llvm/ExecutionEngine/Orc/Core.h"
 #include "llvm/ExecutionEngine/Orc/ExecutionUtils.h"
+#include "llvm/ExecutionEngine/Orc/Layer.h"
 #include "llvm/ExecutionEngine/Orc/Shared/ExecutorAddress.h"
+#include "llvm/ExecutionEngine/Orc/SimpleRemoteEPC.h"
+#include "llvm/Support/Error.h"
 
+#include <cstdint>
 #include <memory>
+#include <string>
 
 namespace llvm {
 class Error;
@@ -39,6 +46,7 @@ class IncrementalExecutor {
   using CtorDtorIterator = llvm::orc::CtorDtorIterator;
   std::unique_ptr<llvm::orc::LLJIT> Jit;
   llvm::orc::ThreadSafeContext &TSCtx;
+  uint32_t OutOfProcessChildPid = -1;
 
   llvm::DenseMap<const PartialTranslationUnit *, llvm::orc::ResourceTrackerSP>
       ResourceTrackers;
@@ -50,7 +58,8 @@ class IncrementalExecutor {
   enum SymbolNameKind { IRName, LinkerName };
 
   IncrementalExecutor(llvm::orc::ThreadSafeContext &TSC,
-                      llvm::orc::LLJITBuilder &JITBuilder, llvm::Error &Err);
+                      llvm::orc::LLJITBuilder &JITBuilder,
+                      Interpreter::JITConfig Config, llvm::Error &Err);
   virtual ~IncrementalExecutor();
 
   virtual llvm::Error addModule(PartialTranslationUnit &PTU);
@@ -62,8 +71,21 @@ class IncrementalExecutor {
 
   llvm::orc::LLJIT &GetExecutionEngine() { return *Jit; }
 
+  uint32_t getOutOfProcessChildPid() const { return OutOfProcessChildPid; }
+
   static llvm::Expected<std::unique_ptr<llvm::orc::LLJITBuilder>>
   createDefaultJITBuilder(llvm::orc::JITTargetMachineBuilder JTMB);
+
+  static llvm::Expected<
+      std::pair<std::unique_ptr<llvm::orc::SimpleRemoteEPC>, uint32_t>>
+  launchExecutor(llvm::StringRef ExecutablePath, bool UseSharedMemory,
+                 unsigned SlabAllocateSize);
+
+#if LLVM_ON_UNIX && LLVM_ENABLE_THREADS
+  static llvm::Expected<std::unique_ptr<llvm::orc::SimpleRemoteEPC>>
+  connectTCPSocket(llvm::StringRef NetworkAddress, bool UseSharedMemory,
+                   unsigned SlabAllocateSize);
+#endif
 };
 
 } // end namespace clang

diff  --git a/clang/lib/Interpreter/Interpreter.cpp 
b/clang/lib/Interpreter/Interpreter.cpp
index 47995216fac46..043e0c1e5754e 100644
--- a/clang/lib/Interpreter/Interpreter.cpp
+++ b/clang/lib/Interpreter/Interpreter.cpp
@@ -251,7 +251,8 @@ IncrementalCompilerBuilder::CreateCudaHost() {
 Interpreter::Interpreter(std::unique_ptr<CompilerInstance> Instance,
                          llvm::Error &ErrOut,
                          std::unique_ptr<llvm::orc::LLJITBuilder> JITBuilder,
-                         std::unique_ptr<clang::ASTConsumer> Consumer)
+                         std::unique_ptr<clang::ASTConsumer> Consumer,
+                         JITConfig Config)
     : JITBuilder(std::move(JITBuilder)) {
   CI = std::move(Instance);
   llvm::ErrorAsOutParameter EAO(&ErrOut);
@@ -285,7 +286,7 @@ Interpreter::Interpreter(std::unique_ptr<CompilerInstance> 
Instance,
       ASTContext &C = CI->getASTContext();
       IncrParser->RegisterPTU(C.getTranslationUnitDecl(), std::move(M));
     }
-    if (llvm::Error Err = CreateExecutor()) {
+    if (llvm::Error Err = CreateExecutor(Config)) {
       ErrOut = joinErrors(std::move(ErrOut), std::move(Err));
       return;
     }
@@ -347,20 +348,116 @@ const char *const Runtimes = R"(
   EXTERN_C void __clang_Interpreter_SetValueNoAlloc(void *This, void *OutVal, 
void *OpaqueType, ...);
 )";
 
+llvm::Expected<std::pair<std::unique_ptr<llvm::orc::LLJITBuilder>, uint32_t>>
+Interpreter::outOfProcessJITBuilder(JITConfig Config) {
+  std::unique_ptr<llvm::orc::ExecutorProcessControl> EPC;
+  uint32_t childPid = -1;
+  if (!Config.OOPExecutor.empty()) {
+    // Launch an out-of-process executor locally in a child process.
+    auto ResultOrErr = IncrementalExecutor::launchExecutor(
+        Config.OOPExecutor, Config.UseSharedMemory, Config.SlabAllocateSize);
+    if (!ResultOrErr)
+      return ResultOrErr.takeError();
+    childPid = ResultOrErr->second;
+    auto EPCOrErr = std::move(ResultOrErr->first);
+    EPC = std::move(EPCOrErr);
+  } else if (Config.OOPExecutorConnect != "") {
+#if LLVM_ON_UNIX && LLVM_ENABLE_THREADS
+    auto EPCOrErr = IncrementalExecutor::connectTCPSocket(
+        Config.OOPExecutorConnect, Config.UseSharedMemory,
+        Config.SlabAllocateSize);
+    if (!EPCOrErr)
+      return EPCOrErr.takeError();
+    EPC = std::move(*EPCOrErr);
+#else
+    return llvm::make_error<llvm::StringError>(
+        "Out-of-process JIT over TCP is not supported on this platform",
+        std::error_code());
+#endif
+  }
+
+  std::unique_ptr<llvm::orc::LLJITBuilder> JB;
+  if (EPC) {
+    auto JBOrErr = clang::Interpreter::createLLJITBuilder(
+        std::move(EPC), Config.OrcRuntimePath);
+    if (!JBOrErr)
+      return JBOrErr.takeError();
+    JB = std::move(*JBOrErr);
+  }
+
+  return std::make_pair(std::move(JB), childPid);
+}
+
+llvm::Expected<std::string>
+Interpreter::getOrcRuntimePath(const driver::ToolChain &TC) {
+  std::optional<std::string> CompilerRTPath = TC.getCompilerRTPath();
+  std::optional<std::string> ResourceDir = TC.getRuntimePath();
+
+  if (!CompilerRTPath) {
+    return llvm::make_error<llvm::StringError>("CompilerRT path not found",
+                                               std::error_code());
+  }
+
+  const std::array<const char *, 3> OrcRTLibNames = {
+      "liborc_rt.a", "liborc_rt_osx.a", "liborc_rt-x86_64.a"};
+
+  for (const char *LibName : OrcRTLibNames) {
+    llvm::SmallString<256> CandidatePath((*CompilerRTPath).c_str());
+    llvm::sys::path::append(CandidatePath, LibName);
+
+    if (llvm::sys::fs::exists(CandidatePath)) {
+      return CandidatePath.str().str();
+    }
+  }
+
+  return llvm::make_error<llvm::StringError>(
+      llvm::Twine("OrcRuntime library not found in: ") + (*CompilerRTPath),
+      std::error_code());
+}
+
 llvm::Expected<std::unique_ptr<Interpreter>>
-Interpreter::create(std::unique_ptr<CompilerInstance> CI,
-                    std::unique_ptr<llvm::orc::LLJITBuilder> JB) {
+Interpreter::create(std::unique_ptr<CompilerInstance> CI, JITConfig Config) {
   llvm::Error Err = llvm::Error::success();
-  auto Interp = std::unique_ptr<Interpreter>(
-      new Interpreter(std::move(CI), Err, JB ? std::move(JB) : nullptr));
-  if (Err)
-    return std::move(Err);
+
+  std::unique_ptr<llvm::orc::LLJITBuilder> JB;
+
+  if (Config.IsOutOfProcess) {
+    const TargetInfo &TI = CI->getTarget();
+    const llvm::Triple &Triple = TI.getTriple();
+
+    DiagnosticsEngine &Diags = CI->getDiagnostics();
+    std::string BinaryName = llvm::sys::fs::getMainExecutable(nullptr, 
nullptr);
+    driver::Driver Driver(BinaryName, Triple.str(), Diags);
+    // Need fake args to get the driver to create a compilation.
+    std::vector<const char *> Args = {"clang", "--version"};
+    std::unique_ptr<clang::driver::Compilation> C(
+        Driver.BuildCompilation(Args));
+    if (!C) {
+      return llvm::make_error<llvm::StringError>(
+          "Failed to create driver compilation for out-of-process JIT",
+          std::error_code());
+    }
+    if (Config.OrcRuntimePath == "") {
+      const clang::driver::ToolChain &TC = C->getDefaultToolChain();
+
+      auto OrcRuntimePathOrErr = getOrcRuntimePath(TC);
+      if (!OrcRuntimePathOrErr) {
+        return OrcRuntimePathOrErr.takeError();
+      }
+
+      Config.OrcRuntimePath = *OrcRuntimePathOrErr;
+    }
+  }
+
+  auto Interp = std::unique_ptr<Interpreter>(new Interpreter(
+      std::move(CI), Err, std::move(JB), /*Consumer=*/nullptr, Config));
+  if (auto E = std::move(Err))
+    return std::move(E);
 
   // Add runtime code and set a marker to hide it from user code. Undo will not
   // go through that.
-  Err = Interp->ParseAndExecute(Runtimes);
-  if (Err)
-    return std::move(Err);
+  if (auto E = Interp->ParseAndExecute(Runtimes))
+    return std::move(E);
 
   Interp->markUserCodeStart();
 
@@ -444,6 +541,12 @@ size_t Interpreter::getEffectivePTUSize() const {
   return PTUs.size() - InitPTUSize;
 }
 
+uint32_t Interpreter::getOutOfProcessExecutorPID() const {
+  if (IncrExecutor)
+    return IncrExecutor->getOutOfProcessChildPid();
+  return -1;
+}
+
 llvm::Expected<PartialTranslationUnit &>
 Interpreter::Parse(llvm::StringRef Code) {
   // If we have a device parser, parse it first. The generated code will be
@@ -512,7 +615,7 @@ Interpreter::createLLJITBuilder(
   return std::move(*JB);
 }
 
-llvm::Error Interpreter::CreateExecutor() {
+llvm::Error Interpreter::CreateExecutor(JITConfig Config) {
   if (IncrExecutor)
     return llvm::make_error<llvm::StringError>("Operation failed. "
                                                "Execution engine exists",
@@ -521,8 +624,26 @@ llvm::Error Interpreter::CreateExecutor() {
     return llvm::make_error<llvm::StringError>("Operation failed. "
                                                "No code generator available",
                                                std::error_code());
+
+  const std::string &TT = getCompilerInstance()->getTargetOpts().Triple;
+  llvm::Triple TargetTriple(TT);
+  bool IsWindowsTarget = TargetTriple.isOSWindows();
+
+  if (!IsWindowsTarget && Config.IsOutOfProcess) {
+    if (!JITBuilder) {
+      auto ResOrErr = outOfProcessJITBuilder(Config);
+      if (!ResOrErr)
+        return ResOrErr.takeError();
+      JITBuilder = std::move(ResOrErr->first);
+      Config.ExecutorPID = ResOrErr->second;
+    }
+    if (!JITBuilder)
+      return llvm::make_error<llvm::StringError>(
+          "Operation failed. No LLJITBuilder for out-of-process JIT",
+          std::error_code());
+  }
+
   if (!JITBuilder) {
-    const std::string &TT = getCompilerInstance()->getTargetOpts().Triple;
     auto JTMB = createJITTargetMachineBuilder(TT);
     if (!JTMB)
       return JTMB.takeError();
@@ -533,11 +654,15 @@ llvm::Error Interpreter::CreateExecutor() {
   }
 
   llvm::Error Err = llvm::Error::success();
+
+  // Fix: Declare Executor as the appropriate unique_ptr type
+  std::unique_ptr<IncrementalExecutor> Executor;
+
 #ifdef __EMSCRIPTEN__
-  auto Executor = std::make_unique<WasmIncrementalExecutor>(*TSCtx);
+  Executor = std::make_unique<WasmIncrementalExecutor>(*TSCtx);
 #else
-  auto Executor =
-      std::make_unique<IncrementalExecutor>(*TSCtx, *JITBuilder, Err);
+  Executor =
+      std::make_unique<IncrementalExecutor>(*TSCtx, *JITBuilder, Config, Err);
 #endif
   if (!Err)
     IncrExecutor = std::move(Executor);

diff  --git a/clang/lib/Interpreter/RemoteJITUtils.cpp 
b/clang/lib/Interpreter/RemoteJITUtils.cpp
deleted file mode 100644
index c0e663b764785..0000000000000
--- a/clang/lib/Interpreter/RemoteJITUtils.cpp
+++ /dev/null
@@ -1,267 +0,0 @@
-//===-- RemoteJITUtils.cpp - Utilities for remote-JITing --------*- C++ 
-*-===//
-//
-// Part of the LLVM Project, under the Apache License v2.0 with LLVM 
Exceptions.
-// See https://llvm.org/LICENSE.txt for license information.
-// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
-//
-//===----------------------------------------------------------------------===//
-//
-// FIXME: Unify this code with similar functionality in llvm-jitlink.
-//
-//===----------------------------------------------------------------------===//
-
-#include "clang/Interpreter/RemoteJITUtils.h"
-
-#include "llvm/ADT/StringExtras.h"
-#include "llvm/ExecutionEngine/Orc/DebugObjectManagerPlugin.h"
-#include "llvm/ExecutionEngine/Orc/EPCDebugObjectRegistrar.h"
-#include "llvm/ExecutionEngine/Orc/EPCDynamicLibrarySearchGenerator.h"
-#include "llvm/ExecutionEngine/Orc/MapperJITLinkMemoryManager.h"
-#include "llvm/ExecutionEngine/Orc/Shared/OrcRTBridge.h"
-#include "llvm/ExecutionEngine/Orc/Shared/SimpleRemoteEPCUtils.h"
-#include "llvm/ExecutionEngine/Orc/TargetProcess/JITLoaderGDB.h"
-#include "llvm/Support/FileSystem.h"
-#include "llvm/Support/Path.h"
-
-#ifdef LLVM_ON_UNIX
-#include <netdb.h>
-#include <netinet/in.h>
-#include <sys/socket.h>
-#include <unistd.h>
-#endif // LLVM_ON_UNIX
-
-using namespace llvm;
-using namespace llvm::orc;
-
-Expected<uint64_t> getSlabAllocSize(StringRef SizeString) {
-  SizeString = SizeString.trim();
-
-  uint64_t Units = 1024;
-
-  if (SizeString.ends_with_insensitive("kb"))
-    SizeString = SizeString.drop_back(2).rtrim();
-  else if (SizeString.ends_with_insensitive("mb")) {
-    Units = 1024 * 1024;
-    SizeString = SizeString.drop_back(2).rtrim();
-  } else if (SizeString.ends_with_insensitive("gb")) {
-    Units = 1024 * 1024 * 1024;
-    SizeString = SizeString.drop_back(2).rtrim();
-  }
-
-  uint64_t SlabSize = 0;
-  if (SizeString.getAsInteger(10, SlabSize))
-    return make_error<StringError>("Invalid numeric format for slab size",
-                                   inconvertibleErrorCode());
-
-  return SlabSize * Units;
-}
-
-Expected<std::unique_ptr<jitlink::JITLinkMemoryManager>>
-createSharedMemoryManager(SimpleRemoteEPC &SREPC,
-                          StringRef SlabAllocateSizeString) {
-  SharedMemoryMapper::SymbolAddrs SAs;
-  if (auto Err = SREPC.getBootstrapSymbols(
-          {{SAs.Instance, rt::ExecutorSharedMemoryMapperServiceInstanceName},
-           {SAs.Reserve,
-            rt::ExecutorSharedMemoryMapperServiceReserveWrapperName},
-           {SAs.Initialize,
-            rt::ExecutorSharedMemoryMapperServiceInitializeWrapperName},
-           {SAs.Deinitialize,
-            rt::ExecutorSharedMemoryMapperServiceDeinitializeWrapperName},
-           {SAs.Release,
-            rt::ExecutorSharedMemoryMapperServiceReleaseWrapperName}}))
-    return std::move(Err);
-
-#ifdef _WIN32
-  size_t SlabSize = 1024 * 1024;
-#else
-  size_t SlabSize = 1024 * 1024 * 1024;
-#endif
-
-  if (!SlabAllocateSizeString.empty()) {
-    if (Expected<uint64_t> S = getSlabAllocSize(SlabAllocateSizeString))
-      SlabSize = *S;
-    else
-      return S.takeError();
-  }
-
-  return MapperJITLinkMemoryManager::CreateWithMapper<SharedMemoryMapper>(
-      SlabSize, SREPC, SAs);
-}
-
-Expected<std::unique_ptr<SimpleRemoteEPC>>
-launchExecutor(StringRef ExecutablePath, bool UseSharedMemory,
-               llvm::StringRef SlabAllocateSizeString) {
-#ifndef LLVM_ON_UNIX
-  // FIXME: Add support for Windows.
-  return make_error<StringError>("-" + ExecutablePath +
-                                     " not supported on non-unix platforms",
-                                 inconvertibleErrorCode());
-#elif !LLVM_ENABLE_THREADS
-  // Out of process mode using SimpleRemoteEPC depends on threads.
-  return make_error<StringError>(
-      "-" + ExecutablePath +
-          " requires threads, but LLVM was built with "
-          "LLVM_ENABLE_THREADS=Off",
-      inconvertibleErrorCode());
-#else
-
-  if (!sys::fs::can_execute(ExecutablePath))
-    return make_error<StringError>(
-        formatv("Specified executor invalid: {0}", ExecutablePath),
-        inconvertibleErrorCode());
-
-  constexpr int ReadEnd = 0;
-  constexpr int WriteEnd = 1;
-
-  // Pipe FDs.
-  int ToExecutor[2];
-  int FromExecutor[2];
-
-  pid_t ChildPID;
-
-  // Create pipes to/from the executor..
-  if (pipe(ToExecutor) != 0 || pipe(FromExecutor) != 0)
-    return make_error<StringError>("Unable to create pipe for executor",
-                                   inconvertibleErrorCode());
-
-  ChildPID = fork();
-
-  if (ChildPID == 0) {
-    // In the child...
-
-    // Close the parent ends of the pipes
-    close(ToExecutor[WriteEnd]);
-    close(FromExecutor[ReadEnd]);
-
-    // Execute the child process.
-    std::unique_ptr<char[]> ExecutorPath, FDSpecifier;
-    {
-      ExecutorPath = std::make_unique<char[]>(ExecutablePath.size() + 1);
-      strcpy(ExecutorPath.get(), ExecutablePath.data());
-
-      std::string FDSpecifierStr("filedescs=");
-      FDSpecifierStr += utostr(ToExecutor[ReadEnd]);
-      FDSpecifierStr += ',';
-      FDSpecifierStr += utostr(FromExecutor[WriteEnd]);
-      FDSpecifier = std::make_unique<char[]>(FDSpecifierStr.size() + 1);
-      strcpy(FDSpecifier.get(), FDSpecifierStr.c_str());
-    }
-
-    char *const Args[] = {ExecutorPath.get(), FDSpecifier.get(), nullptr};
-    int RC = execvp(ExecutorPath.get(), Args);
-    if (RC != 0) {
-      errs() << "unable to launch out-of-process executor \""
-             << ExecutorPath.get() << "\"\n";
-      exit(1);
-    }
-  }
-  // else we're the parent...
-
-  // Close the child ends of the pipes
-  close(ToExecutor[ReadEnd]);
-  close(FromExecutor[WriteEnd]);
-
-  SimpleRemoteEPC::Setup S = SimpleRemoteEPC::Setup();
-  if (UseSharedMemory)
-    S.CreateMemoryManager = [SlabAllocateSizeString](SimpleRemoteEPC &EPC) {
-      return createSharedMemoryManager(EPC, SlabAllocateSizeString);
-    };
-
-  return SimpleRemoteEPC::Create<FDSimpleRemoteEPCTransport>(
-      std::make_unique<DynamicThreadPoolTaskDispatcher>(std::nullopt),
-      std::move(S), FromExecutor[ReadEnd], ToExecutor[WriteEnd]);
-#endif
-}
-
-#if LLVM_ON_UNIX && LLVM_ENABLE_THREADS
-
-static Expected<int> connectTCPSocketImpl(std::string Host,
-                                          std::string PortStr) {
-  addrinfo *AI;
-  addrinfo Hints{};
-  Hints.ai_family = AF_INET;
-  Hints.ai_socktype = SOCK_STREAM;
-  Hints.ai_flags = AI_NUMERICSERV;
-
-  if (int EC = getaddrinfo(Host.c_str(), PortStr.c_str(), &Hints, &AI))
-    return make_error<StringError>(
-        formatv("address resolution failed ({0})", gai_strerror(EC)),
-        inconvertibleErrorCode());
-  // Cycle through the returned addrinfo structures and connect to the first
-  // reachable endpoint.
-  int SockFD;
-  addrinfo *Server;
-  for (Server = AI; Server != nullptr; Server = Server->ai_next) {
-    // socket might fail, e.g. if the address family is not supported. Skip to
-    // the next addrinfo structure in such a case.
-    if ((SockFD = socket(AI->ai_family, AI->ai_socktype, AI->ai_protocol)) < 0)
-      continue;
-
-    // If connect returns null, we exit the loop with a working socket.
-    if (connect(SockFD, Server->ai_addr, Server->ai_addrlen) == 0)
-      break;
-
-    close(SockFD);
-  }
-  freeaddrinfo(AI);
-
-  // If we reached the end of the loop without connecting to a valid endpoint,
-  // dump the last error that was logged in socket() or connect().
-  if (Server == nullptr)
-    return make_error<StringError>("invalid hostname",
-                                   inconvertibleErrorCode());
-
-  return SockFD;
-}
-#endif
-
-Expected<std::unique_ptr<SimpleRemoteEPC>>
-connectTCPSocket(StringRef NetworkAddress, bool UseSharedMemory,
-                 llvm::StringRef SlabAllocateSizeString) {
-#ifndef LLVM_ON_UNIX
-  // FIXME: Add TCP support for Windows.
-  return make_error<StringError>("-" + NetworkAddress +
-                                     " not supported on non-unix platforms",
-                                 inconvertibleErrorCode());
-#elif !LLVM_ENABLE_THREADS
-  // Out of process mode using SimpleRemoteEPC depends on threads.
-  return make_error<StringError>(
-      "-" + NetworkAddress +
-          " requires threads, but LLVM was built with "
-          "LLVM_ENABLE_THREADS=Off",
-      inconvertibleErrorCode());
-#else
-
-  auto CreateErr = [NetworkAddress](Twine Details) {
-    return make_error<StringError>(
-        formatv("Failed to connect TCP socket '{0}': {1}", NetworkAddress,
-                Details),
-        inconvertibleErrorCode());
-  };
-
-  StringRef Host, PortStr;
-  std::tie(Host, PortStr) = NetworkAddress.split(':');
-  if (Host.empty())
-    return CreateErr("Host name for -" + NetworkAddress + " can not be empty");
-  if (PortStr.empty())
-    return CreateErr("Port number in -" + NetworkAddress + " can not be 
empty");
-  int Port = 0;
-  if (PortStr.getAsInteger(10, Port))
-    return CreateErr("Port number '" + PortStr + "' is not a valid integer");
-
-  Expected<int> SockFD = connectTCPSocketImpl(Host.str(), PortStr.str());
-  if (!SockFD)
-    return SockFD.takeError();
-
-  SimpleRemoteEPC::Setup S = SimpleRemoteEPC::Setup();
-  if (UseSharedMemory)
-    S.CreateMemoryManager = [SlabAllocateSizeString](SimpleRemoteEPC &EPC) {
-      return createSharedMemoryManager(EPC, SlabAllocateSizeString);
-    };
-
-  return SimpleRemoteEPC::Create<FDSimpleRemoteEPCTransport>(
-      std::make_unique<DynamicThreadPoolTaskDispatcher>(std::nullopt),
-      std::move(S), *SockFD, *SockFD);
-#endif
-}

diff  --git a/clang/tools/clang-repl/ClangRepl.cpp 
b/clang/tools/clang-repl/ClangRepl.cpp
index b666959c33b73..1d508816d7047 100644
--- a/clang/tools/clang-repl/ClangRepl.cpp
+++ b/clang/tools/clang-repl/ClangRepl.cpp
@@ -10,8 +10,6 @@
 //
 
//===----------------------------------------------------------------------===//
 
-#include "clang/Interpreter/RemoteJITUtils.h"
-
 #include "clang/Basic/Diagnostic.h"
 #include "clang/Basic/Version.h"
 #include "clang/Config/config.h"
@@ -22,16 +20,25 @@
 #include "clang/Lex/Preprocessor.h"
 #include "clang/Sema/Sema.h"
 
+#include "llvm/ADT/SmallString.h"
+#include "llvm/ADT/StringRef.h"
 #include "llvm/ExecutionEngine/Orc/LLJIT.h"
 #include "llvm/LineEditor/LineEditor.h"
 #include "llvm/Support/CommandLine.h"
+#include "llvm/Support/FileSystem.h"
 #include "llvm/Support/ManagedStatic.h" // llvm_shutdown
+#include "llvm/Support/Path.h"
 #include "llvm/Support/Signals.h"
 #include "llvm/Support/TargetSelect.h"
+#include "llvm/Support/VirtualFileSystem.h"
 #include "llvm/Support/raw_ostream.h"
 #include "llvm/TargetParser/Host.h"
+#include "llvm/TargetParser/Triple.h"
 #include <optional>
 
+#include <string>
+#include <vector>
+
 #include "llvm/ExecutionEngine/Orc/Debugging/DebuggerSupport.h"
 
 // Disable LSan for this test.
@@ -114,25 +121,8 @@ static llvm::Error sanitizeOopArguments(const char *ArgV0) 
{
           llvm::inconvertibleErrorCode());
   }
 
-  // Out-of-process executors require the ORC runtime.
-  if (OrcRuntimePath.empty() && (OOPExecutor.getNumOccurrences() ||
-                                 OOPExecutorConnect.getNumOccurrences())) {
-    llvm::SmallString<256> BasePath(llvm::sys::fs::getMainExecutable(
-        ArgV0, reinterpret_cast<void *>(&sanitizeOopArguments)));
-    llvm::sys::path::remove_filename(BasePath); // Remove clang-repl filename.
-    llvm::sys::path::remove_filename(BasePath); // Remove ./bin directory.
-    llvm::sys::path::append(BasePath, CLANG_INSTALL_LIBDIR_BASENAME, "clang",
-                            CLANG_VERSION_MAJOR_STRING);
-    if (SystemTriple.isOSBinFormatELF())
-      OrcRuntimePath =
-          BasePath.str().str() + "/lib/x86_64-unknown-linux-gnu/liborc_rt.a";
-    else if (SystemTriple.isOSBinFormatMachO())
-      OrcRuntimePath = BasePath.str().str() + "/lib/darwin/liborc_rt_osx.a";
-    else
-      return llvm::make_error<llvm::StringError>(
-          "Out-of-process execution is not supported on non-unix platforms",
-          llvm::inconvertibleErrorCode());
-  }
+  // Out-of-process executors require the ORC runtime. ORC Runtime Path
+  // resolution is done in Interpreter.cpp.
 
   // If -oop-executor was used but no value was specified then use a sensible
   // default.
@@ -147,6 +137,30 @@ static llvm::Error sanitizeOopArguments(const char *ArgV0) 
{
   return llvm::Error::success();
 }
 
+static llvm::Expected<unsigned> getSlabAllocSize(llvm::StringRef SizeString) {
+  SizeString = SizeString.trim();
+
+  uint64_t Units = 1024;
+
+  if (SizeString.ends_with_insensitive("kb"))
+    SizeString = SizeString.drop_back(2).rtrim();
+  else if (SizeString.ends_with_insensitive("mb")) {
+    Units = 1024 * 1024;
+    SizeString = SizeString.drop_back(2).rtrim();
+  } else if (SizeString.ends_with_insensitive("gb")) {
+    Units = 1024 * 1024 * 1024;
+    SizeString = SizeString.drop_back(2).rtrim();
+  } else if (SizeString.empty())
+    return 0;
+
+  uint64_t SlabSize = 0;
+  if (SizeString.getAsInteger(10, SlabSize))
+    return llvm::make_error<llvm::StringError>(
+        "Invalid numeric format for slab size", 
llvm::inconvertibleErrorCode());
+
+  return SlabSize * Units;
+}
+
 static void LLVMErrorHandler(void *UserData, const char *Message,
                              bool GenCrashDiag) {
   auto &Diags = *static_cast<clang::DiagnosticsEngine *>(UserData);
@@ -186,7 +200,7 @@ struct ReplListCompleter {
   clang::Interpreter &MainInterp;
   ReplListCompleter(clang::IncrementalCompilerBuilder &CB,
                     clang::Interpreter &Interp)
-      : CB(CB), MainInterp(Interp){};
+      : CB(CB), MainInterp(Interp) {};
 
   std::vector<llvm::LineEditor::Completion> operator()(llvm::StringRef Buffer,
                                                        size_t Pos) const;
@@ -285,22 +299,16 @@ int main(int argc, const char **argv) {
 
   ExitOnErr(sanitizeOopArguments(argv[0]));
 
-  std::unique_ptr<llvm::orc::ExecutorProcessControl> EPC;
-  if (OOPExecutor.getNumOccurrences()) {
-    // Launch an out-of-process executor locally in a child process.
-    EPC = ExitOnErr(
-        launchExecutor(OOPExecutor, UseSharedMemory, SlabAllocateSizeString));
-  } else if (OOPExecutorConnect.getNumOccurrences()) {
-    EPC = ExitOnErr(connectTCPSocket(OOPExecutorConnect, UseSharedMemory,
-                                     SlabAllocateSizeString));
-  }
-
-  std::unique_ptr<llvm::orc::LLJITBuilder> JB;
-  if (EPC) {
-    CB.SetTargetTriple(EPC->getTargetTriple().getTriple());
-    JB = ExitOnErr(
-        clang::Interpreter::createLLJITBuilder(std::move(EPC), 
OrcRuntimePath));
+  clang::Interpreter::JITConfig Config;
+  Config.IsOutOfProcess = !OOPExecutor.empty() || !OOPExecutorConnect.empty();
+  Config.OOPExecutor = OOPExecutor;
+  auto SizeOrErr = getSlabAllocSize(SlabAllocateSizeString);
+  if (!SizeOrErr) {
+    llvm::logAllUnhandledErrors(SizeOrErr.takeError(), llvm::errs(), "error: 
");
+    return EXIT_FAILURE;
   }
+  Config.SlabAllocateSize = *SizeOrErr;
+  Config.UseSharedMemory = UseSharedMemory;
 
   // FIXME: Investigate if we could use runToolOnCodeWithArgs from tooling. It
   // can replace the boilerplate code for creation of the compiler instance.
@@ -333,11 +341,9 @@ int main(int argc, const char **argv) {
       auto CudaRuntimeLibPath = CudaPath + "/lib/libcudart.so";
       ExitOnErr(Interp->LoadDynamicLibrary(CudaRuntimeLibPath.c_str()));
     }
-  } else if (JB) {
-    Interp =
-        ExitOnErr(clang::Interpreter::create(std::move(CI), std::move(JB)));
-  } else
-    Interp = ExitOnErr(clang::Interpreter::create(std::move(CI)));
+  } else {
+    Interp = ExitOnErr(clang::Interpreter::create(std::move(CI), Config));
+  }
 
   bool HasError = false;
 


        
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to