Browse Source

Merge pull request #1973 from fitzgen/table-fill

wasmtime: Implement `table.fill`
pull/1982/head
Nick Fitzgerald 4 years ago
committed by GitHub
parent
commit
80ff22fd18
No known key found for this signature in database GPG Key ID: 4AEE18F83AFDEB23
  1. 5
      build.rs
  2. 46
      crates/environ/src/func_environ.rs
  3. 35
      crates/runtime/src/libcalls.rs
  4. 20
      crates/runtime/src/table.rs
  5. 4
      crates/runtime/src/vmcontext.rs

5
build.rs

@ -203,11 +203,6 @@ fn ignore(testsuite: &str, testname: &str, strategy: &str) -> bool {
("simd", "simd_load") => return true, // FIXME Unsupported feature: proposed SIMD operator I32x4TruncSatF32x4S ("simd", "simd_load") => return true, // FIXME Unsupported feature: proposed SIMD operator I32x4TruncSatF32x4S
("simd", "simd_splat") => return true, // FIXME Unsupported feature: proposed SIMD operator I32x4TruncSatF32x4S ("simd", "simd_splat") => return true, // FIXME Unsupported feature: proposed SIMD operator I32x4TruncSatF32x4S
// Still working on implementing these. See #929.
("reference_types", "table_fill") => {
return true;
}
// TODO(#1886): Ignore reference types tests if this isn't x64, // TODO(#1886): Ignore reference types tests if this isn't x64,
// because Cranelift only supports reference types on x64. // because Cranelift only supports reference types on x64.
("reference_types", _) => { ("reference_types", _) => {

46
crates/environ/src/func_environ.rs

@ -170,6 +170,10 @@ declare_builtin_functions! {
table_grow_funcref(vmctx, i32, i32, pointer) -> (i32); table_grow_funcref(vmctx, i32, i32, pointer) -> (i32);
/// Returns an index for Wasm's `table.grow` instruction for `externref`s. /// Returns an index for Wasm's `table.grow` instruction for `externref`s.
table_grow_externref(vmctx, i32, i32, reference) -> (i32); table_grow_externref(vmctx, i32, i32, reference) -> (i32);
/// Returns an index for Wasm's `table.fill` instruction for `externref`s.
table_fill_externref(vmctx, i32, i32, reference, i32) -> ();
/// Returns an index for Wasm's `table.fill` instruction for `funcref`s.
table_fill_funcref(vmctx, i32, i32, pointer, i32) -> ();
/// Returns an index to drop a `VMExternRef`. /// Returns an index to drop a `VMExternRef`.
drop_externref(pointer) -> (); drop_externref(pointer) -> ();
/// Returns an index to do a GC and then insert a `VMExternRef` into the /// Returns an index to do a GC and then insert a `VMExternRef` into the
@ -1009,15 +1013,41 @@ impl<'module_environment> cranelift_wasm::FuncEnvironment for FuncEnvironment<'m
fn translate_table_fill( fn translate_table_fill(
&mut self, &mut self,
_: cranelift_codegen::cursor::FuncCursor<'_>, mut pos: cranelift_codegen::cursor::FuncCursor<'_>,
_: TableIndex, table_index: TableIndex,
_: ir::Value, dst: ir::Value,
_: ir::Value, val: ir::Value,
_: ir::Value, len: ir::Value,
) -> WasmResult<()> { ) -> WasmResult<()> {
Err(WasmError::Unsupported( let (builtin_idx, builtin_sig) =
"the `table.fill` instruction is not supported yet".into(), match self.module.table_plans[table_index].table.wasm_ty {
)) WasmType::FuncRef => (
BuiltinFunctionIndex::table_fill_funcref(),
self.builtin_function_signatures
.table_fill_funcref(&mut pos.func),
),
WasmType::ExternRef => (
BuiltinFunctionIndex::table_fill_externref(),
self.builtin_function_signatures
.table_fill_externref(&mut pos.func),
),
_ => return Err(WasmError::Unsupported(
"`table.fill` with a table element type that is not `funcref` or `externref`"
.into(),
)),
};
let (vmctx, builtin_addr) =
self.translate_load_builtin_function_address(&mut pos, builtin_idx);
let table_index_arg = pos.ins().iconst(I32, table_index.as_u32() as i64);
pos.ins().call_indirect(
builtin_sig,
builtin_addr,
&[vmctx, table_index_arg, dst, val, len],
);
Ok(())
} }
fn translate_ref_null( fn translate_ref_null(

35
crates/runtime/src/libcalls.rs

@ -265,6 +265,41 @@ pub unsafe extern "C" fn wasmtime_table_grow(
} }
} }
/// Implementation of `table.fill`.
pub unsafe extern "C" fn wasmtime_table_fill(
vmctx: *mut VMContext,
table_index: u32,
dst: u32,
// NB: we don't know whether this is a `VMExternRef` or a pointer to a
// `VMCallerCheckedAnyfunc` until we look at the table's element type.
val: *mut u8,
len: u32,
) {
let result = {
let instance = (&mut *vmctx).instance();
let table_index = TableIndex::from_u32(table_index);
let table = instance.get_table(table_index);
match table.element_type() {
TableElementType::Func => {
let val = val as *mut VMCallerCheckedAnyfunc;
table.fill(dst, val.into(), len)
}
TableElementType::Val(ty) => {
debug_assert_eq!(ty, crate::ref_type());
let val = if val.is_null() {
None
} else {
Some(VMExternRef::clone_from_raw(val))
};
table.fill(dst, val.into(), len)
}
}
};
if let Err(trap) = result {
raise_lib_trap(trap);
}
}
/// Implementation of `table.copy`. /// Implementation of `table.copy`.
pub unsafe extern "C" fn wasmtime_table_copy( pub unsafe extern "C" fn wasmtime_table_copy(
vmctx: *mut VMContext, vmctx: *mut VMContext,

20
crates/runtime/src/table.rs

@ -67,6 +67,26 @@ impl Table {
} }
} }
/// Fill `table[dst..dst + len]` with `val`.
///
/// Returns a trap error on out-of-bounds accesses.
pub fn fill(&self, dst: u32, val: TableElement, len: u32) -> Result<(), Trap> {
let start = dst;
let end = start
.checked_add(len)
.ok_or_else(|| Trap::wasm(ir::TrapCode::TableOutOfBounds))?;
if end > self.size() {
return Err(Trap::wasm(ir::TrapCode::TableOutOfBounds));
}
for i in start..end {
self.set(i, val.clone()).unwrap();
}
Ok(())
}
/// Grow table by the specified amount of elements. /// Grow table by the specified amount of elements.
/// ///
/// Returns the previous size of the table if growth is successful. /// Returns the previous size of the table if growth is successful.

4
crates/runtime/src/vmcontext.rs

@ -594,6 +594,10 @@ impl VMBuiltinFunctionsArray {
wasmtime_externref_global_get as usize; wasmtime_externref_global_get as usize;
ptrs[BuiltinFunctionIndex::externref_global_set().index() as usize] = ptrs[BuiltinFunctionIndex::externref_global_set().index() as usize] =
wasmtime_externref_global_set as usize; wasmtime_externref_global_set as usize;
ptrs[BuiltinFunctionIndex::table_fill_externref().index() as usize] =
wasmtime_table_fill as usize;
ptrs[BuiltinFunctionIndex::table_fill_funcref().index() as usize] =
wasmtime_table_fill as usize;
if cfg!(debug_assertions) { if cfg!(debug_assertions) {
for i in 0..ptrs.len() { for i in 0..ptrs.len() {

Loading…
Cancel
Save