1 use crate::store::{AutoAssertNoGc, StoreOpaque}; 2 use crate::{Result, ValRaw, ValType, WasmTy}; 3 use core::cmp::Ordering; 4 use core::mem::MaybeUninit; 5 use 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)] 24 pub 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 31 impl 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. 39 impl From<u128> for V128 { 40 fn from(val: u128) -> V128 { 41 Self(val.to_ne_bytes()) 42 } 43 } 44 45 impl From<V128> for u128 { 46 fn from(val: V128) -> u128 { 47 val.as_u128() 48 } 49 } 50 51 impl fmt::Debug for V128 { 52 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { 53 self.as_u128().fmt(f) 54 } 55 } 56 57 impl PartialEq for V128 { 58 fn eq(&self, other: &V128) -> bool { 59 self.as_u128() == other.as_u128() 60 } 61 } 62 63 impl Eq for V128 {} 64 65 impl PartialOrd for V128 { 66 fn partial_cmp(&self, other: &V128) -> Option<Ordering> { 67 Some(self.cmp(other)) 68 } 69 } 70 71 impl 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. 79 unsafe 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 } 110