diff --git a/cranelift/wasm/src/code_translator.rs b/cranelift/wasm/src/code_translator.rs index e6055cea17..c50b00b39d 100644 --- a/cranelift/wasm/src/code_translator.rs +++ b/cranelift/wasm/src/code_translator.rs @@ -965,8 +965,8 @@ pub fn translate_operator( let val = builder.ins().is_null(arg); state.push1(val); } - Operator::RefFunc { .. } => { - return Err(wasm_unsupported!("proposed ref operator {:?}", op)) + Operator::RefFunc { function_index } => { + state.push1(environ.translate_ref_func(builder.cursor(), *function_index)?); } Operator::AtomicNotify { .. } | Operator::I32AtomicWait { .. } @@ -1089,56 +1089,73 @@ pub fn translate_operator( table, )?); } - Operator::TableCopy { .. } => { - // The WebAssembly MVP only supports one table and wasmparser will - // ensure that the table index specified is zero. - let dst_table_index = 0; - let dst_table = state.get_table(builder.func, dst_table_index, environ)?; - let src_table_index = 0; - let src_table = state.get_table(builder.func, src_table_index, environ)?; + Operator::TableGrow { table } => { + let delta = state.pop1(); + let init_value = state.pop1(); + state.push1(environ.translate_table_grow( + builder.cursor(), + *table, + delta, + init_value, + )?); + } + Operator::TableGet { table } => { + let index = state.pop1(); + state.push1(environ.translate_table_get(builder.cursor(), *table, index)?); + } + Operator::TableSet { table } => { + let value = state.pop1(); + let index = state.pop1(); + environ.translate_table_set(builder.cursor(), *table, value, index)?; + } + Operator::TableCopy { + dst_table: dst_table_index, + src_table: src_table_index, + } => { + let dst_table = state.get_table(builder.func, *dst_table_index, environ)?; + let src_table = state.get_table(builder.func, *src_table_index, environ)?; let len = state.pop1(); let src = state.pop1(); let dest = state.pop1(); environ.translate_table_copy( builder.cursor(), - TableIndex::from_u32(dst_table_index), + TableIndex::from_u32(*dst_table_index), dst_table, - TableIndex::from_u32(src_table_index), + TableIndex::from_u32(*src_table_index), src_table, dest, src, len, )?; } - Operator::TableInit { segment, table: _ } => { + Operator::TableFill { table } => { + let len = state.pop1(); + let val = state.pop1(); + let dest = state.pop1(); + environ.translate_table_fill(builder.cursor(), *table, dest, val, len)?; + } + Operator::TableInit { + segment, + table: table_index, + } => { // The WebAssembly MVP only supports one table and we assume it here. - let table_index = 0; - let table = state.get_table(builder.func, table_index, environ)?; + let table = state.get_table(builder.func, *table_index, environ)?; let len = state.pop1(); let src = state.pop1(); let dest = state.pop1(); environ.translate_table_init( builder.cursor(), *segment, - TableIndex::from_u32(table_index), + TableIndex::from_u32(*table_index), table, dest, src, len, )?; } - Operator::TableFill { .. } => { - return Err(wasm_unsupported!("proposed table operator {:?}", op)); - } Operator::ElemDrop { segment } => { environ.translate_elem_drop(builder.cursor(), *segment)?; } - Operator::TableGet { .. } | Operator::TableSet { .. } | Operator::TableGrow { .. } => { - return Err(wasm_unsupported!( - "proposed reference types operator {:?}", - op - )); - } Operator::V128Const { value } => { let data = value.bytes().to_vec().into(); let handle = builder.func.dfg.constants.insert(data); diff --git a/cranelift/wasm/src/environ/dummy.rs b/cranelift/wasm/src/environ/dummy.rs index 6b6f210166..1fc11cf3e7 100644 --- a/cranelift/wasm/src/environ/dummy.rs +++ b/cranelift/wasm/src/environ/dummy.rs @@ -426,6 +426,35 @@ impl<'dummy_environment> FuncEnvironment for DummyFuncEnvironment<'dummy_environ Ok(pos.ins().iconst(I32, -1)) } + fn translate_table_grow( + &mut self, + mut pos: FuncCursor, + _table_index: u32, + _delta: ir::Value, + _init_value: ir::Value, + ) -> WasmResult { + Ok(pos.ins().iconst(I32, -1)) + } + + fn translate_table_get( + &mut self, + mut pos: FuncCursor, + _table_index: u32, + _index: ir::Value, + ) -> WasmResult { + Ok(pos.ins().null(self.reference_type())) + } + + fn translate_table_set( + &mut self, + _pos: FuncCursor, + _table_index: u32, + _value: ir::Value, + _index: ir::Value, + ) -> WasmResult<()> { + Ok(()) + } + fn translate_table_copy( &mut self, _pos: FuncCursor, @@ -440,6 +469,17 @@ impl<'dummy_environment> FuncEnvironment for DummyFuncEnvironment<'dummy_environ Ok(()) } + fn translate_table_fill( + &mut self, + _pos: FuncCursor, + _table_index: u32, + _dst: ir::Value, + _val: ir::Value, + _len: ir::Value, + ) -> WasmResult<()> { + Ok(()) + } + fn translate_table_init( &mut self, _pos: FuncCursor, @@ -456,6 +496,14 @@ impl<'dummy_environment> FuncEnvironment for DummyFuncEnvironment<'dummy_environ fn translate_elem_drop(&mut self, _pos: FuncCursor, _seg_index: u32) -> WasmResult<()> { Ok(()) } + + fn translate_ref_func( + &mut self, + mut pos: FuncCursor, + _func_index: u32, + ) -> WasmResult { + Ok(pos.ins().null(self.reference_type())) + } } impl TargetEnvironment for DummyEnvironment { diff --git a/cranelift/wasm/src/environ/spec.rs b/cranelift/wasm/src/environ/spec.rs index c6928a491f..dad2c7f50f 100644 --- a/cranelift/wasm/src/environ/spec.rs +++ b/cranelift/wasm/src/environ/spec.rs @@ -337,6 +337,32 @@ pub trait FuncEnvironment: TargetEnvironment { table: ir::Table, ) -> WasmResult; + /// Translate a `table.grow` WebAssembly instruction. + fn translate_table_grow( + &mut self, + pos: FuncCursor, + table_index: u32, + delta: ir::Value, + init_value: ir::Value, + ) -> WasmResult; + + /// Translate a `table.get` WebAssembly instruction. + fn translate_table_get( + &mut self, + pos: FuncCursor, + table_index: u32, + index: ir::Value, + ) -> WasmResult; + + /// Translate a `table.set` WebAssembly instruction. + fn translate_table_set( + &mut self, + pos: FuncCursor, + table_index: u32, + value: ir::Value, + index: ir::Value, + ) -> WasmResult<()>; + /// Translate a `table.copy` WebAssembly instruction. #[allow(clippy::too_many_arguments)] fn translate_table_copy( @@ -351,6 +377,16 @@ pub trait FuncEnvironment: TargetEnvironment { len: ir::Value, ) -> WasmResult<()>; + /// Translate a `table.fill` WebAssembly instruction. + fn translate_table_fill( + &mut self, + pos: FuncCursor, + table_index: u32, + dst: ir::Value, + val: ir::Value, + len: ir::Value, + ) -> WasmResult<()>; + /// Translate a `table.init` WebAssembly instruction. #[allow(clippy::too_many_arguments)] fn translate_table_init( @@ -367,6 +403,9 @@ pub trait FuncEnvironment: TargetEnvironment { /// Translate a `elem.drop` WebAssembly instruction. fn translate_elem_drop(&mut self, pos: FuncCursor, seg_index: u32) -> WasmResult<()>; + /// Translate a `ref.func` WebAssembly instruction. + fn translate_ref_func(&mut self, pos: FuncCursor, func_index: u32) -> WasmResult; + /// Emit code at the beginning of every wasm loop. /// /// This can be used to insert explicit interrupt or safepoint checking at