[...] struct Hello : public FunctionPass { [...] bool runOnFunction(Function &F) override { [...] } }; static RegisterPass<Hello> X( "hello", "Hello World Pass", false, false);
$ opt -load lib/LLVMHello.so \ -hello < hello.bc > /dev/null
Serge « sans paille » Guelton
Compiler Engineer / Wood Craft Lover / Red Hat employee
LLVM Developers Meeting — 8th of October 2020
static RegisterStandardPasses Y( PassManagerBuilder::EP_EarlyAsPossible, [](const PassManagerBuilder &Builder, legacy::PassManagerBase &PM) { PM.add(new Hello()); });
$ clang -Xclang -load -Xclang lib/LLVMHello.so \ -O1 hello.c -o /dev/null
credits: https://github.com/banach-space/llvm-tutor/
void run(Function &F) { [...] } // New PM implementation struct HelloWorld : PassInfoMixin<HelloWorld> { PreservedAnalyses run(Function &F, FunctionAnalysisManager &) { run(F); return PreservedAnalyses::all(); } }; llvm::PassPluginLibraryInfo getHelloWorldPluginInfo() { return {LLVM_PLUGIN_API_VERSION, "HelloWorld", LLVM_VERSION_STRING, [](PassBuilder &PB) { PB.registerPipelineParsingCallback([...]); }}; } extern "C" LLVM_ATTRIBUTE_WEAK ::llvm::PassPluginLibraryInfo llvmGetPassPluginInfo() { return getHelloWorldPluginInfo(); }
// Legacy PM implementation struct LegacyHelloWorld : public FunctionPass { static char ID; LegacyHelloWorld() : FunctionPass(ID) {} bool runOnFunction(Function &F) override { /* >>>> */ run(F); /* <<<< */ return false; } };
a.k.a a set of passes available both as in and out of tree passes
$ % git grep -i polly origin/release/9.x \ | grep -E -v '(www)|(test)|(doc)|(:polly)' -c 58
Intrusive in both cmake, llvm and clang codebase :-/
What about generalizing the approach?
A combination of CMake and C++ glue to provide:
See llvm-project/llvm/examples/Bye/
+ #ifndef LLVM_BYE_LINK_INTO_TOOLS extern "C" LLVM_ATTRIBUTE_WEAK ::llvm::PassPluginLibraryInfo llvmGetPassPluginInfo() { return getByePluginInfo(); } + #endif
add_llvm_pass_plugin(Bye Bye.cpp DEPENDS intrinsics_gen )
$ cmake -DLLVM_BYE_LINK_INTO_TOOLS=$(($RANDOM %2))
Without Polly
$ llvm-config --components (...) extensions (...] $ llvm-config --libs extensions -lLLVMExtensions -lLLVMSupport -lLLVMDemangle
With Polly and -DLLVM_POLLY_LINK_INTO_TOOLS=OFF
$ llvm-config --libs extensions -lLLVMExtensions -lLLVMSupport -lLLVMDemangle
With Polly and -DLLVM_POLLY_LINK_INTO_TOOLS=ON
$ llvm-config --libs extensions -lLLVMExtensions -lPolly -lPollyISL (...) -lLLVMDemangle
libLLVM10 aggregates all components, so:
from clang/lib/CodeGen/BackendUtil.cpp
#define HANDLE_EXTENSION(Ext) \ llvm::PassPluginLibraryInfo get##Ext##PluginInfo(); #include "llvm/Support/Extension.def" [...] void EmitAssemblyHelper:: EmitAssemblyWithNewPassManager(...) { [...] #define HANDLE_EXTENSION(Ext) \ get##Ext##PluginInfo().RegisterPassBuilderCallbacks(PB); #include "llvm/Support/Extension.def" [...] }
Thanks to that work: