Skip to content

Conversation

kr-2003
Copy link
Contributor

@kr-2003 kr-2003 commented Aug 24, 2025

This PR builds upon the changes introduced in #152562.

Introduces:

  1. Custom lambda function in launchExecutor.
  2. Fetching PID of the launched out-of-process(OOP) JIT executor.
  3. Dynamic fetching of liborc_rt path.

Comment on lines +334 to +337
if (::OffloadArch.empty()) {
::OffloadArch = "sm_35";
}
CB.SetOffloadArch(OffloadArch);
CB.SetOffloadArch(::OffloadArch);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Are these changes relevant to the current PR?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yes. if not done, it gives following error:

error: reference to 'OffloadArch' is ambiguous

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Which compiler is this? Why it works upstream?

@vgvassilev vgvassilev requested a review from lhames August 25, 2025 12:07
Copy link

github-actions bot commented Aug 25, 2025

⚠️ C/C++ code formatter, clang-format found issues in your code. ⚠️

You can test this locally with the following command:
git-clang-format --diff origin/main HEAD --extensions h,cpp -- clang/include/clang/Interpreter/OutOfProcessJITConfig.h clang/unittests/Interpreter/OutOfProcessInterpreterTests.cpp clang/include/clang/Interpreter/Interpreter.h clang/include/clang/Interpreter/RemoteJITUtils.h clang/lib/Driver/ToolChain.cpp clang/lib/Interpreter/IncrementalExecutor.cpp clang/lib/Interpreter/IncrementalExecutor.h clang/lib/Interpreter/Interpreter.cpp clang/lib/Interpreter/RemoteJITUtils.cpp clang/tools/clang-repl/ClangRepl.cpp clang/unittests/Interpreter/InterpreterTest.cpp

⚠️
The reproduction instructions above might return results for more than one PR
in a stack if you are using a stacked PR workflow. You can limit the results by
changing origin/main to the base branch/commit you want to compare against.
⚠️

View the diff from clang-format here.
diff --git a/clang/include/clang/Interpreter/Interpreter.h b/clang/include/clang/Interpreter/Interpreter.h
index 33117c65e..afa0688e6 100644
--- a/clang/include/clang/Interpreter/Interpreter.h
+++ b/clang/include/clang/Interpreter/Interpreter.h
@@ -121,7 +121,8 @@ 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, OutOfProcessJITConfig OOPConfig = {});
+              std::unique_ptr<clang::ASTConsumer> Consumer = nullptr,
+              OutOfProcessJITConfig OOPConfig = {});
 
   // Create the internal IncrementalExecutor, or re-create it after calling
   // ResetExecutor().
@@ -142,7 +143,8 @@ public:
   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>, pid_t>>
+  static llvm::Expected<
+      std::pair<std::unique_ptr<llvm::orc::LLJITBuilder>, pid_t>>
   outOfProcessJITBuilder(OutOfProcessJITConfig OutOfProcessConfig);
   static llvm::Expected<std::string>
   getOrcRuntimePath(const driver::ToolChain &TC);
diff --git a/clang/lib/Interpreter/IncrementalExecutor.cpp b/clang/lib/Interpreter/IncrementalExecutor.cpp
index 6f77b18b5..bc1c8e684 100644
--- a/clang/lib/Interpreter/IncrementalExecutor.cpp
+++ b/clang/lib/Interpreter/IncrementalExecutor.cpp
@@ -15,29 +15,28 @@
 #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/RTDyldObjectLinkingLayer.h"
-#include "llvm/ExecutionEngine/Orc/TargetProcess/JITLoaderGDB.h"
-#include "llvm/ExecutionEngine/SectionMemoryManager.h"
-#include "llvm/IR/Module.h"
-#include "llvm/Support/ManagedStatic.h"
-#include "llvm/Support/TargetSelect.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/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"
 
 #ifdef LLVM_ON_UNIX
 #include <netdb.h>
