Skip to content

Commit

Permalink
[PassBuilder] Add a mechanism for adding passbuilder callbacks withou…
Browse files Browse the repository at this point in the history
…t an extension mechanism or dlopen of plugin
  • Loading branch information
wsmoses committed Oct 26, 2023
1 parent 35d771f commit 547d498
Show file tree
Hide file tree
Showing 9 changed files with 156 additions and 0 deletions.
6 changes: 6 additions & 0 deletions clang/include/clang/Basic/CodeGenOptions.h
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,9 @@
#include <string>
#include <vector>

namespace llvm {
class PassBuilder;
}
namespace clang {

/// Bitfields of CodeGenOptions, split out from CodeGenOptions to ensure
Expand Down Expand Up @@ -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.
Expand Down
3 changes: 3 additions & 0 deletions clang/lib/CodeGen/BackendUtil.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand Down
1 change: 1 addition & 0 deletions clang/test/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
6 changes: 6 additions & 0 deletions clang/test/DriverPlugin/plugintest.c
Original file line number Diff line number Diff line change
@@ -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

1 change: 1 addition & 0 deletions clang/tools/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down
59 changes: 59 additions & 0 deletions clang/tools/clang-hello-plugin-test/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -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)
66 changes: 66 additions & 0 deletions clang/tools/clang-hello-plugin-test/helloplugin.cpp
Original file line number Diff line number Diff line change
@@ -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);
}
9 changes: 9 additions & 0 deletions clang/tools/driver/cc1_main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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
//===----------------------------------------------------------------------===//
Expand Down Expand Up @@ -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.
Expand Down
5 changes: 5 additions & 0 deletions llvm/include/llvm/Passes/PassBuilder.h
Original file line number Diff line number Diff line change
Expand Up @@ -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

0 comments on commit 547d498

Please sign in to comment.