Attempt to add memory copy/fill (2)

This commit is contained in:
bainchild 2023-01-03 01:02:26 -06:00
parent 2f8eadad6c
commit 50b93641f2
5 changed files with 138 additions and 5 deletions

View File

@ -4,8 +4,8 @@ use std::{
}; };
use wasm_ast::node::{ use wasm_ast::node::{
Block, Br, BrIf, BrTable, Call, CallIndirect, FuncData, If, LabelType, MemoryGrow, SetGlobal, Block, Br, BrIf, BrTable, Call, CallIndirect, FuncData, If, LabelType, MemoryGrow, MemoryCopy,
SetLocal, SetTemporary, Statement, StoreAt, Terminator, MemoryFill, SetGlobal, SetLocal, SetTemporary, Statement, StoreAt, Terminator,
}; };
use wasmparser::ValType; use wasmparser::ValType;
@ -282,6 +282,32 @@ impl DriverNoContext for MemoryGrow {
} }
} }
impl DriverNoContext for MemoryCopy {
fn write(&self, w: &mut dyn Write) -> Result<()> {
let dst = self.dst();
let src = self.src();
write!(w, "rt.allocator.copy(memory_at_0, {dst}, {src}, ")?;
self.size().write(w)?;
write!(w, ")")
}
}
impl DriverNoContext for MemoryFill {
fn write(&self, w: &mut dyn Write) -> Result<()> {
let mem = self.mem();
let value = self.value();
let n = self.n();
write!(w, "rt.allocator.fill(memory_at_0, {mem}, ")?;
value.write(w)?;
write!(w, ", ")?;
n.write(w)?;
write!(w, ")")
}
}
fn write_stat(stat: &dyn DriverNoContext, mng: &mut Manager, w: &mut dyn Write) -> Result<()> { fn write_stat(stat: &dyn DriverNoContext, mng: &mut Manager, w: &mut dyn Write) -> Result<()> {
indentation!(mng, w)?; indentation!(mng, w)?;
stat.write(w)?; stat.write(w)?;
@ -301,6 +327,8 @@ impl Driver for Statement {
Self::SetGlobal(s) => write_stat(s, mng, w), Self::SetGlobal(s) => write_stat(s, mng, w),
Self::StoreAt(s) => write_stat(s, mng, w), Self::StoreAt(s) => write_stat(s, mng, w),
Self::MemoryGrow(s) => write_stat(s, mng, w), Self::MemoryGrow(s) => write_stat(s, mng, w),
Self::MemoryCopy(s) => write_stat(s, mng, w),
Self::MemoryFill(s) => write_stat(s, mng, w)
} }
} }
} }

View File

@ -944,6 +944,20 @@ do
return old return old
end end
end end
function allocator.copy(memory, dst, src, len)
for i = 1, len do
local v = load_byte(memory, src + i - 1)
store_byte(memory, dst + i - 1, v)
end
end
function allocator.fill(memory, dst, value, len)
for i = 1, len do
store_byte(memory, dst + i - 1, value)
end
end
module.load = load module.load = load
module.store = store module.store = store
@ -951,3 +965,4 @@ do
end end
return module return module

View File

@ -5,8 +5,8 @@ use crate::{
node::{ node::{
BinOp, BinOpType, Block, Br, BrIf, BrTable, Call, CallIndirect, CmpOp, CmpOpType, BinOp, BinOpType, Block, Br, BrIf, BrTable, Call, CallIndirect, CmpOp, CmpOpType,
Expression, FuncData, GetGlobal, GetLocal, If, LabelType, LoadAt, LoadType, MemoryGrow, Expression, FuncData, GetGlobal, GetLocal, If, LabelType, LoadAt, LoadType, MemoryGrow,
MemorySize, Select, SetGlobal, SetLocal, Statement, StoreAt, StoreType, Terminator, UnOp, MemoryCopy, MemoryFill, MemorySize, Select, SetGlobal, SetLocal, Statement, StoreAt,
UnOpType, Value, StoreType, Terminator, UnOp, UnOpType, Value,
}, },
stack::{ReadType, Stack}, stack::{ReadType, Stack},
}; };
@ -609,6 +609,29 @@ impl<'a> Factory<'a> {
self.target.leak_memory_write(memory); self.target.leak_memory_write(memory);
self.target.code.push(data); self.target.code.push(data);
} }
Operator::MemoryCopy { src, dst } => {
let size = self.target.stack.pop().into();
let data = Statement::MemoryCopy(MemoryCopy {
dst,
src,
size,
});
self.target.code.push(data);
}
Operator::MemoryFill { mem } => {
let n = self.target.stack.pop().into();
let value = self.target.stack.pop().into();
let data = Statement::MemoryFill(MemoryFill {
mem,
n,
value,
});
self.target.code.push(data);
}
Operator::I32Const { value } => self.target.push_constant(value), Operator::I32Const { value } => self.target.push_constant(value),
Operator::I64Const { value } => self.target.push_constant(value), Operator::I64Const { value } => self.target.push_constant(value),
Operator::F32Const { value } => self.target.push_constant(value.bits()), Operator::F32Const { value } => self.target.push_constant(value.bits()),

