summaryrefslogtreecommitdiff
path: root/crates/parser
diff options
context:
space:
mode:
Diffstat (limited to 'crates/parser')
-rw-r--r--crates/parser/src/conversion.rs18
-rw-r--r--crates/parser/src/lib.rs2
-rw-r--r--crates/parser/src/module.rs22
-rw-r--r--crates/parser/src/visit.rs33
4 files changed, 58 insertions, 17 deletions
diff --git a/crates/parser/src/conversion.rs b/crates/parser/src/conversion.rs
index 214487f..c733dcc 100644
--- a/crates/parser/src/conversion.rs
+++ b/crates/parser/src/conversion.rs
@@ -176,7 +176,7 @@ pub(crate) fn convert_module_code(
// maps a local's address to the index in the type's locals array
let mut local_addr_map = Vec::with_capacity(count as usize);
- let mut local_counts = LocalCounts::default();
+ let mut local_counts = ValueCounts::default();
for (i, local) in locals_reader.into_iter().enumerate() {
let local = local?;
@@ -186,20 +186,20 @@ pub(crate) fn convert_module_code(
for i in 0..validator.len_locals() {
match validator.get_local_type(i) {
Some(wasmparser::ValType::I32) | Some(wasmparser::ValType::F32) => {
- local_addr_map.push(local_counts.local_32);
- local_counts.local_32 += 1;
+ local_addr_map.push(local_counts.c32);
+ local_counts.c32 += 1;
}
Some(wasmparser::ValType::I64) | Some(wasmparser::ValType::F64) => {
- local_addr_map.push(local_counts.local_64);
- local_counts.local_64 += 1;
+ local_addr_map.push(local_counts.c64);
+ local_counts.c64 += 1;
}
Some(wasmparser::ValType::V128) => {
- local_addr_map.push(local_counts.local_128);
- local_counts.local_128 += 1;
+ local_addr_map.push(local_counts.c128);
+ local_counts.c128 += 1;
}
Some(wasmparser::ValType::Ref(_)) => {
- local_addr_map.push(local_counts.local_ref);
- local_counts.local_ref += 1;
+ local_addr_map.push(local_counts.cref);
+ local_counts.cref += 1;
}
None => return Err(crate::ParseError::UnsupportedOperator("Unknown local type".to_string())),
}
diff --git a/crates/parser/src/lib.rs b/crates/parser/src/lib.rs
index 77349b2..40f5fe2 100644
--- a/crates/parser/src/lib.rs
+++ b/crates/parser/src/lib.rs
@@ -59,6 +59,7 @@ impl Parser {
sign_extension: true,
saturating_float_to_int: true,
function_references: true,
+ tail_call: true,
component_model: false,
component_model_nested_names: false,
@@ -71,7 +72,6 @@ impl Parser {
memory_control: false,
relaxed_simd: false,
simd: false,
- tail_call: false,
threads: false,
multi_memory: false, // should be working mostly
custom_page_sizes: false,
diff --git a/crates/parser/src/module.rs b/crates/parser/src/module.rs
index 3ee619f..74da1d9 100644
--- a/crates/parser/src/module.rs
+++ b/crates/parser/src/module.rs
@@ -3,12 +3,12 @@ use crate::{conversion, ParseError, Result};
use alloc::string::ToString;
use alloc::{boxed::Box, format, vec::Vec};
use tinywasm_types::{
- Data, Element, Export, FuncType, Global, Import, Instruction, LocalCounts, MemoryType, TableType, TinyWasmModule,
- WasmFunction,
+ Data, Element, Export, FuncType, Global, Import, Instruction, MemoryType, TableType, TinyWasmModule, ValType,
+ ValueCounts, ValueCountsSmall, WasmFunction,
};
use wasmparser::{FuncValidatorAllocations, Payload, Validator};
-pub(crate) type Code = (Box<[Instruction]>, LocalCounts);
+pub(crate) type Code = (Box<[Instruction]>, ValueCounts);
#[derive(Default)]
pub(crate) struct ModuleReader {
@@ -193,10 +193,18 @@ impl ModuleReader {
.code
.into_iter()
.zip(self.code_type_addrs)
- .map(|((instructions, locals), ty_idx)| WasmFunction {
- instructions,
- locals,
- ty: self.func_types.get(ty_idx as usize).expect("No func type for func, this is a bug").clone(),
+ .map(|((instructions, locals), ty_idx)| {
+ let mut params = ValueCountsSmall::default();
+ let ty = self.func_types.get(ty_idx as usize).expect("No func type for func, this is a bug").clone();
+ for param in ty.params.iter() {
+ match param {
+ ValType::I32 | ValType::F32 => params.c32 += 1,
+ ValType::I64 | ValType::F64 => params.c64 += 1,
+ ValType::V128 => params.c128 += 1,
+ ValType::RefExtern | ValType::RefFunc => params.cref += 1,
+ }
+ }
+ WasmFunction { instructions, params, locals, ty }
})
.collect::<Vec<_>>()
.into_boxed_slice();
diff --git a/crates/parser/src/visit.rs b/crates/parser/src/visit.rs
index e9844aa..1f282f7 100644
--- a/crates/parser/src/visit.rs
+++ b/crates/parser/src/visit.rs
@@ -122,6 +122,7 @@ macro_rules! impl_visit_operator {
(@@sign_extension $($rest:tt)* ) => {};
(@@saturating_float_to_int $($rest:tt)* ) => {};
(@@bulk_memory $($rest:tt)* ) => {};
+ (@@tail_call $($rest:tt)* ) => {};
(@@$proposal:ident $op:ident $({ $($arg:ident: $argty:ty),* })? => $visit:ident) => {
#[cold]
fn $visit(&mut self $($(,$arg: $argty)*)?) {
@@ -317,6 +318,14 @@ impl<'a, R: WasmModuleResources> wasmparser::VisitOperator<'a> for FunctionBuild
visit_i64_trunc_sat_f64_u, Instruction::I64TruncSatF64U
}
+ fn visit_return_call(&mut self, function_index: u32) -> Self::Output {
+ self.instructions.push(Instruction::ReturnCall(function_index));
+ }
+
+ fn visit_return_call_indirect(&mut self, type_index: u32, table_index: u32) -> Self::Output {
+ self.instructions.push(Instruction::ReturnCallIndirect(type_index, table_index));
+ }
+
fn visit_global_set(&mut self, global_index: u32) -> Self::Output {
match self.validator.get_operand_type(0) {
Some(Some(t)) => self.instructions.push(match t {
@@ -385,6 +394,30 @@ impl<'a, R: WasmModuleResources> wasmparser::VisitOperator<'a> for FunctionBuild
return;
};
+ match self.instructions.last() {
+ Some(Instruction::LocalGet32(from))
+ | Some(Instruction::LocalGet64(from))
+ | Some(Instruction::LocalGet128(from))
+ | Some(Instruction::LocalGetRef(from)) => {
+ let from = *from;
+ self.instructions.pop();
+ // validation will ensure that the last instruction is the correct local.get
+ match self.validator.get_operand_type(0) {
+ Some(Some(t)) => self.instructions.push(match t {
+ wasmparser::ValType::I32 => Instruction::LocalCopy32(from, resolved_idx),
+ wasmparser::ValType::F32 => Instruction::LocalCopy32(from, resolved_idx),
+ wasmparser::ValType::I64 => Instruction::LocalCopy64(from, resolved_idx),
+ wasmparser::ValType::F64 => Instruction::LocalCopy64(from, resolved_idx),
+ wasmparser::ValType::V128 => Instruction::LocalCopy128(from, resolved_idx),
+ wasmparser::ValType::Ref(_) => Instruction::LocalCopyRef(from, resolved_idx),
+ }),
+ _ => self.visit_unreachable(),
+ }
+ return;
+ }
+ _ => {}
+ }
+
match self.validator.get_operand_type(0) {
Some(Some(t)) => self.instructions.push(match t {
wasmparser::ValType::I32 => Instruction::LocalSet32(resolved_idx),