Skip to content

Commit 43e6d23

Browse files
chore: improve new parser arch
Signed-off-by: Henry Gressmann <[email protected]>
1 parent 062515c commit 43e6d23

File tree

5 files changed

+37
-24
lines changed

5 files changed

+37
-24
lines changed

Cargo.lock

+2-2
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

crates/parser/src/conversion.rs

+3-3
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
1-
use crate::visit::process_operators;
21
use crate::Result;
2+
use crate::{module::Code, visit::process_operators};
33
use alloc::{boxed::Box, format, string::ToString, vec::Vec};
44
use tinywasm_types::*;
55
use wasmparser::{FuncValidator, OperatorsReader, ValidatorResources};
@@ -159,7 +159,7 @@ pub(crate) fn convert_module_export(export: wasmparser::Export<'_>) -> Result<Ex
159159
pub(crate) fn convert_module_code(
160160
func: wasmparser::FunctionBody<'_>,
161161
mut validator: FuncValidator<ValidatorResources>,
162-
) -> Result<(Box<[Instruction]>, Box<[ValType]>)> {
162+
) -> Result<Code> {
163163
let locals_reader = func.get_locals_reader()?;
164164
let count = locals_reader.get_count();
165165
let pos = locals_reader.original_position();
@@ -173,7 +173,7 @@ pub(crate) fn convert_module_code(
173173
}
174174
}
175175

176-
let body = process_operators(&mut validator, &func)?;
176+
let body = process_operators(Some(&mut validator), &func)?;
177177
let locals = locals.into_boxed_slice();
178178
Ok((body, locals))
179179
}

