[llvm] [orc-rt] Connect ogre to a controller via a ConnectionSpec (PR #225400)

Lang Hames via llvm-commits llvm-commits at lists.llvm.org
Tue Sep 22 06:48:04 PDT 2026


https://github.com/lhames created https://github.com/llvm/llvm-project/pull/225400

ogre now takes a connection spec as its one positional argument, builds a Session with the bootstrap services registered, registers the "socket:adopt" connector, connects, and runs until the controller disconnects. Arguments after "--" are reserved for the program to run and are not consumed yet.

init.test becomes "ogre --help", since ogre now needs a spec to do anything and has nothing to connect to under lit yet.

>From cfe3e50ab9a980fc59f6aeb3e98f338230ece1bd Mon Sep 17 00:00:00 2001
From: Lang Hames <lhames at gmail.com>
Date: Tue, 22 Sep 2026 18:12:29 +1000
Subject: [PATCH] [orc-rt] Connect ogre to a controller via a ConnectionSpec

ogre now takes a connection spec as its one positional argument, builds
a Session with the bootstrap services registered, registers the
"socket:adopt" connector, connects, and runs until the controller
disconnects. Arguments after "--" are reserved for the program to run
and are not consumed yet.

init.test becomes "ogre --help", since ogre now needs a spec to do
anything and has nothing to connect to under lit yet.
---
 orc-rt/test/regression/init.test |   2 +-
 orc-rt/tools/ogre/ogre.cpp       | 151 +++++++++++++++++++++++++++----
 2 files changed, 134 insertions(+), 19 deletions(-)

diff --git a/orc-rt/test/regression/init.test b/orc-rt/test/regression/init.test
index 4bd17014ca979..15c934d27e698 100644
--- a/orc-rt/test/regression/init.test
+++ b/orc-rt/test/regression/init.test
@@ -1 +1 @@
-RUN: ogre %s %s
+RUN: ogre --help
diff --git a/orc-rt/tools/ogre/ogre.cpp b/orc-rt/tools/ogre/ogre.cpp
index bf5ccb0d79033..1fbef3087e79c 100644
--- a/orc-rt/tools/ogre/ogre.cpp
+++ b/orc-rt/tools/ogre/ogre.cpp
@@ -12,17 +12,30 @@
 //===----------------------------------------------------------------------===//
 
 #include "orc-rt-internal/tools/OptionParser.h"
+#include "orc-rt/bedrock/ConnectionSpec.h"
+#include "orc-rt/bedrock/ConnectorRegistry.h"
+#include "orc-rt/bedrock/NativeDylibManager.h"
+#include "orc-rt/bedrock/Session.h"
+#include "orc-rt/bedrock/SimpleNativeMemoryMap.h"
+#include "orc-rt/bedrock/SocketConnector.h"
+#include "orc-rt/bedrock/ThreadPoolRunner.h"
+#include "orc-rt/bedrock/sps/AllSPSCI.h"
 
-#include <optional>
-#include <stdio.h>
+#include <cstdio>
+#include <cstring>
+#include <future>
+#include <variant>
 
 using namespace orc_rt;
 
 struct Options {
+  ConnectionSpec ConnSpec;
   bool Verbose = false;
 };
 
-static std::optional<Options> parseArgs(int argc, char *argv[]) noexcept {
+/// Parse and handle options. Return the parsed options struct on success, or an
+/// int error code to return from main otherwise.
+static std::variant<Options, int> parseArgs(int argc, char *argv[]) noexcept {
   Options O;
   bool ShowHelp = false;
 
@@ -30,31 +43,133 @@ static std::optional<Options> parseArgs(int argc, char *argv[]) noexcept {
   P.addFlag("verbose", "Print verbose output", false, O.Verbose, 'v')
       .addFlag("help", "Display this help message", false, ShowHelp, 'h');
 
-  auto PrintHelp = [&]() -> std::nullopt_t {
+  auto PrintHelp = [&](Error Err) -> int {
+    bool Failed = !!Err;
+    if (Err)
+      fprintf(stderr, "error: %s\n", toString(std::move(Err)).c_str());
     const char *ProgName = argc != 0 ? argv[0] : "ogre";
-    fprintf(stderr, "%s usage:\n%s\n", ProgName,
-            P.formatHelp(ProgName).c_str());
-    return std::nullopt;
+    fprintf(stderr, "%s", P.formatHelp(ProgName).c_str());
+    return Failed;
   };
 
-  if (auto Err = P.parseAsMainArgs(argc, argv)) {
-    fprintf(stderr, "error: %s\n", toString(std::move(Err)).c_str());
-    return PrintHelp();
-  }
+  // ogre options end at the first '--', or at argc if no '--' is present.
+  int OgreOptsEnd;
+  for (OgreOptsEnd = 0; OgreOptsEnd != argc; ++OgreOptsEnd)
+    if (strcmp(argv[OgreOptsEnd], "--") == 0)
+      break;
+
+  if (auto Err = P.parseAsMainArgs(OgreOptsEnd, argv))
+    return PrintHelp(std::move(Err));
 
   if (ShowHelp)
-    return PrintHelp();
+    return PrintHelp(Error::success());
+
+  if (P.positionals().size() != 1)
+    return PrintHelp(
+        make_error<StringError>("expected one positional argument"));
+
+  if (auto ConnSpec = ConnectionSpec::parse(P.positionals().front()))
+    O.ConnSpec = std::move(*ConnSpec);
+  else
+    return PrintHelp(ConnSpec.takeError());
 
   return O;
 }
 
-int main(int argc, char *argv[]) {
-  auto Opts = parseArgs(argc, argv);
-  if (!Opts)
-    return 1;
+void reportError(Error Err) noexcept {
+  fprintf(stderr, "reported error: %s\n", toString(std::move(Err)).c_str());
+}
+
+void printExecutorProcessInfo(const ExecutorProcessInfo &EPI) noexcept {
+  fprintf(stderr,
+          "executor info: triple = \"%s\", page-size = %zu, "
+          "cpu-features = \"%s\"\n",
+          EPI.targetTriple().c_str(), EPI.pageSize(),
+          EPI.targetCPUFeatures().c_str());
+}
+
+Error setupSession(Session &S, const Options &Opts,
+                   BootstrapInfo &BI) noexcept {
+  if (auto Err = sps_ci::addAll(BI.symbols()))
+    return Err;
+
+  if (auto Err = S.tryCreateService<SimpleNativeMemoryMap>(S, BI.symbols())
+                     .takeError())
+    return Err;
+
+  if (auto Err =
+          S.tryCreateService<NativeDylibManager>(S, BI.symbols()).takeError())
+    return Err;
+
+  return Error::success();
+}
+
+Error trySetupAndConnect(Session &S, const Options &Opts) noexcept {
+  ConnectorRegistry ConnRegistry;
+  if (auto Err = registerSocketConnector(ConnRegistry))
+    return Err;
+  // registerTCPConnect(ConnRegistry);
+
+  auto BI = BootstrapInfo::CreateDefault(S);
+  if (!BI)
+    return BI.takeError();
 
-  if (Opts->Verbose)
-    printf("*unintelligible grunts*\n");
+  if (auto Err = setupSession(S, Opts, *BI))
+    return Err;
+
+  return ConnRegistry.connect(
+      [&]() noexcept -> Expected<ConnectorRegistry::AttachInfo> {
+        return ConnectorRegistry::AttachInfo{S, std::move(*BI)};
+      },
+      Opts.ConnSpec);
+}
+
+Expected<int> runOgre(const Options &Opts) noexcept {
+  // Get the process info.
+  auto EPI = ExecutorProcessInfo::Detect();
+  if (!EPI)
+    return EPI.takeError();
+  if (Opts.Verbose)
+    printExecutorProcessInfo(*EPI);
+
+  // Build the session.
+  ThreadPoolRunner Run(4);
+  Session S(
+      std::move(*EPI), [&Run](Session::Task T) { Run(std::move(T)); },
+      reportError);
+
+  std::promise<void> StopP;
+  auto StopF = StopP.get_future();
+  S.setOnDisconnect([StopP = std::move(StopP)](Error Err) mutable {
+    if (Err)
+      reportError(std::move(Err));
+    StopP.set_value();
+  });
+
+  if (auto Err = trySetupAndConnect(S, Opts))
+    return Err;
+
+  StopF.get();
 
   return 0;
 }
+
+int main(int argc, char *argv[]) {
+  auto OptsOrResult = parseArgs(argc, argv);
+
+  // If parseArgs returned an int then we should just exit with that return
+  // code.
+  if (int *Result = std::get_if<int>(&OptsOrResult))
+    return *Result;
+
+  if (auto *Opts = std::get_if<Options>(&OptsOrResult)) {
+    if (auto Result = runOgre(*Opts))
+      return *Result;
+    else {
+      fprintf(stderr, "error: %s\n", toString(Result.takeError()).c_str());
+      return 1;
+    }
+  }
+
+  ORC_RT_UNREACHABLE("OptsOrResult held unexpected type?");
+}



More information about the llvm-commits mailing list