wasmtime/runtime/
v128.rs

1use crate::store::{AutoAssertNoGc, StoreOpaque};
2use crate::{Result, ValRaw, ValType, WasmTy};
3use core::cmp::Ordering;
4use core::mem::MaybeUninit;
5use core::{fmt, mem};
6
7/// Representation of a 128-bit vector type, `v128`, for WebAssembly.
8///
9/// This type corresponds to the `v128` type in WebAssembly and can be used with
10/// the [`TypedFunc`] API for example. This is additionally
11/// the payload of [`Val::V128`](crate::Val).
12///
13/// # Platform specifics
14///
15/// This type can currently only be used on x86_64 and AArch64 with the
16/// [`TypedFunc`] API. Rust does not have stable support on other platforms for
17/// this type so invoking functions with `v128` parameters requires the
18/// [`Func::call`](crate::Func::call) API (or perhaps
19/// [`Func::call_unchecked`](crate::Func::call_unchecked).
20///
21/// [`TypedFunc`]: crate::TypedFunc
22#[derive(Copy, Clone)]
23#[repr(transparent)]
24pub struct V128(
25    // NB: represent this internally with a `u8` array so that `V128` does not
26    // have 16-byte alignment and force `Val`'s discriminant to be 16-bytes
27    // larger. These bytes are always in native-endian order.
28    [u8; mem::size_of::<u128>()],
29);
30
31impl V128 {
32    /// Returns the representation of this `v128` as a 128-bit integer in Rust.
33    pub fn as_u128(&self) -> u128 {
34        u128::from_ne_bytes(self.0)
35    }
36}
37
38/// Primary constructor of a `V128` type.
39impl From<u128> for V128 {
40    fn from(val: u128) -> V128 {
41        Self(val.to_ne_bytes())
42    }
43}
44
45impl From<V128> for u128 {
46    fn from(val: V128) -> u128 {
47        val.as_u128()
48    }
49}
50
51impl fmt::Debug for V128 {
52    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
53        self.as_u128().fmt(f)
54    }
55}
56
57impl PartialEq for V128 {
58    fn eq(&self, other: &V128) -> bool {
59        self.as_u128() == other.as_u128()
60    }
61}
62
63impl Eq for V128 {}
64
65impl PartialOrd for V128 {
66    fn partial_cmp(&self, other: &V128) -> Option<Ordering> {
67        Some(self.cmp(other))
68    }
69}
70
71impl Ord for V128 {
72    fn cmp(&self, other: &V128) -> Ordering {
73        self.as_u128().cmp(&other.as_u128())
74    }
75}
76
77// Note that this trait is conditionally implemented which is intentional. See
78// the documentation above in the `cfg_if!` for why this is conditional.
79unsafe impl WasmTy for V128 {
80    #[inline]
81    fn valtype() -> ValType {
82        ValType::V128
83    }
84
85    #[inline]
86    fn compatible_with_store(&self, _: &StoreOpaque) -> bool {
87        true
88    }
89
90    fn dynamic_concrete_type_check(
91        &self,
92        _: &StoreOpaque,
93        _: bool,
94        _: &crate::HeapType,
95    ) -> anyhow::Result<()> {
96        unreachable!()
97    }
98
99    #[inline]
100    fn store(self, _store: &mut AutoAssertNoGc<'_>, ptr: &mut MaybeUninit<ValRaw>) -> Result<()> {
101        ptr.write(ValRaw::v128(self.as_u128()));
102        Ok(())
103    }
104
105    #[inline]
106    unsafe fn load(_store: &mut AutoAssertNoGc<'_>, ptr: &ValRaw) -> Self {
107        V128::from(ptr.get_v128())
108    }
109}