summaryrefslogtreecommitdiff
path: root/crates
diff options
context:
space:
mode:
authorHenry Gressmann <mail@henrygressmann.de>2024-05-09 22:36:14 +0200
committerHenry Gressmann <mail@henrygressmann.de>2024-05-09 22:36:14 +0200
commit53bb44f45cfda750250e0835425307e3a1d763bc (patch)
tree4085c249714d76b82157c7a888baa2151fe8f190 /crates
parent11271a201633d3b07adacd07e407ac8d07e5fce3 (diff)
feat: implement I32StoreLocal & I32LocalGetConstAdd
Signed-off-by: Henry Gressmann <mail@henrygressmann.de>
Diffstat (limited to 'crates')
-rw-r--r--crates/parser/src/visit.rs56
-rw-r--r--crates/tinywasm/src/runtime/interpreter/mod.rs15
-rw-r--r--crates/types/src/instructions.rs6
3 files changed, 60 insertions, 17 deletions
diff --git a/crates/parser/src/visit.rs b/crates/parser/src/visit.rs
index 80dc789..48eba30 100644
--- a/crates/parser/src/visit.rs
+++ b/crates/parser/src/visit.rs
@@ -162,7 +162,7 @@ impl<'a> wasmparser::VisitOperator<'a> for FunctionBuilder {
visit_i64_load16_u, I64Load16U,
visit_i64_load32_s, I64Load32S,
visit_i64_load32_u, I64Load32U,
- visit_i32_store, I32Store,
+ // visit_i32_store, I32Store,
visit_i64_store, I64Store,
visit_f32_store, F32Store,
visit_f64_store, F64Store,
@@ -321,6 +321,37 @@ impl<'a> wasmparser::VisitOperator<'a> for FunctionBuilder {
visit_i64_trunc_sat_f64_u, Instruction::I64TruncSatF64U
}
+ fn visit_i32_store(&mut self, memarg: wasmparser::MemArg) -> Self::Output {
+ let arg = convert_memarg(memarg);
+ let i32store = Instruction::I32Store { offset: arg.offset, mem_addr: arg.mem_addr };
+
+ if self.instructions.len() < 3 {
+ return self.visit(i32store);
+ }
+
+ #[cold]
+ fn cold() {}
+
+ if arg.mem_addr > 0xFF || arg.offset > 0xFFFF_FFFF {
+ cold();
+ return self.visit(i32store);
+ }
+
+ match self.instructions[self.instructions.len() - 2..] {
+ [Instruction::LocalGet(a), Instruction::I32Const(b)] => {
+ self.instructions.pop();
+ self.instructions.pop();
+ self.visit(Instruction::I32StoreLocal {
+ local: a,
+ consti32: b,
+ offset: arg.offset as u32,
+ mem_addr: arg.mem_addr as u8,
+ })
+ }
+ _ => self.visit(i32store),
+ }
+ }
+
fn visit_local_get(&mut self, idx: u32) -> Self::Output {
if let Some(instruction) = self.instructions.last_mut() {
match instruction {
@@ -369,19 +400,18 @@ impl<'a> wasmparser::VisitOperator<'a> for FunctionBuilder {
}
fn visit_i32_add(&mut self) -> Self::Output {
- self.visit(Instruction::I32Add)
- // if self.instructions.len() < 2 {
- // return self.visit(Instruction::I32Add);
- // }
+ if self.instructions.len() < 2 {
+ return self.visit(Instruction::I32Add);
+ }
- // match self.instructions[self.instructions.len() - 2..] {
- // // [Instruction::LocalGet(a), Instruction::I32Const(b)] => {
- // // self.instructions.pop();
- // // self.instructions.pop();
- // // self.visit(Instruction::I32LocalGetConstAdd(a, b))
- // // }
- // _ => self.visit(Instruction::I32Add),
- // }
+ match self.instructions[self.instructions.len() - 2..] {
+ [Instruction::LocalGet(a), Instruction::I32Const(b)] => {
+ self.instructions.pop();
+ self.instructions.pop();
+ self.visit(Instruction::I32LocalGetConstAdd(a, b))
+ }
+ _ => self.visit(Instruction::I32Add),
+ }
}
fn visit_block(&mut self, blockty: wasmparser::BlockType) -> Self::Output {
diff --git a/crates/tinywasm/src/runtime/interpreter/mod.rs b/crates/tinywasm/src/runtime/interpreter/mod.rs
index 2f0328b..6ff7be1 100644
--- a/crates/tinywasm/src/runtime/interpreter/mod.rs
+++ b/crates/tinywasm/src/runtime/interpreter/mod.rs
@@ -689,6 +689,21 @@ fn exec_one(cf: &mut CallFrame, stack: &mut Stack, store: &mut Store, module: &M
let res = val ^ mask;
stack.values.push(res.rotate_left(*rotate_by as u32).into());
}
+
+ I32LocalGetConstAdd(local, val) => {
+ let local: i32 = cf.get_local(*local as usize).into();
+ stack.values.push((local + *val).into());
+ }
+
+ I32StoreLocal { local, consti32, offset, mem_addr } => {
+ let (mem_addr, offset) = (*mem_addr as u32, *offset as u32);
+ let mem = store.get_mem(module.resolve_mem_addr(mem_addr) as usize)?;
+ let val = consti32;
+ let val = val.to_le_bytes();
+ let addr: u64 = cf.get_local(*local as usize).into();
+ mem.borrow_mut().store((offset as u64 + addr) as usize, val.len(), &val)?;
+ }
+
i => {
cold();
log::error!("unimplemented instruction: {:?}", i);
diff --git a/crates/types/src/instructions.rs b/crates/types/src/instructions.rs
index 402cc9a..fc6fba2 100644
--- a/crates/types/src/instructions.rs
+++ b/crates/types/src/instructions.rs
@@ -84,16 +84,14 @@ pub enum Instruction {
// Custom Instructions
BrLabel(LabelAddr),
- // Not implemented yet
// LocalGet + I32Const + I32Add
// One of the most common patterns in the Rust compiler output
- // I32LocalGetConstAdd(LocalAddr, i32),
+ I32LocalGetConstAdd(LocalAddr, i32),
- // Not implemented yet
// LocalGet + I32Const + I32Store => I32LocalGetConstStore + I32Const
// Also common, helps us skip the stack entirely.
// Has to be followed by an I32Const instruction
- // I32StoreLocal { local: LocalAddr, offset: i32, mem_addr: MemAddr },
+ I32StoreLocal { local: LocalAddr, consti32: i32, offset: u32, mem_addr: u8 },
// I64Xor + I64Const + I64RotL
// Commonly used by a few crypto libraries