Skip to content

Commit

Permalink
Make ValRaw fields private
Browse files Browse the repository at this point in the history
Force accessing to go through constructors and accessors to localize the
knowledge about little-endian-ness. This is spawned since I made a
mistake in bytecodealliance#4039 about endianness.
  • Loading branch information
alexcrichton committed May 24, 2022
1 parent 140b835 commit 78aa7d3
Show file tree
Hide file tree
Showing 4 changed files with 150 additions and 44 deletions.
126 changes: 119 additions & 7 deletions crates/runtime/src/vmcontext.rs
Original file line number Diff line number Diff line change
Expand Up @@ -794,7 +794,7 @@ pub union ValRaw {
/// or unsigned. The Rust type `i32` is simply chosen for convenience.
///
/// This value is always stored in a little-endian format.
pub i32: i32,
i32: i32,

/// A WebAssembly `i64` value.
///
Expand All @@ -803,7 +803,7 @@ pub union ValRaw {
/// or unsigned. The Rust type `i64` is simply chosen for convenience.
///
/// This value is always stored in a little-endian format.
pub i64: i64,
i64: i64,

/// A WebAssembly `f32` value.
///
Expand All @@ -813,7 +813,7 @@ pub union ValRaw {
/// `u32` value is the return value of `f32::to_bits` in Rust.
///
/// This value is always stored in a little-endian format.
pub f32: u32,
f32: u32,

/// A WebAssembly `f64` value.
///
Expand All @@ -823,7 +823,7 @@ pub union ValRaw {
/// `u64` value is the return value of `f64::to_bits` in Rust.
///
/// This value is always stored in a little-endian format.
pub f64: u64,
f64: u64,

/// A WebAssembly `v128` value.
///
Expand All @@ -833,7 +833,7 @@ pub union ValRaw {
/// underlying bits is left up to the instructions which consume this value.
///
/// This value is always stored in a little-endian format.
pub v128: u128,
v128: u128,

/// A WebAssembly `funcref` value.
///
Expand All @@ -843,7 +843,7 @@ pub union ValRaw {
/// carefully calling the correct functions throughout the runtime.
///
/// This value is always stored in a little-endian format.
pub funcref: usize,
funcref: usize,

/// A WebAssembly `externref` value.
///
Expand All @@ -853,7 +853,119 @@ pub union ValRaw {
/// carefully calling the correct functions throughout the runtime.
///
/// This value is always stored in a little-endian format.
pub externref: usize,
externref: usize,
}

impl ValRaw {
/// Creates a WebAssembly `i32` value
#[inline]
pub fn i32(i: i32) -> ValRaw {
ValRaw { i32: i.to_le() }
}

/// Creates a WebAssembly `i64` value
#[inline]
pub fn i64(i: i64) -> ValRaw {
ValRaw { i64: i.to_le() }
}

/// Creates a WebAssembly `i32` value
#[inline]
pub fn u32(i: u32) -> ValRaw {
ValRaw::i32(i as i32)
}

/// Creates a WebAssembly `i64` value
#[inline]
pub fn u64(i: u64) -> ValRaw {
ValRaw::i64(i as i64)
}

/// Creates a WebAssembly `f32` value
#[inline]
pub fn f32(i: u32) -> ValRaw {
ValRaw { f32: i.to_le() }
}

/// Creates a WebAssembly `f64` value
#[inline]
pub fn f64(i: u64) -> ValRaw {
ValRaw { f64: i.to_le() }
}

/// Creates a WebAssembly `v128` value
#[inline]
pub fn v128(i: u128) -> ValRaw {
ValRaw { v128: i.to_le() }
}

/// Creates a WebAssembly `funcref` value
#[inline]
pub fn funcref(i: usize) -> ValRaw {
ValRaw { funcref: i.to_le() }
}

/// Creates a WebAssembly `externref` value
#[inline]
pub fn externref(i: usize) -> ValRaw {
ValRaw {
externref: i.to_le(),
}
}

/// Gets the WebAssembly `i32` value
#[inline]
pub fn get_i32(&self) -> i32 {
unsafe { i32::from_le(self.i32) }
}

/// Gets the WebAssembly `i64` value
#[inline]
pub fn get_i64(&self) -> i64 {
unsafe { i64::from_le(self.i64) }
}

/// Gets the WebAssembly `i32` value
#[inline]
pub fn get_u32(&self) -> u32 {
self.get_i32() as u32
}

/// Gets the WebAssembly `i64` value
#[inline]
pub fn get_u64(&self) -> u64 {
self.get_i64() as u64
}

/// Gets the WebAssembly `f32` value
#[inline]
pub fn get_f32(&self) -> u32 {
unsafe { u32::from_le(self.f32) }
}

/// Gets the WebAssembly `f64` value
#[inline]
pub fn get_f64(&self) -> u64 {
unsafe { u64::from_le(self.f64) }
}

/// Gets the WebAssembly `v128` value
#[inline]
pub fn get_v128(&self) -> u128 {
unsafe { u128::from_le(self.v128) }
}

/// Gets the WebAssembly `funcref` value
#[inline]
pub fn get_funcref(&self) -> usize {
unsafe { usize::from_le(self.funcref) }
}

/// Gets the WebAssembly `externref` value
#[inline]
pub fn get_externref(&self) -> usize {
unsafe { usize::from_le(self.externref) }
}
}

/// Trampoline function pointer type.
Expand Down
2 changes: 1 addition & 1 deletion crates/wasmtime/src/func.rs
Original file line number Diff line number Diff line change
Expand Up @@ -966,7 +966,7 @@ impl Func {
// Store the argument values into `values_vec`.
let mut values_vec = store.0.take_wasm_val_raw_storage();
debug_assert!(values_vec.is_empty());
values_vec.resize_with(values_vec_size, || ValRaw { i32: 0 });
values_vec.resize_with(values_vec_size, || ValRaw::i32(0));
for (arg, slot) in params.iter().cloned().zip(&mut values_vec) {
unsafe {
*slot = arg.to_raw(&mut *store);
Expand Down
32 changes: 16 additions & 16 deletions crates/wasmtime/src/func/typed.rs
Original file line number Diff line number Diff line change
Expand Up @@ -231,7 +231,7 @@ pub unsafe trait WasmTy: Send {
}

macro_rules! integers {
($($primitive:ident => $ty:ident in $raw:ident)*) => ($(
($($primitive:ident/$get_primitive:ident => $ty:ident in $raw:ident)*) => ($(
unsafe impl WasmTy for $primitive {
type Abi = $primitive;
#[inline]
Expand All @@ -248,11 +248,11 @@ macro_rules! integers {
}
#[inline]
unsafe fn abi_from_raw(raw: *mut ValRaw) -> $primitive {
$primitive::from_le((*raw).$raw as $primitive)
(*raw).$get_primitive()
}
#[inline]
unsafe fn abi_into_raw(abi: $primitive, raw: *mut ValRaw) {
(*raw).$raw = abi.to_le() as $raw;
*raw = ValRaw::$primitive(abi);
}
#[inline]
fn into_abi(self, _store: &mut StoreOpaque) -> Self::Abi {
Expand All @@ -267,14 +267,14 @@ macro_rules! integers {
}

integers! {
i32 => I32 in i32
i64 => I64 in i64
u32 => I32 in i32
u64 => I64 in i64
i32/get_i32 => I32 in i32
i64/get_i64 => I64 in i64
u32/get_u32 => I32 in i32
u64/get_u64 => I64 in i64
}

macro_rules! floats {
($($float:ident/$int:ident => $ty:ident)*) => ($(
($($float:ident/$int:ident/$get_float:ident => $ty:ident)*) => ($(
unsafe impl WasmTy for $float {
type Abi = $float;
#[inline]
Expand All @@ -291,11 +291,11 @@ macro_rules! floats {
}
#[inline]
unsafe fn abi_from_raw(raw: *mut ValRaw) -> $float {
$float::from_bits($int::from_le((*raw).$float))
$float::from_bits((*raw).$get_float())
}
#[inline]
unsafe fn abi_into_raw(abi: $float, raw: *mut ValRaw) {
(*raw).$float = abi.to_bits().to_le();
*raw = ValRaw::$float(abi.to_bits());
}
#[inline]
fn into_abi(self, _store: &mut StoreOpaque) -> Self::Abi {
Expand All @@ -310,8 +310,8 @@ macro_rules! floats {
}

floats! {
f32/u32 => F32
f64/u64 => F64
f32/u32/get_f32 => F32
f64/u64/get_f64 => F64
}

unsafe impl WasmTy for Option<ExternRef> {
Expand All @@ -334,12 +334,12 @@ unsafe impl WasmTy for Option<ExternRef> {

#[inline]
unsafe fn abi_from_raw(raw: *mut ValRaw) -> *mut u8 {
usize::from_le((*raw).externref) as *mut u8
(*raw).get_externref() as *mut u8
}

#[inline]
unsafe fn abi_into_raw(abi: *mut u8, raw: *mut ValRaw) {
(*raw).externref = (abi as usize).to_le();
*raw = ValRaw::externref(abi as usize);
}

#[inline]
Expand Down Expand Up @@ -420,12 +420,12 @@ unsafe impl WasmTy for Option<Func> {

#[inline]
unsafe fn abi_from_raw(raw: *mut ValRaw) -> Self::Abi {
usize::from_le((*raw).funcref) as Self::Abi
(*raw).get_funcref() as Self::Abi
}

#[inline]
unsafe fn abi_into_raw(abi: Self::Abi, raw: *mut ValRaw) {
(*raw).funcref = (abi as usize).to_le();
*raw = ValRaw::funcref(abi as usize);
}

#[inline]
Expand Down
34 changes: 14 additions & 20 deletions crates/wasmtime/src/values.rs
Original file line number Diff line number Diff line change
Expand Up @@ -103,28 +103,24 @@ impl Val {
/// [`Func::to_raw`] are unsafe.
pub unsafe fn to_raw(&self, store: impl AsContextMut) -> ValRaw {
match self {
Val::I32(i) => ValRaw { i32: i.to_le() },
Val::I64(i) => ValRaw { i64: i.to_le() },
Val::F32(u) => ValRaw { f32: u.to_le() },
Val::F64(u) => ValRaw { f64: u.to_le() },
Val::V128(b) => ValRaw { v128: b.to_le() },
Val::I32(i) => ValRaw::i32(*i),
Val::I64(i) => ValRaw::i64(*i),
Val::F32(u) => ValRaw::f32(*u),
Val::F64(u) => ValRaw::f64(*u),
Val::V128(b) => ValRaw::v128(*b),
Val::ExternRef(e) => {
let externref = match e {
Some(e) => e.to_raw(store),
None => 0,
};
ValRaw {
externref: externref.to_le(),
}
ValRaw::externref(externref)
}
Val::FuncRef(f) => {
let funcref = match f {
Some(f) => f.to_raw(store),
None => 0,
};
ValRaw {
funcref: funcref.to_le(),
}
ValRaw::funcref(funcref)
}
}
}
Expand All @@ -138,15 +134,13 @@ impl Val {
/// otherwise that `raw` should have the type `ty` specified.
pub unsafe fn from_raw(store: impl AsContextMut, raw: ValRaw, ty: ValType) -> Val {
match ty {
ValType::I32 => Val::I32(i32::from_le(raw.i32)),
ValType::I64 => Val::I64(i64::from_le(raw.i64)),
ValType::F32 => Val::F32(u32::from_le(raw.f32)),
ValType::F64 => Val::F64(u64::from_le(raw.f64)),
ValType::V128 => Val::V128(u128::from_le(raw.v128)),
ValType::ExternRef => {
Val::ExternRef(ExternRef::from_raw(usize::from_le(raw.externref)))
}
ValType::FuncRef => Val::FuncRef(Func::from_raw(store, usize::from_le(raw.funcref))),
ValType::I32 => Val::I32(raw.get_i32()),
ValType::I64 => Val::I64(raw.get_i64()),
ValType::F32 => Val::F32(raw.get_f32()),
ValType::F64 => Val::F64(raw.get_f64()),
ValType::V128 => Val::V128(raw.get_v128()),
ValType::ExternRef => Val::ExternRef(ExternRef::from_raw(raw.get_externref())),
ValType::FuncRef => Val::FuncRef(Func::from_raw(store, raw.get_funcref())),
}
}

Expand Down

0 comments on commit 78aa7d3

Please sign in to comment.