@@ -90,8 +89,7 @@ IncrementalExecutor::IncrementalExecutor(llvm::orc::ThreadSafeContext &TSC,
 
 IncrementalExecutor::IncrementalExecutor(llvm::orc::ThreadSafeContext &TSC,
                                          llvm::orc::LLJITBuilder &JITBuilder,
-                                         llvm::Error &Err,
-                                         pid_t ChildPid)
+                                         llvm::Error &Err, pid_t ChildPid)
     : TSCtx(TSC), OutOfProcessChildPid(ChildPid) {
   using namespace llvm::orc;
   llvm::ErrorAsOutParameter EAO(&Err);
@@ -210,10 +208,9 @@ createSharedMemoryManager(SimpleRemoteEPC &SREPC,
       SlabSize, SREPC, SAs);
 }
 
-
 llvm::Expected<std::pair<std::unique_ptr<llvm::orc::SimpleRemoteEPC>, pid_t>>
 IncrementalExecutor::launchExecutor(llvm::StringRef ExecutablePath,
-                                   bool UseSharedMemory,
+                                    bool UseSharedMemory,
                                     llvm::StringRef SlabAllocateSizeString,
                                     std::function<void()> CustomizeFork) {
 #ifndef LLVM_ON_UNIX
@@ -348,7 +345,7 @@ static Expected<int> connectTCPSocketImpl(std::string Host,
 
 llvm::Expected<std::unique_ptr<SimpleRemoteEPC>>
 IncrementalExecutor::connectTCPSocket(llvm::StringRef NetworkAddress,
-                                     bool UseSharedMemory,
+                                      bool UseSharedMemory,
                                       llvm::StringRef SlabAllocateSizeString) {
 #ifndef LLVM_ON_UNIX
   // FIXME: Add TCP support for Windows.
diff --git a/clang/lib/Interpreter/Interpreter.cpp b/clang/lib/Interpreter/Interpreter.cpp
index 41ccb106c..e189284c6 100644
--- a/clang/lib/Interpreter/Interpreter.cpp
+++ b/clang/lib/Interpreter/Interpreter.cpp
@@ -253,7 +253,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, OutOfProcessJITConfig OOPConfig)
+                         std::unique_ptr<clang::ASTConsumer> Consumer,
+                         OutOfProcessJITConfig OOPConfig)
     : JITBuilder(std::move(JITBuilder)) {
   CI = std::move(Instance);
   llvm::ErrorAsOutParameter EAO(&ErrOut);
@@ -355,18 +356,20 @@ Interpreter::outOfProcessJITBuilder(OutOfProcessJITConfig OutOfProcessConfig) {
   pid_t childPid = -1;
   if (OutOfProcessConfig.OOPExecutor != "") {
     // Launch an out-of-process executor locally in a child process.
-    auto ResultOrErr = IncrementalExecutor::launchExecutor(OutOfProcessConfig.OOPExecutor,
-                                   OutOfProcessConfig.UseSharedMemory,
-                                   OutOfProcessConfig.SlabAllocateSizeString, OutOfProcessConfig.CustomizeFork);
+    auto ResultOrErr = IncrementalExecutor::launchExecutor(
+        OutOfProcessConfig.OOPExecutor, OutOfProcessConfig.UseSharedMemory,
+        OutOfProcessConfig.SlabAllocateSizeString,
+        OutOfProcessConfig.CustomizeFork);
     if (!ResultOrErr)
       return ResultOrErr.takeError();
     childPid = ResultOrErr->second;
     auto EPCOrErr = std::move(ResultOrErr->first);
     EPC = std::move(EPCOrErr);
   } else if (OutOfProcessConfig.OOPExecutorConnect != "") {
-    auto EPCOrErr = IncrementalExecutor::connectTCPSocket(OutOfProcessConfig.OOPExecutorConnect,
-                                     OutOfProcessConfig.UseSharedMemory,
-                                     OutOfProcessConfig.SlabAllocateSizeString);
+    auto EPCOrErr = IncrementalExecutor::connectTCPSocket(
+        OutOfProcessConfig.OOPExecutorConnect,
+        OutOfProcessConfig.UseSharedMemory,
+        OutOfProcessConfig.SlabAllocateSizeString);
     if (!EPCOrErr)
       return EPCOrErr.takeError();
     EPC = std::move(*EPCOrErr);
@@ -423,8 +426,7 @@ Interpreter::create(std::unique_ptr<CompilerInstance> CI,
     const llvm::Triple &Triple = TI.getTriple();
 
     DiagnosticsEngine &Diags = CI->getDiagnostics();
-    std::string BinaryName =
-        llvm::sys::fs::getMainExecutable(nullptr, nullptr);
+    std::string BinaryName = llvm::sys::fs::getMainExecutable(nullptr, nullptr);
     driver::Driver Driver(BinaryName, Triple.str(), Diags);
     std::vector<const char *> Args = {"clang", "--version"};
     std::unique_ptr<clang::driver::Compilation> C(
@@ -444,13 +446,11 @@ Interpreter::create(std::unique_ptr<CompilerInstance> CI,
 
       OutOfProcessConfig->OrcRuntimePath = *OrcRuntimePathOrErr;
     }
-
   }
 
-  auto Interp = std::unique_ptr<Interpreter>(
-      new Interpreter(std::move(CI), Err, JB ? std::move(JB) : nullptr, nullptr,
-                      OutOfProcessConfig ? *OutOfProcessConfig
-                                        : OutOfProcessJITConfig()));
+  auto Interp = std::unique_ptr<Interpreter>(new Interpreter(
+      std::move(CI), Err, JB ? std::move(JB) : nullptr, nullptr,
+      OutOfProcessConfig ? *OutOfProcessConfig : OutOfProcessJITConfig()));
   if (auto E = std::move(Err))
     return std::move(E);
 
@@ -539,7 +539,6 @@ size_t Interpreter::getEffectivePTUSize() const {
   return PTUs.size() - InitPTUSize;
 }
 
-
 PartialTranslationUnit &
 Interpreter::RegisterPTU(TranslationUnitDecl *TU,
                          std::unique_ptr<llvm::Module> M /*={}*/,
@@ -677,8 +676,8 @@ llvm::Error Interpreter::CreateExecutor(OutOfProcessJITConfig OOPConfig) {
 #ifdef __EMSCRIPTEN__
   auto Executor = std::make_unique<WasmIncrementalExecutor>(*TSCtx);
 #else
-  auto Executor =
-      std::make_unique<IncrementalExecutor>(*TSCtx, *JITBuilder, Err, OOPChildPid);
+  auto Executor = std::make_unique<IncrementalExecutor>(*TSCtx, *JITBuilder,
+                                                        Err, OOPChildPid);
 #endif
   if (!Err)
     IncrExecutor = std::move(Executor);
diff --git a/clang/tools/clang-repl/ClangRepl.cpp b/clang/tools/clang-repl/ClangRepl.cpp
index 126312fba..044a93b4b 100644
--- a/clang/tools/clang-repl/ClangRepl.cpp
+++ b/clang/tools/clang-repl/ClangRepl.cpp
@@ -279,8 +279,8 @@ int main(int argc, const char **argv) {
   ExitOnErr(sanitizeOopArguments(argv[0]));
 
   clang::OutOfProcessJITConfig OutOfProcessConfig;
-  OutOfProcessConfig.IsOutOfProcess = !OOPExecutor.empty() ||
-                                      !OOPExecutorConnect.empty();
+  OutOfProcessConfig.IsOutOfProcess =
+      !OOPExecutor.empty() || !OOPExecutorConnect.empty();
   OutOfProcessConfig.OOPExecutor = OOPExecutor;
   OutOfProcessConfig.SlabAllocateSizeString = SlabAllocateSizeString;
   OutOfProcessConfig.UseSharedMemory = UseSharedMemory;
diff --git a/clang/unittests/Interpreter/OutOfProcessInterpreterTests.cpp b/clang/unittests/Interpreter/OutOfProcessInterpreterTests.cpp
index 81f44ee59..be0e25bc0 100644
--- a/clang/unittests/Interpreter/OutOfProcessInterpreterTests.cpp
+++ b/clang/unittests/Interpreter/OutOfProcessInterpreterTests.cpp
@@ -146,8 +146,7 @@ createInterpreterWithRemoteExecution(const Args &ExtraArgs = {},
   OutOfProcessConfig.IsOutOfProcess = true;
   OutOfProcessConfig.OrcRuntimePath = getOrcRuntimePath();
 
-  std::cout << "OrcRuntimePath: " << OutOfProcessConfig.OrcRuntimePath
-            << "\n";
+  std::cout << "OrcRuntimePath: " << OutOfProcessConfig.OrcRuntimePath << "\n";
 
   std::unique_ptr<llvm::orc::LLJITBuilder> JB;
 

@@ -33,6 +33,10 @@
using namespace llvm;
using namespace llvm::orc;

#if LLVM_ON_UNIX
static std::vector<pid_t> LaunchedExecutorPID;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That should be a member of the Interpreter class I think.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This vector is updated in launchExecutor. And launchExecutor is called before creation of interpreter. I can define it as static but I don't think it is related enough to be in interpreter class.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We need a home for this. The process is not the right home. Either the Interpreter class or the IncrementalExecutor should be good options.

@kr-2003 kr-2003 requested a review from vgvassilev August 26, 2025 15:12
@kr-2003 kr-2003 requested a review from vgvassilev August 27, 2025 16:12
namespace clang {

/// \brief Configuration options for out-of-process JIT execution.
struct OutOfProcessJITConfig {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That struct can go as a nested Interpreter class.

bool UseSharedMemory;

/// String representing the slab allocation size for memory management.
std::string SlabAllocateSizeString;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This should be an unsigned int I think. All of these should have good default values.

@@ -55,6 +57,8 @@
#include "llvm/TargetParser/Host.h"
#include "llvm/Transforms/Utils/Cloning.h" // for CloneModule

#include <iostream>
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We probably do not need this include.

std::unique_ptr<llvm::orc::ExecutorProcessControl> EPC;
if (OutOfProcessConfig.OOPExecutor != "") {
// Launch an out-of-process executor locally in a child process.
EPC = ExitOnErr(launchExecutor(OutOfProcessConfig.OOPExecutor,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Remember this is the library, it must not abort the process. Instead the interface should return llvm::Expected<std::unique_ptr<llvm::orc::LLJITBuilder>> and propagate the error up.

Comment on lines 500 to 501
llvm::SmallString<256> BasePath(llvm::sys::fs::getMainExecutable(
"clang-repl", reinterpret_cast<void *>(&getOrcRuntimePath)));
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That does not work when we are in a library. Why do we need the BasePath at all? I'd think we can ask the TC and that is mostly it. Do you try to get somehow to the source directory?

@@ -33,6 +33,10 @@
using namespace llvm;
using namespace llvm::orc;

#if LLVM_ON_UNIX
static std::vector<pid_t> LaunchedExecutorPID;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We need a home for this. The process is not the right home. Either the Interpreter class or the IncrementalExecutor should be good options.

#include <optional>

#include <iostream>
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We don't need that.

Comment on lines +334 to +337
if (::OffloadArch.empty()) {
::OffloadArch = "sm_35";
}
CB.SetOffloadArch(OffloadArch);
CB.SetOffloadArch(::OffloadArch);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Which compiler is this? Why it works upstream?

} else {
Interp = ExitOnErr(
clang::Interpreter::create(std::move(CI), OutOfProcessConfig));
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nice!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants