diff --git a/Cargo.lock b/Cargo.lock index 531c3d4e4c..ea52ae6aeb 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -99,9 +99,9 @@ checksum = "28b2cd92db5cbd74e8e5028f7e27dd7aa3090e89e4f2a197cc7c8dfb69c7063b" [[package]] name = "arbitrary" -version = "1.0.1" +version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "237430fd6ed3740afe94eefcc278ae21e050285be882804e0d6e8695f0c94691" +checksum = "c38b6b6b79f671c25e1a3e785b7b82d7562ffc9cd3efdc98627e5668a2472490" dependencies = [ "derive_arbitrary", ] @@ -2819,9 +2819,9 @@ checksum = "55937e1799185b12863d447f42597ed69d9928686b8d88a1df17376a097d8369" [[package]] name = "target-lexicon" -version = "0.12.0" +version = "0.12.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "64ae3b39281e4b14b8123bdbaddd472b7dfe215e444181f2f9d2443c2444f834" +checksum = "d7fa7e55043acb85fca6b3c01485a2eeb6b69c5d21002e273c79e465f43b7ac1" [[package]] name = "tempfile" @@ -3594,6 +3594,7 @@ dependencies = [ "env_logger 0.8.3", "log", "rayon", + "target-lexicon", "tempfile", "v8", "wasm-encoder", diff --git a/crates/fuzzing/Cargo.toml b/crates/fuzzing/Cargo.toml index 6c89ab9962..05fe2d170c 100644 --- a/crates/fuzzing/Cargo.toml +++ b/crates/fuzzing/Cargo.toml @@ -9,10 +9,11 @@ license = "Apache-2.0 WITH LLVM-exception" [dependencies] anyhow = "1.0.22" -arbitrary = { version = "1.0.0", features = ["derive"] } +arbitrary = { version = "1.1.0", features = ["derive"] } env_logger = "0.8.1" log = "0.4.8" rayon = "1.2.1" +target-lexicon = "0.12.3" tempfile = "3.3.0" wasmparser = "0.82" wasmprinter = "0.2.32" diff --git a/crates/fuzzing/src/generators.rs b/crates/fuzzing/src/generators.rs index 7988cacea6..bf8b647e6e 100644 --- a/crates/fuzzing/src/generators.rs +++ b/crates/fuzzing/src/generators.rs @@ -251,6 +251,7 @@ pub struct WasmtimeConfig { use_precompiled_cwasm: bool, /// Configuration for the instance allocation strategy to use. pub strategy: InstanceAllocationStrategy, + codegen: CodegenSettings, } #[derive(Arbitrary, Clone, Debug, Eq, Hash, PartialEq)] @@ -306,6 +307,8 @@ impl Config { .memfd(self.wasmtime.memfd) .allocation_strategy(self.wasmtime.strategy.to_wasmtime()); + self.wasmtime.codegen.configure(&mut cfg); + // If the wasm-smith-generated module use nan canonicalization then we // don't need to enable it, but if it doesn't enable it already then we // enable this codegen option. @@ -569,3 +572,92 @@ impl<'a> Arbitrary<'a> for ModuleConfig { Ok(ModuleConfig { config }) } } + +#[derive(Clone, Debug, Eq, Hash, PartialEq)] +enum CodegenSettings { + Native, + #[allow(dead_code)] + Target { + target: String, + flags: Vec<(String, String)>, + }, +} + +impl CodegenSettings { + fn configure(&self, config: &mut wasmtime::Config) { + match self { + CodegenSettings::Native => {} + CodegenSettings::Target { target, flags } => { + config.target(target).unwrap(); + for (key, value) in flags { + unsafe { + config.cranelift_flag_set(key, value).unwrap(); + } + } + } + } + } +} + +impl<'a> Arbitrary<'a> for CodegenSettings { + #[allow(unused_macros, unused_variables)] + fn arbitrary(u: &mut Unstructured<'a>) -> arbitrary::Result { + // Helper macro to enable clif features based on what the native host + // supports. If the input says to enable a feature and the host doesn't + // support it then that test case is rejected with a warning. + macro_rules! target_features { + ( + test:$test:ident, + $(std: $std:tt => clif: $clif:tt $(ratio: $a:tt in $b:tt)?,)* + ) => ({ + let mut flags = Vec::new(); + $( + let (low, hi) = (1, 2); + $(let (low, hi) = ($a, $b);)? + let enable = u.ratio(low, hi)?; + if enable && !std::$test!($std) { + log::error!("want to enable clif `{}` but host doesn't support it", + $clif); + return Err(arbitrary::Error::EmptyChoose) + } + flags.push(( + $clif.to_string(), + enable.to_string(), + )); + )* + flags + }) + } + #[cfg(target_arch = "x86_64")] + { + if u.ratio(1, 10)? { + let flags = target_features! { + test: is_x86_feature_detected, + std:"sse3" => clif:"has_sse3", + std:"ssse3" => clif:"has_ssse3", + std:"sse4.1" => clif:"has_sse41", + std:"sse4.2" => clif:"has_sse42", + std:"popcnt" => clif:"has_popcnt", + std:"avx" => clif:"has_avx", + std:"avx2" => clif:"has_avx2", + std:"bmi1" => clif:"has_bmi1", + std:"bmi2" => clif:"has_bmi2", + std:"lzcnt" => clif:"has_lzcnt", + + // not a lot of of cpus support avx512 so these are weighted + // to get enabled much less frequently. + std:"avx512bitalg" => clif:"has_avx512bitalg" ratio:1 in 1000, + std:"avx512dq" => clif:"has_avx512dq" ratio: 1 in 1000, + std:"avx512f" => clif:"has_avx512f" ratio: 1 in 1000, + std:"avx512vl" => clif:"has_avx512vl" ratio: 1 in 1000, + std:"avx512vbmi" => clif:"has_avx512vbmi" ratio: 1 in 1000, + }; + return Ok(CodegenSettings::Target { + target: target_lexicon::Triple::host().to_string(), + flags, + }); + } + } + Ok(CodegenSettings::Native) + } +}