Skip to content

Commit d64a02c

Browse files
kaivoldicej
andauthored
Override component model Lower::store_list and Lift::load_list for f32/f64 (#9892)
* Override component model Lower::store_list and Lift::load_list for f32/f64 * work with [u8] instead of integers * Import from `core` instead of `std` Co-authored-by: Joel Dice <[email protected]> --------- Co-authored-by: Joel Dice <[email protected]>
1 parent 7e5a7e5 commit d64a02c

File tree

1 file changed

+55
-0
lines changed
  • crates/wasmtime/src/runtime/component/func

1 file changed

+55
-0
lines changed

crates/wasmtime/src/runtime/component/func/typed.rs

Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ use crate::{AsContextMut, StoreContext, StoreContextMut, ValRaw};
88
use alloc::borrow::Cow;
99
use alloc::sync::Arc;
1010
use core::fmt;
11+
use core::iter;
1112
use core::marker;
1213
use core::mem::{self, MaybeUninit};
1314
use core::ptr::NonNull;
@@ -942,6 +943,39 @@ macro_rules! floats {
942943
*ptr = self.to_bits().to_le_bytes();
943944
Ok(())
944945
}
946+
947+
fn store_list<T>(
948+
cx: &mut LowerContext<'_, T>,
949+
ty: InterfaceType,
950+
offset: usize,
951+
items: &[Self],
952+
) -> Result<()> {
953+
debug_assert!(matches!(ty, InterfaceType::$ty));
954+
955+
// Double-check that the CM alignment is at least the host's
956+
// alignment for this type which should be true for all
957+
// platforms.
958+
assert!((Self::ALIGN32 as usize) >= mem::align_of::<Self>());
959+
960+
// Slice `cx`'s memory to the window that we'll be modifying.
961+
// This should all have already been verified in terms of
962+
// alignment and sizing meaning that these assertions here are
963+
// not truly necessary but are instead double-checks.
964+
let dst = &mut cx.as_slice_mut()[offset..][..items.len() * Self::SIZE32];
965+
assert!(dst.as_ptr().cast::<Self>().is_aligned());
966+
967+
// And with all that out of the way perform the copying loop.
968+
// This is not a `copy_from_slice` because endianness needs to
969+
// be handled here, but LLVM should pretty easily transform this
970+
// into a memcpy on little-endian platforms.
971+
// TODO use `as_chunks` when https://github.com/rust-lang/rust/issues/74985
972+
// is stabilized
973+
for (dst, src) in iter::zip(dst.chunks_exact_mut(Self::SIZE32), items) {
974+
let dst: &mut [u8; Self::SIZE32] = dst.try_into().unwrap();
975+
*dst = src.to_le_bytes();
976+
}
977+
Ok(())
978+
}
945979
}
946980

947981
unsafe impl Lift for $float {
@@ -957,6 +991,27 @@ macro_rules! floats {
957991
debug_assert!((bytes.as_ptr() as usize) % Self::SIZE32 == 0);
958992
Ok($float::from_le_bytes(bytes.try_into().unwrap()))
959993
}
994+
995+
fn load_list(cx: &mut LiftContext<'_>, list: &WasmList<Self>) -> Result<Vec<Self>> where Self: Sized {
996+
// See comments in `WasmList::get` for the panicking indexing
997+
let byte_size = list.len * mem::size_of::<Self>();
998+
let bytes = &cx.memory()[list.ptr..][..byte_size];
999+
1000+
// The canonical ABI requires that everything is aligned to its
1001+
// own size, so this should be an aligned array.
1002+
assert!(bytes.as_ptr().cast::<Self>().is_aligned());
1003+
1004+
// Copy the resulting slice to a new Vec, handling endianness
1005+
// in the process
1006+
// TODO use `as_chunks` when https://github.com/rust-lang/rust/issues/74985
1007+
// is stabilized
1008+
Ok(
1009+
bytes
1010+
.chunks_exact(Self::SIZE32)
1011+
.map(|i| $float::from_le_bytes(i.try_into().unwrap()))
1012+
.collect()
1013+
)
1014+
}
9601015
}
9611016
};)*)
9621017
}

0 commit comments

Comments
 (0)