From 97cf461b8f4c0ed0de8fdc1c441b904ddb8b3194 Mon Sep 17 00:00:00 2001 From: Axel Cohen Date: Fri, 19 Nov 2021 17:01:41 +0100 Subject: [PATCH] Add a codegen option to allow loading LLVM pass plugins --- compiler/rustc_codegen_llvm/src/back/write.rs | 4 ++++ compiler/rustc_codegen_llvm/src/llvm/ffi.rs | 2 ++ compiler/rustc_codegen_ssa/src/back/write.rs | 4 ++++ compiler/rustc_interface/src/tests.rs | 1 + .../rustc_llvm/llvm-wrapper/PassWrapper.cpp | 18 +++++++++++++++++- compiler/rustc_session/src/options.rs | 2 ++ 6 files changed, 30 insertions(+), 1 deletion(-) diff --git a/compiler/rustc_codegen_llvm/src/back/write.rs b/compiler/rustc_codegen_llvm/src/back/write.rs index fa4fad30830..a28fca3e700 100644 --- a/compiler/rustc_codegen_llvm/src/back/write.rs +++ b/compiler/rustc_codegen_llvm/src/back/write.rs @@ -470,6 +470,8 @@ pub(crate) unsafe fn optimize_with_new_llvm_pass_manager( let extra_passes = config.passes.join(","); + let pass_plugins = config.pass_plugins.join(" "); + // FIXME: NewPM doesn't provide a facility to pass custom InlineParams. // We would have to add upstream support for this first, before we can support // config.inline_threshold and our more aggressive default thresholds. @@ -499,6 +501,8 @@ pub(crate) unsafe fn optimize_with_new_llvm_pass_manager( selfprofile_after_pass_callback, extra_passes.as_ptr().cast(), extra_passes.len(), + pass_plugins.as_ptr().cast(), + pass_plugins.len(), ); result.into_result().map_err(|()| llvm_err(diag_handler, "failed to run LLVM passes")) } diff --git a/compiler/rustc_codegen_llvm/src/llvm/ffi.rs b/compiler/rustc_codegen_llvm/src/llvm/ffi.rs index d9a6723fe27..a225d59dd40 100644 --- a/compiler/rustc_codegen_llvm/src/llvm/ffi.rs +++ b/compiler/rustc_codegen_llvm/src/llvm/ffi.rs @@ -2304,6 +2304,8 @@ extern "C" { end_callback: SelfProfileAfterPassCallback, ExtraPasses: *const c_char, ExtraPassesLen: size_t, + PassPlugins: *const c_char, + PassPluginsLen: size_t, ) -> LLVMRustResult; pub fn LLVMRustPrintModule( M: &'a Module, diff --git a/compiler/rustc_codegen_ssa/src/back/write.rs b/compiler/rustc_codegen_ssa/src/back/write.rs index d6af6104155..65a13282224 100644 --- a/compiler/rustc_codegen_ssa/src/back/write.rs +++ b/compiler/rustc_codegen_ssa/src/back/write.rs @@ -74,6 +74,8 @@ pub enum BitcodeSection { pub struct ModuleConfig { /// Names of additional optimization passes to run. pub passes: Vec, + /// Paths of LLVM pass plugins to load. + pub pass_plugins: Vec, /// Some(level) to optimize at a certain level, or None to run /// absolutely no optimizations (used for the metadata module). pub opt_level: Option, @@ -170,6 +172,8 @@ impl ModuleConfig { ModuleConfig { passes: if_regular!(sess.opts.cg.passes.clone(), vec![]), + pass_plugins: if_regular!(sess.opts.cg.pass_plugins.clone(), vec![]), + opt_level: opt_level_and_size, opt_size: opt_level_and_size, diff --git a/compiler/rustc_interface/src/tests.rs b/compiler/rustc_interface/src/tests.rs index c651feaaa66..f63c04138e8 100644 --- a/compiler/rustc_interface/src/tests.rs +++ b/compiler/rustc_interface/src/tests.rs @@ -587,6 +587,7 @@ fn test_codegen_options_tracking_hash() { tracked!(overflow_checks, Some(true)); tracked!(panic, Some(PanicStrategy::Abort)); tracked!(passes, vec![String::from("1"), String::from("2")]); + tracked!(pass_plugins, vec![String::from("1"), String::from("2")]); tracked!(prefer_dynamic, true); tracked!(profile_generate, SwitchWithOptPath::Enabled(None)); tracked!(profile_use, Some(PathBuf::from("abc"))); diff --git a/compiler/rustc_llvm/llvm-wrapper/PassWrapper.cpp b/compiler/rustc_llvm/llvm-wrapper/PassWrapper.cpp index 4f77db8a24d..32a2ffcef00 100644 --- a/compiler/rustc_llvm/llvm-wrapper/PassWrapper.cpp +++ b/compiler/rustc_llvm/llvm-wrapper/PassWrapper.cpp @@ -17,6 +17,7 @@ #include "llvm/Object/ObjectFile.h" #include "llvm/Object/IRObjectFile.h" #include "llvm/Passes/PassBuilder.h" +#include "llvm/Passes/PassPlugin.h" #include "llvm/Passes/StandardInstrumentations.h" #include "llvm/Support/CBindingWrapping.h" #include "llvm/Support/FileSystem.h" @@ -753,7 +754,8 @@ LLVMRustOptimizeWithNewPassManager( void* LlvmSelfProfiler, LLVMRustSelfProfileBeforePassCallback BeforePassCallback, LLVMRustSelfProfileAfterPassCallback AfterPassCallback, - const char *ExtraPasses, size_t ExtraPassesLen) { + const char *ExtraPasses, size_t ExtraPassesLen, + const char *PassPlugins, size_t PassPluginsLen) { Module *TheModule = unwrap(ModuleRef); TargetMachine *TM = unwrap(TMRef); OptimizationLevel OptLevel = fromRust(OptLevelRust); @@ -924,6 +926,20 @@ LLVMRustOptimizeWithNewPassManager( } } + if (PassPluginsLen) { + auto PluginsStr = StringRef(PassPlugins, PassPluginsLen); + SmallVector Plugins; + PluginsStr.split(Plugins, ' ', -1, false); + for (auto PluginPath: Plugins) { + auto Plugin = PassPlugin::Load(PluginPath.str()); + if (!Plugin) { + LLVMRustSetLastError(("Failed to load pass plugin" + PluginPath.str()).c_str()); + continue; + } + Plugin->registerPassBuilderCallbacks(PB); + } + } + #if LLVM_VERSION_GE(13, 0) ModulePassManager MPM; #else diff --git a/compiler/rustc_session/src/options.rs b/compiler/rustc_session/src/options.rs index bd7b1639613..dcff4790535 100644 --- a/compiler/rustc_session/src/options.rs +++ b/compiler/rustc_session/src/options.rs @@ -1033,6 +1033,8 @@ options! { "panic strategy to compile crate with"), passes: Vec = (Vec::new(), parse_list, [TRACKED], "a list of extra LLVM passes to run (space separated)"), + pass_plugins: Vec = (Vec::new(), parse_list, [TRACKED], + "a list of LLVM pass plugins to load (space separated)"), prefer_dynamic: bool = (false, parse_bool, [TRACKED], "prefer dynamic linking to static linking (default: no)"), profile_generate: SwitchWithOptPath = (SwitchWithOptPath::Disabled,