Author: Vassil Vassilev
Date: 2026-01-18T18:27:48+01:00
New Revision: f006cd76790e0d7cf34b8c1dbd6be7baf4842158

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

LOG: [clang-repl] Skip out-of-process execution due to compiler-rt path 
mismatch (#176198)

On some setups (Solaris), clang-repl attempts to enable out-of-process
execution,
but fails to locate the ORC runtime due to a mismatch between the
toolchain’s
expected compiler-rt path and the actual on-disk layout.

Specifically, ToolChain::getCompilerRT() relies on
getArchNameForCompilerRTLib(),
which returns an architecture name that does not match the Solaris
compiler-rt
directory naming. As a result, the ORC runtime (orc_rt) is not detected
at the
correct path, even though it exists under
lib/clang/<version>/lib/sunos/.

As an initial workaround, special-case Solaris in
getArchNameForCompilerRTLib() to return "sunos", aligning the expected
path with
the system layout and preventing clang-repl from attempting
out-of-process
execution on Solaris.

Note that compiler-rt libraries on Solaris are suffixed with -<arch>
(e.g.
liborc_rt-x86_64.a) to support multilib configurations, which is not yet
fully
handled by the current lookup logic. A more complete solution will
require
revisiting compiler-rt path resolution for Solaris.

The discussion is available here:
https://github.com/llvm/llvm-project/pull/175322

Added: 
    

Modified: 
    clang/lib/Interpreter/IncrementalExecutor.cpp
    clang/unittests/Interpreter/OutOfProcessInterpreterTests.cpp

Removed: 
    


################################################################################
diff  --git a/clang/lib/Interpreter/IncrementalExecutor.cpp 
b/clang/lib/Interpreter/IncrementalExecutor.cpp
index 71a54dc7d3809..246b844183411 100644
--- a/clang/lib/Interpreter/IncrementalExecutor.cpp
+++ b/clang/lib/Interpreter/IncrementalExecutor.cpp
@@ -501,15 +501,15 @@ llvm::Error 
IncrementalExecutorBuilder::UpdateOrcRuntimePath(
   std::string Joined;
   for (size_t i = 0; i < triedPaths.size(); ++i) {
     if (i > 0)
-      Joined += "\n  "; // Use newlines for better readability
+      Joined += "\n  ";
     Joined += triedPaths[i];
   }
 
   return llvm::make_error<llvm::StringError>(
-      llvm::formatv("OrcRuntime library not found. Checked:\n  {0}",
+      llvm::formatv("OrcRuntime library not found. Checked:  {0}",
                     Joined.empty() ? "<none>" : Joined)
           .str(),
-      llvm::inconvertibleErrorCode());
+      std::make_error_code(std::errc::no_such_file_or_directory));
 }
 
 } // end namespace clang

diff  --git a/clang/unittests/Interpreter/OutOfProcessInterpreterTests.cpp 
b/clang/unittests/Interpreter/OutOfProcessInterpreterTests.cpp
index 36dd678d4647c..3684e7e8148fa 100644
--- a/clang/unittests/Interpreter/OutOfProcessInterpreterTests.cpp
+++ b/clang/unittests/Interpreter/OutOfProcessInterpreterTests.cpp
@@ -104,84 +104,117 @@ static std::string getExecutorPath() {
   return ExecutorPath.str().str();
 }
 
-class OutOfProcessInterpreterTest : public InterpreterTestBase {
-protected:
-  static bool HostSupportsOutOfProcessJIT() {
-    if (!InterpreterTestBase::HostSupportsJIT())
-      return false;
-    return !getExecutorPath().empty();
-  }
-};
-
 struct OutOfProcessInterpreterInfo {
   std::string OrcRuntimePath;
   std::unique_ptr<Interpreter> Interp;
 };
 
