From 062515c39154b29bb0406b207e3c67bae399a449 Mon Sep 17 00:00:00 2001 From: Henry Gressmann Date: Sun, 25 Feb 2024 17:51:41 +0100 Subject: feat: new parser architecture Signed-off-by: Henry Gressmann --- crates/parser/src/conversion.rs | 336 +--------------------------------------- 1 file changed, 8 insertions(+), 328 deletions(-) (limited to 'crates/parser/src/conversion.rs') diff --git a/crates/parser/src/conversion.rs b/crates/parser/src/conversion.rs index f81b9e7..03b5f82 100644 --- a/crates/parser/src/conversion.rs +++ b/crates/parser/src/conversion.rs @@ -1,10 +1,9 @@ -use crate::log; +use crate::visit::process_operators; +use crate::Result; use alloc::{boxed::Box, format, string::ToString, vec::Vec}; use tinywasm_types::*; use wasmparser::{FuncValidator, OperatorsReader, ValidatorResources}; -use crate::{module::CodeSection, Result}; - pub(crate) fn convert_module_elements<'a, T: IntoIterator>>>( elements: T, ) -> Result> { @@ -160,12 +159,12 @@ pub(crate) fn convert_module_export(export: wasmparser::Export<'_>) -> Result, mut validator: FuncValidator, -) -> Result { +) -> Result<(Box<[Instruction]>, Box<[ValType]>)> { let locals_reader = func.get_locals_reader()?; let count = locals_reader.get_count(); let pos = locals_reader.original_position(); - let mut locals = Vec::with_capacity(count as usize); + let mut locals = Vec::with_capacity(count as usize); for (i, local) in locals_reader.into_iter().enumerate() { let local = local?; validator.define_locals(pos + i, local.0, local.1)?; @@ -174,10 +173,9 @@ pub(crate) fn convert_module_code( } } - let body_reader = func.get_operators_reader()?; - let body = process_operators(body_reader, validator)?; - - Ok(CodeSection { locals: locals.into_boxed_slice(), body }) + let body = process_operators(&mut validator, &func)?; + let locals = locals.into_boxed_slice(); + Ok((body, locals)) } pub(crate) fn convert_module_type(ty: wasmparser::RecGroup) -> Result { @@ -254,328 +252,10 @@ pub(crate) fn process_const_operator(op: wasmparser::Operator<'_>) -> Result ValType { +pub(crate) fn convert_heaptype(heap: wasmparser::HeapType) -> ValType { match heap { wasmparser::HeapType::Func => ValType::RefFunc, wasmparser::HeapType::Extern => ValType::RefExtern, _ => unimplemented!("Unsupported heap type: {:?}", heap), } } - -pub(crate) fn process_operators( - ops: OperatorsReader<'_>, - mut validator: FuncValidator, -) -> Result> { - let mut instructions = Vec::with_capacity(1024); - let mut labels_ptrs = Vec::with_capacity(32); - // indexes into the instructions array - let mut offset = ops.original_position(); - - for op in ops { - let op = match op { - Ok(op) => op, - Err(e) => { - cold(); - log::error!("Error while processing operators: {:?}", e); - return Err(crate::ParseError::UnsupportedOperator("Error while processing operators".to_string())); - } - }; - - match validator.op(offset, &op) { - Ok(_) => (), - Err(e) => { - cold(); - log::error!("Error while processing operators: {:?}", e); - return Err(crate::ParseError::UnsupportedOperator("Error while processing operators".to_string())); - } - } - offset += 1; - - use wasmparser::Operator::*; - let res = match op { - BrTable { targets } => { - let def = targets.default(); - - let instrs = targets - .targets() - .map(|t| t.map(Instruction::BrLabel)) - .collect::, wasmparser::BinaryReaderError>>()?; - - instructions.push(Instruction::BrTable(def, instrs.len())); - instructions.extend(instrs); - continue; - } - Unreachable => Instruction::Unreachable, - Nop => Instruction::Nop, - Block { blockty } => { - labels_ptrs.push(instructions.len()); - Instruction::Block(convert_blocktype(blockty), 0) - } - Loop { blockty } => { - labels_ptrs.push(instructions.len()); - Instruction::Loop(convert_blocktype(blockty), 0) - } - If { blockty } => { - labels_ptrs.push(instructions.len()); - Instruction::If(convert_blocktype(blockty), None, 0) - } - Else => { - labels_ptrs.push(instructions.len()); - Instruction::Else(0) - } - End => { - if let Some(label_pointer) = labels_ptrs.pop() { - let current_instr_ptr = instructions.len(); - - // last_label_pointer is Some if we're ending a block - match instructions[label_pointer] { - Instruction::Else(ref mut else_instr_end_offset) => { - *else_instr_end_offset = current_instr_ptr - label_pointer; - - // since we're ending an else block, we need to end the if block as well - let if_label_pointer = labels_ptrs.pop().ok_or(crate::ParseError::UnsupportedOperator( - "Expected to end an if block, but the last label was not an if".to_string(), - ))?; - - let if_instruction = &mut instructions[if_label_pointer]; - let Instruction::If(_, ref mut else_offset, ref mut end_offset) = if_instruction else { - return Err(crate::ParseError::UnsupportedOperator( - "Expected to end an if block, but the last label was not an if".to_string(), - )); - }; - - *else_offset = Some(label_pointer - if_label_pointer); - *end_offset = current_instr_ptr - if_label_pointer; - } - Instruction::Block(_, ref mut end_offset) - | Instruction::Loop(_, ref mut end_offset) - | Instruction::If(_, _, ref mut end_offset) => { - *end_offset = current_instr_ptr - label_pointer; - } - _ => { - return Err(crate::ParseError::UnsupportedOperator( - "Expected to end a block, but the last label was not a block".to_string(), - )) - } - } - - Instruction::EndBlockFrame - } else { - // last_label_pointer is None if we're ending the function - Instruction::EndFunc - } - } - - 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(None), - TypedSelect { ty } => Instruction::Select(Some(convert_valtype(&ty))), - 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 { mem, mem_byte } => Instruction::MemorySize(mem, mem_byte), - MemoryGrow { mem, mem_byte } => Instruction::MemoryGrow(mem, mem_byte), - - MemoryCopy { dst_mem, src_mem } => Instruction::MemoryCopy(src_mem, dst_mem), - MemoryFill { mem } => Instruction::MemoryFill(mem), - MemoryInit { data_index, mem } => Instruction::MemoryInit(data_index, mem), - DataDrop { data_index } => Instruction::DataDrop(data_index), - - I32Const { value } => Instruction::I32Const(value), - I64Const { value } => Instruction::I64Const(value), - F32Const { value } => Instruction::F32Const(f32::from_bits(value.bits())), - F64Const { value } => Instruction::F64Const(f64::from_bits(value.bits())), - RefNull { hty } => Instruction::RefNull(convert_heaptype(hty)), - RefIsNull => Instruction::RefIsNull, - RefFunc { function_index } => Instruction::RefFunc(function_index), - 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, - I64Extend8S => Instruction::I64Extend8S, - I64Extend16S => Instruction::I64Extend16S, - I64Extend32S => Instruction::I64Extend32S, - I64ExtendI32S => Instruction::I64ExtendI32S, - I64ExtendI32U => Instruction::I64ExtendI32U, - I32Extend8S => Instruction::I32Extend8S, - I32Extend16S => Instruction::I32Extend16S, - 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, - I32TruncSatF32S => Instruction::I32TruncSatF32S, - I32TruncSatF32U => Instruction::I32TruncSatF32U, - I32TruncSatF64S => Instruction::I32TruncSatF64S, - I32TruncSatF64U => Instruction::I32TruncSatF64U, - I64TruncSatF32S => Instruction::I64TruncSatF32S, - I64TruncSatF32U => Instruction::I64TruncSatF32U, - I64TruncSatF64S => Instruction::I64TruncSatF64S, - I64TruncSatF64U => Instruction::I64TruncSatF64U, - TableGet { table } => Instruction::TableGet(table), - TableSet { table } => Instruction::TableSet(table), - TableInit { table, elem_index } => Instruction::TableInit(table, elem_index), - TableCopy { src_table, dst_table } => Instruction::TableCopy { from: src_table, to: dst_table }, - TableGrow { table } => Instruction::TableGrow(table), - TableSize { table } => Instruction::TableSize(table), - TableFill { table } => Instruction::TableFill(table), - op => { - cold(); - log::error!("Unsupported instruction: {:?}", op); - return Err(crate::ParseError::UnsupportedOperator(format!("Unsupported instruction: {:?}", op))); - } - }; - instructions.push(res); - } - - if !labels_ptrs.is_empty() { - panic!("last_label_pointer should be None after processing all instructions: {:?}", labels_ptrs); - } - - validator.finish(offset)?; - Ok(instructions.into_boxed_slice()) -} - -#[cold] -fn cold() {} -- cgit v1.3.1