Add hooks for implementing bulk-memory-operations (#1258)
This commit is contained in:
committed by
Benjamin Bouvier
parent
81782f8efa
commit
aabf6559a0
@@ -987,18 +987,104 @@ pub fn translate_operator<FE: FuncEnvironment + ?Sized>(
|
|||||||
| Operator::Fence { .. } => {
|
| Operator::Fence { .. } => {
|
||||||
return Err(wasm_unsupported!("proposed thread operator {:?}", op));
|
return Err(wasm_unsupported!("proposed thread operator {:?}", op));
|
||||||
}
|
}
|
||||||
Operator::MemoryInit { .. }
|
Operator::MemoryCopy => {
|
||||||
| Operator::DataDrop { .. }
|
// The WebAssembly MVP only supports one linear memory and
|
||||||
| Operator::MemoryCopy
|
// wasmparser will ensure that the memory indices specified are
|
||||||
| Operator::MemoryFill
|
// zero.
|
||||||
| Operator::TableInit { .. }
|
let heap_index = MemoryIndex::from_u32(0);
|
||||||
| Operator::ElemDrop { .. }
|
let heap = state.get_heap(builder.func, 0, environ)?;
|
||||||
| Operator::TableCopy
|
let len = state.pop1();
|
||||||
| Operator::TableGet { .. }
|
let src = state.pop1();
|
||||||
| Operator::TableSet { .. }
|
let dest = state.pop1();
|
||||||
| Operator::TableGrow { .. }
|
environ.translate_memory_copy(builder.cursor(), heap_index, heap, dest, src, len)?;
|
||||||
| Operator::TableSize { .. } => {
|
}
|
||||||
return Err(wasm_unsupported!("proposed bulk memory operator {:?}", op));
|
Operator::MemoryFill => {
|
||||||
|
// The WebAssembly MVP only supports one linear memory and
|
||||||
|
// wasmparser will ensure that the memory index specified is
|
||||||
|
// zero.
|
||||||
|
let heap_index = MemoryIndex::from_u32(0);
|
||||||
|
let heap = state.get_heap(builder.func, 0, environ)?;
|
||||||
|
let len = state.pop1();
|
||||||
|
let val = state.pop1();
|
||||||
|
let dest = state.pop1();
|
||||||
|
environ.translate_memory_fill(builder.cursor(), heap_index, heap, dest, val, len)?;
|
||||||
|
}
|
||||||
|
Operator::MemoryInit { segment } => {
|
||||||
|
// The WebAssembly MVP only supports one linear memory and
|
||||||
|
// wasmparser will ensure that the memory index specified is
|
||||||
|
// zero.
|
||||||
|
let heap_index = MemoryIndex::from_u32(0);
|
||||||
|
let heap = state.get_heap(builder.func, 0, environ)?;
|
||||||
|
let len = state.pop1();
|
||||||
|
let src = state.pop1();
|
||||||
|
let dest = state.pop1();
|
||||||
|
environ.translate_memory_init(
|
||||||
|
builder.cursor(),
|
||||||
|
heap_index,
|
||||||
|
heap,
|
||||||
|
*segment,
|
||||||
|
dest,
|
||||||
|
src,
|
||||||
|
len,
|
||||||
|
)?;
|
||||||
|
}
|
||||||
|
Operator::DataDrop { segment } => {
|
||||||
|
environ.translate_data_drop(builder.cursor(), *segment)?;
|
||||||
|
}
|
||||||
|
Operator::TableSize { table: index } => {
|
||||||
|
let table = state.get_table(builder.func, *index, environ)?;
|
||||||
|
state.push1(environ.translate_table_size(
|
||||||
|
builder.cursor(),
|
||||||
|
TableIndex::from_u32(*index),
|
||||||
|
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)?;
|
||||||
|
let len = state.pop1();
|
||||||
|
let src = state.pop1();
|
||||||
|
let dest = state.pop1();
|
||||||
|
environ.translate_table_copy(
|
||||||
|
builder.cursor(),
|
||||||
|
TableIndex::from_u32(dst_table_index),
|
||||||
|
dst_table,
|
||||||
|
TableIndex::from_u32(src_table_index),
|
||||||
|
src_table,
|
||||||
|
dest,
|
||||||
|
src,
|
||||||
|
len,
|
||||||
|
)?;
|
||||||
|
}
|
||||||
|
Operator::TableInit { segment } => {
|
||||||
|
// 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 len = state.pop1();
|
||||||
|
let src = state.pop1();
|
||||||
|
let dest = state.pop1();
|
||||||
|
environ.translate_table_init(
|
||||||
|
builder.cursor(),
|
||||||
|
*segment,
|
||||||
|
TableIndex::from_u32(table_index),
|
||||||
|
table,
|
||||||
|
dest,
|
||||||
|
src,
|
||||||
|
len,
|
||||||
|
)?;
|
||||||
|
}
|
||||||
|
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 } => {
|
Operator::V128Const { value } => {
|
||||||
let data = value.bytes().to_vec().into();
|
let data = value.bytes().to_vec().into();
|
||||||
|
|||||||
@@ -371,6 +371,87 @@ impl<'dummy_environment> FuncEnvironment for DummyFuncEnvironment<'dummy_environ
|
|||||||
) -> WasmResult<ir::Value> {
|
) -> WasmResult<ir::Value> {
|
||||||
Ok(pos.ins().iconst(I32, -1))
|
Ok(pos.ins().iconst(I32, -1))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn translate_memory_copy(
|
||||||
|
&mut self,
|
||||||
|
_pos: FuncCursor,
|
||||||
|
_index: MemoryIndex,
|
||||||
|
_heap: ir::Heap,
|
||||||
|
_dst: ir::Value,
|
||||||
|
_src: ir::Value,
|
||||||
|
_len: ir::Value,
|
||||||
|
) -> WasmResult<()> {
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
fn translate_memory_fill(
|
||||||
|
&mut self,
|
||||||
|
_pos: FuncCursor,
|
||||||
|
_index: MemoryIndex,
|
||||||
|
_heap: ir::Heap,
|
||||||
|
_dst: ir::Value,
|
||||||
|
_val: ir::Value,
|
||||||
|
_len: ir::Value,
|
||||||
|
) -> WasmResult<()> {
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
fn translate_memory_init(
|
||||||
|
&mut self,
|
||||||
|
_pos: FuncCursor,
|
||||||
|
_index: MemoryIndex,
|
||||||
|
_heap: ir::Heap,
|
||||||
|
_seg_index: u32,
|
||||||
|
_dst: ir::Value,
|
||||||
|
_src: ir::Value,
|
||||||
|
_len: ir::Value,
|
||||||
|
) -> WasmResult<()> {
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
fn translate_data_drop(&mut self, _pos: FuncCursor, _seg_index: u32) -> WasmResult<()> {
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
fn translate_table_size(
|
||||||
|
&mut self,
|
||||||
|
mut pos: FuncCursor,
|
||||||
|
_index: TableIndex,
|
||||||
|
_table: ir::Table,
|
||||||
|
) -> WasmResult<ir::Value> {
|
||||||
|
Ok(pos.ins().iconst(I32, -1))
|
||||||
|
}
|
||||||
|
|
||||||
|
fn translate_table_copy(
|
||||||
|
&mut self,
|
||||||
|
_pos: FuncCursor,
|
||||||
|
_dst_index: TableIndex,
|
||||||
|
_dst_table: ir::Table,
|
||||||
|
_src_index: TableIndex,
|
||||||
|
_src_table: ir::Table,
|
||||||
|
_dst: ir::Value,
|
||||||
|
_src: ir::Value,
|
||||||
|
_len: ir::Value,
|
||||||
|
) -> WasmResult<()> {
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
fn translate_table_init(
|
||||||
|
&mut self,
|
||||||
|
_pos: FuncCursor,
|
||||||
|
_seg_index: u32,
|
||||||
|
_table_index: TableIndex,
|
||||||
|
_table: ir::Table,
|
||||||
|
_dst: ir::Value,
|
||||||
|
_src: ir::Value,
|
||||||
|
_len: ir::Value,
|
||||||
|
) -> WasmResult<()> {
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
fn translate_elem_drop(&mut self, _pos: FuncCursor, _seg_index: u32) -> WasmResult<()> {
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'data> ModuleEnvironment<'data> for DummyEnvironment {
|
impl<'data> ModuleEnvironment<'data> for DummyEnvironment {
|
||||||
|
|||||||
@@ -266,6 +266,89 @@ pub trait FuncEnvironment {
|
|||||||
heap: ir::Heap,
|
heap: ir::Heap,
|
||||||
) -> WasmResult<ir::Value>;
|
) -> WasmResult<ir::Value>;
|
||||||
|
|
||||||
|
/// Translate a `memory.copy` WebAssembly instruction.
|
||||||
|
///
|
||||||
|
/// The `index` provided identifies the linear memory to query, and `heap` is the heap reference
|
||||||
|
/// returned by `make_heap` for the same index.
|
||||||
|
fn translate_memory_copy(
|
||||||
|
&mut self,
|
||||||
|
pos: FuncCursor,
|
||||||
|
index: MemoryIndex,
|
||||||
|
heap: ir::Heap,
|
||||||
|
dst: ir::Value,
|
||||||
|
src: ir::Value,
|
||||||
|
len: ir::Value,
|
||||||
|
) -> WasmResult<()>;
|
||||||
|
|
||||||
|
/// Translate a `memory.fill` WebAssembly instruction.
|
||||||
|
///
|
||||||
|
/// The `index` provided identifies the linear memory to query, and `heap` is the heap reference
|
||||||
|
/// returned by `make_heap` for the same index.
|
||||||
|
fn translate_memory_fill(
|
||||||
|
&mut self,
|
||||||
|
pos: FuncCursor,
|
||||||
|
index: MemoryIndex,
|
||||||
|
heap: ir::Heap,
|
||||||
|
dst: ir::Value,
|
||||||
|
val: ir::Value,
|
||||||
|
len: ir::Value,
|
||||||
|
) -> WasmResult<()>;
|
||||||
|
|
||||||
|
/// Translate a `memory.init` WebAssembly instruction.
|
||||||
|
///
|
||||||
|
/// The `index` provided identifies the linear memory to query, and `heap` is the heap reference
|
||||||
|
/// returned by `make_heap` for the same index. `seg_index` is the index of the segment to copy
|
||||||
|
/// from.
|
||||||
|
fn translate_memory_init(
|
||||||
|
&mut self,
|
||||||
|
pos: FuncCursor,
|
||||||
|
index: MemoryIndex,
|
||||||
|
heap: ir::Heap,
|
||||||
|
seg_index: u32,
|
||||||
|
dst: ir::Value,
|
||||||
|
src: ir::Value,
|
||||||
|
len: ir::Value,
|
||||||
|
) -> WasmResult<()>;
|
||||||
|
|
||||||
|
/// Translate a `data.drop` WebAssembly instruction.
|
||||||
|
fn translate_data_drop(&mut self, pos: FuncCursor, seg_index: u32) -> WasmResult<()>;
|
||||||
|
|
||||||
|
/// Translate a `table.size` WebAssembly instruction.
|
||||||
|
fn translate_table_size(
|
||||||
|
&mut self,
|
||||||
|
pos: FuncCursor,
|
||||||
|
index: TableIndex,
|
||||||
|
table: ir::Table,
|
||||||
|
) -> WasmResult<ir::Value>;
|
||||||
|
|
||||||
|
/// Translate a `table.copy` WebAssembly instruction.
|
||||||
|
fn translate_table_copy(
|
||||||
|
&mut self,
|
||||||
|
pos: FuncCursor,
|
||||||
|
dst_table_index: TableIndex,
|
||||||
|
dst_table: ir::Table,
|
||||||
|
src_table_index: TableIndex,
|
||||||
|
src_table: ir::Table,
|
||||||
|
dst: ir::Value,
|
||||||
|
src: ir::Value,
|
||||||
|
len: ir::Value,
|
||||||
|
) -> WasmResult<()>;
|
||||||
|
|
||||||
|
/// Translate a `table.init` WebAssembly instruction.
|
||||||
|
fn translate_table_init(
|
||||||
|
&mut self,
|
||||||
|
pos: FuncCursor,
|
||||||
|
seg_index: u32,
|
||||||
|
table_index: TableIndex,
|
||||||
|
table: ir::Table,
|
||||||
|
dst: ir::Value,
|
||||||
|
src: ir::Value,
|
||||||
|
len: ir::Value,
|
||||||
|
) -> WasmResult<()>;
|
||||||
|
|
||||||
|
/// Translate a `elem.drop` WebAssembly instruction.
|
||||||
|
fn translate_elem_drop(&mut self, pos: FuncCursor, seg_index: u32) -> WasmResult<()>;
|
||||||
|
|
||||||
/// 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