diff options
| -rw-r--r-- | crates/cli/src/bin.rs | 10 | ||||
| -rw-r--r-- | crates/parser/src/conversion.rs | 394 | ||||
| -rw-r--r-- | crates/parser/src/error.rs | 8 | ||||
| -rw-r--r-- | crates/parser/src/lib.rs | 16 | ||||
| -rw-r--r-- | crates/parser/src/module.rs | 22 | ||||
| -rw-r--r-- | crates/tinywasm/src/error.rs | 2 | ||||
| -rw-r--r-- | crates/tinywasm/src/func.rs | 2 | ||||
| -rw-r--r-- | crates/tinywasm/src/runtime/executer.rs | 32 | ||||
| -rw-r--r-- | crates/tinywasm/src/runtime/mod.rs | 2 | ||||
| -rw-r--r-- | crates/tinywasm/src/runtime/stack/call_stack.rs | 10 | ||||
| -rw-r--r-- | crates/tinywasm/src/runtime/stack/value_stack.rs | 19 | ||||
| -rw-r--r-- | crates/tinywasm/src/runtime/value.rs | 84 | ||||
| -rw-r--r-- | crates/tinywasm/src/store.rs | 6 | ||||
| -rw-r--r-- | crates/types/src/instructions.rs | 9 | ||||
| -rw-r--r-- | rustfmt.toml | 1 |
15 files changed, 288 insertions, 329 deletions
diff --git a/crates/cli/src/bin.rs b/crates/cli/src/bin.rs index 3615e4a..2e05f8a 100644 --- a/crates/cli/src/bin.rs +++ b/crates/cli/src/bin.rs @@ -67,9 +67,7 @@ fn main() -> Result<()> { _ => log::LevelFilter::Info, }; - pretty_env_logger::formatted_builder() - .filter_level(level) - .init(); + pretty_env_logger::formatted_builder().filter_level(level).init(); let cwd = std::env::current_dir()?; @@ -84,11 +82,7 @@ fn main() -> Result<()> { tinywasm::Module::parse_bytes(&wasm)? } #[cfg(not(feature = "wat"))] - true => { - return Err(color_eyre::eyre::eyre!( - "wat support is not enabled in this build" - )) - } + true => return Err(color_eyre::eyre::eyre!("wat support is not enabled in this build")), false => tinywasm::Module::parse_file(path)?, }; diff --git a/crates/parser/src/conversion.rs b/crates/parser/src/conversion.rs index 7121922..d08df9b 100644 --- a/crates/parser/src/conversion.rs +++ b/crates/parser/src/conversion.rs @@ -67,7 +67,7 @@ pub(crate) fn convert_module_type(ty: wasmparser::Type) -> Result<FuncType> { Ok(FuncType { params, results }) } -pub(crate) fn convert_blocktype(blocktype: &wasmparser::BlockType) -> BlockArgs { +pub(crate) fn convert_blocktype(blocktype: wasmparser::BlockType) -> BlockArgs { use wasmparser::BlockType::*; match blocktype { Empty => BlockArgs::Empty, @@ -76,7 +76,7 @@ pub(crate) fn convert_blocktype(blocktype: &wasmparser::BlockType) -> BlockArgs // TODO: maybe solve this differently so we can support 128-bit values // without having to increase the size of the WasmValue enum - Type(ty) => BlockArgs::Type(convert_valtype(ty)), + Type(ty) => BlockArgs::Type(convert_valtype(&ty)), // Wasm 2.0 FuncType(_ty) => unimplemented!(), @@ -108,208 +108,200 @@ pub fn process_operators<'a>( ops: impl Iterator<Item = Result<wasmparser::Operator<'a>, wasmparser::BinaryReaderError>>, ) -> Result<Box<[Instruction]>> { let mut instructions = Vec::new(); + for op in ops { - match op? { - wasmparser::Operator::BrTable { targets } => { - instructions.push(Instruction::BrTable(targets.default())); - instructions.extend( - targets - .targets() - .collect::<Result<Vec<u32>, wasmparser::BinaryReaderError>>()? - .into_iter() - .map(Instruction::BrLabel), - ); + use wasmparser::Operator::*; + let res = match op? { + BrTable { targets } => { + let def = targets.default(); + let targets = targets + .targets() + .collect::<Result<Vec<u32>, wasmparser::BinaryReaderError>>()?; + instructions.push(Instruction::BrTable(def, targets.len() as u32)); + instructions.extend(targets.into_iter().map(Instruction::BrLabel)); + continue; } - op => instructions.push(process_operator(&op)?), - } + Unreachable => Instruction::Unreachable, + Nop => Instruction::Nop, + Block { blockty } => Instruction::Block(convert_blocktype(blockty)), + Loop { blockty } => Instruction::Loop(convert_blocktype(blockty)), + If { blockty } => Instruction::If(convert_blocktype(blockty)), + Else => Instruction::Else, + End => Instruction::End, + Br { relative_depth } => Instruction::Br(relative_depth), + BrIf { relative_depth } => Instruction::BrIf(relative_depth), + Return => Instruction::Return, + Call { function_index } => Instruction::Call(function_index), + CallIndirect { + type_index, + table_index, + .. + } => Instruction::CallIndirect(type_index, table_index), + Drop => Instruction::Drop, + Select => Instruction::Select, + LocalGet { local_index } => Instruction::LocalGet(local_index), + LocalSet { local_index } => Instruction::LocalSet(local_index), + LocalTee { local_index } => Instruction::LocalTee(local_index), + GlobalGet { global_index } => Instruction::GlobalGet(global_index), + GlobalSet { global_index } => Instruction::GlobalSet(global_index), + MemorySize { .. } => Instruction::MemorySize, + MemoryGrow { .. } => Instruction::MemoryGrow, + I32Load { memarg } => Instruction::I32Load(convert_memarg(memarg)), + I64Load { memarg } => Instruction::I64Load(convert_memarg(memarg)), + F32Load { memarg } => Instruction::F32Load(convert_memarg(memarg)), + F64Load { memarg } => Instruction::F64Load(convert_memarg(memarg)), + I32Load8S { memarg } => Instruction::I32Load8S(convert_memarg(memarg)), + I32Load8U { memarg } => Instruction::I32Load8U(convert_memarg(memarg)), + I32Load16S { memarg } => Instruction::I32Load16S(convert_memarg(memarg)), + I32Load16U { memarg } => Instruction::I32Load16U(convert_memarg(memarg)), + I64Load8S { memarg } => Instruction::I64Load8S(convert_memarg(memarg)), + I64Load8U { memarg } => Instruction::I64Load8U(convert_memarg(memarg)), + I64Load16S { memarg } => Instruction::I64Load16S(convert_memarg(memarg)), + I64Load16U { memarg } => Instruction::I64Load16U(convert_memarg(memarg)), + I64Load32S { memarg } => Instruction::I64Load32S(convert_memarg(memarg)), + I64Load32U { memarg } => Instruction::I64Load32U(convert_memarg(memarg)), + I32Store { memarg } => Instruction::I32Store(convert_memarg(memarg)), + I64Store { memarg } => Instruction::I64Store(convert_memarg(memarg)), + F32Store { memarg } => Instruction::F32Store(convert_memarg(memarg)), + F64Store { memarg } => Instruction::F64Store(convert_memarg(memarg)), + I32Store8 { memarg } => Instruction::I32Store8(convert_memarg(memarg)), + I32Store16 { memarg } => Instruction::I32Store16(convert_memarg(memarg)), + I64Store8 { memarg } => Instruction::I64Store8(convert_memarg(memarg)), + I64Store16 { memarg } => Instruction::I64Store16(convert_memarg(memarg)), + I64Store32 { memarg } => Instruction::I64Store32(convert_memarg(memarg)), + I32Eqz => Instruction::I32Eqz, + I32Eq => Instruction::I32Eq, + I32Ne => Instruction::I32Ne, + I32LtS => Instruction::I32LtS, + I32LtU => Instruction::I32LtU, + I32GtS => Instruction::I32GtS, + I32GtU => Instruction::I32GtU, + I32LeS => Instruction::I32LeS, + I32LeU => Instruction::I32LeU, + I32GeS => Instruction::I32GeS, + I32GeU => Instruction::I32GeU, + I64Eqz => Instruction::I64Eqz, + I64Eq => Instruction::I64Eq, + I64Ne => Instruction::I64Ne, + I64LtS => Instruction::I64LtS, + I64LtU => Instruction::I64LtU, + I64GtS => Instruction::I64GtS, + I64GtU => Instruction::I64GtU, + I64LeS => Instruction::I64LeS, + I64LeU => Instruction::I64LeU, + I64GeS => Instruction::I64GeS, + I64GeU => Instruction::I64GeU, + F32Eq => Instruction::F32Eq, + F32Ne => Instruction::F32Ne, + F32Lt => Instruction::F32Lt, + F32Gt => Instruction::F32Gt, + F32Le => Instruction::F32Le, + F32Ge => Instruction::F32Ge, + F64Eq => Instruction::F64Eq, + F64Ne => Instruction::F64Ne, + F64Lt => Instruction::F64Lt, + F64Gt => Instruction::F64Gt, + F64Le => Instruction::F64Le, + F64Ge => Instruction::F64Ge, + I32Clz => Instruction::I32Clz, + I32Ctz => Instruction::I32Ctz, + I32Popcnt => Instruction::I32Popcnt, + I32Add => Instruction::I32Add, + I32Sub => Instruction::I32Sub, + I32Mul => Instruction::I32Mul, + I32DivS => Instruction::I32DivS, + I32DivU => Instruction::I32DivU, + I32RemS => Instruction::I32RemS, + I32RemU => Instruction::I32RemU, + I32And => Instruction::I32And, + I32Or => Instruction::I32Or, + I32Xor => Instruction::I32Xor, + I32Shl => Instruction::I32Shl, + I32ShrS => Instruction::I32ShrS, + I32ShrU => Instruction::I32ShrU, + I32Rotl => Instruction::I32Rotl, + I32Rotr => Instruction::I32Rotr, + I64Clz => Instruction::I64Clz, + I64Ctz => Instruction::I64Ctz, + I64Popcnt => Instruction::I64Popcnt, + I64Add => Instruction::I64Add, + I64Sub => Instruction::I64Sub, + I64Mul => Instruction::I64Mul, + I64DivS => Instruction::I64DivS, + I64DivU => Instruction::I64DivU, + I64RemS => Instruction::I64RemS, + I64RemU => Instruction::I64RemU, + I64And => Instruction::I64And, + I64Or => Instruction::I64Or, + I64Xor => Instruction::I64Xor, + I64Shl => Instruction::I64Shl, + I64ShrS => Instruction::I64ShrS, + I64ShrU => Instruction::I64ShrU, + I64Rotl => Instruction::I64Rotl, + I64Rotr => Instruction::I64Rotr, + F32Abs => Instruction::F32Abs, + F32Neg => Instruction::F32Neg, + F32Ceil => Instruction::F32Ceil, + F32Floor => Instruction::F32Floor, + F32Trunc => Instruction::F32Trunc, + F32Nearest => Instruction::F32Nearest, + F32Sqrt => Instruction::F32Sqrt, + F32Add => Instruction::F32Add, + F32Sub => Instruction::F32Sub, + F32Mul => Instruction::F32Mul, + F32Div => Instruction::F32Div, + F32Min => Instruction::F32Min, + F32Max => Instruction::F32Max, + F32Copysign => Instruction::F32Copysign, + F64Abs => Instruction::F64Abs, + F64Neg => Instruction::F64Neg, + F64Ceil => Instruction::F64Ceil, + F64Floor => Instruction::F64Floor, + F64Trunc => Instruction::F64Trunc, + F64Nearest => Instruction::F64Nearest, + F64Sqrt => Instruction::F64Sqrt, + F64Add => Instruction::F64Add, + F64Sub => Instruction::F64Sub, + F64Mul => Instruction::F64Mul, + F64Div => Instruction::F64Div, + F64Min => Instruction::F64Min, + F64Max => Instruction::F64Max, + F64Copysign => Instruction::F64Copysign, + I32WrapI64 => Instruction::I32WrapI64, + I32TruncF32S => Instruction::I32TruncF32S, + I32TruncF32U => Instruction::I32TruncF32U, + I32TruncF64S => Instruction::I32TruncF64S, + I32TruncF64U => Instruction::I32TruncF64U, + I64ExtendI32S => Instruction::I64ExtendI32S, + I64ExtendI32U => Instruction::I64ExtendI32U, + I64TruncF32S => Instruction::I64TruncF32S, + I64TruncF32U => Instruction::I64TruncF32U, + I64TruncF64S => Instruction::I64TruncF64S, + I64TruncF64U => Instruction::I64TruncF64U, + F32ConvertI32S => Instruction::F32ConvertI32S, + F32ConvertI32U => Instruction::F32ConvertI32U, + F32ConvertI64S => Instruction::F32ConvertI64S, + F32ConvertI64U => Instruction::F32ConvertI64U, + F32DemoteF64 => Instruction::F32DemoteF64, + F64ConvertI32S => Instruction::F64ConvertI32S, + F64ConvertI32U => Instruction::F64ConvertI32U, + F64ConvertI64S => Instruction::F64ConvertI64S, + F64ConvertI64U => Instruction::F64ConvertI64U, + F64PromoteF32 => Instruction::F64PromoteF32, + I32ReinterpretF32 => Instruction::I32ReinterpretF32, + I64ReinterpretF64 => Instruction::I64ReinterpretF64, + F32ReinterpretI32 => Instruction::F32ReinterpretI32, + F64ReinterpretI64 => Instruction::F64ReinterpretI64, + op => { + return Err(crate::ParseError::UnsupportedOperator(format!( + "Unsupported instruction: {:?}", + op + ))) + } + }; + + instructions.push(res); } Ok(instructions.into_boxed_slice()) } - -#[inline] -pub(crate) fn process_operator(op: &wasmparser::Operator) -> Result<Instruction> { - use wasmparser::Operator::*; - let v = match op { - Unreachable => Instruction::Unreachable, - Nop => Instruction::Nop, - Block { blockty } => Instruction::Block(convert_blocktype(blockty)), - Loop { blockty } => Instruction::Loop(convert_blocktype(blockty)), - If { blockty } => Instruction::If(convert_blocktype(blockty)), - Else => Instruction::Else, - End => Instruction::End, - Br { relative_depth } => Instruction::Br(*relative_depth), - BrIf { relative_depth } => Instruction::BrIf(*relative_depth), - BrTable { targets } => Instruction::BrTable(targets.default()), - Return => Instruction::Return, - Call { function_index } => Instruction::Call(*function_index), - CallIndirect { - type_index, - table_index, - .. - } => Instruction::CallIndirect(*type_index, *table_index), - Drop => Instruction::Drop, - Select => Instruction::Select, - LocalGet { local_index } => Instruction::LocalGet(*local_index), - LocalSet { local_index } => Instruction::LocalSet(*local_index), - LocalTee { local_index } => Instruction::LocalTee(*local_index), - GlobalGet { global_index } => Instruction::GlobalGet(*global_index), - GlobalSet { global_index } => Instruction::GlobalSet(*global_index), - MemorySize { .. } => Instruction::MemorySize, - MemoryGrow { .. } => Instruction::MemoryGrow, - I32Load { memarg } => Instruction::I32Load(convert_memarg(*memarg)), - I64Load { memarg } => Instruction::I64Load(convert_memarg(*memarg)), - F32Load { memarg } => Instruction::F32Load(convert_memarg(*memarg)), - F64Load { memarg } => Instruction::F64Load(convert_memarg(*memarg)), - I32Load8S { memarg } => Instruction::I32Load8S(convert_memarg(*memarg)), - I32Load8U { memarg } => Instruction::I32Load8U(convert_memarg(*memarg)), - I32Load16S { memarg } => Instruction::I32Load16S(convert_memarg(*memarg)), - I32Load16U { memarg } => Instruction::I32Load16U(convert_memarg(*memarg)), - I64Load8S { memarg } => Instruction::I64Load8S(convert_memarg(*memarg)), - I64Load8U { memarg } => Instruction::I64Load8U(convert_memarg(*memarg)), - I64Load16S { memarg } => Instruction::I64Load16S(convert_memarg(*memarg)), - I64Load16U { memarg } => Instruction::I64Load16U(convert_memarg(*memarg)), - I64Load32S { memarg } => Instruction::I64Load32S(convert_memarg(*memarg)), - I64Load32U { memarg } => Instruction::I64Load32U(convert_memarg(*memarg)), - I32Store { memarg } => Instruction::I32Store(convert_memarg(*memarg)), - I64Store { memarg } => Instruction::I64Store(convert_memarg(*memarg)), - F32Store { memarg } => Instruction::F32Store(convert_memarg(*memarg)), - F64Store { memarg } => Instruction::F64Store(convert_memarg(*memarg)), - I32Store8 { memarg } => Instruction::I32Store8(convert_memarg(*memarg)), - I32Store16 { memarg } => Instruction::I32Store16(convert_memarg(*memarg)), - I64Store8 { memarg } => Instruction::I64Store8(convert_memarg(*memarg)), - I64Store16 { memarg } => Instruction::I64Store16(convert_memarg(*memarg)), - I64Store32 { memarg } => Instruction::I64Store32(convert_memarg(*memarg)), - I32Eqz => Instruction::I32Eqz, - I32Eq => Instruction::I32Eq, - I32Ne => Instruction::I32Ne, - I32LtS => Instruction::I32LtS, - I32LtU => Instruction::I32LtU, - I32GtS => Instruction::I32GtS, - I32GtU => Instruction::I32GtU, - I32LeS => Instruction::I32LeS, - I32LeU => Instruction::I32LeU, - I32GeS => Instruction::I32GeS, - I32GeU => Instruction::I32GeU, - I64Eqz => Instruction::I64Eqz, - I64Eq => Instruction::I64Eq, - I64Ne => Instruction::I64Ne, - I64LtS => Instruction::I64LtS, - I64LtU => Instruction::I64LtU, - I64GtS => Instruction::I64GtS, - I64GtU => Instruction::I64GtU, - I64LeS => Instruction::I64LeS, - I64LeU => Instruction::I64LeU, - I64GeS => Instruction::I64GeS, - I64GeU => Instruction::I64GeU, - F32Eq => Instruction::F32Eq, - F32Ne => Instruction::F32Ne, - F32Lt => Instruction::F32Lt, - F32Gt => Instruction::F32Gt, - F32Le => Instruction::F32Le, - F32Ge => Instruction::F32Ge, - F64Eq => Instruction::F64Eq, - F64Ne => Instruction::F64Ne, - F64Lt => Instruction::F64Lt, - F64Gt => Instruction::F64Gt, - F64Le => Instruction::F64Le, - F64Ge => Instruction::F64Ge, - I32Clz => Instruction::I32Clz, - I32Ctz => Instruction::I32Ctz, - I32Popcnt => Instruction::I32Popcnt, - I32Add => Instruction::I32Add, - I32Sub => Instruction::I32Sub, - I32Mul => Instruction::I32Mul, - I32DivS => Instruction::I32DivS, - I32DivU => Instruction::I32DivU, - I32RemS => Instruction::I32RemS, - I32RemU => Instruction::I32RemU, - I32And => Instruction::I32And, - I32Or => Instruction::I32Or, - I32Xor => Instruction::I32Xor, - I32Shl => Instruction::I32Shl, - I32ShrS => Instruction::I32ShrS, - I32ShrU => Instruction::I32ShrU, - I32Rotl => Instruction::I32Rotl, - I32Rotr => Instruction::I32Rotr, - I64Clz => Instruction::I64Clz, - I64Ctz => Instruction::I64Ctz, - I64Popcnt => Instruction::I64Popcnt, - I64Add => Instruction::I64Add, - I64Sub => Instruction::I64Sub, - I64Mul => Instruction::I64Mul, - I64DivS => Instruction::I64DivS, - I64DivU => Instruction::I64DivU, - I64RemS => Instruction::I64RemS, - I64RemU => Instruction::I64RemU, - I64And => Instruction::I64And, - I64Or => Instruction::I64Or, - I64Xor => Instruction::I64Xor, - I64Shl => Instruction::I64Shl, - I64ShrS => Instruction::I64ShrS, - I64ShrU => Instruction::I64ShrU, - I64Rotl => Instruction::I64Rotl, - I64Rotr => Instruction::I64Rotr, - F32Abs => Instruction::F32Abs, - F32Neg => Instruction::F32Neg, - F32Ceil => Instruction::F32Ceil, - F32Floor => Instruction::F32Floor, - F32Trunc => Instruction::F32Trunc, - F32Nearest => Instruction::F32Nearest, - F32Sqrt => Instruction::F32Sqrt, - F32Add => Instruction::F32Add, - F32Sub => Instruction::F32Sub, - F32Mul => Instruction::F32Mul, - F32Div => Instruction::F32Div, - F32Min => Instruction::F32Min, - F32Max => Instruction::F32Max, - F32Copysign => Instruction::F32Copysign, - F64Abs => Instruction::F64Abs, - F64Neg => Instruction::F64Neg, - F64Ceil => Instruction::F64Ceil, - F64Floor => Instruction::F64Floor, - F64Trunc => Instruction::F64Trunc, - F64Nearest => Instruction::F64Nearest, - F64Sqrt => Instruction::F64Sqrt, - F64Add => Instruction::F64Add, - F64Sub => Instruction::F64Sub, - F64Mul => Instruction::F64Mul, - F64Div => Instruction::F64Div, - F64Min => Instruction::F64Min, - F64Max => Instruction::F64Max, - F64Copysign => Instruction::F64Copysign, - I32WrapI64 => Instruction::I32WrapI64, - I32TruncF32S => Instruction::I32TruncF32S, - I32TruncF32U => Instruction::I32TruncF32U, - I32TruncF64S => Instruction::I32TruncF64S, - I32TruncF64U => Instruction::I32TruncF64U, - I64ExtendI32S => Instruction::I64ExtendI32S, - I64ExtendI32U => Instruction::I64ExtendI32U, - I64TruncF32S => Instruction::I64TruncF32S, - I64TruncF32U => Instruction::I64TruncF32U, - I64TruncF64S => Instruction::I64TruncF64S, - I64TruncF64U => Instruction::I64TruncF64U, - F32ConvertI32S => Instruction::F32ConvertI32S, - F32ConvertI32U => Instruction::F32ConvertI32U, - F32ConvertI64S => Instruction::F32ConvertI64S, - F32ConvertI64U => Instruction::F32ConvertI64U, - F32DemoteF64 => Instruction::F32DemoteF64, - F64ConvertI32S => Instruction::F64ConvertI32S, - F64ConvertI32U => Instruction::F64ConvertI32U, - F64ConvertI64S => Instruction::F64ConvertI64S, - F64ConvertI64U => Instruction::F64ConvertI64U, - F64PromoteF32 => Instruction::F64PromoteF32, - I32ReinterpretF32 => Instruction::I32ReinterpretF32, - I64ReinterpretF64 => Instruction::I64ReinterpretF64, - F32ReinterpretI32 => Instruction::F32ReinterpretI32, - F64ReinterpretI64 => Instruction::F64ReinterpretI64, - _ => { - return Err(crate::ParseError::UnsupportedOperator(format!( - "Unsupported instruction: {:?}", - op - ))) - } - }; - - Ok(v) -} diff --git a/crates/parser/src/error.rs b/crates/parser/src/error.rs index 6fa9e25..a5c807a 100644 --- a/crates/parser/src/error.rs +++ b/crates/parser/src/error.rs @@ -28,11 +28,9 @@ impl Debug for ParseError { write!(f, "error parsing module: {} at offset {}", message, offset) } Self::InvalidEncoding(encoding) => write!(f, "invalid encoding: {:?}", encoding), - Self::InvalidLocalCount { expected, actual } => write!( - f, - "invalid local count: expected {}, actual {}", - expected, actual - ), + Self::InvalidLocalCount { expected, actual } => { + write!(f, "invalid local count: expected {}, actual {}", expected, actual) + } Self::EndNotReached => write!(f, "end of module not reached"), Self::Other(message) => write!(f, "unknown error: {}", message), } diff --git a/crates/parser/src/lib.rs b/crates/parser/src/lib.rs index fdfea49..31e8cc8 100644 --- a/crates/parser/src/lib.rs +++ b/crates/parser/src/lib.rs @@ -38,14 +38,10 @@ impl Parser { } #[cfg(feature = "std")] - pub fn parse_module_file( - &self, - path: impl AsRef<crate::std::path::Path> + Clone, - ) -> Result<TinyWasmModule> { + pub fn parse_module_file(&self, path: impl AsRef<crate::std::path::Path> + Clone) -> Result<TinyWasmModule> { use alloc::format; - let f = crate::std::fs::File::open(path.clone()).map_err(|e| { - ParseError::Other(format!("Error opening file {:?}: {}", path.as_ref(), e)) - })?; + let f = crate::std::fs::File::open(path.clone()) + .map_err(|e| ParseError::Other(format!("Error opening file {:?}: {}", path.as_ref(), e)))?; let mut reader = crate::std::io::BufReader::new(f); self.parse_module_stream(&mut reader) @@ -66,9 +62,9 @@ impl Parser { wasmparser::Chunk::NeedMoreData(hint) => { let len = buffer.len(); buffer.extend((0..hint).map(|_| 0u8)); - let read_bytes = stream.read(&mut buffer[len..]).map_err(|e| { - ParseError::Other(format!("Error reading from stream: {}", e)) - })?; + let read_bytes = stream + .read(&mut buffer[len..]) + .map_err(|e| ParseError::Other(format!("Error reading from stream: {}", e)))?; buffer.truncate(len + read_bytes); eof = read_bytes == 0; } diff --git a/crates/parser/src/module.rs b/crates/parser/src/module.rs index 2beba9e..5bdbcd8 100644 --- a/crates/parser/src/module.rs +++ b/crates/parser/src/module.rs @@ -58,18 +58,12 @@ impl ModuleReader { use wasmparser::Payload::*; match payload { - Version { - num, - encoding, - range, - } => { + Version { num, encoding, range } => { validator.version(num, encoding, &range)?; self.version = Some(num); match encoding { wasmparser::Encoding::Module => {} - wasmparser::Encoding::Component => { - return Err(ParseError::InvalidEncoding(encoding)) - } + wasmparser::Encoding::Component => return Err(ParseError::InvalidEncoding(encoding)), } } StartSection { func, range } => { @@ -88,10 +82,7 @@ impl ModuleReader { FunctionSection(reader) => { debug!("Found function section"); validator.function_section(&reader)?; - self.function_section = reader - .into_iter() - .map(|f| Ok(f?)) - .collect::<Result<Vec<_>>>()?; + self.function_section = reader.into_iter().map(|f| Ok(f?)).collect::<Result<Vec<_>>>()?; } TableSection(_reader) => { return Err(ParseError::UnsupportedSection("Table section".into())); @@ -135,8 +126,7 @@ impl ModuleReader { debug!("Found code section entry"); validator.code_section_entry(&function)?; - self.code_section - .push(conversion::convert_module_code(function)?); + self.code_section.push(conversion::convert_module_code(function)?); } ImportSection(_reader) => { return Err(ParseError::UnsupportedSection("Import section".into())); @@ -166,9 +156,7 @@ impl ModuleReader { debug!("Found custom section"); debug!("Skipping custom section: {:?}", reader.name()); } - UnknownSection { .. } => { - return Err(ParseError::UnsupportedSection("Unknown section".into())) - } + UnknownSection { .. } => return Err(ParseError::UnsupportedSection("Unknown section".into())), section => { return Err(ParseError::UnsupportedSection(format!( "Unsupported section: {:?}", diff --git a/crates/tinywasm/src/error.rs b/crates/tinywasm/src/error.rs index fc43534..bc7028d 100644 --- a/crates/tinywasm/src/error.rs +++ b/crates/tinywasm/src/error.rs @@ -10,6 +10,7 @@ pub enum Error { FuncDidNotReturn, StackUnderflow, + BlockStackUnderflow, CallStackEmpty, InvalidStore, @@ -22,6 +23,7 @@ impl Display for Error { fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { match self { Self::FuncDidNotReturn => write!(f, "function did not return"), + Self::BlockStackUnderflow => write!(f, "block stack underflow"), Self::StackUnderflow => write!(f, "stack underflow"), Self::ParseError(err) => write!(f, "error parsing module: {:?}", err), Self::UnsupportedFeature(feature) => write!(f, "unsupported feature: {}", feature), diff --git a/crates/tinywasm/src/func.rs b/crates/tinywasm/src/func.rs index d967a45..cf49e22 100644 --- a/crates/tinywasm/src/func.rs +++ b/crates/tinywasm/src/func.rs @@ -68,7 +68,7 @@ impl FuncHandle { Ok(res .iter() .zip(func_ty.results.iter()) - .map(|(v, ty)| v.into_typed(*ty)) + .map(|(v, ty)| v.attach_type(*ty)) .collect()) } } diff --git a/crates/tinywasm/src/runtime/executer.rs b/crates/tinywasm/src/runtime/executer.rs index 19e0a29..85a9823 100644 --- a/crates/tinywasm/src/runtime/executer.rs +++ b/crates/tinywasm/src/runtime/executer.rs @@ -1,19 +1,37 @@ use super::{Runtime, Stack}; use crate::{Error, Result}; +use alloc::vec; use log::debug; use tinywasm_types::Instruction; +enum BlockMarker { + Top, + Loop, + If, + Else, + Block, +} + impl<const CHECK_TYPES: bool> Runtime<CHECK_TYPES> { - pub(crate) fn exec( - &self, - stack: &mut Stack, - instrs: core::slice::Iter<Instruction>, - ) -> Result<()> { + pub(crate) fn exec(&self, stack: &mut Stack, instrs: core::slice::Iter<Instruction>) -> Result<()> { let call_frame = stack.call_stack.top_mut()?; + let mut blocks = vec![BlockMarker::Top]; for instr in instrs { use tinywasm_types::Instruction::*; match instr { + End => { + let block = blocks.pop().ok_or(Error::BlockStackUnderflow)?; + + use BlockMarker::*; + match block { + Top => return Ok(()), + Block => todo!(), + Loop => todo!(), + If => todo!(), + Else => todo!(), + } + } LocalGet(local_index) => { let val = call_frame.get_local(*local_index as usize); debug!("local: {:#?}", val); @@ -52,10 +70,6 @@ impl<const CHECK_TYPES: bool> Runtime<CHECK_TYPES> { let b: i32 = b.into(); stack.values.push((a - b).into()); } - End => { - debug!("stack: {:?}", stack); - return Ok(()); - } _ => todo!(), } } diff --git a/crates/tinywasm/src/runtime/mod.rs b/crates/tinywasm/src/runtime/mod.rs index ed5701c..f0b6d66 100644 --- a/crates/tinywasm/src/runtime/mod.rs +++ b/crates/tinywasm/src/runtime/mod.rs @@ -3,7 +3,7 @@ mod stack; mod value; pub use stack::*; -pub use value::UntypedWasmValue; +pub(crate) use value::RawWasmValue; /// A WebAssembly Runtime. /// See https://webassembly.github.io/spec/core/exec/runtime.html diff --git a/crates/tinywasm/src/runtime/stack/call_stack.rs b/crates/tinywasm/src/runtime/stack/call_stack.rs index eb5256e..dd721a6 100644 --- a/crates/tinywasm/src/runtime/stack/call_stack.rs +++ b/crates/tinywasm/src/runtime/stack/call_stack.rs @@ -1,4 +1,4 @@ -use crate::{runtime::UntypedWasmValue, Error, Result}; +use crate::{runtime::RawWasmValue, Error, Result}; use alloc::{boxed::Box, vec::Vec}; use tinywasm_types::{ValType, WasmValue}; @@ -51,14 +51,14 @@ pub struct CallFrame<const CHECK: bool> { pub instr_ptr: usize, pub func_ptr: usize, - pub locals: Box<[UntypedWasmValue]>, + pub locals: Box<[RawWasmValue]>, pub local_count: usize, } impl<const CHECK: bool> CallFrame<CHECK> { pub fn new(func_ptr: usize, params: &[WasmValue], local_types: Vec<ValType>) -> Self { let mut locals = Vec::with_capacity(local_types.len() + params.len()); - locals.extend(params.iter().map(|v| UntypedWasmValue::from(*v))); + locals.extend(params.iter().map(|v| RawWasmValue::from(*v))); Self { instr_ptr: 0, @@ -69,7 +69,7 @@ impl<const CHECK: bool> CallFrame<CHECK> { } #[inline] - pub(crate) fn set_local(&mut self, local_index: usize, value: UntypedWasmValue) { + pub(crate) fn set_local(&mut self, local_index: usize, value: RawWasmValue) { if local_index >= self.local_count { panic!("Invalid local index"); } @@ -78,7 +78,7 @@ impl<const CHECK: bool> CallFrame<CHECK> { } #[inline] - pub(crate) fn get_local(&self, local_index: usize) -> UntypedWasmValue { + pub(crate) fn get_local(&self, local_index: usize) -> RawWasmValue { if local_index >= self.local_count { panic!("Invalid local index"); } diff --git a/crates/tinywasm/src/runtime/stack/value_stack.rs b/crates/tinywasm/src/runtime/stack/value_stack.rs index 83f54c9..8281e92 100644 --- a/crates/tinywasm/src/runtime/stack/value_stack.rs +++ b/crates/tinywasm/src/runtime/stack/value_stack.rs @@ -1,4 +1,4 @@ -use crate::{runtime::UntypedWasmValue, Error, Result}; +use crate::{runtime::RawWasmValue, Error, Result}; use alloc::vec::Vec; // minimum stack size @@ -6,7 +6,7 @@ pub const STACK_SIZE: usize = 1024; #[derive(Debug)] pub struct ValueStack { - stack: Vec<UntypedWasmValue>, + stack: Vec<RawWasmValue>, top: usize, } @@ -21,28 +21,25 @@ impl Default for ValueStack { impl ValueStack { #[inline] - pub(crate) fn _extend( - &mut self, - values: impl IntoIterator<Item = UntypedWasmValue> + ExactSizeIterator, - ) { + pub(crate) fn _extend(&mut self, values: impl IntoIterator<Item = RawWasmValue> + ExactSizeIterator) { self.top += values.len(); self.stack.extend(values); } #[inline] - pub(crate) fn push(&mut self, value: UntypedWasmValue) { + pub(crate) fn push(&mut self, value: RawWasmValue) { self.top += 1; self.stack.push(value); } #[inline] - pub(crate) fn pop(&mut self) -> Option<UntypedWasmValue> { + pub(crate) fn pop(&mut self) -> Option<RawWasmValue> { self.top -= 1; self.stack.pop() } #[inline] - pub(crate) fn pop_n(&mut self, n: usize) -> Result<Vec<UntypedWasmValue>> { + pub(crate) fn pop_n(&mut self, n: usize) -> Result<Vec<RawWasmValue>> { if self.top < n { return Err(Error::StackUnderflow); } @@ -52,12 +49,12 @@ impl ValueStack { } #[inline] - pub(crate) fn pop_n_const<const N: usize>(&mut self) -> Result<[UntypedWasmValue; N]> { + pub(crate) fn pop_n_const<const N: usize>(&mut self) -> Result<[RawWasmValue; N]> { if self.top < N { return Err(Error::StackUnderflow); } self.top -= N; - let mut res = [UntypedWasmValue::default(); N]; + let mut res = [RawWasmValue::default(); N]; for i in res.iter_mut().rev() { *i = self.stack.pop().ok_or(Error::InvalidStore)?; } diff --git a/crates/tinywasm/src/runtime/value.rs b/crates/tinywasm/src/runtime/value.rs index dcab276..534d245 100644 --- a/crates/tinywasm/src/runtime/value.rs +++ b/crates/tinywasm/src/runtime/value.rs @@ -1,10 +1,13 @@ use tinywasm_types::{ValType, WasmValue}; +/// A raw wasm value. +/// This is the internal representation of all wasm values +/// See [`WasmValue`] for the public representation. #[derive(Debug, Clone, Copy, Default)] -pub struct UntypedWasmValue(u64); +pub struct RawWasmValue(u64); -impl UntypedWasmValue { - pub fn into_typed(self, ty: ValType) -> WasmValue { +impl RawWasmValue { + pub fn attach_type(self, ty: ValType) -> WasmValue { match ty { ValType::I32 => WasmValue::I32(self.0 as i32), ValType::I64 => WasmValue::I64(self.0 as i64), @@ -17,55 +20,7 @@ impl UntypedWasmValue { } } -impl From<i32> for UntypedWasmValue { - fn from(i: i32) -> Self { - Self(i as u64) - } -} - -impl From<UntypedWasmValue> for i32 { - fn from(v: UntypedWasmValue) -> Self { - v.0 as i32 - } -} - -impl From<i64> for UntypedWasmValue { - fn from(i: i64) -> Self { - Self(i as u64) - } -} - -impl From<UntypedWasmValue> for i64 { - fn from(v: UntypedWasmValue) -> Self { - v.0 as i64 - } -} - -impl From<f32> for UntypedWasmValue { - fn from(i: f32) -> Self { - Self(i.to_bits() as u64) - } -} - -impl From<UntypedWasmValue> for f32 { - fn from(v: UntypedWasmValue) -> Self { - f32::from_bits(v.0 as u32) - } -} - -impl From<f64> for UntypedWasmValue { - fn from(i: f64) -> Self { - Self(i.to_bits()) - } -} - -impl From<UntypedWasmValue> for f64 { - fn from(v: UntypedWasmValue) -> Self { - f64::from_bits(v.0) - } -} - -impl From<WasmValue> for UntypedWasmValue { +impl From<WasmValue> for RawWasmValue { fn from(v: WasmValue) -> Self { match v { WasmValue::I32(i) => Self(i as u64), @@ -75,3 +30,28 @@ impl From<WasmValue> for UntypedWasmValue { } } } + +macro_rules! impl_from_raw_wasm_value { + ($type:ty, $to_raw:expr, $from_raw:expr) => { + // Implement From<$type> for RawWasmValue + impl From<$type> for RawWasmValue { + fn from(value: $type) -> Self { + #[allow(clippy::redundant_closure_call)] // the comiler will figure it out :) + Self($to_raw(value)) + } + } + + // Implement From<RawWasmValue> for $type + impl From<RawWasmValue> for $type { + fn from(value: RawWasmValue) -> Self { + #[allow(clippy::redundant_closure_call)] // the comiler will figure it out :) + $from_raw(value.0) + } + } + }; +} + +impl_from_raw_wasm_value!(i32, |x| x as u64, |x| x as i32); +impl_from_raw_wasm_value!(i64, |x| x as u64, |x| x as i64); +impl_from_raw_wasm_value!(f32, |x| f32::to_bits(x) as u64, |x| f32::from_bits(x as u32)); +impl_from_raw_wasm_value!(f64, f64::to_bits, f64::from_bits); diff --git a/crates/tinywasm/src/store.rs b/crates/tinywasm/src/store.rs index ec0d3b0..b12be95 100644 --- a/crates/tinywasm/src/store.rs +++ b/crates/tinywasm/src/store.rs @@ -97,11 +97,7 @@ impl Store { Ok(()) } - pub(crate) fn add_funcs( - &mut self, - funcs: Vec<Function>, - idx: ModuleInstanceAddr, - ) -> Vec<FuncAddr> { + pub(crate) fn add_funcs(&mut self, funcs: Vec<Function>, idx: ModuleInstanceAddr) -> Vec<FuncAddr> { let mut func_addrs = Vec::with_capacity(funcs.len()); for func in funcs.into_iter() { self.data.funcs.push(FunctionInstance { diff --git a/crates/types/src/instructions.rs b/crates/types/src/instructions.rs index 13f8ce0..40bb9f4 100644 --- a/crates/types/src/instructions.rs +++ b/crates/types/src/instructions.rs @@ -4,8 +4,7 @@ use super::{FuncAddr, GlobalAddr, LabelAddr, LocalAddr, TableAddr, TypeAddr, Val pub enum BlockArgs { Empty, Type(ValType), - // TODO: wasm 2.0 - // FuncType(u32), + FuncType(u32), } /// Represents a memory immediate in a WebAssembly memory instruction. @@ -22,6 +21,9 @@ pub struct MemArg { /// For example, `br_table` stores the jump lables in the following `br_label` instructions to keep this enum small. #[derive(Debug, Clone, Copy, PartialEq)] pub enum Instruction { + // Custom Instructions + BrLabel(LabelAddr), + // Control Instructions // See https://webassembly.github.io/spec/core/binary/instructions.html#control-instructions Unreachable, @@ -33,8 +35,7 @@ pub enum Instruction { End, Br(LabelAddr), BrIf(LabelAddr), - BrTable(u32), // has to be followed by multiple BrLabel instructions - BrLabel(LabelAddr), + BrTable(u32, u32), // has to be followed by multiple BrLabel instructions Return, Call(FuncAddr), CallIndirect(TypeAddr, TableAddr), diff --git a/rustfmt.toml b/rustfmt.toml new file mode 100644 index 0000000..94ac875 --- /dev/null +++ b/rustfmt.toml @@ -0,0 +1 @@ +max_width=120 |
