https://github.com/weliveindetail updated 
https://github.com/llvm/llvm-project/pull/231516

From fd90348d281d2297f6942b1f01cbf69bdbb10bbb Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Stefan=20Gr=C3=A4nitz?= <[email protected]>
Date: Mon, 21 Sep 2026 15:57:03 +0200
Subject: [PATCH 1/2] [LTO] Support PreCodeGenCallback for pass-plugins in lld
 and clang

Co-Authored-By: Claude Opus 5.5 <[email protected]>
---
 clang/test/CodeGen/codegen-plugins-thinlto.c | 21 ++++++++++
 lld/test/ELF/lto/pre-codegen-plugin.ll       | 28 +++++++++++++
 llvm/lib/LTO/LTOBackend.cpp                  | 44 +++++++++++++++-----
 llvm/test/Feature/codegen-plugin.ll          | 10 +++++
 4 files changed, 92 insertions(+), 11 deletions(-)
 create mode 100644 clang/test/CodeGen/codegen-plugins-thinlto.c
 create mode 100644 lld/test/ELF/lto/pre-codegen-plugin.ll

diff --git a/clang/test/CodeGen/codegen-plugins-thinlto.c 
b/clang/test/CodeGen/codegen-plugins-thinlto.c
new file mode 100644
index 00000000000000..9f5fae5c1c65b4
--- /dev/null
+++ b/clang/test/CodeGen/codegen-plugins-thinlto.c
@@ -0,0 +1,21 @@
+// REQUIRES: plugins, llvm-examples
+// UNSUPPORTED: target={{.*windows.*}}
+// Plugins are currently broken on AIX, at least in the CI.
+// XFAIL: target={{.*}}-aix{{.*}}
+
+// RUN: %clang_cc1 -O2 -flto=thin -emit-llvm-bc %s -o %t.o
+// RUN: llvm-lto -thinlto -o %t %t.o
+// RUN: %clang_cc1 -O2 -x ir %t.o -fthinlto-index=%t.thinlto.bc -S -o - 
-fpass-plugin=%llvmshlibdir/Bye%pluginext 2>&1 | FileCheck %s 
--check-prefix=CHECK-INACTIVE
+// RUN: %clang_cc1 -O2 -x ir %t.o -fthinlto-index=%t.thinlto.bc -S -o - 
-fpass-plugin=%llvmshlibdir/Bye%pluginext -mllvm -last-words | FileCheck %s 
--check-prefix=CHECK-ACTIVE
+// RUN: %clang_cc1 -O2 -x ir %t.o -fthinlto-index=%t.thinlto.bc -emit-llvm -o 
- -fpass-plugin=%llvmshlibdir/Bye%pluginext -mllvm -last-words | FileCheck %s 
--check-prefix=CHECK-LLVM
+// RUN: not %clang_cc1 -O2 -x ir %t.o -fthinlto-index=%t.thinlto.bc -emit-obj 
-o - -fpass-plugin=%llvmshlibdir/Bye%pluginext -mllvm -last-words 2>&1 | 
FileCheck %s --check-prefix=CHECK-ERR
+
+// CHECK-INACTIVE-NOT: Bye
+// CHECK-INACTIVE: f:
+// CHECK-ACTIVE: CodeGen Bye
+// CHECK-LLVM: define{{.*}} i32 @f
+// CHECK-ERR: error: last words unsupported for binary output
+
+int f(int x) {
+  return x;
+}
diff --git a/lld/test/ELF/lto/pre-codegen-plugin.ll 
b/lld/test/ELF/lto/pre-codegen-plugin.ll
new file mode 100644
index 00000000000000..880d422adff9d0
--- /dev/null
+++ b/lld/test/ELF/lto/pre-codegen-plugin.ll
@@ -0,0 +1,28 @@
+; REQUIRES: x86, plugins, examples
+; UNSUPPORTED: target={{.*windows.*}}
+; Plugins are currently broken on AIX, at least in the CI.
+; XFAIL: target={{.*}}-aix{{.*}}
+
+; RUN: opt %s -o %t.o
+; RUN: ld.lld -shared --lto-emit-asm -%loadnewpmbye %t.o -o %t.inactive 2>&1 | 
count 0
+; RUN: FileCheck %s --check-prefix=INACTIVE < %t.inactive.lto.s
+; RUN: ld.lld -shared --lto-emit-asm -%loadnewpmbye -mllvm=%loadbye 
-mllvm=-last-words %t.o -o %t.active
+; RUN: FileCheck %s --check-prefix=ACTIVE < %t.active.lto.s
+; RUN: not ld.lld -shared -%loadnewpmbye -mllvm=%loadbye -mllvm=-last-words 
%t.o -o %t.err 2>&1 | FileCheck %s --check-prefix=ERR
+; RUN: ld.lld -shared --lto-emit-asm --lto-partitions=2 -%loadnewpmbye 
-mllvm=%loadbye -mllvm=-last-words %t.o -o %t.parallel
+; RUN: FileCheck %s --check-prefix=PARALLEL0 < %t.parallel.lto.s
+; RUN: FileCheck %s --check-prefix=PARALLEL1 < %t.parallel.lto.1.s
+
+; INACTIVE-NOT: Bye
+; INACTIVE: f:
+; ACTIVE: CodeGen Bye
+; ERR: error: last words unsupported for binary output
+; PARALLEL0: CodeGen Bye
+; PARALLEL1: CodeGen Bye
+
+target datalayout = 
"e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-i128:128-f80:128-n8:16:32:64-S128"
+target triple = "x86_64-unknown-linux-gnu"
+
+define i32 @f(i32 %x) {
+  ret i32 %x
+}
diff --git a/llvm/lib/LTO/LTOBackend.cpp b/llvm/lib/LTO/LTOBackend.cpp
index 13b5e6e93335dc..3be710a7864bb4 100644
--- a/llvm/lib/LTO/LTOBackend.cpp
+++ b/llvm/lib/LTO/LTOBackend.cpp
@@ -199,23 +199,34 @@ Error Config::addSaveTemps(std::string OutputFileName, 
bool UseInputModulePath,
 #include "llvm/Support/Extension.def"
 #undef HANDLE_EXTENSION
 
+// Obtain dynamic pass-plugins in registration order: the ones requested by 
file
+// name followed by those pre-loaded in the host application
+static SmallVector<PassPlugin *, 2>
+getPassPlugins(const Config &Conf, SmallVectorImpl<PassPlugin> &Storage) {
+  for (const std::string &PluginFN : Conf.PassPluginFilenames) {
+    Expected<PassPlugin> Plugin = PassPlugin::load(PluginFN);
+    if (!Plugin)
+      reportFatalUsageError(Plugin.takeError());
+    Storage.push_back(std::move(*Plugin));
+  }
+
+  SmallVector<PassPlugin *, 2> Plugins(make_pointer_range(Storage));
+  append_range(Plugins, Conf.LoadedPassPlugins);
+  return Plugins;
+}
+
+// Call pass builder registration callbacks for all pass-plugins
 static void RegisterPassPlugins(const Config &Conf, PassBuilder &PB) {
+  // Static built-in plugins
 #define HANDLE_EXTENSION(Ext)                                                  
\
   get##Ext##PluginInfo().RegisterPassBuilderCallbacks(PB);
 #include "llvm/Support/Extension.def"
 #undef HANDLE_EXTENSION
 
-  // Load requested pass plugins and let them register pass builder callbacks
-  for (auto &PluginFN : Conf.PassPluginFilenames) {
-    auto PassPlugin = PassPlugin::load(PluginFN);
-    if (!PassPlugin)
-      reportFatalUsageError(PassPlugin.takeError());
-    PassPlugin->registerPassBuilderCallbacks(PB);
-  }
-
-  // Register already loaded plugins
-  for (auto *LoadedPlugin : Conf.LoadedPassPlugins)
-    LoadedPlugin->registerPassBuilderCallbacks(PB);
+  // Dynamic plugins
+  SmallVector<PassPlugin, 2> Storage;
+  for (const PassPlugin *Plugin : getPassPlugins(Conf, Storage))
+    Plugin->registerPassBuilderCallbacks(PB);
 }
 
 static std::unique_ptr<TargetMachine>
@@ -479,6 +490,17 @@ static void codegen(const Config &Conf, TargetMachine *TM,
   std::unique_ptr<CachedFileStream> &Stream = *StreamOrErr;
   TM->Options.ObjectFilenameForDebug = Stream->ObjectPathName;
 
+  // Allow plugins to handle or even take over code generation entirely.
+  SmallVector<PassPlugin, 2> PluginStorage;
+  for (PassPlugin *Plugin : getPassPlugins(Conf, PluginStorage)) {
+    if (Plugin->invokePreCodeGenCallback(Mod, *TM, Conf.CGFileType,
+                                         *Stream->OS)) {
+      if (Error Err = Stream->commit())
+        reportFatalUsageError(std::move(Err));
+      return;
+    }
+  }
+
   // Create the codegen pipeline in its own scope so it gets deleted before
   // Stream->commit() is called. The commit function of CacheStream deletes
   // the raw stream, which is too early as streamers (e.g. MCAsmStreamer)
diff --git a/llvm/test/Feature/codegen-plugin.ll 
b/llvm/test/Feature/codegen-plugin.ll
index 571c7e348520e9..bdbca8723c3afb 100644
--- a/llvm/test/Feature/codegen-plugin.ll
+++ b/llvm/test/Feature/codegen-plugin.ll
@@ -2,6 +2,15 @@
 ; RUN: llc < %s %loadnewpmbye | FileCheck %s --check-prefix=CHECK-ASM
 ; RUN: llc < %s %loadnewpmbye -plugin-arg=Bye,-last-words | FileCheck %s 
--check-prefix=CHECK-ACTIVE
 ; RUN: not llc < %s %loadnewpmbye -plugin-arg=Bye,-last-words -filetype=obj 
2>&1 | FileCheck %s --check-prefix=CHECK-ERR
+
+; LTO tools do not support -plugin-arg yet, so load Bye early to register its 
options
+; RUN: llvm-as %s -o %t.bc
+; RUN: llvm-lto2 run %t.bc -o %t.inactive -r %t.bc,somefunk,plx -r 
%t.bc,junk,plx -filetype=asm %loadnewpmbye
+; RUN: FileCheck %s --check-prefix=CHECK-ASM < %t.inactive.0
+; RUN: llvm-lto2 run %t.bc -o %t.active -r %t.bc,somefunk,plx -r 
%t.bc,junk,plx -filetype=asm %loadbye %loadnewpmbye -last-words
+; RUN: FileCheck %s --check-prefix=CHECK-ACTIVE < %t.active.0
+; RUN: not llvm-lto2 run %t.bc -o %t.err -r %t.bc,somefunk,plx -r 
%t.bc,junk,plx -filetype=obj %loadbye %loadnewpmbye -last-words 2>&1 | 
FileCheck %s --check-prefix=CHECK-LTO2-ERR
+
 ; REQUIRES: plugins, examples
 ; UNSUPPORTED: target={{.*windows.*}}
 ; Plugins are currently broken on AIX, at least in the CI.
@@ -9,6 +18,7 @@
 ; CHECK-ASM: somefunk:
 ; CHECK-ACTIVE: CodeGen Bye
 ; CHECK-ERR: error: last words unsupported for binary output
+; CHECK-LTO2-ERR: last words unsupported for binary output
 
 target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
 target triple = "x86_64-unknown-linux-gnu"

From 230a6d89d6f659c47bbbd7fe9a1d828de115a344 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Stefan=20Gr=C3=A4nitz?= <[email protected]>
Date: Thu, 15 Oct 2026 00:49:44 +0200
Subject: [PATCH 2/2] Switch getPassPlugins() to PassPluginLibraryInfos

---
 llvm/lib/LTO/LTOBackend.cpp | 25 ++++++++++++-------------
 1 file changed, 12 insertions(+), 13 deletions(-)

diff --git a/llvm/lib/LTO/LTOBackend.cpp b/llvm/lib/LTO/LTOBackend.cpp
index 3be710a7864bb4..4b818f08eb6518 100644
--- a/llvm/lib/LTO/LTOBackend.cpp
+++ b/llvm/lib/LTO/LTOBackend.cpp
@@ -201,17 +201,17 @@ Error Config::addSaveTemps(std::string OutputFileName, 
bool UseInputModulePath,
 
 // Obtain dynamic pass-plugins in registration order: the ones requested by 
file
 // name followed by those pre-loaded in the host application
-static SmallVector<PassPlugin *, 2>
-getPassPlugins(const Config &Conf, SmallVectorImpl<PassPlugin> &Storage) {
+static SmallVector<PassPluginLibraryInfo, 0>
+getPassPlugins(const Config &Conf) {
+  SmallVector<PassPluginLibraryInfo, 0> Plugins;
   for (const std::string &PluginFN : Conf.PassPluginFilenames) {
     Expected<PassPlugin> Plugin = PassPlugin::load(PluginFN);
     if (!Plugin)
       reportFatalUsageError(Plugin.takeError());
-    Storage.push_back(std::move(*Plugin));
+    Plugins.push_back(Plugin->getInfo());
   }
-
-  SmallVector<PassPlugin *, 2> Plugins(make_pointer_range(Storage));
-  append_range(Plugins, Conf.LoadedPassPlugins);
+  for (const PassPlugin *Plugin : Conf.LoadedPassPlugins)
+    Plugins.push_back(Plugin->getInfo());
   return Plugins;
 }
 
@@ -224,9 +224,9 @@ static void RegisterPassPlugins(const Config &Conf, 
PassBuilder &PB) {
 #undef HANDLE_EXTENSION
 
   // Dynamic plugins
-  SmallVector<PassPlugin, 2> Storage;
-  for (const PassPlugin *Plugin : getPassPlugins(Conf, Storage))
-    Plugin->registerPassBuilderCallbacks(PB);
+  for (const PassPluginLibraryInfo &Plugin : getPassPlugins(Conf))
+    if (Plugin.RegisterPassBuilderCallbacks)
+      Plugin.RegisterPassBuilderCallbacks(PB);
 }
 
 static std::unique_ptr<TargetMachine>
@@ -491,10 +491,9 @@ static void codegen(const Config &Conf, TargetMachine *TM,
   TM->Options.ObjectFilenameForDebug = Stream->ObjectPathName;
 
   // Allow plugins to handle or even take over code generation entirely.
-  SmallVector<PassPlugin, 2> PluginStorage;
-  for (PassPlugin *Plugin : getPassPlugins(Conf, PluginStorage)) {
-    if (Plugin->invokePreCodeGenCallback(Mod, *TM, Conf.CGFileType,
-                                         *Stream->OS)) {
+  for (const PassPluginLibraryInfo &Plugin : getPassPlugins(Conf)) {
+    if (Plugin.PreCodeGenCallback &&
+        Plugin.PreCodeGenCallback(Mod, *TM, Conf.CGFileType, *Stream->OS)) {
       if (Error Err = Stream->commit())
         reportFatalUsageError(std::move(Err));
       return;

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

Reply via email to