diff options
| author | Henry Gressmann <mail@henrygressmann.de> | 2024-05-09 22:36:14 +0200 |
|---|---|---|
| committer | Henry Gressmann <mail@henrygressmann.de> | 2024-05-09 22:36:14 +0200 |
| commit | 53bb44f45cfda750250e0835425307e3a1d763bc (patch) | |
| tree | 4085c249714d76b82157c7a888baa2151fe8f190 /crates | |
| parent | 11271a201633d3b07adacd07e407ac8d07e5fce3 (diff) | |
feat: implement I32StoreLocal & I32LocalGetConstAdd
Signed-off-by: Henry Gressmann <mail@henrygressmann.de>
Diffstat (limited to 'crates')
| -rw-r--r-- | crates/parser/src/visit.rs | 56 | ||||
| -rw-r--r-- | crates/tinywasm/src/runtime/interpreter/mod.rs | 15 | ||||
| -rw-r--r-- | crates/types/src/instructions.rs | 6 |
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 |
