[clang] [PassBuilder] Add a mechanism for adding passbuilder callbacks for static builds (PR #70171)
William Moses via cfe-commits
cfe-commits at lists.llvm.org
Wed Oct 25 22:33:50 PDT 2023
https://github.com/wsmoses updated https://github.com/llvm/llvm-project/pull/70171
>From 227a494be06d8cb3b590c78f52f717bd781a8f0e Mon Sep 17 00:00:00 2001
From: "William S. Moses" <gh at wsmoses.com>
Date: Wed, 25 Oct 2023 02:10:32 -0500
Subject: [PATCH] [PassBuilder] Add a mechanism for adding passbuilder
callbacks without an extension mechanism or dlopen of plugin
---
clang/include/clang/Basic/CodeGenOptions.h | 6 ++
clang/lib/CodeGen/BackendUtil.cpp | 3 +
clang/test/CMakeLists.txt | 1 +
clang/test/DriverPlugin/plugintest.c | 6 ++
clang/tools/CMakeLists.txt | 1 +
.../clang-hello-plugin-test/CMakeLists.txt | 59 +++++++++++++++++
.../clang-hello-plugin-test/helloplugin.cpp | 66 +++++++++++++++++++
clang/tools/driver/cc1_main.cpp | 9 +++
llvm/include/llvm/Passes/PassBuilder.h | 5 ++
9 files changed, 156 insertions(+)
create mode 100644 clang/test/DriverPlugin/plugintest.c
create mode 100644 clang/tools/clang-hello-plugin-test/CMakeLists.txt
create mode 100644 clang/tools/clang-hello-plugin-test/helloplugin.cpp
diff --git a/clang/include/clang/Basic/CodeGenOptions.h b/clang/include/clang/Basic/CodeGenOptions.h
index 12be4e0025a7054..c8e2544f891cc2b 100644
--- a/clang/include/clang/Basic/CodeGenOptions.h
+++ b/clang/include/clang/Basic/CodeGenOptions.h
@@ -26,6 +26,9 @@
#include <string>
#include <vector>
+namespace llvm {
+class PassBuilder;
+}
namespace clang {
/// Bitfields of CodeGenOptions, split out from CodeGenOptions to ensure
@@ -408,6 +411,9 @@ class CodeGenOptions : public CodeGenOptionsBase {
/// List of dynamic shared object files to be loaded as pass plugins.
std::vector<std::string> PassPlugins;
+ /// List of pass builder callbacks.
+ std::vector<std::function<void(llvm::PassBuilder &)>> PassBuilderCallbacks;
+
/// Path to allowlist file specifying which objects
/// (files, functions) should exclusively be instrumented
/// by sanitizer coverage pass.
diff --git a/clang/lib/CodeGen/BackendUtil.cpp b/clang/lib/CodeGen/BackendUtil.cpp
index 70accce456d3c07..a8db38fce6425fb 100644
--- a/clang/lib/CodeGen/BackendUtil.cpp
+++ b/clang/lib/CodeGen/BackendUtil.cpp
@@ -906,6 +906,9 @@ void EmitAssemblyHelper::RunOptimizationPipeline(
<< PluginFN << toString(PassPlugin.takeError());
}
}
+ for (auto PassCallback : CodeGenOpts.PassBuilderCallbacks) {
+ PassCallback(PB);
+ }
#define HANDLE_EXTENSION(Ext) \
get##Ext##PluginInfo().RegisterPassBuilderCallbacks(PB);
#include "llvm/Support/Extension.def"
diff --git a/clang/test/CMakeLists.txt b/clang/test/CMakeLists.txt
index 31b494f39cce577..a64dfe467c43abc 100644
--- a/clang/test/CMakeLists.txt
+++ b/clang/test/CMakeLists.txt
@@ -62,6 +62,7 @@ list(APPEND CLANG_TEST_DEPS
apinotes-test
c-index-test
clang
+ clang-hello-plugin-test
clang-fuzzer-dictionary
clang-resource-headers
clang-format
diff --git a/clang/test/DriverPlugin/plugintest.c b/clang/test/DriverPlugin/plugintest.c
new file mode 100644
index 000000000000000..e80866f0d1dd2fe
--- /dev/null
+++ b/clang/test/DriverPlugin/plugintest.c
@@ -0,0 +1,6 @@
+// RUN: clang-hello-plugin-test %s -o /dev/null -S | FileCheck %s
+
+int myfunction() { return 0; }
+
+// CHECK: [HelloPass] Found function: myfunction
+
diff --git a/clang/tools/CMakeLists.txt b/clang/tools/CMakeLists.txt
index f60db6ef0ba3454..9742e2a155a0d30 100644
--- a/clang/tools/CMakeLists.txt
+++ b/clang/tools/CMakeLists.txt
@@ -2,6 +2,7 @@ create_subdirectory_options(CLANG TOOL)
add_clang_subdirectory(diagtool)
add_clang_subdirectory(driver)
+add_clang_subdirectory(clang-hello-plugin-test)
add_clang_subdirectory(apinotes-test)
add_clang_subdirectory(clang-diff)
add_clang_subdirectory(clang-format)
diff --git a/clang/tools/clang-hello-plugin-test/CMakeLists.txt b/clang/tools/clang-hello-plugin-test/CMakeLists.txt
new file mode 100644
index 000000000000000..2b951677542c217
--- /dev/null
+++ b/clang/tools/clang-hello-plugin-test/CMakeLists.txt
@@ -0,0 +1,59 @@
+set( LLVM_LINK_COMPONENTS
+ ${LLVM_TARGETS_TO_BUILD}
+ Analysis
+ CodeGen
+ Core
+ IPO
+ AggressiveInstCombine
+ InstCombine
+ Instrumentation
+ MC
+ MCParser
+ ObjCARCOpts
+ Option
+ ScalarOpts
+ Support
+ TargetParser
+ TransformUtils
+ Vectorize
+ )
+
+# Support plugins.
+if(CLANG_PLUGIN_SUPPORT)
+ set(support_plugins SUPPORT_PLUGINS)
+endif()
+
+add_clang_tool(clang-hello-plugin-test
+ ../driver/driver.cpp
+ ../driver/cc1_main.cpp
+ ../driver/cc1as_main.cpp
+ ../driver/cc1gen_reproducer_main.cpp
+ helloplugin.cpp
+ DEPENDS
+ intrinsics_gen
+ ${support_plugins}
+ GENERATE_DRIVER
+ )
+
+clang_target_link_libraries(clang-hello-plugin-test
+ PRIVATE
+ clangBasic
+ clangCodeGen
+ clangDriver
+ clangFrontend
+ clangFrontendTool
+ clangSerialization
+ )
+
+if(WIN32 AND NOT CYGWIN)
+ # Prevent versioning if the buildhost is targeting for Win32.
+else()
+ set_target_properties(clang-hello-plugin-test PROPERTIES VERSION ${CLANG_EXECUTABLE_VERSION})
+endif()
+
+# Support plugins.
+if(CLANG_PLUGIN_SUPPORT)
+ export_executable_symbols_for_plugins(clang-hello-plugin-test)
+endif()
+
+add_dependencies(clang-hello-plugin-test clang-resource-headers)
diff --git a/clang/tools/clang-hello-plugin-test/helloplugin.cpp b/clang/tools/clang-hello-plugin-test/helloplugin.cpp
new file mode 100644
index 000000000000000..52551d12af0a350
--- /dev/null
+++ b/clang/tools/clang-hello-plugin-test/helloplugin.cpp
@@ -0,0 +1,66 @@
+//===-- helloplugin.cpp - Hello World test static link plugin ------------===//
+//
+// 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
+//
+//===----------------------------------------------------------------------===//
+//
+// This is a test/example mechanism for statically adding functionality to Clang
+// Codegen without requiring a fork of Clang.
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/ADT/SmallVector.h"
+#include "llvm/IR/PassManager.h"
+#include "llvm/Passes/PassBuilder.h"
+#include "llvm/Support/LLVMDriver.h"
+
+#include <functional>
+
+using namespace llvm;
+
+extern SmallVector<std::function<void(llvm::PassBuilder &)>>
+ PassBuilderCallbacks;
+
+class StaticPlugin {
+public:
+ StaticPlugin(std::function<void(llvm::PassBuilder &)> f) {
+ PassBuilderCallbacks.push_back(f);
+ }
+};
+
+class HelloPass final : public llvm::AnalysisInfoMixin<HelloPass> {
+ friend struct llvm::AnalysisInfoMixin<HelloPass>;
+
+private:
+ static llvm::AnalysisKey Key;
+
+public:
+ using Result = llvm::PreservedAnalyses;
+
+ Result run(llvm::Module &M, llvm::ModuleAnalysisManager &MAM) {
+ for (auto &F : M)
+ llvm::outs() << "[HelloPass] Found function: " << F.getName() << "\n";
+ return PreservedAnalyses::all();
+ }
+
+ static bool isRequired() { return true; }
+};
+
+void HelloCallback(llvm::PassBuilder &PB) {
+ PB.registerPipelineStartEPCallback(
+ [](ModulePassManager &MPM, OptimizationLevel) {
+ MPM.addPass(HelloPass());
+ });
+}
+
+StaticPlugin P(HelloCallback);
+
+extern int clang_main(int Argc, char **Argv,
+ const llvm::ToolContext &ToolContext);
+
+int clang_hello_plugin_main(int Argc, char **Argv,
+ const llvm::ToolContext &ToolContext) {
+ return clang_main(Argc, Argv, ToolContext);
+}
diff --git a/clang/tools/driver/cc1_main.cpp b/clang/tools/driver/cc1_main.cpp
index e9d2c6aad371dbb..c409d5e170dd6cc 100644
--- a/clang/tools/driver/cc1_main.cpp
+++ b/clang/tools/driver/cc1_main.cpp
@@ -57,6 +57,11 @@
using namespace clang;
using namespace llvm::opt;
+//! List of pass builder callbacks to be applied, for adding additional
+//! functionality via static linking, without maintaining a separate fork of
+//! LLVM.
+SmallVector<std::function<void(llvm::PassBuilder &)>> PassBuilderCallbacks;
+
//===----------------------------------------------------------------------===//
// Main driver
//===----------------------------------------------------------------------===//
@@ -227,6 +232,10 @@ int cc1_main(ArrayRef<const char *> Argv, const char *Argv0, void *MainAddr) {
ensureSufficientStack();
std::unique_ptr<CompilerInstance> Clang(new CompilerInstance());
+ for (auto PassCallback : PassBuilderCallbacks) {
+ Clang->getCodeGenOpts().PassBuilderCallbacks.push_back(PassCallback);
+ }
+
IntrusiveRefCntPtr<DiagnosticIDs> DiagID(new DiagnosticIDs());
// Register the support for object-file-wrapped Clang modules.
diff --git a/llvm/include/llvm/Passes/PassBuilder.h b/llvm/include/llvm/Passes/PassBuilder.h
index 2c7ceda7998eda1..d018dd1e69166f0 100644
--- a/llvm/include/llvm/Passes/PassBuilder.h
+++ b/llvm/include/llvm/Passes/PassBuilder.h
@@ -739,6 +739,11 @@ bool parseAnalysisUtilityPasses(
return false;
}
+
+//! List of pass builder callbacks to be applied, in addition to those imported
+//! from plugins or LLVM extensions.
+extern SmallVector<std::function<void(PassBuilder &)>>
+ ListRegisterPassBuilderCallbacks;
}
#endif
More information about the cfe-commits
mailing list