Path: blob/main/crates/fuzzing/src/generators/codegen_settings.rs
1693 views
//! Generate Cranelift compiler settings.12use arbitrary::{Arbitrary, Unstructured};34/// Choose between matching the host architecture or a cross-compilation target.5#[derive(Clone, Debug, Eq, Hash, PartialEq)]6pub enum CodegenSettings {7/// Use the host's feature set.8Native,9/// Generate a modified flag set for the current host.10Target {11/// The target triple of the host.12target: String,13/// A list of CPU features to enable, e.g., `("has_avx", "false")`.14flags: Vec<(String, String)>,15},16}1718impl CodegenSettings {19/// Configure Wasmtime with these codegen settings.20pub fn configure(&self, config: &mut wasmtime_cli_flags::CommonOptions) {21match self {22CodegenSettings::Native => {}23CodegenSettings::Target { target, flags } => {24config.target = Some(target.to_string());25for (key, value) in flags {26config27.codegen28.cranelift29.push((key.clone(), Some(value.clone())));30}31}32}33}3435/// Returns the flags used for codegen.36pub(crate) fn flags(&self) -> &[(String, String)] {37if let Self::Target { flags, .. } = self {38flags39} else {40&[]41}42}43}4445impl<'a> Arbitrary<'a> for CodegenSettings {46#[expect(unused_variables, reason = "macro-generated code")]47fn arbitrary(u: &mut Unstructured<'a>) -> arbitrary::Result<Self> {48// Helper macro to enable clif features based on what the native host49// supports. If the input says to enable a feature and the host doesn't50// support it then that test case is rejected with a warning.51//52// Note that this specifically consumes bytes from the fuzz input for53// features for all targets, discarding anything which isn't applicable54// to the current target. The theory behind this is that most fuzz bugs55// won't be related to this feature selection so by consistently56// consuming input irrespective of the current platform reproducing fuzz57// bugs should be easier between different architectures.58macro_rules! target_features {59(60$(61$arch:tt => {62test:$test:ident,63$(std: $std:tt => clif: $clif:tt $(ratio: $a:tt in $b:tt)?,)*64},65)*66) => ({67let mut flags = Vec::new();68$( // for each `$arch`69$( // for each `$std`/`$clif` pair70// Use the input to generate whether `$clif` will be71// enabled. By default this is a 1 in 2 chance but each72// feature supports a custom ratio as well which shadows73// the (low, hi)74let (low, hi) = (1, 2);75$(let (low, hi) = ($a, $b);)?76let enable = u.ratio(low, hi)?;7778// If we're actually on the relevant platform and the79// feature is enabled be sure to check that this host80// supports it. If the host doesn't support it then81// print a warning and return an error because this fuzz82// input must be discarded.83#[cfg(target_arch = $arch)]84if enable && !std::arch::$test!($std) {85log::warn!("want to enable clif `{}` but host doesn't support it",86$clif);87return Err(arbitrary::Error::EmptyChoose)88}8990// And finally actually push the feature into the set of91// flags to enable, but only if we're on the right92// architecture.93if cfg!(target_arch = $arch) {94flags.push((95$clif.to_string(),96enable.to_string(),97));98}99)*100)*101flags102})103}104if u.ratio(1, 10)? {105let flags = target_features! {106"x86_64" => {107test: is_x86_feature_detected,108109std:"cmpxchg16b" => clif:"has_cmpxchg16b",110std:"sse3" => clif:"has_sse3",111std:"ssse3" => clif:"has_ssse3",112std:"sse4.1" => clif:"has_sse41",113std:"sse4.2" => clif:"has_sse42",114std:"popcnt" => clif:"has_popcnt",115std:"avx" => clif:"has_avx",116std:"avx2" => clif:"has_avx2",117std:"fma" => clif:"has_fma",118std:"bmi1" => clif:"has_bmi1",119std:"bmi2" => clif:"has_bmi2",120std:"lzcnt" => clif:"has_lzcnt",121122// not a lot of of cpus support avx512 so these are weighted123// to get enabled much less frequently.124std:"avx512bitalg" => clif:"has_avx512bitalg" ratio:1 in 1000,125std:"avx512dq" => clif:"has_avx512dq" ratio: 1 in 1000,126std:"avx512f" => clif:"has_avx512f" ratio: 1 in 1000,127std:"avx512vl" => clif:"has_avx512vl" ratio: 1 in 1000,128std:"avx512vbmi" => clif:"has_avx512vbmi" ratio: 1 in 1000,129},130"aarch64" => {131test: is_aarch64_feature_detected,132133std: "bti" => clif: "use_bti",134std: "lse" => clif: "has_lse",135std: "fp16" => clif: "has_fp16",136// even though the natural correspondence seems to be137// between "paca" and "has_pauth", the latter has no effect138// in isolation, so we actually use the setting that affects139// code generation140std: "paca" => clif: "sign_return_address",141// "paca" and "pacg" check for the same underlying142// architectural feature, so we use the latter to cover more143// code generation settings, of which we have chosen the one144// with the most significant effect145std: "pacg" => clif: "sign_return_address_all" ratio: 1 in 2,146},147};148return Ok(CodegenSettings::Target {149target: target_lexicon::Triple::host().to_string(),150flags,151});152}153Ok(CodegenSettings::Native)154}155}156157158