-static OutOfProcessInterpreterInfo
+static llvm::Expected<OutOfProcessInterpreterInfo>
 createInterpreterWithRemoteExecution(std::shared_ptr<IOContext> io_ctx,
                                      const Args &ExtraArgs = {}) {
   Args ClangArgs = {"-Xclang", "-emit-llvm-only"};
   llvm::append_range(ClangArgs, ExtraArgs);
 
   auto Config = std::make_unique<IncrementalExecutorBuilder>();
-  llvm::Triple SystemTriple(llvm::sys::getProcessTriple());
-
-  if (SystemTriple.isOSBinFormatELF() || SystemTriple.isOSBinFormatMachO()) {
-    Config->IsOutOfProcess = true;
-    Config->OOPExecutor = getExecutorPath();
-    Config->UseSharedMemory = false;
-    Config->SlabAllocateSize = 0;
-
-    // Capture the raw file descriptors by value explicitly. This lambda will
-    // be invoked in the child process after fork(), so capturing the fd ints 
is
-    // safe and avoids capturing FILE* pointers or outer 'this'.
-    int stdin_fd = fileno(io_ctx->stdin_file.get());
-    int stdout_fd = fileno(io_ctx->stdout_file.get());
-    int stderr_fd = fileno(io_ctx->stderr_file.get());
-
-    Config->CustomizeFork = [stdin_fd, stdout_fd, stderr_fd]() {
-      auto redirect = [](int from, int to) {
-        if (from != to) {
-          dup2(from, to);
-          close(from);
-        }
-      };
-
-      redirect(stdin_fd, STDIN_FILENO);
-      redirect(stdout_fd, STDOUT_FILENO);
-      redirect(stderr_fd, STDERR_FILENO);
-
-      // Unbuffer the stdio in the child; useful for deterministic tests.
-      setvbuf(stdout, nullptr, _IONBF, 0);
-      setvbuf(stderr, nullptr, _IONBF, 0);
-
-      // Helpful marker for the unit-test to assert that fork customization 
ran.
-      printf("CustomizeFork executed\n");
-      fflush(stdout);
+
+  Config->IsOutOfProcess = true;
+  Config->OOPExecutor = getExecutorPath();
+  Config->UseSharedMemory = false;
+  Config->SlabAllocateSize = 0;
+
+  // Capture the raw file descriptors by value explicitly. This lambda will
+  // be invoked in the child process after fork(), so capturing the fd ints is
+  // safe and avoids capturing FILE* pointers or outer 'this'.
+  int stdin_fd = fileno(io_ctx->stdin_file.get());
+  int stdout_fd = fileno(io_ctx->stdout_file.get());
+  int stderr_fd = fileno(io_ctx->stderr_file.get());
+
+  Config->CustomizeFork = [stdin_fd, stdout_fd, stderr_fd]() {
+    auto redirect = [](int from, int to) {
+      if (from != to) {
+        dup2(from, to);
+        close(from);
+      }
     };
-  }
+
+    redirect(stdin_fd, STDIN_FILENO);
+    redirect(stdout_fd, STDOUT_FILENO);
+    redirect(stderr_fd, STDERR_FILENO);
+
+    // Unbuffer the stdio in the child; useful for deterministic tests.
+    setvbuf(stdout, nullptr, _IONBF, 0);
+    setvbuf(stderr, nullptr, _IONBF, 0);
+
+    // Helpful marker for the unit-test to assert that fork customization ran.
+    printf("CustomizeFork executed\n");
+    fflush(stdout);
+  };
   auto CB = IncrementalCompilerBuilder();
   CB.SetCompilerArgs(ClangArgs);
   CB.SetDriverCompilationCallback(Config->UpdateOrcRuntimePathCB);
-  auto CI = cantFail(CB.CreateCpp());
-  return {Config->OrcRuntimePath,
-          cantFail(Interpreter::create(std::move(CI), std::move(Config)))};
+
+  auto CIOrErr = CB.CreateCpp();
+  if (!CIOrErr)
+    return CIOrErr.takeError();
+
+  OutOfProcessInterpreterInfo Info;
+  Info.OrcRuntimePath = Config->OrcRuntimePath;
+
+  auto InterpOrErr =
+      Interpreter::create(std::move(*CIOrErr), std::move(Config));
+  if (!InterpOrErr)
+    return InterpOrErr.takeError();
+
+  Info.Interp = std::move(*InterpOrErr);
+  return Info;
 }
 
+class OutOfProcessInterpreterTest : public InterpreterTestBase {
+protected:
+  static bool HostSupportsOutOfProcessJIT() {
+    if (!InterpreterTestBase::HostSupportsJIT())
+      return false;
+
+    llvm::Triple SystemTriple(llvm::sys::getProcessTriple());
+    if (!SystemTriple.isOSBinFormatELF() && !SystemTriple.isOSBinFormatMachO())
+      return false;
+
+    return !getExecutorPath().empty();
+  }
+
+  static void SetUpTestSuite() {
+    if (!HostSupportsOutOfProcessJIT())
+      GTEST_SKIP() << "Host does not support out-of-process JIT";
+
+    auto io_ctx = std::make_shared<IOContext>();
+    if (!io_ctx->initializeTempFiles())
+      GTEST_SKIP() << "Cannot initialize temporary files";
+
+    auto ErrOrI = createInterpreterWithRemoteExecution(io_ctx);
+    if (!ErrOrI) {
+      consumeError(llvm::handleErrors(
+          ErrOrI.takeError(), [](const llvm::StringError &SE) {
+            // check for your specific error code
+            if (SE.convertToErrorCode() ==
+                std::errc::no_such_file_or_directory) {
+              // skip the test
+              GTEST_SKIP() << "File not found: " << SE.getMessage();
+            }
+          }));
+    }
+  }
+};
+
 static size_t DeclsSize(TranslationUnitDecl *PTUDecl) {
   return std::distance(PTUDecl->decls().begin(), PTUDecl->decls().end());
 }
 
 TEST_F(OutOfProcessInterpreterTest, SanityWithRemoteExecution) {
-  if (!HostSupportsOutOfProcessJIT())
-    GTEST_SKIP();
-
   auto io_ctx = std::make_shared<IOContext>();
   ASSERT_TRUE(io_ctx->initializeTempFiles());
 
   OutOfProcessInterpreterInfo Info =
-      createInterpreterWithRemoteExecution(io_ctx);
+      cantFail(createInterpreterWithRemoteExecution(io_ctx));
   Interpreter *Interp = Info.Interp.get();
   ASSERT_TRUE(Interp);
 
@@ -199,14 +232,12 @@ TEST_F(OutOfProcessInterpreterTest, 
SanityWithRemoteExecution) {
 }
 
 TEST_F(OutOfProcessInterpreterTest, FindRuntimeInterface) {
-  if (!HostSupportsOutOfProcessJIT())
-    GTEST_SKIP();
-
   // make a fresh io context for this test
   auto io_ctx = std::make_shared<IOContext>();
   ASSERT_TRUE(io_ctx->initializeTempFiles());
 
-  OutOfProcessInterpreterInfo I = createInterpreterWithRemoteExecution(io_ctx);
+  OutOfProcessInterpreterInfo I =
+      cantFail(createInterpreterWithRemoteExecution(io_ctx));
   ASSERT_TRUE(I.Interp);
 
   // FIXME: Not yet supported.


        
_______________________________________________
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to