crates/parser/src/lib.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -52,13 +52,13 @@ impl Parser {
5252
let features = WasmFeatures {
5353
bulk_memory: true,
5454
floats: true,
55-
function_references: true,
5655
multi_value: true,
5756
mutable_global: true,
5857
reference_types: true,
5958
sign_extension: true,
6059
saturating_float_to_int: true,
6160

61+
function_references: false,
6262
component_model: false,
6363
component_model_nested_names: false,
6464
component_model_values: false,

crates/parser/src/module.rs

+3-1
Original file line numberDiff line numberDiff line change
@@ -4,14 +4,16 @@ use alloc::{boxed::Box, format, vec::Vec};
44
use tinywasm_types::{Data, Element, Export, FuncType, Global, Import, Instruction, MemoryType, TableType, ValType};
55
use wasmparser::{Payload, Validator};
66

7+
pub(crate) type Code = (Box<[Instruction]>, Box<[ValType]>);
8+
79
#[derive(Default)]
810
pub(crate) struct ModuleReader {
911
pub(crate) version: Option<u16>,
1012
pub(crate) start_func: Option<u32>,
1113
pub(crate) func_types: Vec<FuncType>,
1214
pub(crate) code_type_addrs: Vec<u32>,
1315
pub(crate) exports: Vec<Export>,
14-
pub(crate) code: Vec<(Box<[Instruction]>, Box<[ValType]>)>,
16+
pub(crate) code: Vec<Code>,
1517
pub(crate) globals: Vec<Global>,
1618
pub(crate) table_types: Vec<TableType>,
1719
pub(crate) memory_types: Vec<MemoryType>,

crates/parser/src/visit.rs

+28-17
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ struct ValidateThenVisit<'a, T, U>(T, &'a mut U);
1010
macro_rules! validate_then_visit {
1111
($( @$proposal:ident $op:ident $({ $($arg:ident: $argty:ty),* })? => $visit:ident)*) => {
1212
$(
13+
#[inline]
1314
fn $visit(&mut self $($(,$arg: $argty)*)?) -> Self::Output {
1415
self.0.$visit($($($arg.clone()),*)?)?;
1516
Ok(self.1.$visit($($($arg),*)?))
@@ -24,23 +25,29 @@ where
2425
U: VisitOperator<'a>,
2526
{
2627
type Output = Result<U::Output>;
27-
2828
wasmparser::for_each_operator!(validate_then_visit);
2929
}
3030

3131
pub(crate) fn process_operators<R: WasmModuleResources>(
32-
validator: &mut FuncValidator<R>,
32+
validator: Option<&mut FuncValidator<R>>,
3333
body: &FunctionBody<'_>,
3434
) -> Result<Box<[Instruction]>> {
3535
let mut reader = body.get_operators_reader()?;
36-
let mut builder = FunctionBuilder::new(1024);
36+
let remaining = reader.get_binary_reader().bytes_remaining();
37+
let mut builder = FunctionBuilder::new(remaining);
3738

38-
while !reader.eof() {
39-
let validate = validator.visitor(reader.original_position());
40-
reader.visit_operator(&mut ValidateThenVisit(validate, &mut builder))???;
39+
if let Some(validator) = validator {
40+
while !reader.eof() {
41+
let validate = validator.visitor(reader.original_position());
42+
reader.visit_operator(&mut ValidateThenVisit(validate, &mut builder))???;
43+
}
44+
validator.finish(reader.original_position())?;
45+
} else {
46+
while !reader.eof() {
47+
reader.visit_operator(&mut builder)??;
48+
}
4149
}
4250

43-
validator.finish(reader.original_position())?;
4451
Ok(builder.instructions.into_boxed_slice())
4552
}
4653

@@ -114,7 +121,7 @@ pub(crate) struct FunctionBuilder {
114121

115122
impl FunctionBuilder {
116123
pub(crate) fn new(instr_capacity: usize) -> Self {
117-
Self { instructions: Vec::with_capacity(instr_capacity), label_ptrs: Vec::with_capacity(64) }
124+
Self { instructions: Vec::with_capacity(instr_capacity), label_ptrs: Vec::with_capacity(128) }
118125
}
119126

120127
#[cold]
@@ -124,7 +131,8 @@ impl FunctionBuilder {
124131

125132
#[inline]
126133
fn visit(&mut self, op: Instruction) -> Result<()> {
127-
Ok(self.instructions.push(op))
134+
self.instructions.push(op);
135+
Ok(())
128136
}
129137
}
130138

@@ -337,6 +345,7 @@ impl<'a> wasmparser::VisitOperator<'a> for FunctionBuilder {
337345
self.visit(Instruction::Else(0))
338346
}
339347

348+
#[inline]
340349
fn visit_end(&mut self) -> Self::Output {
341350
let Some(label_pointer) = self.label_ptrs.pop() else {
342351
return self.visit(Instruction::EndFunc);
@@ -348,16 +357,19 @@ impl<'a> wasmparser::VisitOperator<'a> for FunctionBuilder {
348357
Instruction::Else(ref mut else_instr_end_offset) => {
349358
*else_instr_end_offset = current_instr_ptr - label_pointer;
350359

360+
#[cold]
361+
fn error() -> crate::ParseError {
362+
crate::ParseError::UnsupportedOperator(
363+
"Expected to end an if block, but the last label was not an if".to_string(),
364+
)
365+
}
366+
351367
// since we're ending an else block, we need to end the if block as well
352-
let if_label_pointer = self.label_ptrs.pop().ok_or(crate::ParseError::UnsupportedOperator(
353-
"Expected to end an if block, but the last label was not an if".to_string(),
354-
))?;
368+
let if_label_pointer = self.label_ptrs.pop().ok_or_else(error)?;
355369

356370
let if_instruction = &mut self.instructions[if_label_pointer];
357371
let Instruction::If(_, ref mut else_offset, ref mut end_offset) = if_instruction else {
358-
return Err(crate::ParseError::UnsupportedOperator(
359-
"Expected to end an if block, but the last label was not an if".to_string(),
360-
));
372+
return Err(error());
361373
};
362374

363375
*else_offset = Some(label_pointer - if_label_pointer);
@@ -386,8 +398,7 @@ impl<'a> wasmparser::VisitOperator<'a> for FunctionBuilder {
386398
.collect::<Result<Vec<Instruction>, wasmparser::BinaryReaderError>>()
387399
.expect("BrTable targets are invalid, this should have been caught by the validator");
388400

389-
self.instructions
390-
.extend(IntoIterator::into_iter([Instruction::BrTable(def, instrs.len())]).chain(instrs.into_iter()));
401+
self.instructions.extend(IntoIterator::into_iter([Instruction::BrTable(def, instrs.len())]).chain(instrs));
391402
Ok(())
392403
}
393404

0 commit comments

Comments
 (0)