[clang] [lld] [llvm] Reapply [Support] ToolSession for in-process tool invocation (PR #224515)

via cfe-commits cfe-commits at lists.llvm.org
Thu Sep 17 22:02:59 PDT 2026


llvmorg-github-actions[bot] wrote:


<!--LLVM PR SUMMARY COMMENT-->

@llvm/pr-subscribers-llvm-support

Author: Anutosh Bhat (anutosh491)

<details>
<summary>Changes</summary>

Hey @<!-- -->petrhosek , @<!-- -->aganea , @<!-- -->rnk 

This PR Relands #<!-- -->221996, which was approved and merged but reverted in #<!-- -->224368 after failures in the Fuchsia builders.

This PR contains two commits:

1. The original approved commit, reapplied without changes.
2. A small follow-up fixing the reported failures.

The problem was that a direct Clang invocation was incorrectly marked as needing a prepended tool name. When Clang launched cc1 out of process, we produced:

    clang clang -cc1 ...

instead of:

    clang -cc1 ...

This affected `cc-print-proc-stat.c` and the macOS runtime compiler checks.

The second commit determines whether the session executable already dispatches to the selected tool before setting `NeedsPrependArg`. It also adds regression tests for direct invocation and overlapping tool names.

Tested with the ToolSession unit tests, llvm-driver tests, the previously failing Clang test, and forced out-of-process cc1 compilation.

---

Patch is 36.39 KiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/224515.diff


37 Files Affected:

- (modified) clang/tools/clang-installapi/ClangInstallAPI.cpp (+1-1) 
- (modified) clang/tools/clang-scan-deps/ClangScanDeps.cpp (+1-1) 
- (modified) clang/tools/driver/cc1gen_reproducer_main.cpp (+1-1) 
- (modified) clang/tools/driver/driver.cpp (+1-1) 
- (modified) lld/tools/lld/lld.cpp (+1-1) 
- (modified) llvm/cmake/modules/llvm-driver-template.cpp.in (+1-1) 
- (added) llvm/include/llvm/Support/Driver.h (+96) 
- (removed) llvm/include/llvm/Support/LLVMDriver.h (-27) 
- (modified) llvm/lib/Support/CMakeLists.txt (+1) 
- (added) llvm/lib/Support/Driver.cpp (+134) 
- (added) llvm/test/tools/llvm-driver/session-dispatch.test (+9) 
- (modified) llvm/tools/dsymutil/dsymutil.cpp (+1-1) 
- (modified) llvm/tools/llvm-ar/llvm-ar.cpp (+1-1) 
- (modified) llvm/tools/llvm-cgdata/llvm-cgdata.cpp (+1-1) 
- (modified) llvm/tools/llvm-cxxfilt/llvm-cxxfilt.cpp (+1-1) 
- (modified) llvm/tools/llvm-debuginfod-find/llvm-debuginfod-find.cpp (+1-1) 
- (modified) llvm/tools/llvm-debuginfod/llvm-debuginfod.cpp (+1-1) 
- (modified) llvm/tools/llvm-driver/llvm-driver.cpp (+20-48) 
- (modified) llvm/tools/llvm-dwp/llvm-dwp.cpp (+1-1) 
- (modified) llvm/tools/llvm-gsymutil/llvm-gsymutil.cpp (+1-1) 
- (modified) llvm/tools/llvm-ifs/llvm-ifs.cpp (+1-1) 
- (modified) llvm/tools/llvm-libtool-darwin/llvm-libtool-darwin.cpp (+1-1) 
- (modified) llvm/tools/llvm-lipo/llvm-lipo.cpp (+1-1) 
- (modified) llvm/tools/llvm-ml/llvm-ml.cpp (+1-1) 
- (modified) llvm/tools/llvm-mt/llvm-mt.cpp (+1-1) 
- (modified) llvm/tools/llvm-nm/llvm-nm.cpp (+1-1) 
- (modified) llvm/tools/llvm-objcopy/llvm-objcopy.cpp (+1-1) 
- (modified) llvm/tools/llvm-objdump/llvm-objdump.cpp (+1-1) 
- (modified) llvm/tools/llvm-rc/llvm-rc.cpp (+1-1) 
- (modified) llvm/tools/llvm-readobj/llvm-readobj.cpp (+1-1) 
- (modified) llvm/tools/llvm-readtapi/llvm-readtapi.cpp (+1-1) 
- (modified) llvm/tools/llvm-size/llvm-size.cpp (+1-1) 
- (modified) llvm/tools/llvm-symbolizer/llvm-symbolizer.cpp (+1-1) 
- (modified) llvm/tools/sancov/sancov.cpp (+1-1) 
- (modified) llvm/unittests/Support/CMakeLists.txt (+1) 
- (added) llvm/unittests/Support/LLVMToolSession/CMakeLists.txt (+20) 
- (added) llvm/unittests/Support/LLVMToolSession/LLVMToolSessionTest.cpp (+162) 


``````````diff
diff --git a/clang/tools/clang-installapi/ClangInstallAPI.cpp b/clang/tools/clang-installapi/ClangInstallAPI.cpp
index baa10ff3e28129..e7251dfb2ded79 100644
--- a/clang/tools/clang-installapi/ClangInstallAPI.cpp
+++ b/clang/tools/clang-installapi/ClangInstallAPI.cpp
@@ -25,7 +25,7 @@
 #include "llvm/ADT/ArrayRef.h"
 #include "llvm/Option/Option.h"
 #include "llvm/Support/CommandLine.h"
-#include "llvm/Support/LLVMDriver.h"
+#include "llvm/Support/Driver.h"
 #include "llvm/Support/ManagedStatic.h"
 #include "llvm/Support/PrettyStackTrace.h"
 #include "llvm/Support/Process.h"
diff --git a/clang/tools/clang-scan-deps/ClangScanDeps.cpp b/clang/tools/clang-scan-deps/ClangScanDeps.cpp
index 83b4860c130c38..cb4d3f53ff1895 100644
--- a/clang/tools/clang-scan-deps/ClangScanDeps.cpp
+++ b/clang/tools/clang-scan-deps/ClangScanDeps.cpp
@@ -19,11 +19,11 @@
 #include "llvm/ADT/STLExtras.h"
 #include "llvm/ADT/Twine.h"
 #include "llvm/Support/CommandLine.h"
+#include "llvm/Support/Driver.h"
 #include "llvm/Support/FileSystem.h"
 #include "llvm/Support/FileUtilities.h"
 #include "llvm/Support/Format.h"
 #include "llvm/Support/JSON.h"
-#include "llvm/Support/LLVMDriver.h"
 #include "llvm/Support/MemoryBuffer.h"
 #include "llvm/Support/Program.h"
 #include "llvm/Support/Signals.h"
diff --git a/clang/tools/driver/cc1gen_reproducer_main.cpp b/clang/tools/driver/cc1gen_reproducer_main.cpp
index d8e4a0d470bc57..810d96363b91b2 100644
--- a/clang/tools/driver/cc1gen_reproducer_main.cpp
+++ b/clang/tools/driver/cc1gen_reproducer_main.cpp
@@ -17,9 +17,9 @@
 #include "clang/Driver/Driver.h"
 #include "llvm/ADT/ArrayRef.h"
 #include "llvm/ADT/STLExtras.h"
+#include "llvm/Support/Driver.h"
 #include "llvm/Support/FileSystem.h"
 #include "llvm/Support/IOSandbox.h"
-#include "llvm/Support/LLVMDriver.h"
 #include "llvm/Support/TargetSelect.h"
 #include "llvm/Support/VirtualFileSystem.h"
 #include "llvm/Support/YAMLTraits.h"
diff --git a/clang/tools/driver/driver.cpp b/clang/tools/driver/driver.cpp
index d4d913a8977a42..af96812e9ebd97 100644
--- a/clang/tools/driver/driver.cpp
+++ b/clang/tools/driver/driver.cpp
@@ -36,10 +36,10 @@
 #include "llvm/Support/BuryPointer.h"
 #include "llvm/Support/CommandLine.h"
 #include "llvm/Support/CrashRecoveryContext.h"
+#include "llvm/Support/Driver.h"
 #include "llvm/Support/ErrorHandling.h"
 #include "llvm/Support/FileSystem.h"
 #include "llvm/Support/IOSandbox.h"
-#include "llvm/Support/LLVMDriver.h"
 #include "llvm/Support/Path.h"
 #include "llvm/Support/PrettyStackTrace.h"
 #include "llvm/Support/Process.h"
diff --git a/lld/tools/lld/lld.cpp b/lld/tools/lld/lld.cpp
index d6800fa1eea4b9..53f0cbc6d9814d 100644
--- a/lld/tools/lld/lld.cpp
+++ b/lld/tools/lld/lld.cpp
@@ -33,7 +33,7 @@
 #include "llvm/ADT/Twine.h"
 #include "llvm/Support/CommandLine.h"
 #include "llvm/Support/CrashRecoveryContext.h"
-#include "llvm/Support/LLVMDriver.h"
+#include "llvm/Support/Driver.h"
 #include "llvm/Support/Path.h"
 #include "llvm/Support/PluginLoader.h"
 #include "llvm/Support/Process.h"
diff --git a/llvm/cmake/modules/llvm-driver-template.cpp.in b/llvm/cmake/modules/llvm-driver-template.cpp.in
index d4c385c8cf4129..f51b21104afb03 100644
--- a/llvm/cmake/modules/llvm-driver-template.cpp.in
+++ b/llvm/cmake/modules/llvm-driver-template.cpp.in
@@ -8,7 +8,7 @@
 
 #include "llvm/ADT/ArrayRef.h"
 #include "llvm/Support/InitLLVM.h"
-#include "llvm/Support/LLVMDriver.h"
+#include "llvm/Support/Driver.h"
 
 int @TOOL_NAME at _main(int argc, char **, const llvm::ToolContext &);
 
diff --git a/llvm/include/llvm/Support/Driver.h b/llvm/include/llvm/Support/Driver.h
new file mode 100644
index 00000000000000..eef1d21cc8e0a9
--- /dev/null
+++ b/llvm/include/llvm/Support/Driver.h
@@ -0,0 +1,96 @@
+//===- Driver.h -------------------------------------------------*- 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
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_SUPPORT_DRIVER_H
+#define LLVM_SUPPORT_DRIVER_H
+
+#include "llvm/ADT/ArrayRef.h"
+#include "llvm/ADT/StringRef.h"
+#include "llvm/Support/Compiler.h"
+#include "llvm/Support/ErrorOr.h"
+
+#include <functional>
+#include <memory>
+
+namespace llvm {
+
+class ToolSession;
+class ToolContext;
+
+using ToolMainFn = std::function<int(int, char **, const ToolContext &)>;
+
+/// An LLVM command-line tool that can be invoked without creating a process.
+struct CallableTool {
+  StringRef Name;
+  ToolMainFn Main;
+
+  explicit operator bool() const { return static_cast<bool>(Main); }
+};
+
+/// Describes how a tool was invoked and provides access to its host session.
+class ToolContext {
+  ToolSession *Session = nullptr;
+
+  friend class ToolSession;
+
+public:
+  const char *Path;
+  const char *PrependArg;
+  // PrependArg will be added unconditionally by the llvm-driver, but
+  // NeedsPrependArg will be false if Path is adequate to reinvoke the tool.
+  // This is useful if realpath is ever called on Path, in which case it will
+  // point to the llvm-driver executable, where PrependArg will be needed to
+  // invoke the correct tool.
+  bool NeedsPrependArg;
+
+  ToolContext(const char *Path, const char *PrependArg, bool NeedsPrependArg)
+      : Path(Path), PrependArg(PrependArg), NeedsPrependArg(NeedsPrependArg) {}
+
+  /// Finds a tool registered with the session that owns this context.
+  LLVM_ABI ErrorOr<CallableTool> getCallableTool(StringRef Name) const;
+
+  /// Invokes another tool registered with the same host session.
+  LLVM_ABI ErrorOr<int> callTool(ArrayRef<const char *> Args) const;
+};
+
+/// Owns LLVM process initialization and an in-process tool registry.
+///
+/// A long-lived host constructs one session and uses it for every embedded
+/// tool invocation. The individual tools borrow a ToolContext and therefore do
+/// not initialize or shut down LLVM themselves.
+///
+/// LLVM tools may use process-global state. Tool invocations must be externally
+/// serialized; concurrent calls are not supported.
+class LLVM_ABI ToolSession {
+public:
+  ToolSession(int &Argc, char **&Argv, ArrayRef<CallableTool> Tools,
+              bool InstallPipeSignalExitHandler = true,
+              bool NeedsPOSIXUtilitySignalHandling = false);
+  ~ToolSession();
+
+  ToolSession(const ToolSession &) = delete;
+  ToolSession &operator=(const ToolSession &) = delete;
+
+  /// Invokes the tool named by Args[0]. Args may instead contain a
+  /// process-style argv beginning with the session executable or an LLVM
+  /// multicall name.
+  ErrorOr<int> callTool(ArrayRef<const char *> Args);
+
+private:
+  struct Impl;
+  std::unique_ptr<Impl> PImpl;
+
+  ErrorOr<CallableTool> findTool(StringRef Name) const;
+  ToolContext makeContext(StringRef RegisteredName, const char *PrependArg);
+
+  friend class ToolContext;
+};
+
+} // namespace llvm
+
+#endif
diff --git a/llvm/include/llvm/Support/LLVMDriver.h b/llvm/include/llvm/Support/LLVMDriver.h
deleted file mode 100644
index 0b2e265d50b423..00000000000000
--- a/llvm/include/llvm/Support/LLVMDriver.h
+++ /dev/null
@@ -1,27 +0,0 @@
-//===- LLVMDriver.h ---------------------------------------------*- 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
-//
-//===----------------------------------------------------------------------===//
-
-#ifndef LLVM_SUPPORT_LLVMDRIVER_H
-#define LLVM_SUPPORT_LLVMDRIVER_H
-
-namespace llvm {
-
-struct ToolContext {
-  const char *Path;
-  const char *PrependArg;
-  // PrependArg will be added unconditionally by the llvm-driver, but
-  // NeedsPrependArg will be false if Path is adequate to reinvoke the tool.
-  // This is useful if realpath is ever called on Path, in which case it will
-  // point to the llvm-driver executable, where PrependArg will be needed to
-  // invoke the correct tool.
-  bool NeedsPrependArg;
-};
-
-} // namespace llvm
-
-#endif
diff --git a/llvm/lib/Support/CMakeLists.txt b/llvm/lib/Support/CMakeLists.txt
index e7dfcb0dcd891d..6e4cd150252061 100644
--- a/llvm/lib/Support/CMakeLists.txt
+++ b/llvm/lib/Support/CMakeLists.txt
@@ -227,6 +227,7 @@ add_llvm_component_library(LLVMSupport
   KnownFPClass.cpp
   LEB128.cpp
   LineIterator.cpp
+  Driver.cpp
   Locale.cpp
   LockFileManager.cpp
   ManagedStatic.cpp
diff --git a/llvm/lib/Support/Driver.cpp b/llvm/lib/Support/Driver.cpp
new file mode 100644
index 00000000000000..6a113f1dd8c3e8
--- /dev/null
+++ b/llvm/lib/Support/Driver.cpp
@@ -0,0 +1,134 @@
+//===-- Driver.cpp -------------------------------------------------------===//
+//
+// 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
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/Support/Driver.h"
+
+#include "llvm/ADT/SmallVector.h"
+#include "llvm/ADT/StringExtras.h"
+#include "llvm/Support/InitLLVM.h"
+#include "llvm/Support/Path.h"
+
+#include <cassert>
+#include <string>
+#include <system_error>
+#include <utility>
+#include <vector>
+
+using namespace llvm;
+
+namespace {
+
+bool matchesToolName(StringRef RegisteredName, StringRef InvokedName) {
+  StringRef Stem = sys::path::stem(InvokedName);
+  StringRef Filename = sys::path::filename(InvokedName);
+  auto Matches = [RegisteredName](StringRef Candidate) {
+    size_t Position = Candidate.rfind_insensitive(RegisteredName);
+    return Position != StringRef::npos &&
+           (Position + RegisteredName.size() == Candidate.size() ||
+            !llvm::isAlnum(Candidate[Position + RegisteredName.size()]));
+  };
+  return Matches(Stem) || Matches(Filename);
+}
+
+bool isMulticallName(StringRef Name) { return matchesToolName("llvm", Name); }
+
+} // namespace
+
+struct ToolSession::Impl {
+  InitLLVM Initialization;
+  std::string ExecutablePath;
+  std::vector<std::pair<std::string, ToolMainFn>> Tools;
+
+  Impl(int &Argc, char **&Argv, ArrayRef<CallableTool> RegisteredTools,
+       bool InstallPipeSignalExitHandler, bool NeedsPOSIXUtilitySignalHandling)
+      : Initialization(Argc, Argv, InstallPipeSignalExitHandler,
+                       NeedsPOSIXUtilitySignalHandling),
+        ExecutablePath(Argv[0]) {
+    Tools.reserve(RegisteredTools.size());
+    for (const CallableTool &Tool : RegisteredTools)
+      Tools.emplace_back(Tool.Name.str(), Tool.Main);
+  }
+};
+
+ToolSession::ToolSession(int &Argc, char **&Argv, ArrayRef<CallableTool> Tools,
+                         bool InstallPipeSignalExitHandler,
+                         bool NeedsPOSIXUtilitySignalHandling) {
+  assert(Argc > 0 && Argv && Argv[0] && "ToolSession requires a valid argv[0]");
+  PImpl =
+      std::make_unique<Impl>(Argc, Argv, Tools, InstallPipeSignalExitHandler,
+                             NeedsPOSIXUtilitySignalHandling);
+}
+
+ToolSession::~ToolSession() = default;
+
+ErrorOr<CallableTool> ToolSession::findTool(StringRef Name) const {
+  StringRef Stem = sys::path::stem(Name);
+  StringRef Filename = sys::path::filename(Name);
+  for (const auto &[RegisteredName, Main] : PImpl->Tools)
+    if (Stem.equals_insensitive(RegisteredName) ||
+        Filename.equals_insensitive(RegisteredName))
+      return CallableTool{RegisteredName, Main};
+
+  for (const auto &[RegisteredName, Main] : PImpl->Tools)
+    if (matchesToolName(RegisteredName, Name))
+      return CallableTool{RegisteredName, Main};
+  return make_error_code(std::errc::no_such_file_or_directory);
+}
+
+ToolContext ToolSession::makeContext(StringRef RegisteredName,
+                                     const char *PrependArg) {
+  ErrorOr<CallableTool> ExecutableTool = findTool(PImpl->ExecutablePath);
+  bool NeedsPrependArg =
+      !ExecutableTool ||
+      !ExecutableTool->Name.equals_insensitive(RegisteredName);
+  ToolContext Context(PImpl->ExecutablePath.c_str(), PrependArg,
+                      NeedsPrependArg);
+  Context.Session = this;
+  return Context;
+}
+
+ErrorOr<int> ToolSession::callTool(ArrayRef<const char *> Args) {
+  if (Args.empty())
+    return make_error_code(std::errc::invalid_argument);
+
+  StringRef InvokedName = Args.front();
+  ErrorOr<CallableTool> Tool = findTool(InvokedName);
+  if (!Tool) {
+    if (InvokedName != PImpl->ExecutablePath && !isMulticallName(InvokedName))
+      return make_error_code(std::errc::no_such_file_or_directory);
+    Args = Args.drop_front();
+    if (Args.empty())
+      return make_error_code(std::errc::invalid_argument);
+    InvokedName = Args.front();
+    Tool = findTool(InvokedName);
+  }
+
+  if (!Tool)
+    return Tool.getError();
+
+  std::string PrependArg = sys::path::stem(InvokedName).str();
+  ToolContext Context = makeContext(Tool->Name, PrependArg.c_str());
+  SmallVector<char *, 16> MutableArgs;
+  MutableArgs.reserve(Args.size() + 1);
+  for (const char *Arg : Args)
+    MutableArgs.push_back(const_cast<char *>(Arg));
+  MutableArgs.push_back(nullptr);
+  return Tool->Main(Args.size(), MutableArgs.data(), Context);
+}
+
+ErrorOr<CallableTool> ToolContext::getCallableTool(StringRef Name) const {
+  if (!Session)
+    return make_error_code(std::errc::operation_not_permitted);
+  return Session->findTool(Name);
+}
+
+ErrorOr<int> ToolContext::callTool(ArrayRef<const char *> Args) const {
+  if (!Session)
+    return make_error_code(std::errc::operation_not_permitted);
+  return Session->callTool(Args);
+}
diff --git a/llvm/test/tools/llvm-driver/session-dispatch.test b/llvm/test/tools/llvm-driver/session-dispatch.test
new file mode 100644
index 00000000000000..a8e627f5a13059
--- /dev/null
+++ b/llvm/test/tools/llvm-driver/session-dispatch.test
@@ -0,0 +1,9 @@
+# REQUIRES: llvm-driver
+
+## Exercise a real LLVM tool entry point through ToolSession rather than
+## only testing the registry with synthetic callbacks.
+# RUN: %llvm cxxfilt _Z3foov | FileCheck %s --check-prefix=CXXFILT
+# RUN: %llvm --help | FileCheck %s --check-prefix=HELP
+
+# CXXFILT: foo()
+# HELP: OVERVIEW: llvm toolchain driver
diff --git a/llvm/tools/dsymutil/dsymutil.cpp b/llvm/tools/dsymutil/dsymutil.cpp
index 76c4d4140488c5..244eb0cc9eb398 100644
--- a/llvm/tools/dsymutil/dsymutil.cpp
+++ b/llvm/tools/dsymutil/dsymutil.cpp
@@ -35,10 +35,10 @@
 #include "llvm/Option/Option.h"
 #include "llvm/Support/CommandLine.h"
 #include "llvm/Support/CrashRecoveryContext.h"
+#include "llvm/Support/Driver.h"
 #include "llvm/Support/FileCollector.h"
 #include "llvm/Support/FileSystem.h"
 #include "llvm/Support/FormatVariadic.h"
-#include "llvm/Support/LLVMDriver.h"
 #include "llvm/Support/MemoryBuffer.h"
 #include "llvm/Support/Path.h"
 #include "llvm/Support/Program.h"
diff --git a/llvm/tools/llvm-ar/llvm-ar.cpp b/llvm/tools/llvm-ar/llvm-ar.cpp
index 38f929f63b39f1..6ab53375509c8c 100644
--- a/llvm/tools/llvm-ar/llvm-ar.cpp
+++ b/llvm/tools/llvm-ar/llvm-ar.cpp
@@ -22,11 +22,11 @@
 #include "llvm/Support/Chrono.h"
 #include "llvm/Support/CommandLine.h"
 #include "llvm/Support/ConvertUTF.h"
+#include "llvm/Support/Driver.h"
 #include "llvm/Support/Errc.h"
 #include "llvm/Support/FileSystem.h"
 #include "llvm/Support/Format.h"
 #include "llvm/Support/FormatVariadic.h"
-#include "llvm/Support/LLVMDriver.h"
 #include "llvm/Support/LineIterator.h"
 #include "llvm/Support/MemoryBuffer.h"
 #include "llvm/Support/Path.h"
diff --git a/llvm/tools/llvm-cgdata/llvm-cgdata.cpp b/llvm/tools/llvm-cgdata/llvm-cgdata.cpp
index 66a74107829225..1212cab0b5e139 100644
--- a/llvm/tools/llvm-cgdata/llvm-cgdata.cpp
+++ b/llvm/tools/llvm-cgdata/llvm-cgdata.cpp
@@ -21,7 +21,7 @@
 #include "llvm/Option/ArgList.h"
 #include "llvm/Option/Option.h"
 #include "llvm/Support/CommandLine.h"
-#include "llvm/Support/LLVMDriver.h"
+#include "llvm/Support/Driver.h"
 #include "llvm/Support/Path.h"
 #include "llvm/Support/VirtualFileSystem.h"
 #include "llvm/Support/WithColor.h"
diff --git a/llvm/tools/llvm-cxxfilt/llvm-cxxfilt.cpp b/llvm/tools/llvm-cxxfilt/llvm-cxxfilt.cpp
index 1467093e78c0b4..d4b8c23bd02be6 100644
--- a/llvm/tools/llvm-cxxfilt/llvm-cxxfilt.cpp
+++ b/llvm/tools/llvm-cxxfilt/llvm-cxxfilt.cpp
@@ -13,7 +13,7 @@
 #include "llvm/Option/ArgList.h"
 #include "llvm/Option/Option.h"
 #include "llvm/Support/CommandLine.h"
-#include "llvm/Support/LLVMDriver.h"
+#include "llvm/Support/Driver.h"
 #include "llvm/Support/WithColor.h"
 #include "llvm/Support/raw_ostream.h"
 #include "llvm/TargetParser/Host.h"
diff --git a/llvm/tools/llvm-debuginfod-find/llvm-debuginfod-find.cpp b/llvm/tools/llvm-debuginfod-find/llvm-debuginfod-find.cpp
index 9aeda9f55bb967..9f515d444565a5 100644
--- a/llvm/tools/llvm-debuginfod-find/llvm-debuginfod-find.cpp
+++ b/llvm/tools/llvm-debuginfod-find/llvm-debuginfod-find.cpp
@@ -23,8 +23,8 @@
 #include "llvm/Option/ArgList.h"
 #include "llvm/Option/Option.h"
 #include "llvm/Support/CommandLine.h"
+#include "llvm/Support/Driver.h"
 #include "llvm/Support/InitLLVM.h"
-#include "llvm/Support/LLVMDriver.h"
 
 using namespace llvm;
 
diff --git a/llvm/tools/llvm-debuginfod/llvm-debuginfod.cpp b/llvm/tools/llvm-debuginfod/llvm-debuginfod.cpp
index c44bf915361f1f..e24fa297188879 100644
--- a/llvm/tools/llvm-debuginfod/llvm-debuginfod.cpp
+++ b/llvm/tools/llvm-debuginfod/llvm-debuginfod.cpp
@@ -22,7 +22,7 @@
 #include "llvm/Option/ArgList.h"
 #include "llvm/Option/Option.h"
 #include "llvm/Support/CommandLine.h"
-#include "llvm/Support/LLVMDriver.h"
+#include "llvm/Support/Driver.h"
 #include "llvm/Support/ThreadPool.h"
 
 using namespace llvm;
diff --git a/llvm/tools/llvm-driver/llvm-driver.cpp b/llvm/tools/llvm-driver/llvm-driver.cpp
index 14ce162faee46c..9cbe750fc563be 100644
--- a/llvm/tools/llvm-driver/llvm-driver.cpp
+++ b/llvm/tools/llvm-driver/llvm-driver.cpp
@@ -6,14 +6,11 @@
 //
 //===----------------------------------------------------------------------===//
 
-#include "llvm/ADT/StringExtras.h"
+#include "llvm/ADT/SmallVector.h"
 #include "llvm/ADT/StringRef.h"
-#include "llvm/Support/CommandLine.h"
-#include "llvm/Support/ErrorHandling.h"
-#include "llvm/Support/InitLLVM.h"
-#include "llvm/Support/LLVMDriver.h"
+#include "llvm/Support/Driver.h"
 #include "llvm/Support/Path.h"
-#include "llvm/Support/WithColor.h"
+#include "llvm/Support/raw_ostream.h"
 
 using namespace llvm;
 
@@ -36,51 +33,26 @@ static void printHelpMessage() {
                << "OPTIONS:\n\n  --help - Display this message\n";
 }
 
-static int findTool(int Argc, char **Argv, const char *Argv0) {
-  if (!Argc) {
-    printHelpMessage();
-    return 1;
-  }
+int main(int Argc, char **Argv) {
+  const CallableTool Tools[] = {
+#define LLVM_DRIVER_TOOL(tool, entry) {tool, entry##_main},
+#include "LLVMDriverTools.def"
+  };
 
-  StringRef ToolName = Argv[0];
+  ToolSession Session(Argc, Argv, Tools);
 
-  if (ToolName == "--help") {
+  StringRef Stem = sys::path::stem(Argv[0]);
+  if (Stem.equals_insensitive("llvm") &&
+      (Argc == 1 || (Argc == 2 && StringRef(Argv[1]) == "--help"))) {
     printHelpMessage();
-    return 0;
+    return Argc == 1 ? 1 : 0;
   }
 
-  StringRef Stem = sys::path::stem(ToolName);
-  auto Is = [=](StringRef Tool) {
-    auto IsImpl = [=](StringRef Stem) {
-      auto I = Stem.rfind_insensitive(Tool);
-      return I != StringRef::npos && (I + Tool.size() == Stem.size() ||
-                                      !llvm::isAlnum(Stem[I + Tool.size()]));
-    };
-    for (StringRef S : {Stem, sys::path::filename(ToolName)})
-      if (IsImpl(S))
-        return true;
-    return false;
-  };
-
-  auto MakeDriverArgs = [=]() -> llvm::ToolContext {
-    if (ToolName != Argv0)
-      return {Argv0, ToolName.data(), true};
-    return {Argv0, sys::path::filename(Argv0).data(), false};
-  };
-
-#define LLVM_DRIVER_TOOL(tool, entry)                                          \
-  if (Is(tool))                                                                \
-    return entry##_main(Argc, Argv, MakeDriverArgs());
-#include "LLVMDriverTools.def"
-
-  if (Is("llvm") || Argv0 == Argv[0])
-    return findTool(Argc - 1, Argv + 1, Argv0);
-
-  printHelpMessage();
-  return 1;
-}
-
-int main(int Argc, char **Argv) {
-  llvm::InitLLVM X(Argc, Argv);
-  return findTo...
[truncated]

``````````

</details>


https://github.com/llvm/llvm-project/pull/224515


More information about the cfe-commits mailing list