wasmtime/runtime/
v128.rs

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