[llvm] [LLVM] Register static pass plugins in LLVMRunPasses C-API (PR #196754)

via llvm-commits llvm-commits at lists.llvm.org
Sat May 9 13:55:54 PDT 2026


https://github.com/Vadmeme created https://github.com/llvm/llvm-project/pull/196754

LLVMRunPasses and LLVMRunPassesOnFunction create their own PassBuilder, but did not register statically linked pass plugin callbacks from Extension.def. This made C API pipelines fail to parse passes provided by statically linked plugins, even when the same plugins were available to opt and LTO.

Register the static extension callbacks after constructing the PassBuilder, matching opt's NewPMDriver behavior.

Add coverage using the Bye plugin when it is linked into tools.

>From a5744f7ca812493f12c0ef6dde4d1368b09a7fe3 Mon Sep 17 00:00:00 2001
From: Vadmeme <invalid at example.com>
Date: Sat, 9 May 2026 13:31:07 -0700
Subject: [PATCH] [LLVM] Register static pass plugins in LLVMRunPasses C-API

LLVMRunPasses and LLVMRunPassesOnFunction create their own PassBuilder,
but did not register statically linked pass plugin callbacks from
Extension.def. This made C API pipelines fail to parse passes provided by
statically linked plugins, even when the same plugins were available to
opt and LTO.

Register the static extension callbacks after constructing the PassBuilder,
matching opt's NewPMDriver behavior.

Add coverage using the Bye plugin when it is linked into tools.
---
 llvm/lib/Passes/PassBuilderBindings.cpp       | 11 ++++++++++
 .../Passes/PassBuilderBindings/CMakeLists.txt |  5 ++++-
 .../PassBuilderBindingsTest.cpp               | 21 +++++++++++++++++++
 .../Passes/PassBuilderBindings/BUILD.gn       |  1 +
 4 files changed, 37 insertions(+), 1 deletion(-)

diff --git a/llvm/lib/Passes/PassBuilderBindings.cpp b/llvm/lib/Passes/PassBuilderBindings.cpp
index 933fe89e53a94..2c88433d446cc 100644
--- a/llvm/lib/Passes/PassBuilderBindings.cpp
+++ b/llvm/lib/Passes/PassBuilderBindings.cpp
@@ -17,6 +17,7 @@
 #include "llvm/IR/Verifier.h"
 #include "llvm/Passes/PassBuilder.h"
 #include "llvm/Passes/StandardInstrumentations.h"
+#include "llvm/Plugins/PassPlugin.h"
 #include "llvm/Support/CBindingWrapping.h"
 
 using namespace llvm;
@@ -48,6 +49,11 @@ static TargetMachine *unwrap(LLVMTargetMachineRef P) {
 DEFINE_SIMPLE_CONVERSION_FUNCTIONS(LLVMPassBuilderOptions,
                                    LLVMPassBuilderOptionsRef)
 
+#define HANDLE_EXTENSION(Ext)                                                  \
+  llvm::PassPluginLibraryInfo get##Ext##PluginInfo();
+#include "llvm/Support/Extension.def"
+#undef HANDLE_EXTENSION
+
 static LLVMErrorRef runPasses(Module *Mod, Function *Fun, const char *Passes,
                               TargetMachine *Machine,
                               LLVMPassBuilderOptions *PassOpts) {
@@ -57,6 +63,11 @@ static LLVMErrorRef runPasses(Module *Mod, Function *Fun, const char *Passes,
   PassInstrumentationCallbacks PIC;
   PassBuilder PB(Machine, PassOpts->PTO, std::nullopt, &PIC);
 
+#define HANDLE_EXTENSION(Ext)                                                  \
+  get##Ext##PluginInfo().RegisterPassBuilderCallbacks(PB);
+#include "llvm/Support/Extension.def"
+#undef HANDLE_EXTENSION
+
   LoopAnalysisManager LAM;
   FunctionAnalysisManager FAM;
   CGSCCAnalysisManager CGAM;
diff --git a/llvm/unittests/Passes/PassBuilderBindings/CMakeLists.txt b/llvm/unittests/Passes/PassBuilderBindings/CMakeLists.txt
index e3b2ecee6313a..a839da215f0d8 100644
--- a/llvm/unittests/Passes/PassBuilderBindings/CMakeLists.txt
+++ b/llvm/unittests/Passes/PassBuilderBindings/CMakeLists.txt
@@ -1,5 +1,8 @@
-set(LLVM_LINK_COMPONENTS Support Passes Core Target native AllTargetsInfos)
+set(LLVM_LINK_COMPONENTS Support Passes Core Target native AllTargetsInfos Extensions)
 add_llvm_unittest(PassesBindingsTests
 PassBuilderBindingsTest.cpp
 )
 target_link_libraries(PassesBindingsTests PRIVATE LLVMTestingSupport)
+if(LLVM_BYE_LINK_INTO_TOOLS AND TARGET Bye)
+  target_compile_definitions(PassesBindingsTests PRIVATE PASSBUILDER_HAS_BYE_PLUGIN=1)
+endif()
diff --git a/llvm/unittests/Passes/PassBuilderBindings/PassBuilderBindingsTest.cpp b/llvm/unittests/Passes/PassBuilderBindings/PassBuilderBindingsTest.cpp
index 4e17b1ad09e2b..3f37d6b0b4f60 100644
--- a/llvm/unittests/Passes/PassBuilderBindings/PassBuilderBindingsTest.cpp
+++ b/llvm/unittests/Passes/PassBuilderBindings/PassBuilderBindingsTest.cpp
@@ -94,3 +94,24 @@ TEST_F(PassBuilderCTest, Function) {
   }
   LLVMDisposePassBuilderOptions(Options);
 }
+
+#ifdef PASSBUILDER_HAS_BYE_PLUGIN
+TEST_F(PassBuilderCTest, StaticPassExtension) {
+  LLVMPassBuilderOptionsRef Options = LLVMCreatePassBuilderOptions();
+  if (LLVMErrorRef E = LLVMRunPasses(Module, "function(goodbye)", TM,
+                                     Options)) {
+    char *Msg = LLVMGetErrorMessage(E);
+    LLVMDisposePassBuilderOptions(Options);
+    FAIL() << "Failed to run statically linked extension pass on module: "
+           << Msg;
+  }
+  if (LLVMErrorRef E =
+          LLVMRunPassesOnFunction(Function, "goodbye", TM, Options)) {
+    char *Msg = LLVMGetErrorMessage(E);
+    LLVMDisposePassBuilderOptions(Options);
+    FAIL() << "Failed to run statically linked extension pass on function: "
+           << Msg;
+  }
+  LLVMDisposePassBuilderOptions(Options);
+}
+#endif
diff --git a/llvm/utils/gn/secondary/llvm/unittests/Passes/PassBuilderBindings/BUILD.gn b/llvm/utils/gn/secondary/llvm/unittests/Passes/PassBuilderBindings/BUILD.gn
index 1a1a6dfe59a6c..346e5cc9577d1 100644
--- a/llvm/utils/gn/secondary/llvm/unittests/Passes/PassBuilderBindings/BUILD.gn
+++ b/llvm/utils/gn/secondary/llvm/unittests/Passes/PassBuilderBindings/BUILD.gn
@@ -4,6 +4,7 @@ unittest("PassesBindingsTests") {
     "//llvm/include/llvm/Config:config",
     "//llvm/lib/IR",
     "//llvm/lib/Passes",
+    "//llvm/lib/Extensions",
     "//llvm/lib/Support",
     "//llvm/lib/Target:TargetsToBuild",
     "//llvm/lib/Testing/Support",



More information about the llvm-commits mailing list