Fuzz multiple targets in cranelift-icache (#5482)

Fuzz additional targets in the cranelift-icache target. The list of targets fuzzed is controlled by the targets enabled in fuzz/Cargo.toml.

This PR also reworks how instruction disabling is done in function generator, moving the deny-list to a function to make the decision at runtime instead of compile time.
This commit is contained in:
Trevor Elliott
2023-01-05 10:49:23 -08:00
committed by GitHub
parent ee6a909ccb
commit 36e5bdfd0e
8 changed files with 341 additions and 242 deletions

1
Cargo.lock generated
View File

@@ -635,6 +635,7 @@ dependencies = [
"arbitrary", "arbitrary",
"cranelift", "cranelift",
"cranelift-native", "cranelift-native",
"target-lexicon",
] ]
[[package]] [[package]]

View File

@@ -105,6 +105,11 @@ pub fn lookup(triple: Triple) -> Result<Builder, LookupError> {
} }
} }
/// The string names of all the supported, but possibly not enabled, architectures. The elements of
/// this slice are suitable to be passed to the [lookup_by_name] function to obtain the default
/// configuration for that architecture.
pub const ALL_ARCHITECTURES: &[&str] = &["x86_64", "aarch64", "s390x", "riscv64"];
/// Look for a supported ISA with the given `name`. /// Look for a supported ISA with the given `name`.
/// Return a builder that can create a corresponding `TargetIsa`. /// Return a builder that can create a corresponding `TargetIsa`.
pub fn lookup_by_name(name: &str) -> Result<Builder, LookupError> { pub fn lookup_by_name(name: &str) -> Result<Builder, LookupError> {

View File

@@ -16,3 +16,4 @@ cranelift-native = { workspace = true }
anyhow = { workspace = true } anyhow = { workspace = true }
arbitrary = "1.0.0" arbitrary = "1.0.0"
target-lexicon = { workspace = true, features = ["std"] }

View File

@@ -17,6 +17,7 @@ use cranelift::prelude::{
}; };
use std::collections::HashMap; use std::collections::HashMap;
use std::ops::RangeInclusive; use std::ops::RangeInclusive;
use target_lexicon::{Architecture, Triple};
/// Generates a Vec with `len` elements comprised of `options` /// Generates a Vec with `len` elements comprised of `options`
fn arbitrary_vec<T: Clone>( fn arbitrary_vec<T: Clone>(
@@ -144,10 +145,15 @@ fn insert_cmp(
let rhs = builder.use_var(rhs); let rhs = builder.use_var(rhs);
let res = if opcode == Opcode::Fcmp { let res = if opcode == Opcode::Fcmp {
let cc = *fgen.u.choose(FloatCC::all())?;
// Some FloatCC's are not implemented on AArch64, see: // Some FloatCC's are not implemented on AArch64, see:
// https://github.com/bytecodealliance/wasmtime/issues/4850 // https://github.com/bytecodealliance/wasmtime/issues/4850
let float_cc = if cfg!(target_arch = "aarch64") { // We filter out condition codes that aren't supported by the target at
&[ // this point after randomly choosing one, instead of randomly choosing a
// supported one, to avoid invalidating the corpus when these get implemented.
if matches!(fgen.target_triple.architecture, Architecture::Aarch64(_))
&& ![
FloatCC::Ordered, FloatCC::Ordered,
FloatCC::Unordered, FloatCC::Unordered,
FloatCC::Equal, FloatCC::Equal,
@@ -157,11 +163,11 @@ fn insert_cmp(
FloatCC::GreaterThan, FloatCC::GreaterThan,
FloatCC::GreaterThanOrEqual, FloatCC::GreaterThanOrEqual,
] ]
} else { .contains(&cc)
FloatCC::all() {
return Err(arbitrary::Error::IncorrectFormat.into());
}; };
let cc = *fgen.u.choose(float_cc)?;
builder.ins().fcmp(cc, lhs, rhs) builder.ins().fcmp(cc, lhs, rhs)
} else { } else {
let cc = *fgen.u.choose(IntCC::all())?; let cc = *fgen.u.choose(IntCC::all())?;
@@ -251,14 +257,222 @@ type OpcodeInserter = fn(
&'static [Type], &'static [Type],
) -> Result<()>; ) -> Result<()>;
// TODO: Derive this from the `cranelift-meta` generator. /// Returns true if we believe this `OpcodeSignature` should compile correctly
#[rustfmt::skip] /// for the given target triple. We currently have a range of known issues
const OPCODE_SIGNATURES: &'static [( /// with specific lowerings on specific backends, and we don't want to get
/// fuzz bug reports for those. Over time our goal is to eliminate all of these
/// exceptions.
fn valid_for_target(triple: &Triple, op: Opcode, args: &[Type], rets: &[Type]) -> bool {
macro_rules! exceptions {
( $(($($cases:pat),*)),* $(,)?) => {
match (op, args, rets) {
$( ($($cases,)* ..) => false, )*
_ => true,
}
}
}
match triple.architecture {
Architecture::X86_64 => {
exceptions!(
(Opcode::IaddCout, &[I8, I8]),
(Opcode::IaddCout, &[I16, I16]),
(Opcode::IaddCout, &[I128, I128]),
// https://github.com/bytecodealliance/wasmtime/issues/5468
(Opcode::Smulhi, &[I8, I8]),
// https://github.com/bytecodealliance/wasmtime/issues/5468
(Opcode::Umulhi, &[I8, I8]),
// https://github.com/bytecodealliance/wasmtime/issues/4756
(Opcode::Udiv, &[I128, I128]),
// https://github.com/bytecodealliance/wasmtime/issues/4770
(Opcode::Sdiv, &[I128, I128]),
// https://github.com/bytecodealliance/wasmtime/issues/5474
(Opcode::Urem, &[I128, I128]),
// https://github.com/bytecodealliance/wasmtime/issues/5470
(Opcode::Srem, &[I8, I8]),
// https://github.com/bytecodealliance/wasmtime/issues/5474
(Opcode::Srem, &[I128, I128]),
// https://github.com/bytecodealliance/wasmtime/issues/5466
(Opcode::Iabs),
// https://github.com/bytecodealliance/wasmtime/issues/3370
(Opcode::Smin, &[I128, I128]),
// https://github.com/bytecodealliance/wasmtime/issues/3370
(Opcode::Umin, &[I128, I128]),
// https://github.com/bytecodealliance/wasmtime/issues/3370
(Opcode::Smax, &[I128, I128]),
// https://github.com/bytecodealliance/wasmtime/issues/3370
(Opcode::Umax, &[I128, I128]),
// https://github.com/bytecodealliance/wasmtime/issues/4870
(Opcode::Band, &[F32, F32]),
(Opcode::Band, &[F64, F64]),
// https://github.com/bytecodealliance/wasmtime/issues/4870
(Opcode::Bor, &[F32, F32]),
(Opcode::Bor, &[F64, F64]),
// https://github.com/bytecodealliance/wasmtime/issues/4870
(Opcode::Bxor, &[F32, F32]),
(Opcode::Bxor, &[F64, F64]),
// https://github.com/bytecodealliance/wasmtime/issues/4870
(Opcode::Bnot, &[F32, F32]),
(Opcode::Bnot, &[F64, F64]),
// https://github.com/bytecodealliance/wasmtime/issues/5041
(Opcode::BandNot, &[I8, I8]),
(Opcode::BandNot, &[I16, I16]),
(Opcode::BandNot, &[I32, I32]),
(Opcode::BandNot, &[I64, I64]),
(Opcode::BandNot, &[I128, I128]),
// https://github.com/bytecodealliance/wasmtime/issues/4870
(Opcode::BandNot, &[F32, F32]),
(Opcode::BandNot, &[F64, F64]),
// https://github.com/bytecodealliance/wasmtime/issues/5041
(Opcode::BorNot, &[I8, I8]),
(Opcode::BorNot, &[I16, I16]),
(Opcode::BorNot, &[I32, I32]),
(Opcode::BorNot, &[I64, I64]),
(Opcode::BorNot, &[I128, I128]),
// https://github.com/bytecodealliance/wasmtime/issues/4870
(Opcode::BorNot, &[F32, F32]),
(Opcode::BorNot, &[F64, F64]),
// https://github.com/bytecodealliance/wasmtime/issues/5041
(Opcode::BxorNot, &[I8, I8]),
(Opcode::BxorNot, &[I16, I16]),
(Opcode::BxorNot, &[I32, I32]),
(Opcode::BxorNot, &[I64, I64]),
(Opcode::BxorNot, &[I128, I128]),
// https://github.com/bytecodealliance/wasmtime/issues/4870
(Opcode::BxorNot, &[F32, F32]),
(Opcode::BxorNot, &[F64, F64]),
// https://github.com/bytecodealliance/wasmtime/issues/5107
(Opcode::Cls, &[I8], &[I8]),
(Opcode::Cls, &[I16], &[I16]),
(Opcode::Cls, &[I32], &[I32]),
(Opcode::Cls, &[I64], &[I64]),
(Opcode::Cls, &[I128], &[I128]),
// https://github.com/bytecodealliance/wasmtime/issues/5197
(Opcode::Bitselect, &[I8, I8, I8]),
(Opcode::Bitselect, &[I16, I16, I16]),
(Opcode::Bitselect, &[I32, I32, I32]),
(Opcode::Bitselect, &[I64, I64, I64]),
(Opcode::Bitselect, &[I128, I128, I128]),
// https://github.com/bytecodealliance/wasmtime/issues/4897
// https://github.com/bytecodealliance/wasmtime/issues/4899
(Opcode::FcvtToUint, &[F32], &[I8]),
(Opcode::FcvtToUint, &[F32], &[I16]),
(Opcode::FcvtToUint, &[F32], &[I128]),
(Opcode::FcvtToUint, &[F64], &[I8]),
(Opcode::FcvtToUint, &[F64], &[I16]),
(Opcode::FcvtToUint, &[F64], &[I128]),
// https://github.com/bytecodealliance/wasmtime/issues/4897
// https://github.com/bytecodealliance/wasmtime/issues/4899
(Opcode::FcvtToUintSat, &[F32], &[I8]),
(Opcode::FcvtToUintSat, &[F32], &[I16]),
(Opcode::FcvtToUintSat, &[F32], &[I128]),
(Opcode::FcvtToUintSat, &[F64], &[I8]),
(Opcode::FcvtToUintSat, &[F64], &[I16]),
(Opcode::FcvtToUintSat, &[F64], &[I128]),
// https://github.com/bytecodealliance/wasmtime/issues/4897
// https://github.com/bytecodealliance/wasmtime/issues/4899
(Opcode::FcvtToSint, &[F32], &[I8]),
(Opcode::FcvtToSint, &[F32], &[I16]),
(Opcode::FcvtToSint, &[F32], &[I128]),
(Opcode::FcvtToSint, &[F64], &[I8]),
(Opcode::FcvtToSint, &[F64], &[I16]),
(Opcode::FcvtToSint, &[F64], &[I128]),
// https://github.com/bytecodealliance/wasmtime/issues/4897
// https://github.com/bytecodealliance/wasmtime/issues/4899
(Opcode::FcvtToSintSat, &[F32], &[I8]),
(Opcode::FcvtToSintSat, &[F32], &[I16]),
(Opcode::FcvtToSintSat, &[F32], &[I128]),
(Opcode::FcvtToSintSat, &[F64], &[I8]),
(Opcode::FcvtToSintSat, &[F64], &[I16]),
(Opcode::FcvtToSintSat, &[F64], &[I128]),
// https://github.com/bytecodealliance/wasmtime/issues/4900
(Opcode::FcvtFromUint, &[I128], &[F32]),
(Opcode::FcvtFromUint, &[I128], &[F64]),
// https://github.com/bytecodealliance/wasmtime/issues/4900
(Opcode::FcvtFromSint, &[I128], &[F32]),
(Opcode::FcvtFromSint, &[I128], &[F64]),
)
}
Architecture::Aarch64(_) => {
exceptions!(
(Opcode::IaddCout, &[I128, I128]),
// https://github.com/bytecodealliance/wasmtime/issues/4864
(Opcode::Udiv, &[I128, I128]),
// https://github.com/bytecodealliance/wasmtime/issues/4864
(Opcode::Sdiv, &[I128, I128]),
// https://github.com/bytecodealliance/wasmtime/issues/5472
(Opcode::Urem, &[I128, I128]),
// https://github.com/bytecodealliance/wasmtime/issues/5472
(Opcode::Srem, &[I128, I128]),
// https://github.com/bytecodealliance/wasmtime/issues/5467
(Opcode::Iabs, &[I128]),
// https://github.com/bytecodealliance/wasmtime/issues/4313
(Opcode::Smin, &[I128, I128]),
// https://github.com/bytecodealliance/wasmtime/issues/4313
(Opcode::Umin, &[I128, I128]),
// https://github.com/bytecodealliance/wasmtime/issues/4313
(Opcode::Smax, &[I128, I128]),
// https://github.com/bytecodealliance/wasmtime/issues/4313
(Opcode::Umax, &[I128, I128]),
// https://github.com/bytecodealliance/wasmtime/issues/4870
(Opcode::Band, &[F32, F32]),
(Opcode::Band, &[F64, F64]),
// https://github.com/bytecodealliance/wasmtime/issues/4870
(Opcode::Bor, &[F32, F32]),
(Opcode::Bor, &[F64, F64]),
// https://github.com/bytecodealliance/wasmtime/issues/4870
(Opcode::Bxor, &[F32, F32]),
(Opcode::Bxor, &[F64, F64]),
// https://github.com/bytecodealliance/wasmtime/issues/4870
(Opcode::Bnot, &[F32, F32]),
(Opcode::Bnot, &[F64, F64]),
// https://github.com/bytecodealliance/wasmtime/issues/4870
(Opcode::BandNot, &[F32, F32]),
(Opcode::BandNot, &[F64, F64]),
// https://github.com/bytecodealliance/wasmtime/issues/4870
(Opcode::BorNot, &[F32, F32]),
(Opcode::BorNot, &[F64, F64]),
// https://github.com/bytecodealliance/wasmtime/issues/4870
(Opcode::BxorNot, &[F32, F32]),
(Opcode::BxorNot, &[F64, F64]),
// https://github.com/bytecodealliance/wasmtime/issues/5198
(Opcode::Bitselect, &[I128, I128, I128]),
// https://github.com/bytecodealliance/wasmtime/issues/4934
(Opcode::FcvtToUint, &[F32]),
(Opcode::FcvtToUint, &[F64]),
// https://github.com/bytecodealliance/wasmtime/issues/4934
(Opcode::FcvtToUintSat, &[F32]),
(Opcode::FcvtToUintSat, &[F64]),
// https://github.com/bytecodealliance/wasmtime/issues/4934
(Opcode::FcvtToSint, &[F32]),
(Opcode::FcvtToSint, &[F64]),
// https://github.com/bytecodealliance/wasmtime/issues/4934
(Opcode::FcvtToSintSat, &[F32]),
(Opcode::FcvtToSintSat, &[F64]),
// https://github.com/bytecodealliance/wasmtime/issues/4933
(Opcode::FcvtFromUint, &[I128], &[F32]),
(Opcode::FcvtFromUint, &[I128], &[F64]),
// https://github.com/bytecodealliance/wasmtime/issues/4933
(Opcode::FcvtFromSint, &[I128], &[F32]),
(Opcode::FcvtFromSint, &[I128], &[F64]),
)
}
_ => true,
}
}
type OpcodeSignature = (
Opcode, Opcode,
&'static [Type], // Args &'static [Type], // Args
&'static [Type], // Rets &'static [Type], // Rets
OpcodeInserter, OpcodeInserter,
)] = &[ );
// TODO: Derive this from the `cranelift-meta` generator.
#[rustfmt::skip]
const OPCODE_SIGNATURES: &[OpcodeSignature] = &[
(Opcode::Nop, &[], &[], insert_opcode), (Opcode::Nop, &[], &[], insert_opcode),
// Iadd // Iadd
(Opcode::Iadd, &[I8, I8], &[I8], insert_opcode), (Opcode::Iadd, &[I8, I8], &[I8], insert_opcode),
@@ -267,14 +481,10 @@ const OPCODE_SIGNATURES: &'static [(
(Opcode::Iadd, &[I64, I64], &[I64], insert_opcode), (Opcode::Iadd, &[I64, I64], &[I64], insert_opcode),
(Opcode::Iadd, &[I128, I128], &[I128], insert_opcode), (Opcode::Iadd, &[I128, I128], &[I128], insert_opcode),
// IaddCout // IaddCout
// IaddCout not implemented in x64
#[cfg(not(target_arch = "x86_64"))]
(Opcode::IaddCout, &[I8, I8], &[I8, I8], insert_opcode), (Opcode::IaddCout, &[I8, I8], &[I8, I8], insert_opcode),
#[cfg(not(target_arch = "x86_64"))]
(Opcode::IaddCout, &[I16, I16], &[I16, I8], insert_opcode), (Opcode::IaddCout, &[I16, I16], &[I16, I8], insert_opcode),
(Opcode::IaddCout, &[I32, I32], &[I32, I8], insert_opcode), (Opcode::IaddCout, &[I32, I32], &[I32, I8], insert_opcode),
(Opcode::IaddCout, &[I64, I64], &[I64, I8], insert_opcode), (Opcode::IaddCout, &[I64, I64], &[I64, I8], insert_opcode),
#[cfg(not(any(target_arch = "x86_64", target_arch = "aarch64")))]
(Opcode::IaddCout, &[I128, I128], &[I128, I8], insert_opcode), (Opcode::IaddCout, &[I128, I128], &[I128, I8], insert_opcode),
// Isub // Isub
(Opcode::Isub, &[I8, I8], &[I8], insert_opcode), (Opcode::Isub, &[I8, I8], &[I8], insert_opcode),
@@ -289,15 +499,11 @@ const OPCODE_SIGNATURES: &'static [(
(Opcode::Imul, &[I64, I64], &[I64], insert_opcode), (Opcode::Imul, &[I64, I64], &[I64], insert_opcode),
(Opcode::Imul, &[I128, I128], &[I128], insert_opcode), (Opcode::Imul, &[I128, I128], &[I128], insert_opcode),
// Smulhi // Smulhi
// Not implemented on x64: https://github.com/bytecodealliance/wasmtime/issues/5468
#[cfg(not(target_arch = "x86_64"))]
(Opcode::Smulhi, &[I8, I8], &[I8], insert_opcode), (Opcode::Smulhi, &[I8, I8], &[I8], insert_opcode),
(Opcode::Smulhi, &[I16, I16], &[I16], insert_opcode), (Opcode::Smulhi, &[I16, I16], &[I16], insert_opcode),
(Opcode::Smulhi, &[I32, I32], &[I32], insert_opcode), (Opcode::Smulhi, &[I32, I32], &[I32], insert_opcode),
(Opcode::Smulhi, &[I64, I64], &[I64], insert_opcode), (Opcode::Smulhi, &[I64, I64], &[I64], insert_opcode),
// Umulhi // Umulhi
// Not implemented on x64: https://github.com/bytecodealliance/wasmtime/issues/5468
#[cfg(not(target_arch = "x86_64"))]
(Opcode::Umulhi, &[I8, I8], &[I8], insert_opcode), (Opcode::Umulhi, &[I8, I8], &[I8], insert_opcode),
(Opcode::Umulhi, &[I16, I16], &[I16], insert_opcode), (Opcode::Umulhi, &[I16, I16], &[I16], insert_opcode),
(Opcode::Umulhi, &[I32, I32], &[I32], insert_opcode), (Opcode::Umulhi, &[I32, I32], &[I32], insert_opcode),
@@ -307,42 +513,24 @@ const OPCODE_SIGNATURES: &'static [(
(Opcode::Udiv, &[I16, I16], &[I16], insert_opcode), (Opcode::Udiv, &[I16, I16], &[I16], insert_opcode),
(Opcode::Udiv, &[I32, I32], &[I32], insert_opcode), (Opcode::Udiv, &[I32, I32], &[I32], insert_opcode),
(Opcode::Udiv, &[I64, I64], &[I64], insert_opcode), (Opcode::Udiv, &[I64, I64], &[I64], insert_opcode),
// udiv.i128 not implemented in some backends:
// x64: https://github.com/bytecodealliance/wasmtime/issues/4756
// aarch64: https://github.com/bytecodealliance/wasmtime/issues/4864
#[cfg(not(any(target_arch = "x86_64", target_arch = "aarch64")))]
(Opcode::Udiv, &[I128, I128], &[I128], insert_opcode), (Opcode::Udiv, &[I128, I128], &[I128], insert_opcode),
// Sdiv // Sdiv
(Opcode::Sdiv, &[I8, I8], &[I8], insert_opcode), (Opcode::Sdiv, &[I8, I8], &[I8], insert_opcode),
(Opcode::Sdiv, &[I16, I16], &[I16], insert_opcode), (Opcode::Sdiv, &[I16, I16], &[I16], insert_opcode),
(Opcode::Sdiv, &[I32, I32], &[I32], insert_opcode), (Opcode::Sdiv, &[I32, I32], &[I32], insert_opcode),
(Opcode::Sdiv, &[I64, I64], &[I64], insert_opcode), (Opcode::Sdiv, &[I64, I64], &[I64], insert_opcode),
// sdiv.i128 not implemented in some backends:
// x64: https://github.com/bytecodealliance/wasmtime/issues/4770
// aarch64: https://github.com/bytecodealliance/wasmtime/issues/4864
#[cfg(not(any(target_arch = "x86_64", target_arch = "aarch64")))]
(Opcode::Sdiv, &[I128, I128], &[I128], insert_opcode), (Opcode::Sdiv, &[I128, I128], &[I128], insert_opcode),
// Urem // Urem
(Opcode::Urem, &[I8, I8], &[I8], insert_opcode), (Opcode::Urem, &[I8, I8], &[I8], insert_opcode),
(Opcode::Urem, &[I16, I16], &[I16], insert_opcode), (Opcode::Urem, &[I16, I16], &[I16], insert_opcode),
(Opcode::Urem, &[I32, I32], &[I32], insert_opcode), (Opcode::Urem, &[I32, I32], &[I32], insert_opcode),
(Opcode::Urem, &[I64, I64], &[I64], insert_opcode), (Opcode::Urem, &[I64, I64], &[I64], insert_opcode),
// urem.i128 not implemented in some backends:
// x64: https://github.com/bytecodealliance/wasmtime/issues/5474
// aarch64: https://github.com/bytecodealliance/wasmtime/issues/5472
#[cfg(not(any(target_arch = "x86_64", target_arch = "aarch64")))]
(Opcode::Urem, &[I128, I128], &[I128], insert_opcode), (Opcode::Urem, &[I128, I128], &[I128], insert_opcode),
// Srem // Srem
// Issues on x64: https://github.com/bytecodealliance/wasmtime/issues/5470
#[cfg(not(target_arch = "x86_64"))]
(Opcode::Srem, &[I8, I8], &[I8], insert_opcode), (Opcode::Srem, &[I8, I8], &[I8], insert_opcode),
(Opcode::Srem, &[I16, I16], &[I16], insert_opcode), (Opcode::Srem, &[I16, I16], &[I16], insert_opcode),
(Opcode::Srem, &[I32, I32], &[I32], insert_opcode), (Opcode::Srem, &[I32, I32], &[I32], insert_opcode),
(Opcode::Srem, &[I64, I64], &[I64], insert_opcode), (Opcode::Srem, &[I64, I64], &[I64], insert_opcode),
// srem.i128 not implemented in some backends:
// x64: https://github.com/bytecodealliance/wasmtime/issues/5474
// aarch64: https://github.com/bytecodealliance/wasmtime/issues/5472
#[cfg(not(any(target_arch = "x86_64", target_arch = "aarch64")))]
(Opcode::Srem, &[I128, I128], &[I128], insert_opcode), (Opcode::Srem, &[I128, I128], &[I128], insert_opcode),
// Ineg // Ineg
(Opcode::Ineg, &[I8, I8], &[I8], insert_opcode), (Opcode::Ineg, &[I8, I8], &[I8], insert_opcode),
@@ -351,58 +539,34 @@ const OPCODE_SIGNATURES: &'static [(
(Opcode::Ineg, &[I64, I64], &[I64], insert_opcode), (Opcode::Ineg, &[I64, I64], &[I64], insert_opcode),
(Opcode::Ineg, &[I128, I128], &[I128], insert_opcode), (Opcode::Ineg, &[I128, I128], &[I128], insert_opcode),
// Iabs // Iabs
// Some variants missing:
// x64: https://github.com/bytecodealliance/wasmtime/issues/5466
// aarch64: https://github.com/bytecodealliance/wasmtime/issues/5467
#[cfg(not(target_arch = "x86_64"))]
(Opcode::Iabs, &[I8], &[I8], insert_opcode), (Opcode::Iabs, &[I8], &[I8], insert_opcode),
#[cfg(not(target_arch = "x86_64"))]
(Opcode::Iabs, &[I16], &[I16], insert_opcode), (Opcode::Iabs, &[I16], &[I16], insert_opcode),
#[cfg(not(target_arch = "x86_64"))]
(Opcode::Iabs, &[I32], &[I32], insert_opcode), (Opcode::Iabs, &[I32], &[I32], insert_opcode),
#[cfg(not(target_arch = "x86_64"))]
(Opcode::Iabs, &[I64], &[I64], insert_opcode), (Opcode::Iabs, &[I64], &[I64], insert_opcode),
#[cfg(not(any(target_arch = "x86_64", target_arch = "aarch64")))]
(Opcode::Iabs, &[I128], &[I128], insert_opcode), (Opcode::Iabs, &[I128], &[I128], insert_opcode),
// Smin // Smin
// smin.i128 is not implemented in some backends:
// x64: https://github.com/bytecodealliance/wasmtime/issues/3370
// aarch64: https://github.com/bytecodealliance/wasmtime/issues/4313
(Opcode::Smin, &[I8, I8], &[I8], insert_opcode), (Opcode::Smin, &[I8, I8], &[I8], insert_opcode),
(Opcode::Smin, &[I16, I16], &[I16], insert_opcode), (Opcode::Smin, &[I16, I16], &[I16], insert_opcode),
(Opcode::Smin, &[I32, I32], &[I32], insert_opcode), (Opcode::Smin, &[I32, I32], &[I32], insert_opcode),
(Opcode::Smin, &[I64, I64], &[I64], insert_opcode), (Opcode::Smin, &[I64, I64], &[I64], insert_opcode),
#[cfg(not(any(target_arch = "x86_64", target_arch = "aarch64")))]
(Opcode::Smin, &[I128, I128], &[I128], insert_opcode), (Opcode::Smin, &[I128, I128], &[I128], insert_opcode),
// Umin // Umin
// umin.i128 is not implemented in some backends:
// x64: https://github.com/bytecodealliance/wasmtime/issues/3370
// aarch64: https://github.com/bytecodealliance/wasmtime/issues/4313
(Opcode::Umin, &[I8, I8], &[I8], insert_opcode), (Opcode::Umin, &[I8, I8], &[I8], insert_opcode),
(Opcode::Umin, &[I16, I16], &[I16], insert_opcode), (Opcode::Umin, &[I16, I16], &[I16], insert_opcode),
(Opcode::Umin, &[I32, I32], &[I32], insert_opcode), (Opcode::Umin, &[I32, I32], &[I32], insert_opcode),
(Opcode::Umin, &[I64, I64], &[I64], insert_opcode), (Opcode::Umin, &[I64, I64], &[I64], insert_opcode),
#[cfg(not(any(target_arch = "x86_64", target_arch = "aarch64")))]
(Opcode::Umin, &[I128, I128], &[I128], insert_opcode), (Opcode::Umin, &[I128, I128], &[I128], insert_opcode),
// Smax // Smax
// smax.i128 is not implemented in some backends:
// x64: https://github.com/bytecodealliance/wasmtime/issues/3370
// aarch64: https://github.com/bytecodealliance/wasmtime/issues/4313
(Opcode::Smax, &[I8, I8], &[I8], insert_opcode), (Opcode::Smax, &[I8, I8], &[I8], insert_opcode),
(Opcode::Smax, &[I16, I16], &[I16], insert_opcode), (Opcode::Smax, &[I16, I16], &[I16], insert_opcode),
(Opcode::Smax, &[I32, I32], &[I32], insert_opcode), (Opcode::Smax, &[I32, I32], &[I32], insert_opcode),
(Opcode::Smax, &[I64, I64], &[I64], insert_opcode), (Opcode::Smax, &[I64, I64], &[I64], insert_opcode),
#[cfg(not(any(target_arch = "x86_64", target_arch = "aarch64")))]
(Opcode::Smax, &[I128, I128], &[I128], insert_opcode), (Opcode::Smax, &[I128, I128], &[I128], insert_opcode),
// Umax // Umax
// umax.i128 is not implemented in some backends:
// x64: https://github.com/bytecodealliance/wasmtime/issues/3370
// aarch64: https://github.com/bytecodealliance/wasmtime/issues/4313
(Opcode::Umax, &[I8, I8], &[I8], insert_opcode), (Opcode::Umax, &[I8, I8], &[I8], insert_opcode),
(Opcode::Umax, &[I16, I16], &[I16], insert_opcode), (Opcode::Umax, &[I16, I16], &[I16], insert_opcode),
(Opcode::Umax, &[I32, I32], &[I32], insert_opcode), (Opcode::Umax, &[I32, I32], &[I32], insert_opcode),
(Opcode::Umax, &[I64, I64], &[I64], insert_opcode), (Opcode::Umax, &[I64, I64], &[I64], insert_opcode),
#[cfg(not(any(target_arch = "x86_64", target_arch = "aarch64")))]
(Opcode::Umax, &[I128, I128], &[I128], insert_opcode), (Opcode::Umax, &[I128, I128], &[I128], insert_opcode),
// Rotr // Rotr
(Opcode::Rotr, &[I8, I8], &[I8], insert_opcode), (Opcode::Rotr, &[I8, I8], &[I8], insert_opcode),
@@ -577,11 +741,7 @@ const OPCODE_SIGNATURES: &'static [(
(Opcode::Band, &[I32, I32], &[I32], insert_opcode), (Opcode::Band, &[I32, I32], &[I32], insert_opcode),
(Opcode::Band, &[I64, I64], &[I64], insert_opcode), (Opcode::Band, &[I64, I64], &[I64], insert_opcode),
(Opcode::Band, &[I128, I128], &[I128], insert_opcode), (Opcode::Band, &[I128, I128], &[I128], insert_opcode),
// Float bitops are currently not supported:
// See: https://github.com/bytecodealliance/wasmtime/issues/4870
#[cfg(not(any(target_arch = "x86_64", target_arch = "aarch64")))]
(Opcode::Band, &[F32, F32], &[F32], insert_opcode), (Opcode::Band, &[F32, F32], &[F32], insert_opcode),
#[cfg(not(any(target_arch = "x86_64", target_arch = "aarch64")))]
(Opcode::Band, &[F64, F64], &[F64], insert_opcode), (Opcode::Band, &[F64, F64], &[F64], insert_opcode),
// Bor // Bor
(Opcode::Bor, &[I8, I8], &[I8], insert_opcode), (Opcode::Bor, &[I8, I8], &[I8], insert_opcode),
@@ -589,11 +749,7 @@ const OPCODE_SIGNATURES: &'static [(
(Opcode::Bor, &[I32, I32], &[I32], insert_opcode), (Opcode::Bor, &[I32, I32], &[I32], insert_opcode),
(Opcode::Bor, &[I64, I64], &[I64], insert_opcode), (Opcode::Bor, &[I64, I64], &[I64], insert_opcode),
(Opcode::Bor, &[I128, I128], &[I128], insert_opcode), (Opcode::Bor, &[I128, I128], &[I128], insert_opcode),
// Float bitops are currently not supported:
// See: https://github.com/bytecodealliance/wasmtime/issues/4870
#[cfg(not(any(target_arch = "x86_64", target_arch = "aarch64")))]
(Opcode::Bor, &[F32, F32], &[F32], insert_opcode), (Opcode::Bor, &[F32, F32], &[F32], insert_opcode),
#[cfg(not(any(target_arch = "x86_64", target_arch = "aarch64")))]
(Opcode::Bor, &[F64, F64], &[F64], insert_opcode), (Opcode::Bor, &[F64, F64], &[F64], insert_opcode),
// Bxor // Bxor
(Opcode::Bxor, &[I8, I8], &[I8], insert_opcode), (Opcode::Bxor, &[I8, I8], &[I8], insert_opcode),
@@ -601,11 +757,7 @@ const OPCODE_SIGNATURES: &'static [(
(Opcode::Bxor, &[I32, I32], &[I32], insert_opcode), (Opcode::Bxor, &[I32, I32], &[I32], insert_opcode),
(Opcode::Bxor, &[I64, I64], &[I64], insert_opcode), (Opcode::Bxor, &[I64, I64], &[I64], insert_opcode),
(Opcode::Bxor, &[I128, I128], &[I128], insert_opcode), (Opcode::Bxor, &[I128, I128], &[I128], insert_opcode),
// Float bitops are currently not supported:
// See: https://github.com/bytecodealliance/wasmtime/issues/4870
#[cfg(not(any(target_arch = "x86_64", target_arch = "aarch64")))]
(Opcode::Bxor, &[F32, F32], &[F32], insert_opcode), (Opcode::Bxor, &[F32, F32], &[F32], insert_opcode),
#[cfg(not(any(target_arch = "x86_64", target_arch = "aarch64")))]
(Opcode::Bxor, &[F64, F64], &[F64], insert_opcode), (Opcode::Bxor, &[F64, F64], &[F64], insert_opcode),
// Bnot // Bnot
(Opcode::Bnot, &[I8, I8], &[I8], insert_opcode), (Opcode::Bnot, &[I8, I8], &[I8], insert_opcode),
@@ -613,65 +765,31 @@ const OPCODE_SIGNATURES: &'static [(
(Opcode::Bnot, &[I32, I32], &[I32], insert_opcode), (Opcode::Bnot, &[I32, I32], &[I32], insert_opcode),
(Opcode::Bnot, &[I64, I64], &[I64], insert_opcode), (Opcode::Bnot, &[I64, I64], &[I64], insert_opcode),
(Opcode::Bnot, &[I128, I128], &[I128], insert_opcode), (Opcode::Bnot, &[I128, I128], &[I128], insert_opcode),
// Float bitops are currently not supported:
// See: https://github.com/bytecodealliance/wasmtime/issues/4870
#[cfg(not(any(target_arch = "x86_64", target_arch = "aarch64")))]
(Opcode::Bnot, &[F32, F32], &[F32], insert_opcode), (Opcode::Bnot, &[F32, F32], &[F32], insert_opcode),
#[cfg(not(any(target_arch = "x86_64", target_arch = "aarch64")))]
(Opcode::Bnot, &[F64, F64], &[F64], insert_opcode), (Opcode::Bnot, &[F64, F64], &[F64], insert_opcode),
// BandNot // BandNot
// Some Integer ops not supported on x86: https://github.com/bytecodealliance/wasmtime/issues/5041
#[cfg(not(target_arch = "x86_64"))]
(Opcode::BandNot, &[I8, I8], &[I8], insert_opcode), (Opcode::BandNot, &[I8, I8], &[I8], insert_opcode),
#[cfg(not(target_arch = "x86_64"))]
(Opcode::BandNot, &[I16, I16], &[I16], insert_opcode), (Opcode::BandNot, &[I16, I16], &[I16], insert_opcode),
#[cfg(not(target_arch = "x86_64"))]
(Opcode::BandNot, &[I32, I32], &[I32], insert_opcode), (Opcode::BandNot, &[I32, I32], &[I32], insert_opcode),
#[cfg(not(target_arch = "x86_64"))]
(Opcode::BandNot, &[I64, I64], &[I64], insert_opcode), (Opcode::BandNot, &[I64, I64], &[I64], insert_opcode),
#[cfg(not(target_arch = "x86_64"))]
(Opcode::BandNot, &[I128, I128], &[I128], insert_opcode), (Opcode::BandNot, &[I128, I128], &[I128], insert_opcode),
// Float bitops are currently not supported:
// See: https://github.com/bytecodealliance/wasmtime/issues/4870
#[cfg(not(any(target_arch = "x86_64", target_arch = "aarch64")))]
(Opcode::BandNot, &[F32, F32], &[F32], insert_opcode), (Opcode::BandNot, &[F32, F32], &[F32], insert_opcode),
#[cfg(not(any(target_arch = "x86_64", target_arch = "aarch64")))]
(Opcode::BandNot, &[F64, F64], &[F64], insert_opcode), (Opcode::BandNot, &[F64, F64], &[F64], insert_opcode),
// BorNot // BorNot
// Some Integer ops not supported on x86: https://github.com/bytecodealliance/wasmtime/issues/5041
#[cfg(not(target_arch = "x86_64"))]
(Opcode::BorNot, &[I8, I8], &[I8], insert_opcode), (Opcode::BorNot, &[I8, I8], &[I8], insert_opcode),
#[cfg(not(target_arch = "x86_64"))]
(Opcode::BorNot, &[I16, I16], &[I16], insert_opcode), (Opcode::BorNot, &[I16, I16], &[I16], insert_opcode),
#[cfg(not(target_arch = "x86_64"))]
(Opcode::BorNot, &[I32, I32], &[I32], insert_opcode), (Opcode::BorNot, &[I32, I32], &[I32], insert_opcode),
#[cfg(not(target_arch = "x86_64"))]
(Opcode::BorNot, &[I64, I64], &[I64], insert_opcode), (Opcode::BorNot, &[I64, I64], &[I64], insert_opcode),
#[cfg(not(target_arch = "x86_64"))]
(Opcode::BorNot, &[I128, I128], &[I128], insert_opcode), (Opcode::BorNot, &[I128, I128], &[I128], insert_opcode),
// Float bitops are currently not supported:
// See: https://github.com/bytecodealliance/wasmtime/issues/4870
#[cfg(not(any(target_arch = "x86_64", target_arch = "aarch64")))]
(Opcode::BorNot, &[F32, F32], &[F32], insert_opcode), (Opcode::BorNot, &[F32, F32], &[F32], insert_opcode),
#[cfg(not(any(target_arch = "x86_64", target_arch = "aarch64")))]
(Opcode::BorNot, &[F64, F64], &[F64], insert_opcode), (Opcode::BorNot, &[F64, F64], &[F64], insert_opcode),
// BxorNot // BxorNot
// Some Integer ops not supported on x86: https://github.com/bytecodealliance/wasmtime/issues/5041
#[cfg(not(target_arch = "x86_64"))]
(Opcode::BxorNot, &[I8, I8], &[I8], insert_opcode), (Opcode::BxorNot, &[I8, I8], &[I8], insert_opcode),
#[cfg(not(target_arch = "x86_64"))]
(Opcode::BxorNot, &[I16, I16], &[I16], insert_opcode), (Opcode::BxorNot, &[I16, I16], &[I16], insert_opcode),
#[cfg(not(target_arch = "x86_64"))]
(Opcode::BxorNot, &[I32, I32], &[I32], insert_opcode), (Opcode::BxorNot, &[I32, I32], &[I32], insert_opcode),
#[cfg(not(target_arch = "x86_64"))]
(Opcode::BxorNot, &[I64, I64], &[I64], insert_opcode), (Opcode::BxorNot, &[I64, I64], &[I64], insert_opcode),
#[cfg(not(target_arch = "x86_64"))]
(Opcode::BxorNot, &[I128, I128], &[I128], insert_opcode), (Opcode::BxorNot, &[I128, I128], &[I128], insert_opcode),
// Float bitops are currently not supported:
// See: https://github.com/bytecodealliance/wasmtime/issues/4870
#[cfg(not(any(target_arch = "x86_64", target_arch = "aarch64")))]
(Opcode::BxorNot, &[F32, F32], &[F32], insert_opcode), (Opcode::BxorNot, &[F32, F32], &[F32], insert_opcode),
#[cfg(not(any(target_arch = "x86_64", target_arch = "aarch64")))]
(Opcode::BxorNot, &[F64, F64], &[F64], insert_opcode), (Opcode::BxorNot, &[F64, F64], &[F64], insert_opcode),
// Bitrev // Bitrev
(Opcode::Bitrev, &[I8], &[I8], insert_opcode), (Opcode::Bitrev, &[I8], &[I8], insert_opcode),
@@ -686,17 +804,10 @@ const OPCODE_SIGNATURES: &'static [(
(Opcode::Clz, &[I64], &[I64], insert_opcode), (Opcode::Clz, &[I64], &[I64], insert_opcode),
(Opcode::Clz, &[I128], &[I128], insert_opcode), (Opcode::Clz, &[I128], &[I128], insert_opcode),
// Cls // Cls
// cls not implemented in some backends:
// x64: https://github.com/bytecodealliance/wasmtime/issues/5107
#[cfg(not(target_arch = "x86_64"))]
(Opcode::Cls, &[I8], &[I8], insert_opcode), (Opcode::Cls, &[I8], &[I8], insert_opcode),
#[cfg(not(target_arch = "x86_64"))]
(Opcode::Cls, &[I16], &[I16], insert_opcode), (Opcode::Cls, &[I16], &[I16], insert_opcode),
#[cfg(not(target_arch = "x86_64"))]
(Opcode::Cls, &[I32], &[I32], insert_opcode), (Opcode::Cls, &[I32], &[I32], insert_opcode),
#[cfg(not(target_arch = "x86_64"))]
(Opcode::Cls, &[I64], &[I64], insert_opcode), (Opcode::Cls, &[I64], &[I64], insert_opcode),
#[cfg(not(target_arch = "x86_64"))]
(Opcode::Cls, &[I128], &[I128], insert_opcode), (Opcode::Cls, &[I128], &[I128], insert_opcode),
// Ctz // Ctz
(Opcode::Ctz, &[I8], &[I8], insert_opcode), (Opcode::Ctz, &[I8], &[I8], insert_opcode),
@@ -742,18 +853,10 @@ const OPCODE_SIGNATURES: &'static [(
(Opcode::Bswap, &[I64], &[I64], insert_opcode), (Opcode::Bswap, &[I64], &[I64], insert_opcode),
(Opcode::Bswap, &[I128], &[I128], insert_opcode), (Opcode::Bswap, &[I128], &[I128], insert_opcode),
// Bitselect // Bitselect
// TODO: Some ops disabled:
// x64: https://github.com/bytecodealliance/wasmtime/issues/5197
// AArch64: https://github.com/bytecodealliance/wasmtime/issues/5198
#[cfg(not(target_arch = "x86_64"))]
(Opcode::Bitselect, &[I8, I8, I8], &[I8], insert_opcode), (Opcode::Bitselect, &[I8, I8, I8], &[I8], insert_opcode),
#[cfg(not(target_arch = "x86_64"))]
(Opcode::Bitselect, &[I16, I16, I16], &[I16], insert_opcode), (Opcode::Bitselect, &[I16, I16, I16], &[I16], insert_opcode),
#[cfg(not(target_arch = "x86_64"))]
(Opcode::Bitselect, &[I32, I32, I32], &[I32], insert_opcode), (Opcode::Bitselect, &[I32, I32, I32], &[I32], insert_opcode),
#[cfg(not(target_arch = "x86_64"))]
(Opcode::Bitselect, &[I64, I64, I64], &[I64], insert_opcode), (Opcode::Bitselect, &[I64, I64, I64], &[I64], insert_opcode),
#[cfg(not(any(target_arch = "x86_64", target_arch = "aarch64")))]
(Opcode::Bitselect, &[I128, I128, I128], &[I128], insert_opcode), (Opcode::Bitselect, &[I128, I128, I128], &[I128], insert_opcode),
// Select // Select
(Opcode::Select, &[I8, I8, I8], &[I8], insert_opcode), (Opcode::Select, &[I8, I8, I8], &[I8], insert_opcode),
@@ -863,120 +966,70 @@ const OPCODE_SIGNATURES: &'static [(
// Fdemote // Fdemote
(Opcode::Fdemote, &[F64], &[F32], insert_opcode), (Opcode::Fdemote, &[F64], &[F32], insert_opcode),
// FcvtToUint // FcvtToUint
// TODO: Some ops disabled:
// x64: https://github.com/bytecodealliance/wasmtime/issues/4897
// x64: https://github.com/bytecodealliance/wasmtime/issues/4899
// aarch64: https://github.com/bytecodealliance/wasmtime/issues/4934
#[cfg(not(target_arch = "x86_64"))]
(Opcode::FcvtToUint, &[F32], &[I8], insert_opcode), (Opcode::FcvtToUint, &[F32], &[I8], insert_opcode),
#[cfg(not(target_arch = "x86_64"))]
(Opcode::FcvtToUint, &[F32], &[I16], insert_opcode), (Opcode::FcvtToUint, &[F32], &[I16], insert_opcode),
(Opcode::FcvtToUint, &[F32], &[I32], insert_opcode), (Opcode::FcvtToUint, &[F32], &[I32], insert_opcode),
(Opcode::FcvtToUint, &[F32], &[I64], insert_opcode), (Opcode::FcvtToUint, &[F32], &[I64], insert_opcode),
#[cfg(not(any(target_arch = "x86_64", target_arch = "aarch64")))]
(Opcode::FcvtToUint, &[F32], &[I128], insert_opcode), (Opcode::FcvtToUint, &[F32], &[I128], insert_opcode),
#[cfg(not(target_arch = "x86_64"))]
(Opcode::FcvtToUint, &[F64], &[I8], insert_opcode), (Opcode::FcvtToUint, &[F64], &[I8], insert_opcode),
#[cfg(not(target_arch = "x86_64"))]
(Opcode::FcvtToUint, &[F64], &[I16], insert_opcode), (Opcode::FcvtToUint, &[F64], &[I16], insert_opcode),
(Opcode::FcvtToUint, &[F64], &[I32], insert_opcode), (Opcode::FcvtToUint, &[F64], &[I32], insert_opcode),
(Opcode::FcvtToUint, &[F64], &[I64], insert_opcode), (Opcode::FcvtToUint, &[F64], &[I64], insert_opcode),
#[cfg(not(any(target_arch = "x86_64", target_arch = "aarch64")))]
(Opcode::FcvtToUint, &[F64], &[I128], insert_opcode), (Opcode::FcvtToUint, &[F64], &[I128], insert_opcode),
// FcvtToUintSat // FcvtToUintSat
// TODO: Some ops disabled:
// x64: https://github.com/bytecodealliance/wasmtime/issues/4897
// x64: https://github.com/bytecodealliance/wasmtime/issues/4899
// aarch64: https://github.com/bytecodealliance/wasmtime/issues/4934
#[cfg(not(target_arch = "x86_64"))]
(Opcode::FcvtToUintSat, &[F32], &[I8], insert_opcode), (Opcode::FcvtToUintSat, &[F32], &[I8], insert_opcode),
#[cfg(not(target_arch = "x86_64"))]
(Opcode::FcvtToUintSat, &[F32], &[I16], insert_opcode), (Opcode::FcvtToUintSat, &[F32], &[I16], insert_opcode),
(Opcode::FcvtToUintSat, &[F32], &[I32], insert_opcode), (Opcode::FcvtToUintSat, &[F32], &[I32], insert_opcode),
(Opcode::FcvtToUintSat, &[F32], &[I64], insert_opcode), (Opcode::FcvtToUintSat, &[F32], &[I64], insert_opcode),
#[cfg(not(any(target_arch = "x86_64", target_arch = "aarch64")))]
(Opcode::FcvtToUintSat, &[F32], &[I128], insert_opcode), (Opcode::FcvtToUintSat, &[F32], &[I128], insert_opcode),
#[cfg(not(target_arch = "x86_64"))]
(Opcode::FcvtToUintSat, &[F64], &[I8], insert_opcode), (Opcode::FcvtToUintSat, &[F64], &[I8], insert_opcode),
#[cfg(not(target_arch = "x86_64"))]
(Opcode::FcvtToUintSat, &[F64], &[I16], insert_opcode), (Opcode::FcvtToUintSat, &[F64], &[I16], insert_opcode),
(Opcode::FcvtToUintSat, &[F64], &[I32], insert_opcode), (Opcode::FcvtToUintSat, &[F64], &[I32], insert_opcode),
(Opcode::FcvtToUintSat, &[F64], &[I64], insert_opcode), (Opcode::FcvtToUintSat, &[F64], &[I64], insert_opcode),
#[cfg(not(any(target_arch = "x86_64", target_arch = "aarch64")))]
(Opcode::FcvtToUintSat, &[F64], &[I128], insert_opcode), (Opcode::FcvtToUintSat, &[F64], &[I128], insert_opcode),
// FcvtToSint // FcvtToSint
// TODO: Some ops disabled:
// x64: https://github.com/bytecodealliance/wasmtime/issues/4897
// x64: https://github.com/bytecodealliance/wasmtime/issues/4899
// aarch64: https://github.com/bytecodealliance/wasmtime/issues/4934
#[cfg(not(target_arch = "x86_64"))]
(Opcode::FcvtToSint, &[F32], &[I8], insert_opcode), (Opcode::FcvtToSint, &[F32], &[I8], insert_opcode),
#[cfg(not(target_arch = "x86_64"))]
(Opcode::FcvtToSint, &[F32], &[I16], insert_opcode), (Opcode::FcvtToSint, &[F32], &[I16], insert_opcode),
(Opcode::FcvtToSint, &[F32], &[I32], insert_opcode), (Opcode::FcvtToSint, &[F32], &[I32], insert_opcode),
(Opcode::FcvtToSint, &[F32], &[I64], insert_opcode), (Opcode::FcvtToSint, &[F32], &[I64], insert_opcode),
#[cfg(not(any(target_arch = "x86_64", target_arch = "aarch64")))]
(Opcode::FcvtToSint, &[F32], &[I128], insert_opcode), (Opcode::FcvtToSint, &[F32], &[I128], insert_opcode),
#[cfg(not(target_arch = "x86_64"))]
(Opcode::FcvtToSint, &[F64], &[I8], insert_opcode), (Opcode::FcvtToSint, &[F64], &[I8], insert_opcode),
#[cfg(not(target_arch = "x86_64"))]
(Opcode::FcvtToSint, &[F64], &[I16], insert_opcode), (Opcode::FcvtToSint, &[F64], &[I16], insert_opcode),
(Opcode::FcvtToSint, &[F64], &[I32], insert_opcode), (Opcode::FcvtToSint, &[F64], &[I32], insert_opcode),
(Opcode::FcvtToSint, &[F64], &[I64], insert_opcode), (Opcode::FcvtToSint, &[F64], &[I64], insert_opcode),
#[cfg(not(any(target_arch = "x86_64", target_arch = "aarch64")))]
(Opcode::FcvtToSint, &[F64], &[I128], insert_opcode), (Opcode::FcvtToSint, &[F64], &[I128], insert_opcode),
// FcvtToSintSat // FcvtToSintSat
// TODO: Some ops disabled:
// x64: https://github.com/bytecodealliance/wasmtime/issues/4897
// x64: https://github.com/bytecodealliance/wasmtime/issues/4899
// aarch64: https://github.com/bytecodealliance/wasmtime/issues/4934
#[cfg(not(target_arch = "x86_64"))]
(Opcode::FcvtToSintSat, &[F32], &[I8], insert_opcode), (Opcode::FcvtToSintSat, &[F32], &[I8], insert_opcode),
#[cfg(not(target_arch = "x86_64"))]
(Opcode::FcvtToSintSat, &[F32], &[I16], insert_opcode), (Opcode::FcvtToSintSat, &[F32], &[I16], insert_opcode),
(Opcode::FcvtToSintSat, &[F32], &[I32], insert_opcode), (Opcode::FcvtToSintSat, &[F32], &[I32], insert_opcode),
(Opcode::FcvtToSintSat, &[F32], &[I64], insert_opcode), (Opcode::FcvtToSintSat, &[F32], &[I64], insert_opcode),
#[cfg(not(any(target_arch = "x86_64", target_arch = "aarch64")))]
(Opcode::FcvtToSintSat, &[F32], &[I128], insert_opcode), (Opcode::FcvtToSintSat, &[F32], &[I128], insert_opcode),
#[cfg(not(target_arch = "x86_64"))]
(Opcode::FcvtToSintSat, &[F64], &[I8], insert_opcode), (Opcode::FcvtToSintSat, &[F64], &[I8], insert_opcode),
#[cfg(not(target_arch = "x86_64"))]
(Opcode::FcvtToSintSat, &[F64], &[I16], insert_opcode), (Opcode::FcvtToSintSat, &[F64], &[I16], insert_opcode),
(Opcode::FcvtToSintSat, &[F64], &[I32], insert_opcode), (Opcode::FcvtToSintSat, &[F64], &[I32], insert_opcode),
(Opcode::FcvtToSintSat, &[F64], &[I64], insert_opcode), (Opcode::FcvtToSintSat, &[F64], &[I64], insert_opcode),
#[cfg(not(any(target_arch = "x86_64", target_arch = "aarch64")))]
(Opcode::FcvtToSintSat, &[F64], &[I128], insert_opcode), (Opcode::FcvtToSintSat, &[F64], &[I128], insert_opcode),
// FcvtFromUint // FcvtFromUint
// TODO: Some ops disabled:
// x64: https://github.com/bytecodealliance/wasmtime/issues/4900
// aarch64: https://github.com/bytecodealliance/wasmtime/issues/4933
(Opcode::FcvtFromUint, &[I8], &[F32], insert_opcode), (Opcode::FcvtFromUint, &[I8], &[F32], insert_opcode),
(Opcode::FcvtFromUint, &[I16], &[F32], insert_opcode), (Opcode::FcvtFromUint, &[I16], &[F32], insert_opcode),
(Opcode::FcvtFromUint, &[I32], &[F32], insert_opcode), (Opcode::FcvtFromUint, &[I32], &[F32], insert_opcode),
(Opcode::FcvtFromUint, &[I64], &[F32], insert_opcode), (Opcode::FcvtFromUint, &[I64], &[F32], insert_opcode),
#[cfg(not(any(target_arch = "x86_64", target_arch = "aarch64")))]
(Opcode::FcvtFromUint, &[I128], &[F32], insert_opcode), (Opcode::FcvtFromUint, &[I128], &[F32], insert_opcode),
(Opcode::FcvtFromUint, &[I8], &[F64], insert_opcode), (Opcode::FcvtFromUint, &[I8], &[F64], insert_opcode),
(Opcode::FcvtFromUint, &[I16], &[F64], insert_opcode), (Opcode::FcvtFromUint, &[I16], &[F64], insert_opcode),
(Opcode::FcvtFromUint, &[I32], &[F64], insert_opcode), (Opcode::FcvtFromUint, &[I32], &[F64], insert_opcode),
(Opcode::FcvtFromUint, &[I64], &[F64], insert_opcode), (Opcode::FcvtFromUint, &[I64], &[F64], insert_opcode),
#[cfg(not(any(target_arch = "x86_64", target_arch = "aarch64")))]
(Opcode::FcvtFromUint, &[I128], &[F64], insert_opcode), (Opcode::FcvtFromUint, &[I128], &[F64], insert_opcode),
// FcvtFromSint // FcvtFromSint
// TODO: Some ops disabled:
// x64: https://github.com/bytecodealliance/wasmtime/issues/4900
// aarch64: https://github.com/bytecodealliance/wasmtime/issues/4933
(Opcode::FcvtFromSint, &[I8], &[F32], insert_opcode), (Opcode::FcvtFromSint, &[I8], &[F32], insert_opcode),
(Opcode::FcvtFromSint, &[I16], &[F32], insert_opcode), (Opcode::FcvtFromSint, &[I16], &[F32], insert_opcode),
(Opcode::FcvtFromSint, &[I32], &[F32], insert_opcode), (Opcode::FcvtFromSint, &[I32], &[F32], insert_opcode),
(Opcode::FcvtFromSint, &[I64], &[F32], insert_opcode), (Opcode::FcvtFromSint, &[I64], &[F32], insert_opcode),
#[cfg(not(any(target_arch = "x86_64", target_arch = "aarch64")))]
(Opcode::FcvtFromSint, &[I128], &[F32], insert_opcode), (Opcode::FcvtFromSint, &[I128], &[F32], insert_opcode),
(Opcode::FcvtFromSint, &[I8], &[F64], insert_opcode), (Opcode::FcvtFromSint, &[I8], &[F64], insert_opcode),
(Opcode::FcvtFromSint, &[I16], &[F64], insert_opcode), (Opcode::FcvtFromSint, &[I16], &[F64], insert_opcode),
(Opcode::FcvtFromSint, &[I32], &[F64], insert_opcode), (Opcode::FcvtFromSint, &[I32], &[F64], insert_opcode),
(Opcode::FcvtFromSint, &[I64], &[F64], insert_opcode), (Opcode::FcvtFromSint, &[I64], &[F64], insert_opcode),
#[cfg(not(any(target_arch = "x86_64", target_arch = "aarch64")))]
(Opcode::FcvtFromSint, &[I128], &[F64], insert_opcode), (Opcode::FcvtFromSint, &[I128], &[F64], insert_opcode),
// Fcmp // Fcmp
(Opcode::Fcmp, &[F32, F32], &[I8], insert_cmp), (Opcode::Fcmp, &[F32, F32], &[I8], insert_cmp),
@@ -1075,6 +1128,7 @@ where
u: &'r mut Unstructured<'data>, u: &'r mut Unstructured<'data>,
config: &'r Config, config: &'r Config,
resources: Resources, resources: Resources,
target_triple: Triple,
} }
#[derive(Debug, Clone)] #[derive(Debug, Clone)]
@@ -1137,11 +1191,12 @@ impl<'r, 'data> FunctionGenerator<'r, 'data>
where where
'data: 'r, 'data: 'r,
{ {
pub fn new(u: &'r mut Unstructured<'data>, config: &'r Config) -> Self { pub fn new(u: &'r mut Unstructured<'data>, config: &'r Config, target_triple: Triple) -> Self {
Self { Self {
u, u,
config, config,
resources: Resources::default(), resources: Resources::default(),
target_triple,
} }
} }
@@ -1396,6 +1451,14 @@ where
fn generate_instructions(&mut self, builder: &mut FunctionBuilder) -> Result<()> { fn generate_instructions(&mut self, builder: &mut FunctionBuilder) -> Result<()> {
for _ in 0..self.param(&self.config.instructions_per_block)? { for _ in 0..self.param(&self.config.instructions_per_block)? {
let (op, args, rets, inserter) = *self.u.choose(OPCODE_SIGNATURES)?; let (op, args, rets, inserter) = *self.u.choose(OPCODE_SIGNATURES)?;
// We filter out instructions that aren't supported by the target at this point instead
// of building a single vector of valid instructions at the beginning of function
// generation, to avoid invalidating the corpus when instructions are enabled/disabled.
if !valid_for_target(&self.target_triple, op, args, rets) {
return Err(arbitrary::Error::IncorrectFormat.into());
}
inserter(self, builder, op, args, rets)?; inserter(self, builder, op, args, rets)?;
} }

View File

@@ -7,9 +7,11 @@ use cranelift::codegen::data_value::DataValue;
use cranelift::codegen::ir::types::*; use cranelift::codegen::ir::types::*;
use cranelift::codegen::ir::Function; use cranelift::codegen::ir::Function;
use cranelift::codegen::Context; use cranelift::codegen::Context;
use cranelift::prelude::isa;
use cranelift::prelude::*; use cranelift::prelude::*;
use cranelift_native::builder_with_options; use cranelift_native::builder_with_options;
use std::fmt; use std::fmt;
use target_lexicon::{Architecture, Triple};
mod config; mod config;
mod function_generator; mod function_generator;
@@ -24,15 +26,77 @@ pub struct SingleFunction(pub Function);
impl<'a> Arbitrary<'a> for SingleFunction { impl<'a> Arbitrary<'a> for SingleFunction {
fn arbitrary(u: &mut Unstructured<'a>) -> arbitrary::Result<Self> { fn arbitrary(u: &mut Unstructured<'a>) -> arbitrary::Result<Self> {
FuzzGen::new(u) FuzzGen::new(u)
.generate_func() .generate_func(Triple::host())
.map_err(|_| arbitrary::Error::IncorrectFormat) .map_err(|_| arbitrary::Error::IncorrectFormat)
.map(Self) .map(Self)
} }
} }
/// Print only non default flags.
fn write_non_default_flags(f: &mut fmt::Formatter<'_>, flags: &settings::Flags) -> fmt::Result {
let default_flags = settings::Flags::new(settings::builder());
for (default, flag) in default_flags.iter().zip(flags.iter()) {
assert_eq!(default.name, flag.name);
if default.value_string() != flag.value_string() {
writeln!(f, "set {}={}", flag.name, flag.value_string())?;
}
}
Ok(())
}
/// A generated function with an ISA that targets one of cranelift's backends.
pub struct FunctionWithIsa {
/// TargetIsa to use when compiling this test case
pub isa: Box<dyn isa::TargetIsa>,
/// Function under test
pub func: Function,
}
impl fmt::Debug for FunctionWithIsa {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
writeln!(f, ";; Compile test case\n")?;
write_non_default_flags(f, self.isa.flags())?;
writeln!(f, "test compile")?;
writeln!(f, "target {}", self.isa.triple().architecture)?;
writeln!(f, "{}", self.func)?;
Ok(())
}
}
impl<'a> Arbitrary<'a> for FunctionWithIsa {
fn arbitrary(u: &mut arbitrary::Unstructured<'a>) -> arbitrary::Result<Self> {
// We filter out targets that aren't supported in the current build
// configuration after randomly choosing one, instead of randomly choosing
// a supported one, so that the same fuzz input works across different build
// configurations.
let target = u.choose(isa::ALL_ARCHITECTURES)?;
let builder = isa::lookup_by_name(target).map_err(|_| arbitrary::Error::IncorrectFormat)?;
let mut gen = FuzzGen::new(u);
let flags = gen
.generate_flags(builder.triple().architecture)
.map_err(|_| arbitrary::Error::IncorrectFormat)?;
let isa = builder
.finish(flags)
.map_err(|_| arbitrary::Error::IncorrectFormat)?;
let func = gen
.generate_func(isa.triple().clone())
.map_err(|_| arbitrary::Error::IncorrectFormat)?;
Ok(FunctionWithIsa { isa, func })
}
}
pub struct TestCase { pub struct TestCase {
/// [Flags] to use when compiling this test case /// TargetIsa to use when compiling this test case
pub flags: Flags, pub isa: Box<dyn isa::TargetIsa>,
/// Function under test /// Function under test
pub func: Function, pub func: Function,
/// Generate multiple test inputs for each test case. /// Generate multiple test inputs for each test case.
@@ -46,23 +110,10 @@ impl fmt::Debug for TestCase {
writeln!(f, "test interpret")?; writeln!(f, "test interpret")?;
writeln!(f, "test run")?; writeln!(f, "test run")?;
// Print only non default flags write_non_default_flags(f, self.isa.flags())?;
let default_flags = Flags::new(settings::builder());
for (default, flag) in default_flags.iter().zip(self.flags.iter()) {
assert_eq!(default.name, flag.name);
if default.value_string() != flag.value_string() {
writeln!(f, "set {}={}", flag.name, flag.value_string())?;
}
}
writeln!(f, "target aarch64")?;
writeln!(f, "target s390x")?;
writeln!(f, "target riscv64")?;
writeln!(f, "target x86_64\n")?;
writeln!(f, "target {}", self.isa.triple().architecture)?;
writeln!(f, "{}", self.func)?; writeln!(f, "{}", self.func)?;
writeln!(f, "; Note: the results in the below test cases are simply a placeholder and probably will be wrong\n")?; writeln!(f, "; Note: the results in the below test cases are simply a placeholder and probably will be wrong\n")?;
for input in self.inputs.iter() { for input in self.inputs.iter() {
@@ -101,7 +152,7 @@ impl fmt::Debug for TestCase {
impl<'a> Arbitrary<'a> for TestCase { impl<'a> Arbitrary<'a> for TestCase {
fn arbitrary(u: &mut Unstructured<'a>) -> arbitrary::Result<Self> { fn arbitrary(u: &mut Unstructured<'a>) -> arbitrary::Result<Self> {
FuzzGen::new(u) FuzzGen::new(u)
.generate_test() .generate_host_test()
.map_err(|_| arbitrary::Error::IncorrectFormat) .map_err(|_| arbitrary::Error::IncorrectFormat)
} }
} }
@@ -224,14 +275,14 @@ where
Ok(ctx.func) Ok(ctx.func)
} }
fn generate_func(&mut self) -> Result<Function> { fn generate_func(&mut self, target_triple: Triple) -> Result<Function> {
let func = FunctionGenerator::new(&mut self.u, &self.config).generate()?; let func = FunctionGenerator::new(&mut self.u, &self.config, target_triple).generate()?;
self.run_func_passes(func) self.run_func_passes(func)
} }
/// Generate a random set of cranelift flags. /// Generate a random set of cranelift flags.
/// Only semantics preserving flags are considered /// Only semantics preserving flags are considered
fn generate_flags(&mut self) -> Result<Flags> { fn generate_flags(&mut self, target_arch: Architecture) -> Result<Flags> {
let mut builder = settings::builder(); let mut builder = settings::builder();
let opt = self.u.choose(OptLevel::all())?; let opt = self.u.choose(OptLevel::all())?;
@@ -267,9 +318,15 @@ where
builder.set(flag_name, value.as_str())?; builder.set(flag_name, value.as_str())?;
} }
let supports_inline_probestack = match target_arch {
Architecture::X86_64 => true,
Architecture::Aarch64(_) => true,
_ => false,
};
// Optionally test inline stackprobes on supported platforms // Optionally test inline stackprobes on supported platforms
// TODO: Test outlined stack probes. // TODO: Test outlined stack probes.
if supports_inline_probestack() && bool::arbitrary(self.u)? { if supports_inline_probestack && bool::arbitrary(self.u)? {
builder.enable("enable_probestack")?; builder.enable("enable_probestack")?;
builder.set("probestack_strategy", "inline")?; builder.set("probestack_strategy", "inline")?;
@@ -283,7 +340,7 @@ where
// We need llvm ABI extensions for i128 values on x86, so enable it regardless of // We need llvm ABI extensions for i128 values on x86, so enable it regardless of
// what we picked above. // what we picked above.
if cfg!(target_arch = "x86_64") { if target_arch == Architecture::X86_64 {
builder.enable("enable_llvm_abi_extensions")?; builder.enable("enable_llvm_abi_extensions")?;
} }
@@ -300,26 +357,23 @@ where
// into compilation anywhere, we leave it on unconditionally to make sure the generation doesn't panic. // into compilation anywhere, we leave it on unconditionally to make sure the generation doesn't panic.
builder.enable("machine_code_cfg_info")?; builder.enable("machine_code_cfg_info")?;
return Ok(Flags::new(builder)); Ok(Flags::new(builder))
fn supports_inline_probestack() -> bool {
cfg!(target_arch = "x86_64") || cfg!(target_arch = "aarch64")
}
} }
pub fn generate_test(mut self) -> Result<TestCase> { pub fn generate_host_test(mut self) -> Result<TestCase> {
// If we're generating test inputs as well as a function, then we're planning to execute // If we're generating test inputs as well as a function, then we're planning to execute
// this function. That means that any function references in it need to exist. We don't yet // this function. That means that any function references in it need to exist. We don't yet
// have infrastructure for generating multiple functions, so just don't generate funcrefs. // have infrastructure for generating multiple functions, so just don't generate funcrefs.
self.config.funcrefs_per_function = 0..=0; self.config.funcrefs_per_function = 0..=0;
let flags = self.generate_flags()?; // TestCase is meant to be consumed by a runner, so we make the assumption here that we're
let func = self.generate_func()?; // generating a TargetIsa for the host.
let builder =
builder_with_options(true).expect("Unable to build a TargetIsa for the current host");
let flags = self.generate_flags(builder.triple().architecture)?;
let isa = builder.finish(flags)?;
let func = self.generate_func(isa.triple().clone())?;
let inputs = self.generate_test_inputs(&func.signature)?; let inputs = self.generate_test_inputs(&func.signature)?;
Ok(TestCase { Ok(TestCase { isa, func, inputs })
flags,
func,
inputs,
})
} }
} }

View File

@@ -10,7 +10,7 @@ cargo-fuzz = true
[dependencies] [dependencies]
anyhow = { workspace = true } anyhow = { workspace = true }
once_cell = { workspace = true } once_cell = { workspace = true }
cranelift-codegen = { workspace = true, features = ["incremental-cache"] } cranelift-codegen = { workspace = true, features = ["incremental-cache", "x86", "arm64"] }
cranelift-reader = { workspace = true } cranelift-reader = { workspace = true }
cranelift-wasm = { workspace = true } cranelift-wasm = { workspace = true }
cranelift-filetests = { workspace = true } cranelift-filetests = { workspace = true }

View File

@@ -7,7 +7,7 @@ use std::sync::atomic::AtomicU64;
use std::sync::atomic::Ordering; use std::sync::atomic::Ordering;
use cranelift_codegen::data_value::DataValue; use cranelift_codegen::data_value::DataValue;
use cranelift_codegen::ir::{LibCall, TrapCode}; use cranelift_codegen::ir::{Function, LibCall, TrapCode};
use cranelift_filetests::function_runner::{TestFileCompiler, Trampoline}; use cranelift_filetests::function_runner::{TestFileCompiler, Trampoline};
use cranelift_fuzzgen::*; use cranelift_fuzzgen::*;
use cranelift_interpreter::environment::FuncIndex; use cranelift_interpreter::environment::FuncIndex;
@@ -139,9 +139,9 @@ fn run_in_host(trampoline: &Trampoline, args: &[DataValue]) -> RunResult {
RunResult::Success(res) RunResult::Success(res)
} }
fn build_interpreter(testcase: &TestCase) -> Interpreter { fn build_interpreter(func: &Function) -> Interpreter {
let mut env = FunctionStore::default(); let mut env = FunctionStore::default();
env.add(testcase.func.name.to_string(), &testcase.func); env.add(func.name.to_string(), &func);
let state = InterpreterState::default() let state = InterpreterState::default()
.with_function_store(env) .with_function_store(env)
@@ -166,7 +166,7 @@ static STATISTICS: Lazy<Statistics> = Lazy::new(Statistics::default);
fuzz_target!(|testcase: TestCase| { fuzz_target!(|testcase: TestCase| {
// This is the default, but we should ensure that it wasn't accidentally turned off anywhere. // This is the default, but we should ensure that it wasn't accidentally turned off anywhere.
assert!(testcase.flags.enable_verifier()); assert!(testcase.isa.flags().enable_verifier());
// Periodically print statistics // Periodically print statistics
let valid_inputs = STATISTICS.valid_inputs.fetch_add(1, Ordering::SeqCst); let valid_inputs = STATISTICS.valid_inputs.fetch_add(1, Ordering::SeqCst);
@@ -174,7 +174,7 @@ fuzz_target!(|testcase: TestCase| {
STATISTICS.print(valid_inputs); STATISTICS.print(valid_inputs);
} }
let mut compiler = TestFileCompiler::with_host_isa(testcase.flags.clone()).unwrap(); let mut compiler = TestFileCompiler::new(testcase.isa);
compiler.declare_function(&testcase.func).unwrap(); compiler.declare_function(&testcase.func).unwrap();
compiler.define_function(testcase.func.clone()).unwrap(); compiler.define_function(testcase.func.clone()).unwrap();
compiler compiler
@@ -188,7 +188,7 @@ fuzz_target!(|testcase: TestCase| {
// We rebuild the interpreter every run so that we don't accidentally carry over any state // We rebuild the interpreter every run so that we don't accidentally carry over any state
// between runs, such as fuel remaining. // between runs, such as fuel remaining.
let mut interpreter = build_interpreter(&testcase); let mut interpreter = build_interpreter(&testcase.func);
let int_res = run_in_interpreter(&mut interpreter, args); let int_res = run_in_interpreter(&mut interpreter, args);
match int_res { match int_res {
RunResult::Success(_) => { RunResult::Success(_) => {

View File

@@ -4,39 +4,14 @@ use cranelift_codegen::{
cursor::{Cursor, FuncCursor}, cursor::{Cursor, FuncCursor},
incremental_cache as icache, incremental_cache as icache,
ir::{self, immediates::Imm64, ExternalName}, ir::{self, immediates::Imm64, ExternalName},
isa,
settings::{self, Configurable as _},
Context, Context,
}; };
use libfuzzer_sys::fuzz_target; use libfuzzer_sys::fuzz_target;
use cranelift_fuzzgen::*; use cranelift_fuzzgen::*;
use target_lexicon::Triple;
fuzz_target!(|func: SingleFunction| { fuzz_target!(|func: FunctionWithIsa| {
let mut func = func.0; let FunctionWithIsa { mut func, isa } = func;
let flags = settings::Flags::new({
let mut builder = settings::builder();
// We need llvm ABI extensions for i128 values on x86
builder.set("enable_llvm_abi_extensions", "true").unwrap();
// This is the default, but we should ensure that it wasn't accidentally turned off anywhere.
builder.set("enable_verifier", "true").unwrap();
builder
});
let isa_builder = isa::lookup(Triple::host())
.map_err(|err| match err {
isa::LookupError::SupportDisabled => {
"support for architecture disabled at compile time"
}
isa::LookupError::Unsupported => "unsupported architecture",
})
.unwrap();
let isa = isa_builder.finish(flags).unwrap();
let cache_key_hash = icache::compute_cache_key(&*isa, &mut func); let cache_key_hash = icache::compute_cache_key(&*isa, &mut func);