View File

@ -1108,6 +1108,48 @@ impl MemoryGrow {
} }
} }
pub struct MemoryCopy {
pub(crate) dst: u32,
pub(crate) src: u32,
pub(crate) size: Box<Expression>,
}
impl MemoryCopy {
#[must_use]
pub fn dst(&self) -> u32 {
self.dst
}
#[must_use]
pub fn src(&self) -> u32 {
self.src
}
#[must_use]
pub fn size(&self) -> &Expression {
&self.size
}
}
pub struct MemoryFill {
pub(crate) mem: u32,
pub(crate) value: Box<Expression>,
pub(crate) n: Box<Expression>,
}
impl MemoryFill {
#[must_use]
pub fn mem(&self) -> u32 {
self.mem
}
#[must_use]
pub fn value(&self) -> &Expression {
&self.value
}
#[must_use]
pub fn n(&self) -> &Expression {
&self.n
}
}
pub enum Statement { pub enum Statement {
Block(Block), Block(Block),
BrIf(BrIf), BrIf(BrIf),
@ -1119,6 +1161,8 @@ pub enum Statement {
SetGlobal(SetGlobal), SetGlobal(SetGlobal),
StoreAt(StoreAt), StoreAt(StoreAt),
MemoryGrow(MemoryGrow), MemoryGrow(MemoryGrow),
MemoryCopy(MemoryCopy),
MemoryFill(MemoryFill)
} }
pub struct FuncData { pub struct FuncData {

View File

@ -1,6 +1,6 @@
use crate::node::{ use crate::node::{
BinOp, Block, Br, BrIf, BrTable, Call, CallIndirect, CmpOp, Expression, FuncData, GetGlobal, BinOp, Block, Br, BrIf, BrTable, Call, CallIndirect, CmpOp, Expression, FuncData, GetGlobal,
GetLocal, GetTemporary, If, LoadAt, MemoryGrow, MemorySize, Select, SetGlobal, SetLocal, GetLocal, GetTemporary, If, LoadAt, MemoryGrow, MemorySize, MemoryCopy, MemoryFill, Select, SetGlobal, SetLocal,
SetTemporary, Statement, StoreAt, Terminator, UnOp, Value, SetTemporary, Statement, StoreAt, Terminator, UnOp, Value,
}; };
@ -55,6 +55,10 @@ pub trait Visitor {
fn visit_memory_grow(&mut self, _: &MemoryGrow) {} fn visit_memory_grow(&mut self, _: &MemoryGrow) {}
fn visit_memory_copy(&mut self, _: &MemoryCopy) {}
fn visit_memory_fill(&mut self, _: &MemoryFill) {}
fn visit_statement(&mut self, _: &Statement) {} fn visit_statement(&mut self, _: &Statement) {}
} }
@ -104,6 +108,23 @@ impl<T: Visitor> Driver<T> for MemorySize {
} }
} }
impl<T: Visitor> Driver<T> for MemoryCopy {
fn accept(&self, visitor: &mut T) {
self.size().accept(visitor);
visitor.visit_memory_copy(self);
}
}
impl<T: Visitor> Driver<T> for MemoryFill {
fn accept(&self, visitor: &mut T) {
self.value().accept(visitor);
self.n().accept(visitor);
visitor.visit_memory_fill(self);
}
}
impl<T: Visitor> Driver<T> for Value { impl<T: Visitor> Driver<T> for Value {
fn accept(&self, visitor: &mut T) { fn accept(&self, visitor: &mut T) {
visitor.visit_value(self); visitor.visit_value(self);
@ -145,6 +166,8 @@ impl<T: Visitor> Driver<T> for Expression {
Self::GetGlobal(v) => v.accept(visitor), Self::GetGlobal(v) => v.accept(visitor),
Self::LoadAt(v) => v.accept(visitor), Self::LoadAt(v) => v.accept(visitor),
Self::MemorySize(v) => v.accept(visitor), Self::MemorySize(v) => v.accept(visitor),
Self::MemoryCopy(v) => v.accept(visitor),
Self::MemoryFill(v) => v.accept(visitor),
Self::Value(v) => v.accept(visitor), Self::Value(v) => v.accept(visitor),
Self::UnOp(v) => v.accept(visitor), Self::UnOp(v) => v.accept(visitor),
Self::BinOp(v) => v.accept(visitor), Self::BinOp(v) => v.accept(visitor),