15ec92d59SAndrew Brown //! Generate Wasm values, primarily for differential execution.
25ec92d59SAndrew Brown 
35ec92d59SAndrew Brown use arbitrary::{Arbitrary, Unstructured};
45ec92d59SAndrew Brown use std::hash::Hash;
5ff93bce0SNick Fitzgerald use wasmtime::HeapType;
65ec92d59SAndrew Brown 
75ec92d59SAndrew Brown /// A value passed to and from evaluation. Note that reference types are not
85ec92d59SAndrew Brown /// (yet) supported.
95ec92d59SAndrew Brown #[derive(Clone, Debug)]
1045b60bd6SAlex Crichton #[expect(missing_docs, reason = "self-describing fields")]
115ec92d59SAndrew Brown pub enum DiffValue {
125ec92d59SAndrew Brown     I32(i32),
135ec92d59SAndrew Brown     I64(i64),
145ec92d59SAndrew Brown     F32(u32),
155ec92d59SAndrew Brown     F64(u64),
165ec92d59SAndrew Brown     V128(u128),
17fd98814bSAlex Crichton     FuncRef { null: bool },
18fd98814bSAlex Crichton     ExternRef { null: bool },
190fa13013SNick Fitzgerald     AnyRef { null: bool },
20eaa4632eSChris Fallin     ExnRef { null: bool },
21*a631d20aSPaul Osborne     ContRef { null: bool },
225ec92d59SAndrew Brown }
235ec92d59SAndrew Brown 
245ec92d59SAndrew Brown impl DiffValue {
ty(&self) -> DiffValueType255ec92d59SAndrew Brown     fn ty(&self) -> DiffValueType {
265ec92d59SAndrew Brown         match self {
275ec92d59SAndrew Brown             DiffValue::I32(_) => DiffValueType::I32,
285ec92d59SAndrew Brown             DiffValue::I64(_) => DiffValueType::I64,
295ec92d59SAndrew Brown             DiffValue::F32(_) => DiffValueType::F32,
305ec92d59SAndrew Brown             DiffValue::F64(_) => DiffValueType::F64,
315ec92d59SAndrew Brown             DiffValue::V128(_) => DiffValueType::V128,
32fd98814bSAlex Crichton             DiffValue::FuncRef { .. } => DiffValueType::FuncRef,
33fd98814bSAlex Crichton             DiffValue::ExternRef { .. } => DiffValueType::ExternRef,
340fa13013SNick Fitzgerald             DiffValue::AnyRef { .. } => DiffValueType::AnyRef,
35eaa4632eSChris Fallin             DiffValue::ExnRef { .. } => DiffValueType::ExnRef,
36*a631d20aSPaul Osborne             DiffValue::ContRef { .. } => DiffValueType::ContRef,
375ec92d59SAndrew Brown         }
385ec92d59SAndrew Brown     }
395ec92d59SAndrew Brown 
405ec92d59SAndrew Brown     /// Generate a [`DiffValue`] of the given `ty` type.
415ec92d59SAndrew Brown     ///
425ec92d59SAndrew Brown     /// This function will bias the returned value 50% of the time towards one
435ec92d59SAndrew Brown     /// of a set of known values (e.g., NaN, -1, 0, infinity, etc.).
arbitrary_of_type( u: &mut Unstructured<'_>, ty: DiffValueType, ) -> arbitrary::Result<Self>445ec92d59SAndrew Brown     pub fn arbitrary_of_type(
455ec92d59SAndrew Brown         u: &mut Unstructured<'_>,
465ec92d59SAndrew Brown         ty: DiffValueType,
475ec92d59SAndrew Brown     ) -> arbitrary::Result<Self> {
485ec92d59SAndrew Brown         use DiffValueType::*;
495ec92d59SAndrew Brown         let val = match ty {
505ec92d59SAndrew Brown             I32 => DiffValue::I32(biased_arbitrary_value(u, KNOWN_I32_VALUES)?),
515ec92d59SAndrew Brown             I64 => DiffValue::I64(biased_arbitrary_value(u, KNOWN_I64_VALUES)?),
525ec92d59SAndrew Brown             F32 => {
535ec92d59SAndrew Brown                 // TODO once `to_bits` is stable as a `const` function, move
545ec92d59SAndrew Brown                 // this to a `const` definition.
555ec92d59SAndrew Brown                 let known_f32_values = &[
565ec92d59SAndrew Brown                     f32::NAN.to_bits(),
575ec92d59SAndrew Brown                     f32::INFINITY.to_bits(),
585ec92d59SAndrew Brown                     f32::NEG_INFINITY.to_bits(),
595ec92d59SAndrew Brown                     f32::MIN.to_bits(),
605ec92d59SAndrew Brown                     (-1.0f32).to_bits(),
615ec92d59SAndrew Brown                     (0.0f32).to_bits(),
625ec92d59SAndrew Brown                     (1.0f32).to_bits(),
635ec92d59SAndrew Brown                     f32::MAX.to_bits(),
645ec92d59SAndrew Brown                 ];
65fd98814bSAlex Crichton                 let bits = biased_arbitrary_value(u, known_f32_values)?;
66fd98814bSAlex Crichton 
671f39f63dSFrankReh                 // If the chosen bits are NaN then always use the canonical bit
681f39f63dSFrankReh                 // pattern of NaN to enable better compatibility with engines
691f39f63dSFrankReh                 // where arbitrary NaN patterns can't make their way into wasm
70fd98814bSAlex Crichton                 // (e.g. v8 through JS can't do that).
71fd98814bSAlex Crichton                 let bits = if f32::from_bits(bits).is_nan() {
72fd98814bSAlex Crichton                     f32::NAN.to_bits()
73fd98814bSAlex Crichton                 } else {
74fd98814bSAlex Crichton                     bits
75fd98814bSAlex Crichton                 };
76fd98814bSAlex Crichton                 DiffValue::F32(bits)
775ec92d59SAndrew Brown             }
785ec92d59SAndrew Brown             F64 => {
795ec92d59SAndrew Brown                 // TODO once `to_bits` is stable as a `const` function, move
805ec92d59SAndrew Brown                 // this to a `const` definition.
815ec92d59SAndrew Brown                 let known_f64_values = &[
825ec92d59SAndrew Brown                     f64::NAN.to_bits(),
835ec92d59SAndrew Brown                     f64::INFINITY.to_bits(),
845ec92d59SAndrew Brown                     f64::NEG_INFINITY.to_bits(),
855ec92d59SAndrew Brown                     f64::MIN.to_bits(),
865ec92d59SAndrew Brown                     (-1.0f64).to_bits(),
875ec92d59SAndrew Brown                     (0.0f64).to_bits(),
885ec92d59SAndrew Brown                     (1.0f64).to_bits(),
895ec92d59SAndrew Brown                     f64::MAX.to_bits(),
905ec92d59SAndrew Brown                 ];
91fd98814bSAlex Crichton                 let bits = biased_arbitrary_value(u, known_f64_values)?;
921f39f63dSFrankReh                 // See `f32` above for why canonical NaN patterns are always
93fd98814bSAlex Crichton                 // used.
94fd98814bSAlex Crichton                 let bits = if f64::from_bits(bits).is_nan() {
95fd98814bSAlex Crichton                     f64::NAN.to_bits()
96fd98814bSAlex Crichton                 } else {
97fd98814bSAlex Crichton                     bits
98fd98814bSAlex Crichton                 };
99fd98814bSAlex Crichton                 DiffValue::F64(bits)
1005ec92d59SAndrew Brown             }
101cd982c5aSAndrew Brown             V128 => {
102cd982c5aSAndrew Brown                 // Generate known values for each sub-type of V128.
103cd982c5aSAndrew Brown                 let ty: DiffSimdTy = u.arbitrary()?;
104cd982c5aSAndrew Brown                 match ty {
105cd982c5aSAndrew Brown                     DiffSimdTy::I8x16 => {
106cd982c5aSAndrew Brown                         let mut i8 = || biased_arbitrary_value(u, KNOWN_I8_VALUES).map(|b| b as u8);
107cd982c5aSAndrew Brown                         let vector = u128::from_le_bytes([
108cd982c5aSAndrew Brown                             i8()?,
109cd982c5aSAndrew Brown                             i8()?,
110cd982c5aSAndrew Brown                             i8()?,
111cd982c5aSAndrew Brown                             i8()?,
112cd982c5aSAndrew Brown                             i8()?,
113cd982c5aSAndrew Brown                             i8()?,
114cd982c5aSAndrew Brown                             i8()?,
115cd982c5aSAndrew Brown                             i8()?,
116cd982c5aSAndrew Brown                             i8()?,
117cd982c5aSAndrew Brown                             i8()?,
118cd982c5aSAndrew Brown                             i8()?,
119cd982c5aSAndrew Brown                             i8()?,
120cd982c5aSAndrew Brown                             i8()?,
121cd982c5aSAndrew Brown                             i8()?,
122cd982c5aSAndrew Brown                             i8()?,
123cd982c5aSAndrew Brown                             i8()?,
124cd982c5aSAndrew Brown                         ]);
125cd982c5aSAndrew Brown                         DiffValue::V128(vector)
126cd982c5aSAndrew Brown                     }
127cd982c5aSAndrew Brown                     DiffSimdTy::I16x8 => {
128cd982c5aSAndrew Brown                         let mut i16 =
129cd982c5aSAndrew Brown                             || biased_arbitrary_value(u, KNOWN_I16_VALUES).map(i16::to_le_bytes);
130cd982c5aSAndrew Brown                         let vector: Vec<u8> = i16()?
131cd982c5aSAndrew Brown                             .into_iter()
132cd982c5aSAndrew Brown                             .chain(i16()?)
133cd982c5aSAndrew Brown                             .chain(i16()?)
134cd982c5aSAndrew Brown                             .chain(i16()?)
135cd982c5aSAndrew Brown                             .chain(i16()?)
136cd982c5aSAndrew Brown                             .chain(i16()?)
137cd982c5aSAndrew Brown                             .chain(i16()?)
138cd982c5aSAndrew Brown                             .chain(i16()?)
139cd982c5aSAndrew Brown                             .collect();
140cd982c5aSAndrew Brown                         DiffValue::V128(u128::from_le_bytes(vector.try_into().unwrap()))
141cd982c5aSAndrew Brown                     }
142cd982c5aSAndrew Brown                     DiffSimdTy::I32x4 => {
143cd982c5aSAndrew Brown                         let mut i32 =
144cd982c5aSAndrew Brown                             || biased_arbitrary_value(u, KNOWN_I32_VALUES).map(i32::to_le_bytes);
145cd982c5aSAndrew Brown                         let vector: Vec<u8> = i32()?
146cd982c5aSAndrew Brown                             .into_iter()
147cd982c5aSAndrew Brown                             .chain(i32()?)
148cd982c5aSAndrew Brown                             .chain(i32()?)
149cd982c5aSAndrew Brown                             .chain(i32()?)
150cd982c5aSAndrew Brown                             .collect();
151cd982c5aSAndrew Brown                         DiffValue::V128(u128::from_le_bytes(vector.try_into().unwrap()))
152cd982c5aSAndrew Brown                     }
153cd982c5aSAndrew Brown                     DiffSimdTy::I64x2 => {
154cd982c5aSAndrew Brown                         let mut i64 =
155cd982c5aSAndrew Brown                             || biased_arbitrary_value(u, KNOWN_I64_VALUES).map(i64::to_le_bytes);
156cd982c5aSAndrew Brown                         let vector: Vec<u8> = i64()?.into_iter().chain(i64()?).collect();
157cd982c5aSAndrew Brown                         DiffValue::V128(u128::from_le_bytes(vector.try_into().unwrap()))
158cd982c5aSAndrew Brown                     }
159cd982c5aSAndrew Brown                     DiffSimdTy::F32x4 => {
160cd982c5aSAndrew Brown                         let mut f32 = || {
161cd982c5aSAndrew Brown                             Self::arbitrary_of_type(u, DiffValueType::F32).map(|v| match v {
162cd982c5aSAndrew Brown                                 DiffValue::F32(v) => v.to_le_bytes(),
163cd982c5aSAndrew Brown                                 _ => unreachable!(),
164cd982c5aSAndrew Brown                             })
165cd982c5aSAndrew Brown                         };
166cd982c5aSAndrew Brown                         let vector: Vec<u8> = f32()?
167cd982c5aSAndrew Brown                             .into_iter()
168cd982c5aSAndrew Brown                             .chain(f32()?)
169cd982c5aSAndrew Brown                             .chain(f32()?)
170cd982c5aSAndrew Brown                             .chain(f32()?)
171cd982c5aSAndrew Brown                             .collect();
172cd982c5aSAndrew Brown                         DiffValue::V128(u128::from_le_bytes(vector.try_into().unwrap()))
173cd982c5aSAndrew Brown                     }
174cd982c5aSAndrew Brown                     DiffSimdTy::F64x2 => {
175cd982c5aSAndrew Brown                         let mut f64 = || {
176cd982c5aSAndrew Brown                             Self::arbitrary_of_type(u, DiffValueType::F64).map(|v| match v {
177cd982c5aSAndrew Brown                                 DiffValue::F64(v) => v.to_le_bytes(),
178cd982c5aSAndrew Brown                                 _ => unreachable!(),
179cd982c5aSAndrew Brown                             })
180cd982c5aSAndrew Brown                         };
181cd982c5aSAndrew Brown                         let vector: Vec<u8> = f64()?.into_iter().chain(f64()?).collect();
182cd982c5aSAndrew Brown                         DiffValue::V128(u128::from_le_bytes(vector.try_into().unwrap()))
183cd982c5aSAndrew Brown                     }
184cd982c5aSAndrew Brown                 }
185cd982c5aSAndrew Brown             }
186fd98814bSAlex Crichton 
187fd98814bSAlex Crichton             // TODO: this isn't working in most engines so just always pass a
188fd98814bSAlex Crichton             // null in which if an engine supports this is should at least
189fd98814bSAlex Crichton             // support doing that.
190fd98814bSAlex Crichton             FuncRef => DiffValue::FuncRef { null: true },
191fd98814bSAlex Crichton             ExternRef => DiffValue::ExternRef { null: true },
1920fa13013SNick Fitzgerald             AnyRef => DiffValue::AnyRef { null: true },
193eaa4632eSChris Fallin             ExnRef => DiffValue::ExnRef { null: true },
194*a631d20aSPaul Osborne             ContRef => DiffValue::ContRef { null: true },
1955ec92d59SAndrew Brown         };
1965ec92d59SAndrew Brown         arbitrary::Result::Ok(val)
1975ec92d59SAndrew Brown     }
1985ec92d59SAndrew Brown }
1995ec92d59SAndrew Brown 
200cd982c5aSAndrew Brown const KNOWN_I8_VALUES: &[i8] = &[i8::MIN, -1, 0, 1, i8::MAX];
201cd982c5aSAndrew Brown const KNOWN_I16_VALUES: &[i16] = &[i16::MIN, -1, 0, 1, i16::MAX];
2025ec92d59SAndrew Brown const KNOWN_I32_VALUES: &[i32] = &[i32::MIN, -1, 0, 1, i32::MAX];
2035ec92d59SAndrew Brown const KNOWN_I64_VALUES: &[i64] = &[i64::MIN, -1, 0, 1, i64::MAX];
2045ec92d59SAndrew Brown 
2055ec92d59SAndrew Brown /// Helper function to pick a known value from the list of `known_values` half
2065ec92d59SAndrew Brown /// the time.
biased_arbitrary_value<'a, T>( u: &mut Unstructured<'a>, known_values: &[T], ) -> arbitrary::Result<T> where T: Arbitrary<'a> + Copy,2075ec92d59SAndrew Brown fn biased_arbitrary_value<'a, T>(
2085ec92d59SAndrew Brown     u: &mut Unstructured<'a>,
2095ec92d59SAndrew Brown     known_values: &[T],
2105ec92d59SAndrew Brown ) -> arbitrary::Result<T>
2115ec92d59SAndrew Brown where
2125ec92d59SAndrew Brown     T: Arbitrary<'a> + Copy,
2135ec92d59SAndrew Brown {
2145ec92d59SAndrew Brown     let pick_from_known_values: bool = u.arbitrary()?;
2155ec92d59SAndrew Brown     if pick_from_known_values {
2165ec92d59SAndrew Brown         Ok(*u.choose(known_values)?)
2175ec92d59SAndrew Brown     } else {
2185ec92d59SAndrew Brown         u.arbitrary()
2195ec92d59SAndrew Brown     }
2205ec92d59SAndrew Brown }
2215ec92d59SAndrew Brown 
2225ec92d59SAndrew Brown impl<'a> Arbitrary<'a> for DiffValue {
arbitrary(u: &mut Unstructured<'a>) -> arbitrary::Result<Self>2235ec92d59SAndrew Brown     fn arbitrary(u: &mut Unstructured<'a>) -> arbitrary::Result<Self> {
2245ec92d59SAndrew Brown         let ty: DiffValueType = u.arbitrary()?;
2255ec92d59SAndrew Brown         DiffValue::arbitrary_of_type(u, ty)
2265ec92d59SAndrew Brown     }
2275ec92d59SAndrew Brown }
2285ec92d59SAndrew Brown 
2295ec92d59SAndrew Brown impl Hash for DiffValue {
hash<H: std::hash::Hasher>(&self, state: &mut H)2305ec92d59SAndrew Brown     fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
2315ec92d59SAndrew Brown         self.ty().hash(state);
2325ec92d59SAndrew Brown         match self {
2335ec92d59SAndrew Brown             DiffValue::I32(n) => n.hash(state),
2345ec92d59SAndrew Brown             DiffValue::I64(n) => n.hash(state),
2355ec92d59SAndrew Brown             DiffValue::F32(n) => n.hash(state),
2365ec92d59SAndrew Brown             DiffValue::F64(n) => n.hash(state),
2375ec92d59SAndrew Brown             DiffValue::V128(n) => n.hash(state),
238fd98814bSAlex Crichton             DiffValue::ExternRef { null } => null.hash(state),
239fd98814bSAlex Crichton             DiffValue::FuncRef { null } => null.hash(state),
2400fa13013SNick Fitzgerald             DiffValue::AnyRef { null } => null.hash(state),
241eaa4632eSChris Fallin             DiffValue::ExnRef { null } => null.hash(state),
242*a631d20aSPaul Osborne             DiffValue::ContRef { null } => null.hash(state),
2435ec92d59SAndrew Brown         }
2445ec92d59SAndrew Brown     }
2455ec92d59SAndrew Brown }
2465ec92d59SAndrew Brown 
2475ec92d59SAndrew Brown /// Implement equality checks. Note that floating-point values are not compared
2485ec92d59SAndrew Brown /// bit-for-bit in the case of NaNs: because Wasm floating-point numbers may be
2495ec92d59SAndrew Brown /// [arithmetic NaNs with arbitrary payloads] and Wasm operations are [not
2505ec92d59SAndrew Brown /// required to propagate NaN payloads], we simply check that both sides are
2515ec92d59SAndrew Brown /// NaNs here. We could be more strict, though: we could check that the NaN
2525ec92d59SAndrew Brown /// signs are equal and that [canonical NaN payloads remain canonical].
2535ec92d59SAndrew Brown ///
2545ec92d59SAndrew Brown /// [arithmetic NaNs with arbitrary payloads]:
2555ec92d59SAndrew Brown ///     https://webassembly.github.io/spec/core/bikeshed/index.html#floating-point%E2%91%A0
2565ec92d59SAndrew Brown /// [not required to propagate NaN payloads]:
2575ec92d59SAndrew Brown ///     https://webassembly.github.io/spec/core/bikeshed/index.html#floating-point-operations%E2%91%A0
2585ec92d59SAndrew Brown /// [canonical NaN payloads remain canonical]:
2595ec92d59SAndrew Brown ///     https://webassembly.github.io/spec/core/bikeshed/index.html#nan-propagation%E2%91%A0
2605ec92d59SAndrew Brown impl PartialEq for DiffValue {
eq(&self, other: &Self) -> bool2615ec92d59SAndrew Brown     fn eq(&self, other: &Self) -> bool {
2625ec92d59SAndrew Brown         match (self, other) {
2635ec92d59SAndrew Brown             (Self::I32(l0), Self::I32(r0)) => l0 == r0,
2645ec92d59SAndrew Brown             (Self::I64(l0), Self::I64(r0)) => l0 == r0,
2655ec92d59SAndrew Brown             (Self::V128(l0), Self::V128(r0)) => l0 == r0,
2665ec92d59SAndrew Brown             (Self::F32(l0), Self::F32(r0)) => {
2675ec92d59SAndrew Brown                 let l0 = f32::from_bits(*l0);
2685ec92d59SAndrew Brown                 let r0 = f32::from_bits(*r0);
2695ec92d59SAndrew Brown                 l0 == r0 || (l0.is_nan() && r0.is_nan())
2705ec92d59SAndrew Brown             }
2715ec92d59SAndrew Brown             (Self::F64(l0), Self::F64(r0)) => {
2725ec92d59SAndrew Brown                 let l0 = f64::from_bits(*l0);
2735ec92d59SAndrew Brown                 let r0 = f64::from_bits(*r0);
2745ec92d59SAndrew Brown                 l0 == r0 || (l0.is_nan() && r0.is_nan())
2755ec92d59SAndrew Brown             }
276fd98814bSAlex Crichton             (Self::FuncRef { null: a }, Self::FuncRef { null: b }) => a == b,
277fd98814bSAlex Crichton             (Self::ExternRef { null: a }, Self::ExternRef { null: b }) => a == b,
2785b9e8765SNick Fitzgerald             (Self::AnyRef { null: a }, Self::AnyRef { null: b }) => a == b,
2793aa39239SChris Fallin             (Self::ExnRef { null: a }, Self::ExnRef { null: b }) => a == b,
280*a631d20aSPaul Osborne             (Self::ContRef { null: a }, Self::ContRef { null: b }) => a == b,
2815ec92d59SAndrew Brown             _ => false,
2825ec92d59SAndrew Brown         }
2835ec92d59SAndrew Brown     }
2845ec92d59SAndrew Brown }
2855ec92d59SAndrew Brown 
2865ec92d59SAndrew Brown /// Enumerate the supported value types.
287fd98814bSAlex Crichton #[derive(Copy, Clone, Debug, Arbitrary, Hash)]
28845b60bd6SAlex Crichton #[expect(missing_docs, reason = "self-describing variants")]
2895ec92d59SAndrew Brown pub enum DiffValueType {
2905ec92d59SAndrew Brown     I32,
2915ec92d59SAndrew Brown     I64,
2925ec92d59SAndrew Brown     F32,
2935ec92d59SAndrew Brown     F64,
2945ec92d59SAndrew Brown     V128,
295fd98814bSAlex Crichton     FuncRef,
296fd98814bSAlex Crichton     ExternRef,
2970fa13013SNick Fitzgerald     AnyRef,
298eaa4632eSChris Fallin     ExnRef,
299*a631d20aSPaul Osborne     ContRef,
3005ec92d59SAndrew Brown }
3015ec92d59SAndrew Brown 
3025ec92d59SAndrew Brown impl TryFrom<wasmtime::ValType> for DiffValueType {
3035ec92d59SAndrew Brown     type Error = &'static str;
try_from(ty: wasmtime::ValType) -> Result<Self, Self::Error>3045ec92d59SAndrew Brown     fn try_from(ty: wasmtime::ValType) -> Result<Self, Self::Error> {
3055ec92d59SAndrew Brown         use wasmtime::ValType::*;
3065ec92d59SAndrew Brown         match ty {
3075ec92d59SAndrew Brown             I32 => Ok(Self::I32),
3085ec92d59SAndrew Brown             I64 => Ok(Self::I64),
3095ec92d59SAndrew Brown             F32 => Ok(Self::F32),
3105ec92d59SAndrew Brown             F64 => Ok(Self::F64),
3115ec92d59SAndrew Brown             V128 => Ok(Self::V128),
312ff93bce0SNick Fitzgerald             Ref(r) => match (r.is_nullable(), r.heap_type()) {
313ff93bce0SNick Fitzgerald                 (true, HeapType::Func) => Ok(Self::FuncRef),
314ff93bce0SNick Fitzgerald                 (true, HeapType::Extern) => Ok(Self::ExternRef),
3150fa13013SNick Fitzgerald                 (true, HeapType::Any) => Ok(Self::AnyRef),
3160fa13013SNick Fitzgerald                 (true, HeapType::I31) => Ok(Self::AnyRef),
3170fa13013SNick Fitzgerald                 (true, HeapType::None) => Ok(Self::AnyRef),
318eaa4632eSChris Fallin                 (true, HeapType::Exn) => Ok(Self::ExnRef),
319*a631d20aSPaul Osborne                 (true, HeapType::Cont) => Ok(Self::ContRef),
3205b9e8765SNick Fitzgerald                 _ => Err("non-null reference types are not supported yet"),
321ff93bce0SNick Fitzgerald             },
3225ec92d59SAndrew Brown         }
3235ec92d59SAndrew Brown     }
3245ec92d59SAndrew Brown }
325cd982c5aSAndrew Brown 
326cd982c5aSAndrew Brown /// Enumerate the types of v128.
327cd982c5aSAndrew Brown #[derive(Copy, Clone, Debug, Arbitrary, Hash)]
328cd982c5aSAndrew Brown pub enum DiffSimdTy {
329cd982c5aSAndrew Brown     I8x16,
330cd982c5aSAndrew Brown     I16x8,
331cd982c5aSAndrew Brown     I32x4,
332cd982c5aSAndrew Brown     I64x2,
333cd982c5aSAndrew Brown     F32x4,
334cd982c5aSAndrew Brown     F64x2,
335cd982c5aSAndrew Brown }
336