Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Clang] Add codegen option to add passbuilder callback functions #70171

Merged
merged 1 commit into from
Nov 7, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions clang/examples/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ if(NOT CLANG_BUILD_EXAMPLES)
endif()

if(CLANG_PLUGIN_SUPPORT)
add_subdirectory(LLVMPrintFunctionNames)
add_subdirectory(PrintFunctionNames)
add_subdirectory(AnnotateFunctions)
add_subdirectory(Attribute)
Expand Down
23 changes: 23 additions & 0 deletions clang/examples/LLVMPrintFunctionNames/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
# If we don't need RTTI or EH, there's no reason to export anything
# from the plugin.
if(NOT MSVC) # MSVC mangles symbols differently, and
# PrintLLVMFunctionNames.export contains C++ symbols.
if(NOT LLVM_REQUIRES_RTTI)
if(NOT LLVM_REQUIRES_EH)
set(LLVM_EXPORTED_SYMBOL_FILE ${CMAKE_CURRENT_SOURCE_DIR}/LLVMPrintFunctionNames.exports)
endif()
endif()
endif()

add_llvm_library(LLVMPrintFunctionNames MODULE LLVMPrintFunctionNames.cpp PLUGIN_TOOL clang)

if(WIN32 OR CYGWIN)
set(LLVM_LINK_COMPONENTS
Support
)
clang_target_link_libraries(LLVMPrintFunctionNames PRIVATE
clangAST
clangBasic
clangFrontend
)
endif()
78 changes: 78 additions & 0 deletions clang/examples/LLVMPrintFunctionNames/LLVMPrintFunctionNames.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
//===- LLVMPrintFunctionNames.cpp
//---------------------------------------------===//
//
// 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
//
//===----------------------------------------------------------------------===//
//
// Example clang plugin which simply prints the names of all the functions
// within the generated LLVM code.
//
//===----------------------------------------------------------------------===//

#include "clang/AST/AST.h"
#include "clang/AST/ASTConsumer.h"
#include "clang/AST/RecursiveASTVisitor.h"
#include "clang/Frontend/CompilerInstance.h"
#include "clang/Frontend/FrontendPluginRegistry.h"
#include "clang/Sema/Sema.h"
#include "llvm/IR/PassManager.h"
#include "llvm/Passes/OptimizationLevel.h"
#include "llvm/Passes/PassBuilder.h"
#include "llvm/Support/raw_ostream.h"
using namespace clang;

namespace {

class PrintPass final : public llvm::AnalysisInfoMixin<PrintPass> {
friend struct llvm::AnalysisInfoMixin<PrintPass>;

private:
static llvm::AnalysisKey key;

public:
using Result = llvm::PreservedAnalyses;

Result run(llvm::Module &M, llvm::ModuleAnalysisManager &MAM) {
for (auto &F : M)
llvm::outs() << "[PrintPass] Found function: " << F.getName() << "\n";
return llvm::PreservedAnalyses::all();
}
static bool isRequired() { return true; }
};

void PrintCallback(llvm::PassBuilder &PB) {
PB.registerPipelineStartEPCallback(
[](llvm::ModulePassManager &MPM, llvm::OptimizationLevel) {
MPM.addPass(PrintPass());
});
}

class LLVMPrintFunctionsConsumer : public ASTConsumer {
public:
LLVMPrintFunctionsConsumer(CompilerInstance &Instance) {
Instance.getCodeGenOpts().PassBuilderCallbacks.push_back(PrintCallback);
}
};

class LLVMPrintFunctionNamesAction : public PluginASTAction {
protected:
std::unique_ptr<ASTConsumer> CreateASTConsumer(CompilerInstance &CI,
llvm::StringRef) override {
return std::make_unique<LLVMPrintFunctionsConsumer>(CI);
}
bool ParseArgs(const CompilerInstance &,
const std::vector<std::string> &) override {
return true;
}
PluginASTAction::ActionType getActionType() override {
return AddBeforeMainAction;
}
};

} // namespace

static FrontendPluginRegistry::Add<LLVMPrintFunctionNamesAction>
X("llvm-print-fns", "print function names, llvm level");
Empty file.
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
2 changes: 2 additions & 0 deletions clang/lib/CodeGen/BackendUtil.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -906,6 +906,8 @@ 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 @@ -100,6 +100,7 @@ if(CLANG_BUILD_EXAMPLES AND CLANG_PLUGIN_SUPPORT)
CallSuperAttr
PluginsOrder
PrintFunctionNames
LLVMPrintFunctionNames
)
endif ()

Expand Down
5 changes: 5 additions & 0 deletions clang/test/Frontend/llvmplugins.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
// RUN: %clang_cc1 -load %llvmshlibdir/LLVMPrintFunctionNames%pluginext -S -o /dev/null -emit-llvm %s 2>&1 | FileCheck %s
// REQUIRES: plugins, examples

// CHECK: [PrintPass] Found function: x
int x(int y){ return y; }