diff --git a/crates/wasmtime/src/runtime.rs b/crates/wasmtime/src/runtime.rs index d3915ae29e..f6eb0e97e4 100644 --- a/crates/wasmtime/src/runtime.rs +++ b/crates/wasmtime/src/runtime.rs @@ -355,6 +355,24 @@ impl Config { self } + /// Allows settings another Cranelift flag defined by a flag name and value. This allows + /// fine-tuning of Cranelift settings. + /// + /// Since Cranelift flags may be unstable, this method should not be considered to be stable + /// either; other `Config` functions should be preferred for stability. + /// + /// Note that this is marked as unsafe, because setting the wrong flag might break invariants, + /// resulting in execution hazards. + /// + /// # Errors + /// + /// This method can fail if the flag's name does not exist, or the value is not appropriate for + /// the flag type. + pub unsafe fn cranelift_other_flag(&mut self, name: &str, value: &str) -> Result<&mut Self> { + self.flags.set(name, value)?; + Ok(self) + } + /// Loads cache configuration specified at `path`. /// /// This method will read the file specified by `path` on the filesystem and diff --git a/src/lib.rs b/src/lib.rs index 6d2241d97d..d0f6476262 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -153,6 +153,10 @@ struct CommonOptions { )] opt_level: wasmtime::OptLevel, + /// Other Cranelift flags to be passed down to Cranelift. + #[structopt(long, parse(try_from_str = parse_cranelift_flag))] + cranelift_flags: Vec, + /// Maximum size in bytes of wasm memory before it becomes dynamically /// relocatable instead of up-front-reserved. #[structopt(long)] @@ -181,6 +185,11 @@ impl CommonOptions { .cranelift_opt_level(self.opt_level()) .strategy(pick_compilation_strategy(self.cranelift, self.lightbeam)?)? .profiler(pick_profiling_strategy(self.jitdump, self.vtune)?)?; + for CraneliftFlag { name, value } in &self.cranelift_flags { + unsafe { + config.cranelift_other_flag(name, value)?; + } + } if !self.disable_cache { match &self.config { Some(path) => { @@ -223,3 +232,23 @@ fn parse_opt_level(opt_level: &str) -> Result { ), } } + +struct CraneliftFlag { + name: String, + value: String, +} + +fn parse_cranelift_flag(name_and_value: &str) -> Result { + let mut split = name_and_value.splitn(2, '='); + let name = if let Some(name) = split.next() { + name.to_string() + } else { + bail!("missing name in cranelift flag"); + }; + let value = if let Some(value) = split.next() { + value.to_string() + } else { + bail!("missing value in cranelift flag"); + }; + Ok(CraneliftFlag { name, value }) +}