| #include "llvm/IR/Function.h" | |
| #include "llvm/IR/LegacyPassManager.h" | |
| #include "llvm/Pass.h" | |
| #include "llvm/Passes/PassBuilder.h" | |
| #include "llvm/Plugins/PassPlugin.h" | |
| #include "llvm/Support/CommandLine.h" | |
| #include "llvm/Support/raw_ostream.h" | |
| using namespace llvm; | |
| static cl::opt<bool> Wave("wave-goodbye", cl::init(false), | |
| cl::desc("wave good bye")); | |
| static cl::opt<bool> LastWords("last-words", cl::init(false), | |
| cl::desc("say last words (suppress codegen)")); | |
| static cl::opt<std::string> Greeting("bye-greeting", | |
| cl::desc("also print this greeting")); | |
| namespace { | |
| bool runBye(Function &F) { | |
| if (Wave) { | |
| errs() << "Bye: "; | |
| errs().write_escaped(F.getName()) << '\n'; | |
| } | |
| if (!Greeting.empty()) { | |
| errs() << Greeting << ": "; | |
| errs().write_escaped(F.getName()) << '\n'; | |
| } | |
| return false; | |
| } | |
| struct LegacyBye : public FunctionPass { | |
| static char ID; | |
| LegacyBye() : FunctionPass(ID) {} | |
| bool runOnFunction(Function &F) override { return runBye(F); } | |
| }; | |
| struct Bye : OptionalPassInfoMixin<Bye> { | |
| PreservedAnalyses run(Function &F, FunctionAnalysisManager &) { | |
| if (!runBye(F)) | |
| return PreservedAnalyses::all(); | |
| return PreservedAnalyses::none(); | |
| } | |
| }; | |
| void registerPassBuilderCallbacks(PassBuilder &PB) { | |
| PB.registerVectorizerStartEPCallback( | |
| [](llvm::FunctionPassManager &PM, OptimizationLevel Level) { | |
| PM.addPass(Bye()); | |
| }); | |
| PB.registerPipelineParsingCallback( | |
| [](StringRef Name, llvm::FunctionPassManager &PM, | |
| ArrayRef<llvm::PassBuilder::PipelineElement>) { | |
| if (Name == "goodbye") { | |
| PM.addPass(Bye()); | |
| return true; | |
| } | |
| return false; | |
| }); | |
| } | |
| bool preCodeGenCallback(Module &M, TargetMachine &, CodeGenFileType CGFT, | |
| raw_pwrite_stream &OS) { | |
| if (LastWords) { | |
| if (CGFT != CodeGenFileType::AssemblyFile) { | |
| // Test error emission. | |
| M.getContext().emitError("last words unsupported for binary output"); | |
| return false; | |
| } | |
| OS << "CodeGen Bye\n"; | |
| return true; // Suppress remaining compilation pipeline. | |
| } | |
| // Do nothing. | |
| return false; | |
| } | |
| } // namespace | |
| char LegacyBye::ID = 0; | |
| static RegisterPass<LegacyBye> X("goodbye", "Good Bye World Pass", | |
| false /* Only looks at CFG */, | |
| false /* Analysis Pass */); | |
| static Error parseArguments(ArrayRef<const char *> Args) { | |
| SmallVector<const char *, 0> Argv = {"Bye"}; | |
| append_range(Argv, Args); | |
| std::string Msg; | |
| raw_string_ostream OS(Msg); | |
| if (!cl::ParseCommandLineOptions(Argv.size(), Argv.data(), "", &OS)) | |
| return createStringError(StringRef(Msg).trim()); | |
| return Error::success(); | |
| } | |
| /* New PM Registration */ | |
| llvm::PassPluginLibraryInfo getByePluginInfo() { | |
| return {LLVM_PLUGIN_API_VERSION, "Bye", | |
| LLVM_VERSION_STRING, registerPassBuilderCallbacks, | |
| preCodeGenCallback, parseArguments}; | |
| } | |
| #ifndef LLVM_BYE_LINK_INTO_TOOLS | |
| extern "C" LLVM_ATTRIBUTE_WEAK ::llvm::PassPluginLibraryInfo | |
| llvmGetPassPluginInfo() { | |
| return getByePluginInfo(); | |
| } | |
| #endif |