https://github.com/wsmoses updated https://github.com/llvm/llvm-project/pull/70171
>From 547d498662c3b8da2cb87abe9f5c13b39123d90f Mon Sep 17 00:00:00 2001 From: "William S. Moses" <g...@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..bccada911b7ce35 --- /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_test_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 _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits