Wasm: Use environment to translate reference types instructions and add support for multiple tables
This commit introduces environment functions to handle the translation of reference type instructions, analogous to how bulk-memory was implemented. Additionally, the bulk-memory instructions that operate on tables are extended to support multiple table indices.
This commit is contained in:
@@ -965,8 +965,8 @@ pub fn translate_operator<FE: FuncEnvironment + ?Sized>(
|
|||||||
let val = builder.ins().is_null(arg);
|
let val = builder.ins().is_null(arg);
|
||||||
state.push1(val);
|
state.push1(val);
|
||||||
}
|
}
|
||||||
Operator::RefFunc { .. } => {
|
Operator::RefFunc { function_index } => {
|
||||||
return Err(wasm_unsupported!("proposed ref operator {:?}", op))
|
state.push1(environ.translate_ref_func(builder.cursor(), *function_index)?);
|
||||||
}
|
}
|
||||||
Operator::AtomicNotify { .. }
|
Operator::AtomicNotify { .. }
|
||||||
| Operator::I32AtomicWait { .. }
|
| Operator::I32AtomicWait { .. }
|
||||||
@@ -1089,56 +1089,73 @@ pub fn translate_operator<FE: FuncEnvironment + ?Sized>(
|
|||||||
table,
|
table,
|
||||||
)?);
|
)?);
|
||||||
}
|
}
|
||||||
Operator::TableCopy { .. } => {
|
Operator::TableGrow { table } => {
|
||||||
// The WebAssembly MVP only supports one table and wasmparser will
|
let delta = state.pop1();
|
||||||
// ensure that the table index specified is zero.
|
let init_value = state.pop1();
|
||||||
let dst_table_index = 0;
|
state.push1(environ.translate_table_grow(
|
||||||
let dst_table = state.get_table(builder.func, dst_table_index, environ)?;
|
builder.cursor(),
|
||||||
let src_table_index = 0;
|
*table,
|
||||||
let src_table = state.get_table(builder.func, src_table_index, environ)?;
|
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 len = state.pop1();
|
||||||
let src = state.pop1();
|
let src = state.pop1();
|
||||||
let dest = state.pop1();
|
let dest = state.pop1();
|
||||||
environ.translate_table_copy(
|
environ.translate_table_copy(
|
||||||
builder.cursor(),
|
builder.cursor(),
|
||||||
TableIndex::from_u32(dst_table_index),
|
TableIndex::from_u32(*dst_table_index),
|
||||||
dst_table,
|
dst_table,
|
||||||
TableIndex::from_u32(src_table_index),
|
TableIndex::from_u32(*src_table_index),
|
||||||
src_table,
|
src_table,
|
||||||
dest,
|
dest,
|
||||||
src,
|
src,
|
||||||
len,
|
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.
|
// 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 len = state.pop1();
|
||||||
let src = state.pop1();
|
let src = state.pop1();
|
||||||
let dest = state.pop1();
|
let dest = state.pop1();
|
||||||
environ.translate_table_init(
|
environ.translate_table_init(
|
||||||
builder.cursor(),
|
builder.cursor(),
|
||||||
*segment,
|
*segment,
|
||||||
TableIndex::from_u32(table_index),
|
TableIndex::from_u32(*table_index),
|
||||||
table,
|
table,
|
||||||
dest,
|
dest,
|
||||||
src,
|
src,
|
||||||
len,
|
len,
|
||||||
)?;
|
)?;
|
||||||
}
|
}
|
||||||
Operator::TableFill { .. } => {
|
|
||||||
return Err(wasm_unsupported!("proposed table operator {:?}", op));
|
|
||||||
}
|
|
||||||
Operator::ElemDrop { segment } => {
|
Operator::ElemDrop { segment } => {
|
||||||
environ.translate_elem_drop(builder.cursor(), *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 } => {
|
Operator::V128Const { value } => {
|
||||||
let data = value.bytes().to_vec().into();
|
let data = value.bytes().to_vec().into();
|
||||||
let handle = builder.func.dfg.constants.insert(data);
|
let handle = builder.func.dfg.constants.insert(data);
|
||||||
|
|||||||
@@ -426,6 +426,35 @@ impl<'dummy_environment> FuncEnvironment for DummyFuncEnvironment<'dummy_environ
|
|||||||
Ok(pos.ins().iconst(I32, -1))
|
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<ir::Value> {
|
||||||
|
Ok(pos.ins().iconst(I32, -1))
|
||||||
|
}
|
||||||
|
|
||||||
|
fn translate_table_get(
|
||||||
|
&mut self,
|
||||||
|
mut pos: FuncCursor,
|
||||||
|
_table_index: u32,
|
||||||
|
_index: ir::Value,
|
||||||
|
) -> WasmResult<ir::Value> {
|
||||||
|
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(
|
fn translate_table_copy(
|
||||||
&mut self,
|
&mut self,
|
||||||
_pos: FuncCursor,
|
_pos: FuncCursor,
|
||||||
@@ -440,6 +469,17 @@ impl<'dummy_environment> FuncEnvironment for DummyFuncEnvironment<'dummy_environ
|
|||||||
Ok(())
|
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(
|
fn translate_table_init(
|
||||||
&mut self,
|
&mut self,
|
||||||
_pos: FuncCursor,
|
_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<()> {
|
fn translate_elem_drop(&mut self, _pos: FuncCursor, _seg_index: u32) -> WasmResult<()> {
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn translate_ref_func(
|
||||||
|
&mut self,
|
||||||
|
mut pos: FuncCursor,
|
||||||
|
_func_index: u32,
|
||||||
|
) -> WasmResult<ir::Value> {
|
||||||
|
Ok(pos.ins().null(self.reference_type()))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl TargetEnvironment for DummyEnvironment {
|
impl TargetEnvironment for DummyEnvironment {
|
||||||
|
|||||||
@@ -337,6 +337,32 @@ pub trait FuncEnvironment: TargetEnvironment {
|
|||||||
table: ir::Table,
|
table: ir::Table,
|
||||||
) -> WasmResult<ir::Value>;
|
) -> WasmResult<ir::Value>;
|
||||||
|
|
||||||
|
/// 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<ir::Value>;
|
||||||
|
|
||||||
|
/// Translate a `table.get` WebAssembly instruction.
|
||||||
|
fn translate_table_get(
|
||||||
|
&mut self,
|
||||||
|
pos: FuncCursor,
|
||||||
|
table_index: u32,
|
||||||
|
index: ir::Value,
|
||||||
|
) -> WasmResult<ir::Value>;
|
||||||
|
|
||||||
|
/// 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.
|
/// Translate a `table.copy` WebAssembly instruction.
|
||||||
#[allow(clippy::too_many_arguments)]
|
#[allow(clippy::too_many_arguments)]
|
||||||
fn translate_table_copy(
|
fn translate_table_copy(
|
||||||
@@ -351,6 +377,16 @@ pub trait FuncEnvironment: TargetEnvironment {
|
|||||||
len: ir::Value,
|
len: ir::Value,
|
||||||
) -> WasmResult<()>;
|
) -> 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.
|
/// Translate a `table.init` WebAssembly instruction.
|
||||||
#[allow(clippy::too_many_arguments)]
|
#[allow(clippy::too_many_arguments)]
|
||||||
fn translate_table_init(
|
fn translate_table_init(
|
||||||
@@ -367,6 +403,9 @@ pub trait FuncEnvironment: TargetEnvironment {
|
|||||||
/// Translate a `elem.drop` WebAssembly instruction.
|
/// Translate a `elem.drop` WebAssembly instruction.
|
||||||
fn translate_elem_drop(&mut self, pos: FuncCursor, seg_index: u32) -> WasmResult<()>;
|
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<ir::Value>;
|
||||||
|
|
||||||
/// Emit code at the beginning of every wasm loop.
|
/// Emit code at the beginning of every wasm loop.
|
||||||
///
|
///
|
||||||
/// This can be used to insert explicit interrupt or safepoint checking at
|
/// This can be used to insert explicit interrupt or safepoint checking at
|
||||||
|
|||||||
Reference in New Issue
Block a user