Implement the memory.fill instruction from the bulk memory proposal
This commit is contained in:
@@ -643,6 +643,7 @@ impl Instance {
|
||||
// https://webassembly.github.io/reference-types/core/exec/instructions.html#exec-memory-copy
|
||||
|
||||
let memory = self.memory(memory_index);
|
||||
|
||||
if src
|
||||
.checked_add(len)
|
||||
.map_or(true, |n| n as usize > memory.current_length)
|
||||
@@ -691,6 +692,69 @@ impl Instance {
|
||||
}
|
||||
}
|
||||
|
||||
/// Perform the `memory.fill` operation on a locally defined memory.
|
||||
///
|
||||
/// # Errors
|
||||
///
|
||||
/// Returns a `Trap` error if the memory range is out of bounds.
|
||||
pub(crate) fn defined_memory_fill(
|
||||
&self,
|
||||
memory_index: DefinedMemoryIndex,
|
||||
dst: u32,
|
||||
val: u32,
|
||||
len: u32,
|
||||
source_loc: ir::SourceLoc,
|
||||
) -> Result<(), Trap> {
|
||||
let memory = self.memory(memory_index);
|
||||
|
||||
if dst
|
||||
.checked_add(len)
|
||||
.map_or(true, |m| m as usize > memory.current_length)
|
||||
{
|
||||
return Err(Trap::Wasm {
|
||||
desc: TrapDescription {
|
||||
source_loc,
|
||||
trap_code: ir::TrapCode::HeapOutOfBounds,
|
||||
},
|
||||
backtrace: Backtrace::new(),
|
||||
});
|
||||
}
|
||||
|
||||
let dst = isize::try_from(dst).unwrap();
|
||||
let val = val as u8;
|
||||
|
||||
// Bounds and casts are checked above, by this point we know that
|
||||
// everything is safe.
|
||||
unsafe {
|
||||
let dst = memory.base.offset(dst);
|
||||
ptr::write_bytes(dst, val, len as usize);
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Perform the `memory.fill` operation on an imported memory.
|
||||
///
|
||||
/// # Errors
|
||||
///
|
||||
/// Returns a `Trap` error if the memory range is out of bounds.
|
||||
pub(crate) fn imported_memory_fill(
|
||||
&self,
|
||||
memory_index: MemoryIndex,
|
||||
dst: u32,
|
||||
val: u32,
|
||||
len: u32,
|
||||
source_loc: ir::SourceLoc,
|
||||
) -> Result<(), Trap> {
|
||||
let import = self.imported_memory(memory_index);
|
||||
unsafe {
|
||||
let foreign_instance = (&*import.vmctx).instance();
|
||||
let foreign_memory = &*import.from;
|
||||
let foreign_index = foreign_instance.memory_index(foreign_memory);
|
||||
foreign_instance.defined_memory_fill(foreign_index, dst, val, len, source_loc)
|
||||
}
|
||||
}
|
||||
|
||||
/// Get a table by index regardless of whether it is locally-defined or an
|
||||
/// imported, foreign table.
|
||||
pub(crate) fn get_table(&self, table_index: TableIndex) -> &Table {
|
||||
|
||||
@@ -298,3 +298,39 @@ pub unsafe extern "C" fn wasmtime_imported_memory_copy(
|
||||
raise_lib_trap(trap);
|
||||
}
|
||||
}
|
||||
|
||||
/// Implementation of `memory.fill` for locally defined memories.
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn wasmtime_memory_fill(
|
||||
vmctx: *mut VMContext,
|
||||
memory_index: u32,
|
||||
dst: u32,
|
||||
val: u32,
|
||||
len: u32,
|
||||
source_loc: u32,
|
||||
) {
|
||||
let memory_index = DefinedMemoryIndex::from_u32(memory_index);
|
||||
let source_loc = ir::SourceLoc::new(source_loc);
|
||||
let instance = (&mut *vmctx).instance();
|
||||
if let Err(trap) = instance.defined_memory_fill(memory_index, dst, val, len, source_loc) {
|
||||
raise_lib_trap(trap);
|
||||
}
|
||||
}
|
||||
|
||||
/// Implementation of `memory.fill` for imported memories.
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn wasmtime_imported_memory_fill(
|
||||
vmctx: *mut VMContext,
|
||||
memory_index: u32,
|
||||
dst: u32,
|
||||
val: u32,
|
||||
len: u32,
|
||||
source_loc: u32,
|
||||
) {
|
||||
let memory_index = MemoryIndex::from_u32(memory_index);
|
||||
let source_loc = ir::SourceLoc::new(source_loc);
|
||||
let instance = (&mut *vmctx).instance();
|
||||
if let Err(trap) = instance.imported_memory_fill(memory_index, dst, val, len, source_loc) {
|
||||
raise_lib_trap(trap);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -567,6 +567,10 @@ impl VMBuiltinFunctionsArray {
|
||||
wasmtime_memory_copy as usize;
|
||||
ptrs[BuiltinFunctionIndex::get_imported_memory_copy_index().index() as usize] =
|
||||
wasmtime_imported_memory_copy as usize;
|
||||
ptrs[BuiltinFunctionIndex::get_memory_fill_index().index() as usize] =
|
||||
wasmtime_memory_fill as usize;
|
||||
ptrs[BuiltinFunctionIndex::get_imported_memory_fill_index().index() as usize] =
|
||||
wasmtime_imported_memory_fill as usize;
|
||||
|
||||
debug_assert!(ptrs.iter().cloned().all(|p| p != 0));
|
||||
|
||||
|
||||
Reference in New Issue
Block a user