Skip to content

Commit 547d498

Browse files
committed
[PassBuilder] Add a mechanism for adding passbuilder callbacks without an extension mechanism or dlopen of plugin
1 parent 35d771f commit 547d498

File tree

9 files changed

+156
-0
lines changed

9 files changed

+156
-0
lines changed

clang/include/clang/Basic/CodeGenOptions.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,9 @@
2626
#include <string>
2727
#include <vector>
2828

29+
namespace llvm {
30+
class PassBuilder;
31+
}
2932
namespace clang {
3033

3134
/// Bitfields of CodeGenOptions, split out from CodeGenOptions to ensure
@@ -408,6 +411,9 @@ class CodeGenOptions : public CodeGenOptionsBase {
408411
/// List of dynamic shared object files to be loaded as pass plugins.
409412
std::vector<std::string> PassPlugins;
410413

414+
/// List of pass builder callbacks.
415+
std::vector<std::function<void(llvm::PassBuilder &)>> PassBuilderCallbacks;
416+
411417
/// Path to allowlist file specifying which objects
412418
/// (files, functions) should exclusively be instrumented
413419
/// by sanitizer coverage pass.

clang/lib/CodeGen/BackendUtil.cpp

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -906,6 +906,9 @@ void EmitAssemblyHelper::RunOptimizationPipeline(
906906
<< PluginFN << toString(PassPlugin.takeError());
907907
}
908908
}
909+
for (auto PassCallback : CodeGenOpts.PassBuilderCallbacks) {
910+
PassCallback(PB);
911+
}
909912
#define HANDLE_EXTENSION(Ext) \
910913
get##Ext##PluginInfo().RegisterPassBuilderCallbacks(PB);
911914
#include "llvm/Support/Extension.def"

clang/test/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,7 @@ list(APPEND CLANG_TEST_DEPS
6262
apinotes-test
6363
c-index-test
6464
clang
65+
clang-hello-plugin-test
6566
clang-fuzzer-dictionary
6667
clang-resource-headers
6768
clang-format

clang/test/DriverPlugin/plugintest.c

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
// RUN: clang-hello-plugin-test %s -o /dev/null -S | FileCheck %s
2+
3+
int myfunction() { return 0; }
4+
5+
// CHECK: [HelloPass] Found function: myfunction
6+

clang/tools/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ create_subdirectory_options(CLANG TOOL)
22

33
add_clang_subdirectory(diagtool)
44
add_clang_subdirectory(driver)
5+
add_clang_subdirectory(clang-hello-plugin-test)
56
add_clang_subdirectory(apinotes-test)
67
add_clang_subdirectory(clang-diff)
78
add_clang_subdirectory(clang-format)
Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
set( LLVM_LINK_COMPONENTS
2+
${LLVM_TARGETS_TO_BUILD}
3+
Analysis
4+
CodeGen
5+
Core
6+
IPO
7+
AggressiveInstCombine
8+
InstCombine
9+
Instrumentation
10+
MC
11+
MCParser
12+
ObjCARCOpts
13+
Option
14+
ScalarOpts
15+
Support
16+
TargetParser
17+
TransformUtils
18+
Vectorize
19+
)
20+
21+
# Support plugins.
22+
if(CLANG_PLUGIN_SUPPORT)
23+
set(support_plugins SUPPORT_PLUGINS)
24+
endif()
25+
26+
add_clang_tool(clang-hello-plugin-test
27+
../driver/driver.cpp
28+
../driver/cc1_main.cpp
29+
../driver/cc1as_main.cpp
30+
../driver/cc1gen_reproducer_main.cpp
31+
helloplugin.cpp
32+
DEPENDS
33+
intrinsics_gen
34+
${support_plugins}
35+
GENERATE_DRIVER
36+
)
37+
38+
clang_target_link_libraries(clang-hello-plugin-test
39+
PRIVATE
40+
clangBasic
41+
clangCodeGen
42+
clangDriver
43+
clangFrontend
44+
clangFrontendTool
45+
clangSerialization
46+
)
47+
48+
if(WIN32 AND NOT CYGWIN)
49+
# Prevent versioning if the buildhost is targeting for Win32.
50+
else()
51+
set_target_properties(clang-hello-plugin-test PROPERTIES VERSION ${CLANG_EXECUTABLE_VERSION})
52+
endif()
53+
54+
# Support plugins.
55+
if(CLANG_PLUGIN_SUPPORT)
56+
export_executable_symbols_for_plugins(clang-hello-plugin-test)
57+
endif()
58+
59+
add_dependencies(clang-hello-plugin-test clang-resource-headers)
Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
1+
//===-- helloplugin.cpp - Hello World test static link plugin ------------===//
2+
//
3+
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4+
// See https://llvm.org/LICENSE.txt for license information.
5+
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6+
//
7+
//===----------------------------------------------------------------------===//
8+
//
9+
// This is a test/example mechanism for statically adding functionality to Clang
10+
// Codegen without requiring a fork of Clang.
11+
//
12+
//===----------------------------------------------------------------------===//
13+
14+
#include "llvm/ADT/SmallVector.h"
15+
#include "llvm/IR/PassManager.h"
16+
#include "llvm/Passes/PassBuilder.h"
17+
#include "llvm/Support/LLVMDriver.h"
18+
19+
#include <functional>
20+
21+
using namespace llvm;
22+
23+
extern SmallVector<std::function<void(llvm::PassBuilder &)>>
24+
PassBuilderCallbacks;
25+
26+
class StaticPlugin {
27+
public:
28+
StaticPlugin(std::function<void(llvm::PassBuilder &)> f) {
29+
PassBuilderCallbacks.push_back(f);
30+
}
31+
};
32+
33+
class HelloPass final : public llvm::AnalysisInfoMixin<HelloPass> {
34+
friend struct llvm::AnalysisInfoMixin<HelloPass>;
35+
36+
private:
37+
static llvm::AnalysisKey Key;
38+
39+
public:
40+
using Result = llvm::PreservedAnalyses;
41+
42+
Result run(llvm::Module &M, llvm::ModuleAnalysisManager &MAM) {
43+
for (auto &F : M)
44+
llvm::outs() << "[HelloPass] Found function: " << F.getName() << "\n";
45+
return PreservedAnalyses::all();
46+
}
47+
48+
static bool isRequired() { return true; }
49+
};
50+
51+
void HelloCallback(llvm::PassBuilder &PB) {
52+
PB.registerPipelineStartEPCallback(
53+
[](ModulePassManager &MPM, OptimizationLevel) {
54+
MPM.addPass(HelloPass());
55+
});
56+
}
57+
58+
StaticPlugin P(HelloCallback);
59+
60+
extern int clang_main(int Argc, char **Argv,
61+
const llvm::ToolContext &ToolContext);
62+
63+
int clang_hello_plugin_test_main(int Argc, char **Argv,
64+
const llvm::ToolContext &ToolContext) {
65+
return clang_main(Argc, Argv, ToolContext);
66+
}

clang/tools/driver/cc1_main.cpp

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,11 @@
5757
using namespace clang;
5858
using namespace llvm::opt;
5959

60+
//! List of pass builder callbacks to be applied, for adding additional
61+
//! functionality via static linking, without maintaining a separate fork of
62+
//! LLVM.
63+
SmallVector<std::function<void(llvm::PassBuilder &)>> PassBuilderCallbacks;
64+
6065
//===----------------------------------------------------------------------===//
6166
// Main driver
6267
//===----------------------------------------------------------------------===//
@@ -227,6 +232,10 @@ int cc1_main(ArrayRef<const char *> Argv, const char *Argv0, void *MainAddr) {
227232
ensureSufficientStack();
228233

229234
std::unique_ptr<CompilerInstance> Clang(new CompilerInstance());
235+
for (auto PassCallback : PassBuilderCallbacks) {
236+
Clang->getCodeGenOpts().PassBuilderCallbacks.push_back(PassCallback);
237+
}
238+
230239
IntrusiveRefCntPtr<DiagnosticIDs> DiagID(new DiagnosticIDs());
231240

232241
// Register the support for object-file-wrapped Clang modules.

llvm/include/llvm/Passes/PassBuilder.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -739,6 +739,11 @@ bool parseAnalysisUtilityPasses(
739739

740740
return false;
741741
}
742+
743+
//! List of pass builder callbacks to be applied, in addition to those imported
744+
//! from plugins or LLVM extensions.
745+
extern SmallVector<std::function<void(PassBuilder &)>>
746+
ListRegisterPassBuilderCallbacks;
742747
}
743748

744749
#endif

0 commit comments

Comments
 (0)