summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorHenry Gressmann <mail@henrygressmann.de>2025-03-01 19:49:41 +0100
committerHenry Gressmann <mail@henrygressmann.de>2025-03-01 19:49:41 +0100
commitafc76e44457975e3d20b3a490c5029dec6f4983a (patch)
tree9a16dd224ac3278f1f291fcad3675223c096071c
parent741a3d6e94970f097d0cd19cbe9f9a7266b67fb4 (diff)
feat: add most basic simd instructions
Signed-off-by: Henry Gressmann <mail@henrygressmann.de>
-rw-r--r--crates/cli/src/args.rs2
-rw-r--r--crates/parser/src/conversion.rs1
-rw-r--r--crates/parser/src/visit.rs10
-rw-r--r--crates/tinywasm/src/interpreter/executor.rs162
-rw-r--r--crates/tinywasm/src/interpreter/mod.rs3
-rw-r--r--crates/tinywasm/src/interpreter/simd.rs3
-rw-r--r--crates/tinywasm/src/interpreter/stack/call_stack.rs7
-rw-r--r--crates/tinywasm/src/interpreter/stack/value_stack.rs2
-rw-r--r--crates/tinywasm/src/interpreter/values.rs29
-rw-r--r--crates/tinywasm/src/store/memory.rs45
-rw-r--r--crates/tinywasm/tests/generated/wasm-simd.csv2
-rw-r--r--crates/tinywasm/tests/testsuite/util.rs28
-rw-r--r--crates/types/src/instructions.rs1
-rw-r--r--crates/types/src/lib.rs2
-rw-r--r--crates/types/src/value.rs8
15 files changed, 244 insertions, 61 deletions
diff --git a/crates/cli/src/args.rs b/crates/cli/src/args.rs
index a23f1f4..1fec2d5 100644
--- a/crates/cli/src/args.rs
+++ b/crates/cli/src/args.rs
@@ -25,7 +25,7 @@ impl FromStr for WasmArg {
"i64" => val.parse::<i64>().map_err(|e| format!("invalid argument value for i64: {e:?}"))?.into(),
"f32" => val.parse::<f32>().map_err(|e| format!("invalid argument value for f32: {e:?}"))?.into(),
"f64" => val.parse::<f64>().map_err(|e| format!("invalid argument value for f64: {e:?}"))?.into(),
- "v128" => val.parse::<u128>().map_err(|e| format!("invalid argument value for v128: {e:?}"))?.into(),
+ "v128" => val.parse::<i128>().map_err(|e| format!("invalid argument value for v128: {e:?}"))?.into(),
t => return Err(format!("Invalid arg type: {t}")),
};
diff --git a/crates/parser/src/conversion.rs b/crates/parser/src/conversion.rs
index 86548d6..a4e3b35 100644
--- a/crates/parser/src/conversion.rs
+++ b/crates/parser/src/conversion.rs
@@ -261,6 +261,7 @@ pub(crate) fn process_const_operators(ops: OperatorsReader<'_>) -> Result<ConstI
wasmparser::Operator::I64Const { value } => Ok(ConstInstruction::I64Const(*value)),
wasmparser::Operator::F32Const { value } => Ok(ConstInstruction::F32Const(f32::from_bits(value.bits()))),
wasmparser::Operator::F64Const { value } => Ok(ConstInstruction::F64Const(f64::from_bits(value.bits()))),
+ wasmparser::Operator::V128Const { value } => Ok(ConstInstruction::V128Const(value.i128())),
wasmparser::Operator::GlobalGet { global_index } => Ok(ConstInstruction::GlobalGet(*global_index)),
op => Err(crate::ParseError::UnsupportedOperator(format!("Unsupported const instruction: {op:?}"))),
}
diff --git a/crates/parser/src/visit.rs b/crates/parser/src/visit.rs
index 2830d3a..270f6c6 100644
--- a/crates/parser/src/visit.rs
+++ b/crates/parser/src/visit.rs
@@ -111,7 +111,7 @@ macro_rules! define_mem_operands_simd_lane {
pub(crate) struct FunctionBuilder<R: WasmModuleResources> {
validator: FuncValidator<R>,
instructions: Vec<Instruction>,
- v128_constants: Vec<u128>,
+ v128_constants: Vec<i128>,
label_ptrs: Vec<usize>,
local_addr_map: Vec<u32>,
errors: Vec<crate::ParseError>,
@@ -530,12 +530,12 @@ impl<R: WasmModuleResources> wasmparser::VisitSimdOperator<'_> for FunctionBuild
}
fn visit_i8x16_shuffle(&mut self, lanes: [u8; 16]) -> Self::Output {
- self.v128_constants.push(u128::from_le_bytes(lanes));
- self.instructions.push(Instruction::I8x16Shuffle(self.v128_constants.len() as u32 - 1));
+ self.instructions.push(Instruction::I8x16Shuffle(self.v128_constants.len() as u32));
+ self.v128_constants.push(i128::from_le_bytes(lanes));
}
fn visit_v128_const(&mut self, value: wasmparser::V128) -> Self::Output {
- self.v128_constants.push(value.i128() as u128);
- self.instructions.push(Instruction::V128Const(self.v128_constants.len() as u32 - 1));
+ self.instructions.push(Instruction::V128Const(self.v128_constants.len() as u32));
+ self.v128_constants.push(value.i128());
}
}
diff --git a/crates/tinywasm/src/interpreter/executor.rs b/crates/tinywasm/src/interpreter/executor.rs
index 100075b..932fad9 100644
--- a/crates/tinywasm/src/interpreter/executor.rs
+++ b/crates/tinywasm/src/interpreter/executor.rs
@@ -3,14 +3,21 @@
use super::no_std_floats::NoStdFloatExt;
use alloc::{format, rc::Rc, string::ToString};
-use core::ops::ControlFlow;
-use core::simd::cmp::{SimdPartialEq, SimdPartialOrd};
-use core::simd::num::SimdUint;
+use core::ops::{ControlFlow, IndexMut, Shl, Shr};
+
use interpreter::stack::CallFrame;
use tinywasm_types::*;
#[cfg(feature = "simd")]
-use super::simd::*;
+mod simd {
+ #[cfg(feature = "std")]
+ pub(super) use crate::std::simd::StdFloat;
+ pub(super) use core::simd::cmp::{SimdOrd, SimdPartialEq, SimdPartialOrd};
+ pub(super) use core::simd::num::{SimdFloat, SimdInt, SimdUint};
+ pub(super) use core::simd::*;
+}
+#[cfg(feature = "simd")]
+use simd::*;
use super::num_helpers::*;
use super::stack::{BlockFrame, BlockType, Stack};
@@ -315,8 +322,16 @@ impl<'store, 'stack> Executor<'store, 'stack> {
V128Or => self.stack.values.calculate_same::<Value128>(|a, b| Ok(a | b)).to_cf()?,
V128Xor => self.stack.values.calculate_same::<Value128>(|a, b| Ok(a ^ b)).to_cf()?,
V128Bitselect => self.stack.values.calculate_same_3::<Value128>(|v1, v2, c| Ok((v1 & c) | (v2 & !c))).to_cf()?,
- V128AnyTrue => self.stack.values.replace_top::<Value128, i32>(|v| Ok((v.reduce_sum() != 0) as i32)).to_cf()?,
+ V128AnyTrue => self.stack.values.replace_top::<Value128, i32>(|v| Ok((v.reduce_or() != 0) as i32)).to_cf()?,
I8x16Swizzle => self.stack.values.calculate_same::<Value128>(|a, s| Ok(a.swizzle_dyn(s))).to_cf()?,
+ V128Load(arg) => self.exec_mem_load::<Value128, 16, _>(arg.mem_addr(), arg.offset(), |v| v)?,
+ V128Store(arg) => self.exec_mem_store::<Value128, Value128, 16>(arg.mem_addr(), arg.offset(), |v| v)?,
+ V128Const(arg) => self.exec_const::<Value128>( self.cf.data().v128_constants[*arg as usize].to_le_bytes().into()),
+
+ V128Load8Lane(arg, lane) => self.exec_mem_load_lane::<i8, i8x16, 1>(arg.mem_addr(), arg.offset(), *lane)?,
+ V128Load16Lane(arg, lane) => self.exec_mem_load_lane::<i16, i16x8, 2>(arg.mem_addr(), arg.offset(), *lane)?,
+ V128Load32Lane(arg, lane) => self.exec_mem_load_lane::<i32, i32x4, 4>(arg.mem_addr(), arg.offset(), *lane)?,
+ V128Load64Lane(arg, lane) => self.exec_mem_load_lane::<i64, i64x2, 8>(arg.mem_addr(), arg.offset(), *lane)?,
I8x16Splat => self.stack.values.replace_top::<i32, i8x16>(|v| Ok(Simd::<i8, 16>::splat(v as i8))).to_cf()?,
I16x8Splat => self.stack.values.replace_top::<i32, i16x8>(|v| Ok(Simd::<i16, 8>::splat(v as i16))).to_cf()?,
@@ -373,6 +388,10 @@ impl<'store, 'stack> Executor<'store, 'stack> {
I16x8LeU => self.stack.values.calculate_same::<i16x8>(|a, b| Ok(a.simd_le(b).to_int())).to_cf()?,
I32x4LeU => self.stack.values.calculate_same::<i32x4>(|a, b| Ok(a.simd_le(b).to_int())).to_cf()?,
+ I8x16GeS => self.stack.values.calculate_same::<i8x16>(|a, b| Ok(a.simd_ge(b).to_int())).to_cf()?,
+ I16x8GeS => self.stack.values.calculate_same::<i16x8>(|a, b| Ok(a.simd_ge(b).to_int())).to_cf()?,
+ I32x4GeS => self.stack.values.calculate_same::<i32x4>(|a, b| Ok(a.simd_ge(b).to_int())).to_cf()?,
+
I8x16GeU => self.stack.values.calculate_same::<i8x16>(|a, b| Ok(a.simd_ge(b).to_int())).to_cf()?,
I16x8GeU => self.stack.values.calculate_same::<i16x8>(|a, b| Ok(a.simd_ge(b).to_int())).to_cf()?,
I32x4GeU => self.stack.values.calculate_same::<i32x4>(|a, b| Ok(a.simd_ge(b).to_int())).to_cf()?,
@@ -382,6 +401,98 @@ impl<'store, 'stack> Executor<'store, 'stack> {
I32x4Abs => self.stack.values.replace_top_same::<i32x4>(|a| Ok(a.abs())).to_cf()?,
I64x2Abs => self.stack.values.replace_top_same::<i64x2>(|a| Ok(a.abs())).to_cf()?,
+ I8x16Neg => self.stack.values.replace_top_same::<i8x16>(|a| Ok(-a)).to_cf()?,
+ I16x8Neg => self.stack.values.replace_top_same::<i16x8>(|a| Ok(-a)).to_cf()?,
+ I32x4Neg => self.stack.values.replace_top_same::<i32x4>(|a| Ok(-a)).to_cf()?,
+ I64x2Neg => self.stack.values.replace_top_same::<i64x2>(|a| Ok(-a)).to_cf()?,
+
+ I8x16AllTrue => self.stack.values.replace_top::<i8x16, i32>(|v| Ok((v != Simd::splat(0)) as i32)).to_cf()?,
+ I16x8AllTrue => self.stack.values.replace_top::<i16x8, i32>(|v| Ok((v != Simd::splat(0)) as i32)).to_cf()?,
+ I32x4AllTrue => self.stack.values.replace_top::<i32x4, i32>(|v| Ok((v != Simd::splat(0)) as i32)).to_cf()?,
+ I64x2AllTrue => self.stack.values.replace_top::<i64x2, i32>(|v| Ok((v != Simd::splat(0)) as i32)).to_cf()?,
+
+ I8x16Bitmask => self.stack.values.replace_top::<i8x16, i32>(|v| Ok(v.simd_lt(Simd::splat(0)).to_bitmask() as i32)).to_cf()?,
+ I16x8Bitmask => self.stack.values.replace_top::<i16x8, i32>(|v| Ok(v.simd_lt(Simd::splat(0)).to_bitmask() as i32)).to_cf()?,
+ I32x4Bitmask => self.stack.values.replace_top::<i32x4, i32>(|v| Ok(v.simd_lt(Simd::splat(0)).to_bitmask() as i32)).to_cf()?,
+ I64x2Bitmask => self.stack.values.replace_top::<i64x2, i32>(|v| Ok(v.simd_lt(Simd::splat(0)).to_bitmask() as i32)).to_cf()?,
+
+ I8x16Shl => self.stack.values.calculate_same::<i8x16>(|a, b| Ok(a.shl(b))).to_cf()?,
+ I16x8Shl => self.stack.values.calculate_same::<i16x8>(|a, b| Ok(a.shl(b))).to_cf()?,
+ I32x4Shl => self.stack.values.calculate_same::<i32x4>(|a, b| Ok(a.shl(b))).to_cf()?,
+ I64x2Shl => self.stack.values.calculate_same::<i64x2>(|a, b| Ok(a.shl(b))).to_cf()?,
+
+ I8x16ShrS => self.stack.values.calculate_same::<i8x16>(|a, b| Ok(a.shr(b))).to_cf()?,
+ I16x8ShrS => self.stack.values.calculate_same::<i16x8>(|a, b| Ok(a.shr(b))).to_cf()?,
+ I32x4ShrS => self.stack.values.calculate_same::<i32x4>(|a, b| Ok(a.shr(b))).to_cf()?,
+ I64x2ShrS => self.stack.values.calculate_same::<i64x2>(|a, b| Ok(a.shr(b))).to_cf()?,
+
+ I8x16ShrU => self.stack.values.calculate_same::<u8x16>(|a, b| Ok(a.shr(b))).to_cf()?,
+ I16x8ShrU => self.stack.values.calculate_same::<u16x8>(|a, b| Ok(a.shr(b))).to_cf()?,
+ I32x4ShrU => self.stack.values.calculate_same::<u32x4>(|a, b| Ok(a.shr(b))).to_cf()?,
+ I64x2ShrU => self.stack.values.calculate_same::<u64x2>(|a, b| Ok(a.shr(b))).to_cf()?,
+
+ I8x16Add => self.stack.values.calculate_same::<i8x16>(|a, b| Ok(a + b)).to_cf()?,
+ I16x8Add => self.stack.values.calculate_same::<i16x8>(|a, b| Ok(a + b)).to_cf()?,
+ I32x4Add => self.stack.values.calculate_same::<i32x4>(|a, b| Ok(a + b)).to_cf()?,
+ I64x2Add => self.stack.values.calculate_same::<i64x2>(|a, b| Ok(a + b)).to_cf()?,
+
+ I8x16Sub => self.stack.values.calculate_same::<i8x16>(|a, b| Ok(a - b)).to_cf()?,
+ I16x8Sub => self.stack.values.calculate_same::<i16x8>(|a, b| Ok(a - b)).to_cf()?,
+ I32x4Sub => self.stack.values.calculate_same::<i32x4>(|a, b| Ok(a - b)).to_cf()?,
+ I64x2Sub => self.stack.values.calculate_same::<i64x2>(|a, b| Ok(a - b)).to_cf()?,
+
+ I8x16MinS => self.stack.values.calculate_same::<i8x16>(|a, b| Ok(a.simd_min(b))).to_cf()?,
+ I16x8MinS => self.stack.values.calculate_same::<i16x8>(|a, b| Ok(a.simd_min(b))).to_cf()?,
+ I32x4MinS => self.stack.values.calculate_same::<i32x4>(|a, b| Ok(a.simd_min(b))).to_cf()?,
+
+ I8x16MinU => self.stack.values.calculate_same::<u8x16>(|a, b| Ok(a.simd_min(b))).to_cf()?,
+ I16x8MinU => self.stack.values.calculate_same::<u16x8>(|a, b| Ok(a.simd_min(b))).to_cf()?,
+ I32x4MinU => self.stack.values.calculate_same::<u32x4>(|a, b| Ok(a.simd_min(b))).to_cf()?,
+
+ I8x16MaxS => self.stack.values.calculate_same::<i8x16>(|a, b| Ok(a.simd_max(b))).to_cf()?,
+ I16x8MaxS => self.stack.values.calculate_same::<i16x8>(|a, b| Ok(a.simd_max(b))).to_cf()?,
+ I32x4MaxS => self.stack.values.calculate_same::<i32x4>(|a, b| Ok(a.simd_max(b))).to_cf()?,
+
+ I8x16MaxU => self.stack.values.calculate_same::<u8x16>(|a, b| Ok(a.simd_max(b))).to_cf()?,
+ I16x8MaxU => self.stack.values.calculate_same::<u16x8>(|a, b| Ok(a.simd_max(b))).to_cf()?,
+ I32x4MaxU => self.stack.values.calculate_same::<u32x4>(|a, b| Ok(a.simd_max(b))).to_cf()?,
+
+ I64x2Mul => self.stack.values.calculate_same::<i64x2>(|a, b| Ok(a * b)).to_cf()?,
+
+ I8x16AddSatS => self.stack.values.calculate_same::<i8x16>(|a, b| Ok(a.saturating_add(b))).to_cf()?,
+ I16x8AddSatS => self.stack.values.calculate_same::<i16x8>(|a, b| Ok(a.saturating_add(b))).to_cf()?,
+ I8x16AddSatU => self.stack.values.calculate_same::<u8x16>(|a, b| Ok(a.saturating_add(b))).to_cf()?,
+ I16x8AddSatU => self.stack.values.calculate_same::<u16x8>(|a, b| Ok(a.saturating_add(b))).to_cf()?,
+ I8x16SubSatS => self.stack.values.calculate_same::<i8x16>(|a, b| Ok(a.saturating_sub(b))).to_cf()?,
+ I16x8SubSatS => self.stack.values.calculate_same::<i16x8>(|a, b| Ok(a.saturating_sub(b))).to_cf()?,
+ I8x16SubSatU => self.stack.values.calculate_same::<u8x16>(|a, b| Ok(a.saturating_sub(b))).to_cf()?,
+ I16x8SubSatU => self.stack.values.calculate_same::<u16x8>(|a, b| Ok(a.saturating_sub(b))).to_cf()?,
+
+ F32x4Ceil => self.stack.values.replace_top_same::<f32x4>(|v| Ok(v.ceil())).to_cf()?,
+ F64x2Ceil => self.stack.values.replace_top_same::<f64x2>(|v| Ok(v.ceil())).to_cf()?,
+ F32x4Floor => self.stack.values.replace_top_same::<f32x4>(|v| Ok(v.floor())).to_cf()?,
+ F64x2Floor => self.stack.values.replace_top_same::<f64x2>(|v| Ok(v.floor())).to_cf()?,
+ F32x4Trunc => self.stack.values.replace_top_same::<f32x4>(|v| Ok(v.trunc())).to_cf()?,
+ F64x2Trunc => self.stack.values.replace_top_same::<f64x2>(|v| Ok(v.trunc())).to_cf()?,
+ F32x4Abs => self.stack.values.replace_top_same::<f32x4>(|v| Ok(v.abs())).to_cf()?,
+ F64x2Abs => self.stack.values.replace_top_same::<f64x2>(|v| Ok(v.abs())).to_cf()?,
+ F32x4Neg => self.stack.values.replace_top_same::<f32x4>(|v| Ok(-v)).to_cf()?,
+ F64x2Neg => self.stack.values.replace_top_same::<f64x2>(|v| Ok(-v)).to_cf()?,
+ F32x4Sqrt => self.stack.values.replace_top_same::<f32x4>(|v| Ok(v.sqrt())).to_cf()?,
+ F64x2Sqrt => self.stack.values.replace_top_same::<f64x2>(|v| Ok(v.sqrt())).to_cf()?,
+ F32x4Add => self.stack.values.calculate_same::<f32x4>(|a, b| Ok(a + b)).to_cf()?,
+ F64x2Add => self.stack.values.calculate_same::<f64x2>(|a, b| Ok(a + b)).to_cf()?,
+ F32x4Sub => self.stack.values.calculate_same::<f32x4>(|a, b| Ok(a - b)).to_cf()?,
+ F64x2Sub => self.stack.values.calculate_same::<f64x2>(|a, b| Ok(a - b)).to_cf()?,
+ F32x4Mul => self.stack.values.calculate_same::<f32x4>(|a, b| Ok(a * b)).to_cf()?,
+ F64x2Mul => self.stack.values.calculate_same::<f64x2>(|a, b| Ok(a * b)).to_cf()?,
+ F32x4Div => self.stack.values.calculate_same::<f32x4>(|a, b| Ok(a / b)).to_cf()?,
+ F64x2Div => self.stack.values.calculate_same::<f64x2>(|a, b| Ok(a / b)).to_cf()?,
+ F32x4Min => self.stack.values.calculate_same::<f32x4>(|a, b| Ok(a.simd_min(b))).to_cf()?,
+ F64x2Min => self.stack.values.calculate_same::<f64x2>(|a, b| Ok(a.simd_min(b))).to_cf()?,
+ F32x4Max => self.stack.values.calculate_same::<f32x4>(|a, b| Ok(a.simd_max(b))).to_cf()?,
+ F64x2Max => self.stack.values.calculate_same::<f64x2>(|a, b| Ok(a.simd_max(b))).to_cf()?,
+
i => return ControlFlow::Break(Some(Error::UnsupportedFeature(format!("unimplemented opcode: {i:?}")))),
};
@@ -689,6 +800,47 @@ impl<'store, 'stack> Executor<'store, 'stack> {
Ok(())
}
+ fn exec_mem_load_lane<
+ LOAD: MemLoadable<LOAD_SIZE>,
+ INTO: InternalValue + IndexMut<usize, Output = LOAD>,
+ const LOAD_SIZE: usize,
+ >(
+ &mut self,
+ mem_addr: tinywasm_types::MemAddr,
+ offset: u64,
+ lanes: u8,
+ ) -> ControlFlow<Option<Error>> {
+ let mem = self.store.get_mem(self.module.resolve_mem_addr(mem_addr));
+ let mut imm = self.stack.values.pop::<INTO>();
+ let val = self.stack.values.pop::<i32>() as u64;
+ let Some(Ok(addr)) = offset.checked_add(val).map(TryInto::try_into) else {
+ cold();
+ return ControlFlow::Break(Some(Error::Trap(Trap::MemoryOutOfBounds {
+ offset: val as usize,
+ len: LOAD_SIZE,
+ max: 0,
+ })));
+ };
+ let val = mem.load_as::<LOAD_SIZE, LOAD>(addr).to_cf()?;
+ imm[lanes as usize] = val;
+ self.stack.values.push(imm);
+ ControlFlow::Continue(())
+ }
+
+ // fn mem_load<LOAD: MemLoadable<LOAD_SIZE>, const LOAD_SIZE: usize, TARGET: InternalValue>(
+ // &mut self,
+ // mem_addr: tinywasm_types::MemAddr,
+ // offset: u64,
+ // ) -> Result<LOAD, Error> {
+ // let mem = self.store.get_mem(self.module.resolve_mem_addr(mem_addr));
+ // let val = self.stack.values.pop::<i32>() as u64;
+ // let Some(Ok(addr)) = offset.checked_add(val).map(TryInto::try_into) else {
+ // cold();
+ // return Err(Error::Trap(Trap::MemoryOutOfBounds { offset: val as usize, len: LOAD_SIZE, max: 0 }));
+ // };
+ // mem.load_as::<LOAD_SIZE, LOAD>(addr)
+ // }
+
fn exec_mem_load<LOAD: MemLoadable<LOAD_SIZE>, const LOAD_SIZE: usize, TARGET: InternalValue>(
&mut self,
mem_addr: tinywasm_types::MemAddr,
diff --git a/crates/tinywasm/src/interpreter/mod.rs b/crates/tinywasm/src/interpreter/mod.rs
index 269bcfb..0b7df2f 100644
--- a/crates/tinywasm/src/interpreter/mod.rs
+++ b/crates/tinywasm/src/interpreter/mod.rs
@@ -6,9 +6,6 @@ mod values;
#[cfg(not(feature = "std"))]
mod no_std_floats;
-#[cfg(feature = "simd")]
-mod simd;
-
use crate::{Result, Store};
pub use values::*;
diff --git a/crates/tinywasm/src/interpreter/simd.rs b/crates/tinywasm/src/interpreter/simd.rs
deleted file mode 100644
index 2042bc6..0000000
--- a/crates/tinywasm/src/interpreter/simd.rs
+++ /dev/null
@@ -1,3 +0,0 @@
-pub(super) use core::simd::num::SimdFloat;
-pub(super) use core::simd::num::SimdInt;
-pub(super) use core::simd::*;
diff --git a/crates/tinywasm/src/interpreter/stack/call_stack.rs b/crates/tinywasm/src/interpreter/stack/call_stack.rs
index 9b6c3fd..25ad81f 100644
--- a/crates/tinywasm/src/interpreter/stack/call_stack.rs
+++ b/crates/tinywasm/src/interpreter/stack/call_stack.rs
@@ -7,7 +7,7 @@ use crate::{Error, unlikely};
use alloc::boxed::Box;
use alloc::{rc::Rc, vec, vec::Vec};
-use tinywasm_types::{Instruction, LocalAddr, ModuleInstanceAddr, WasmFunction, WasmValue};
+use tinywasm_types::{Instruction, LocalAddr, ModuleInstanceAddr, WasmFunction, WasmFunctionData, WasmValue};
pub(crate) const MAX_CALL_STACK_SIZE: usize = 1024;
@@ -71,6 +71,11 @@ impl CallFrame {
}
#[inline]
+ pub(crate) fn data(&self) -> &WasmFunctionData {
+ &self.func_instance.data
+ }
+
+ #[inline]
pub(crate) fn incr_instr_ptr(&mut self) {
self.instr_ptr += 1;
}
diff --git a/crates/tinywasm/src/interpreter/stack/value_stack.rs b/crates/tinywasm/src/interpreter/stack/value_stack.rs
index 843723a..bb5b2ea 100644
--- a/crates/tinywasm/src/interpreter/stack/value_stack.rs
+++ b/crates/tinywasm/src/interpreter/stack/value_stack.rs
@@ -184,7 +184,7 @@ impl ValueStack {
ValType::V128 => WasmValue::V128(self.pop()),
#[cfg(feature = "simd")]
- ValType::V128 => WasmValue::V128(u128::from_ne_bytes(self.pop::<Value128>().to_array())),
+ ValType::V128 => WasmValue::V128(i128::from_le_bytes(self.pop::<Value128>().to_array())),
}
}
diff --git a/crates/tinywasm/src/interpreter/values.rs b/crates/tinywasm/src/interpreter/values.rs
index 98d40af..335da59 100644
--- a/crates/tinywasm/src/interpreter/values.rs
+++ b/crates/tinywasm/src/interpreter/values.rs
@@ -10,7 +10,7 @@ pub(crate) type ValueRef = Option<u32>;
#[cfg(feature = "simd")]
pub(crate) type Value128 = core::simd::u8x16;
#[cfg(not(feature = "simd"))]
-pub(crate) type Value128 = u128;
+pub(crate) type Value128 = i128;
#[derive(Debug, Clone, Copy, PartialEq)]
/// A untyped WebAssembly value
@@ -114,7 +114,7 @@ impl TinyWasmValue {
ValType::RefFunc => WasmValue::RefFunc(FuncRef::new(self.unwrap_ref())),
#[cfg(feature = "simd")]
- ValType::V128 => WasmValue::V128(u128::from_ne_bytes(self.unwrap_128().to_array())),
+ ValType::V128 => WasmValue::V128(i128::from_le_bytes(self.unwrap_128().to_array())),
#[cfg(not(feature = "simd"))]
ValType::V128 => WasmValue::V128(self.unwrap_128()),
@@ -136,7 +136,7 @@ impl From<&WasmValue> for TinyWasmValue {
WasmValue::V128(v) => TinyWasmValue::Value128(*v),
#[cfg(feature = "simd")]
- WasmValue::V128(v) => TinyWasmValue::Value128(v.to_ne_bytes().into()),
+ WasmValue::V128(v) => TinyWasmValue::Value128(v.to_le_bytes().into()),
}
}
}
@@ -269,8 +269,8 @@ impl_internalvalue! {
Value64, stack_64, locals_64, u64, i64, |v| v as u64, |v| v as i64
Value32, stack_32, locals_32, u32, f32, f32::to_bits, f32::from_bits
Value64, stack_64, locals_64, u64, f64, f64::to_bits, f64::from_bits
- Value128, stack_128, locals_128, Value128, Value128, |v| v, |v| v
ValueRef, stack_ref, locals_ref, ValueRef, ValueRef, |v| v, |v| v
+ Value128, stack_128, locals_128, Value128, Value128, |v| v, |v| v
}
#[cfg(feature = "simd")]
@@ -278,15 +278,16 @@ use core::simd::{num::SimdUint, *};
#[cfg(feature = "simd")]
impl_internalvalue! {
- Value128, stack_128, locals_128, u8x16, u128, |v: u128| v.to_ne_bytes().into(), |v: u8x16| u128::from_ne_bytes(v.into())
- Value128, stack_128, locals_128, u8x16, i8x16, |v: i8x16| v.to_ne_bytes(), |v: u8x16| v.cast()
- Value128, stack_128, locals_128, u8x16, i16x8, |v: i16x8| v.to_ne_bytes(), |v: u8x16| i16x8::from_ne_bytes(v)
- Value128, stack_128, locals_128, u8x16, i32x4, |v: i32x4| v.to_ne_bytes(), |v: u8x16| i32x4::from_ne_bytes(v)
- Value128, stack_128, locals_128, u8x16, i64x2, |v: i64x2| v.to_ne_bytes(), |v: u8x16| i64x2::from_ne_bytes(v)
- Value128, stack_128, locals_128, u8x16, f32x4, |v: f32x4| v.to_ne_bytes(), |v: u8x16| f32x4::from_ne_bytes(v)
- Value128, stack_128, locals_128, u8x16, f64x2, |v: f64x2| v.to_ne_bytes(), |v: u8x16| f64x2::from_ne_bytes(v)
+ Value128, stack_128, locals_128, u8x16, i128, |v: i128| v.to_le_bytes().into(), |v: u8x16| i128::from_le_bytes(v.into())
+ Value128, stack_128, locals_128, u8x16, u128, |v: u128| v.to_le_bytes().into(), |v: u8x16| u128::from_le_bytes(v.into())
+ Value128, stack_128, locals_128, u8x16, i8x16, |v: i8x16| v.to_le_bytes(), |v: u8x16| v.cast()
+ Value128, stack_128, locals_128, u8x16, i16x8, |v: i16x8| v.to_le_bytes(), |v: u8x16| i16x8::from_le_bytes(v)
+ Value128, stack_128, locals_128, u8x16, i32x4, |v: i32x4| v.to_le_bytes(), |v: u8x16| i32x4::from_le_bytes(v)
+ Value128, stack_128, locals_128, u8x16, i64x2, |v: i64x2| v.to_le_bytes(), |v: u8x16| i64x2::from_le_bytes(v)
+ Value128, stack_128, locals_128, u8x16, f32x4, |v: f32x4| v.to_le_bytes(), |v: u8x16| f32x4::from_le_bytes(v)
+ Value128, stack_128, locals_128, u8x16, f64x2, |v: f64x2| v.to_le_bytes(), |v: u8x16| f64x2::from_le_bytes(v)
- Value128, stack_128, locals_128, u8x16, u16x8, |v: u16x8| v.to_ne_bytes(), |v: u8x16| u16x8::from_ne_bytes(v)
- Value128, stack_128, locals_128, u8x16, u32x4, |v: u32x4| v.to_ne_bytes(), |v: u8x16| u32x4::from_ne_bytes(v)
- Value128, stack_128, locals_128, u8x16, u64x2, |v: u64x2| v.to_ne_bytes(), |v: u8x16| u64x2::from_ne_bytes(v)
+ Value128, stack_128, locals_128, u8x16, u16x8, |v: u16x8| v.to_le_bytes(), |v: u8x16| u16x8::from_le_bytes(v)
+ Value128, stack_128, locals_128, u8x16, u32x4, |v: u32x4| v.to_le_bytes(), |v: u8x16| u32x4::from_le_bytes(v)
+ Value128, stack_128, locals_128, u8x16, u64x2, |v: u64x2| v.to_le_bytes(), |v: u8x16| u64x2::from_le_bytes(v)
}
diff --git a/crates/tinywasm/src/store/memory.rs b/crates/tinywasm/src/store/memory.rs
index d204c67..a1c7994 100644
--- a/crates/tinywasm/src/store/memory.rs
+++ b/crates/tinywasm/src/store/memory.rs
@@ -2,7 +2,10 @@ use alloc::vec;
use alloc::vec::Vec;
use tinywasm_types::{MemoryType, ModuleInstanceAddr};
-use crate::{Error, Result, cold, log};
+use crate::{Error, Result, cold, interpreter::Value128, log};
+
+#[cfg(feature = "simd")]
+use core::simd::ToBytes;
/// A WebAssembly Memory Instance
///
@@ -80,7 +83,7 @@ impl MemoryInstance {
return Err(self.trap_oob(addr, SIZE));
}
- Ok(T::from_le_bytes(match self.data[addr..end].try_into() {
+ Ok(T::from_mem_bytes(match self.data[addr..end].try_into() {
Ok(bytes) => bytes,
Err(_) => return Err(self.trap_oob(addr, SIZE)),
}))
@@ -158,30 +161,52 @@ pub(crate) trait MemStorable<const N: usize> {
/// A trait for types that can be loaded from memory
pub(crate) trait MemLoadable<const N: usize>: Sized + Copy {
/// Load a value from memory
- fn from_le_bytes(bytes: [u8; N]) -> Self;
+ fn from_mem_bytes(bytes: [u8; N]) -> Self;
}
macro_rules! impl_mem_traits {
- ($($type:ty, $size:expr),*) => {
+ ($($ty:ty, $size:expr),*) => {
$(
- impl MemLoadable<$size> for $type {
+ impl MemLoadable<$size> for $ty {
#[inline(always)]
- fn from_le_bytes(bytes: [u8; $size]) -> Self {
- <$type>::from_le_bytes(bytes)
+ fn from_mem_bytes(bytes: [u8; $size]) -> Self {
+ <$ty>::from_le_bytes(bytes.into())
}
}
- impl MemStorable<$size> for $type {
+ impl MemStorable<$size> for $ty {
#[inline(always)]
fn to_mem_bytes(self) -> [u8; $size] {
- self.to_ne_bytes()
+ self.to_le_bytes().into()
}
}
)*
}
}
-impl_mem_traits!(u8, 1, i8, 1, u16, 2, i16, 2, u32, 4, i32, 4, f32, 4, u64, 8, i64, 8, f64, 8, u128, 16, i128, 16);
+impl_mem_traits!(u8, 1, i8, 1, u16, 2, i16, 2, u32, 4, i32, 4, f32, 4, u64, 8, i64, 8, f64, 8, Value128, 16);
+
+#[cfg(feature = "simd")]
+impl_mem_traits!(
+ core::simd::i8x16,
+ 16,
+ core::simd::i16x8,
+ 16,
+ core::simd::i32x4,
+ 16,
+ core::simd::i64x2,
+ 16,
+ core::simd::u16x8,
+ 16,
+ core::simd::u32x4,
+ 16,
+ core::simd::u64x2,
+ 16,
+ core::simd::f32x4,
+ 16,
+ core::simd::f64x2,
+ 16
+);
#[cfg(test)]
mod memory_instance_tests {
diff --git a/crates/tinywasm/tests/generated/wasm-simd.csv b/crates/tinywasm/tests/generated/wasm-simd.csv
index 210564b..6f37f4d 100644
--- a/crates/tinywasm/tests/generated/wasm-simd.csv
+++ b/crates/tinywasm/tests/generated/wasm-simd.csv
@@ -1,2 +1,2 @@
0.8.0,1300,24679,[{"name":"simd_address.wast","passed":4,"failed":45},{"name":"simd_align.wast","passed":46,"failed":54},{"name":"simd_bit_shift.wast","passed":39,"failed":213},{"name":"simd_bitwise.wast","passed":28,"failed":141},{"name":"simd_boolean.wast","passed":16,"failed":261},{"name":"simd_const.wast","passed":301,"failed":456},{"name":"simd_conversions.wast","passed":48,"failed":234},{"name":"simd_f32x4.wast","passed":16,"failed":774},{"name":"simd_f32x4_arith.wast","passed":16,"failed":1806},{"name":"simd_f32x4_cmp.wast","passed":24,"failed":2583},{"name":"simd_f32x4_pmin_pmax.wast","passed":14,"failed":3873},{"name":"simd_f32x4_rounding.wast","passed":24,"failed":177},{"name":"simd_f64x2.wast","passed":8,"failed":795},{"name":"simd_f64x2_arith.wast","passed":16,"failed":1809},{"name":"simd_f64x2_cmp.wast","passed":24,"failed":2661},{"name":"simd_f64x2_pmin_pmax.wast","passed":14,"failed":3873},{"name":"simd_f64x2_rounding.wast","passed":24,"failed":177},{"name":"simd_i16x8_arith.wast","passed":11,"failed":183},{"name":"simd_i16x8_arith2.wast","passed":19,"failed":153},{"name":"simd_i16x8_cmp.wast","passed":30,"failed":435},{"name":"simd_i16x8_extadd_pairwise_i8x16.wast","passed":4,"failed":17},{"name":"simd_i16x8_extmul_i8x16.wast","passed":12,"failed":105},{"name":"simd_i16x8_q15mulr_sat_s.wast","passed":3,"failed":27},{"name":"simd_i16x8_sat_arith.wast","passed":16,"failed":206},{"name":"simd_i32x4_arith.wast","passed":11,"failed":183},{"name":"simd_i32x4_arith2.wast","passed":26,"failed":123},{"name":"simd_i32x4_cmp.wast","passed":40,"failed":435},{"name":"simd_i32x4_dot_i16x8.wast","passed":3,"failed":27},{"name":"simd_i32x4_extadd_pairwise_i16x8.wast","passed":4,"failed":17},{"name":"simd_i32x4_extmul_i16x8.wast","passed":12,"failed":105},{"name":"simd_i32x4_trunc_sat_f32x4.wast","passed":4,"failed":103},{"name":"simd_i32x4_trunc_sat_f64x2.wast","passed":4,"failed":103},{"name":"simd_i64x2_arith.wast","passed":11,"failed":189},{"name":"simd_i64x2_arith2.wast","passed":2,"failed":23},{"name":"simd_i64x2_cmp.wast","passed":10,"failed":103},{"name":"simd_i64x2_extmul_i32x4.wast","passed":12,"failed":105},{"name":"simd_i8x16_arith.wast","passed":8,"failed":123},{"name":"simd_i8x16_arith2.wast","passed":25,"failed":186},{"name":"simd_i8x16_cmp.wast","passed":30,"failed":415},{"name":"simd_i8x16_sat_arith.wast","passed":24,"failed":190},{"name":"simd_int_to_int_extend.wast","passed":24,"failed":229},{"name":"simd_lane.wast","passed":189,"failed":286},{"name":"simd_linking.wast","passed":0,"failed":3},{"name":"simd_load.wast","passed":8,"failed":31},{"name":"simd_load16_lane.wast","passed":3,"failed":33},{"name":"simd_load32_lane.wast","passed":3,"failed":21},{"name":"simd_load64_lane.wast","passed":3,"failed":13},{"name":"simd_load8_lane.wast","passed":3,"failed":49},{"name":"simd_load_extend.wast","passed":18,"failed":86},{"name":"simd_load_splat.wast","passed":12,"failed":114},{"name":"simd_load_zero.wast","passed":10,"failed":29},{"name":"simd_splat.wast","passed":23,"failed":162},{"name":"simd_store.wast","passed":9,"failed":19},{"name":"simd_store16_lane.wast","passed":3,"failed":33},{"name":"simd_store32_lane.wast","passed":3,"failed":21},{"name":"simd_store64_lane.wast","passed":3,"failed":13},{"name":"simd_store8_lane.wast","passed":3,"failed":49}]
-0.9.0-alpha.0,1808,24172,[{"name":"simd_address.wast","passed":7,"failed":42},{"name":"simd_align.wast","passed":92,"failed":8},{"name":"simd_bit_shift.wast","passed":41,"failed":211},{"name":"simd_bitwise.wast","passed":30,"failed":139},{"name":"simd_boolean.wast","passed":123,"failed":154},{"name":"simd_const.wast","passed":551,"failed":206},{"name":"simd_conversions.wast","passed":50,"failed":232},{"name":"simd_f32x4.wast","passed":18,"failed":772},{"name":"simd_f32x4_arith.wast","passed":19,"failed":1803},{"name":"simd_f32x4_cmp.wast","passed":26,"failed":2581},{"name":"simd_f32x4_pmin_pmax.wast","passed":15,"failed":3872},{"name":"simd_f32x4_rounding.wast","passed":25,"failed":176},{"name":"simd_f64x2.wast","passed":10,"failed":793},{"name":"simd_f64x2_arith.wast","passed":19,"failed":1806},{"name":"simd_f64x2_cmp.wast","passed":26,"failed":2659},{"name":"simd_f64x2_pmin_pmax.wast","passed":15,"failed":3872},{"name":"simd_f64x2_rounding.wast","passed":25,"failed":176},{"name":"simd_i16x8_arith.wast","passed":13,"failed":181},{"name":"simd_i16x8_arith2.wast","passed":21,"failed":151},{"name":"simd_i16x8_cmp.wast","passed":32,"failed":433},{"name":"simd_i16x8_extadd_pairwise_i8x16.wast","passed":5,"failed":16},{"name":"simd_i16x8_extmul_i8x16.wast","passed":13,"failed":104},{"name":"simd_i16x8_q15mulr_sat_s.wast","passed":4,"failed":26},{"name":"simd_i16x8_sat_arith.wast","passed":18,"failed":204},{"name":"simd_i32x4_arith.wast","passed":13,"failed":181},{"name":"simd_i32x4_arith2.wast","passed":28,"failed":121},{"name":"simd_i32x4_cmp.wast","passed":42,"failed":433},{"name":"simd_i32x4_dot_i16x8.wast","passed":4,"failed":26},{"name":"simd_i32x4_extadd_pairwise_i16x8.wast","passed":5,"failed":16},{"name":"simd_i32x4_extmul_i16x8.wast","passed":13,"failed":104},{"name":"simd_i32x4_trunc_sat_f32x4.wast","passed":5,"failed":102},{"name":"simd_i32x4_trunc_sat_f64x2.wast","passed":5,"failed":102},{"name":"simd_i64x2_arith.wast","passed":13,"failed":187},{"name":"simd_i64x2_arith2.wast","passed":4,"failed":21},{"name":"simd_i64x2_cmp.wast","passed":11,"failed":102},{"name":"simd_i64x2_extmul_i32x4.wast","passed":13,"failed":104},{"name":"simd_i8x16_arith.wast","passed":10,"failed":121},{"name":"simd_i8x16_arith2.wast","passed":27,"failed":184},{"name":"simd_i8x16_cmp.wast","passed":32,"failed":413},{"name":"simd_i8x16_sat_arith.wast","passed":26,"failed":188},{"name":"simd_int_to_int_extend.wast","passed":25,"failed":228},{"name":"simd_lane.wast","passed":200,"failed":275},{"name":"simd_linking.wast","passed":0,"failed":3},{"name":"simd_load.wast","passed":22,"failed":17},{"name":"simd_load16_lane.wast","passed":4,"failed":32},{"name":"simd_load32_lane.wast","passed":4,"failed":20},{"name":"simd_load64_lane.wast","passed":4,"failed":12},{"name":"simd_load8_lane.wast","passed":4,"failed":48},{"name":"simd_load_extend.wast","passed":20,"failed":84},{"name":"simd_load_splat.wast","passed":14,"failed":112},{"name":"simd_load_zero.wast","passed":12,"failed":27},{"name":"simd_memory-multi.wast","passed":1,"failed":0},{"name":"simd_splat.wast","passed":26,"failed":159},{"name":"simd_store.wast","passed":11,"failed":17},{"name":"simd_store16_lane.wast","passed":3,"failed":33},{"name":"simd_store32_lane.wast","passed":3,"failed":21},{"name":"simd_store64_lane.wast","passed":3,"failed":13},{"name":"simd_store8_lane.wast","passed":3,"failed":49}]
+0.9.0-alpha.0,14613,11367,[{"name":"simd_address.wast","passed":48,"failed":1},{"name":"simd_align.wast","passed":100,"failed":0},{"name":"simd_bit_shift.wast","passed":41,"failed":211},{"name":"simd_bitwise.wast","passed":169,"failed":0},{"name":"simd_boolean.wast","passed":241,"failed":36},{"name":"simd_const.wast","passed":751,"failed":6},{"name":"simd_conversions.wast","passed":50,"failed":232},{"name":"simd_f32x4.wast","passed":629,"failed":161},{"name":"simd_f32x4_arith.wast","passed":1357,"failed":465},{"name":"simd_f32x4_cmp.wast","passed":2607,"failed":0},{"name":"simd_f32x4_pmin_pmax.wast","passed":15,"failed":3872},{"name":"simd_f32x4_rounding.wast","passed":148,"failed":53},{"name":"simd_f64x2.wast","passed":639,"failed":164},{"name":"simd_f64x2_arith.wast","passed":1360,"failed":465},{"name":"simd_f64x2_cmp.wast","passed":2685,"failed":0},{"name":"simd_f64x2_pmin_pmax.wast","passed":15,"failed":3872},{"name":"simd_f64x2_rounding.wast","passed":148,"failed":53},{"name":"simd_i16x8_arith.wast","passed":138,"failed":56},{"name":"simd_i16x8_arith2.wast","passed":142,"failed":30},{"name":"simd_i16x8_cmp.wast","passed":436,"failed":29},{"name":"simd_i16x8_extadd_pairwise_i8x16.wast","passed":5,"failed":16},{"name":"simd_i16x8_extmul_i8x16.wast","passed":13,"failed":104},{"name":"simd_i16x8_q15mulr_sat_s.wast","passed":4,"failed":26},{"name":"simd_i16x8_sat_arith.wast","passed":222,"failed":0},{"name":"simd_i32x4_arith.wast","passed":138,"failed":56},{"name":"simd_i32x4_arith2.wast","passed":149,"failed":0},{"name":"simd_i32x4_cmp.wast","passed":450,"failed":25},{"name":"simd_i32x4_dot_i16x8.wast","passed":4,"failed":26},{"name":"simd_i32x4_extadd_pairwise_i16x8.wast","passed":5,"failed":16},{"name":"simd_i32x4_extmul_i16x8.wast","passed":13,"failed":104},{"name":"simd_i32x4_trunc_sat_f32x4.wast","passed":5,"failed":102},{"name":"simd_i32x4_trunc_sat_f64x2.wast","passed":5,"failed":102},{"name":"simd_i64x2_arith.wast","passed":200,"failed":0},{"name":"simd_i64x2_arith2.wast","passed":25,"failed":0},{"name":"simd_i64x2_cmp.wast","passed":97,"failed":16},{"name":"simd_i64x2_extmul_i32x4.wast","passed":13,"failed":104},{"name":"simd_i8x16_arith.wast","passed":131,"failed":0},{"name":"simd_i8x16_arith2.wast","passed":148,"failed":63},{"name":"simd_i8x16_cmp.wast","passed":409,"failed":36},{"name":"simd_i8x16_sat_arith.wast","passed":214,"failed":0},{"name":"simd_int_to_int_extend.wast","passed":25,"failed":228},{"name":"simd_lane.wast","passed":213,"failed":262},{"name":"simd_linking.wast","passed":0,"failed":3},{"name":"simd_load.wast","passed":34,"failed":5},{"name":"simd_load16_lane.wast","passed":36,"failed":0},{"name":"simd_load32_lane.wast","passed":24,"failed":0},{"name":"simd_load64_lane.wast","passed":16,"failed":0},{"name":"simd_load8_lane.wast","passed":52,"failed":0},{"name":"simd_load_extend.wast","passed":20,"failed":84},{"name":"simd_load_splat.wast","passed":14,"failed":112},{"name":"simd_load_zero.wast","passed":12,"failed":27},{"name":"simd_memory-multi.wast","passed":1,"failed":0},{"name":"simd_splat.wast","passed":157,"failed":28},{"name":"simd_store.wast","passed":28,"failed":0},{"name":"simd_store16_lane.wast","passed":3,"failed":33},{"name":"simd_store32_lane.wast","passed":3,"failed":21},{"name":"simd_store64_lane.wast","passed":3,"failed":13},{"name":"simd_store8_lane.wast","passed":3,"failed":49}]
diff --git a/crates/tinywasm/tests/testsuite/util.rs b/crates/tinywasm/tests/testsuite/util.rs
index f8f862b..91a1e41 100644
--- a/crates/tinywasm/tests/testsuite/util.rs
+++ b/crates/tinywasm/tests/testsuite/util.rs
@@ -1,9 +1,9 @@
use std::panic::{self, AssertUnwindSafe};
-use eyre::{bail, eyre, Result};
+use eyre::{Result, bail, eyre};
use tinywasm_types::{ExternRef, FuncRef, ModuleInstanceAddr, TinyWasmModule, ValType, WasmValue};
use wasm_testsuite::wast;
-use wasm_testsuite::wast::{core::AbstractHeapType, QuoteWat};
+use wasm_testsuite::wast::{QuoteWat, core::AbstractHeapType};
pub fn try_downcast_panic(panic: Box<dyn std::any::Any + Send>) -> String {
let info = panic.downcast_ref::<panic::PanicHookInfo>().or(None).map(ToString::to_string).clone();
@@ -96,7 +96,7 @@ fn wastarg2tinywasmvalue(arg: wast::WastArg) -> Result<tinywasm_types::WasmValue
bail!("unsupported arg type: Component");
};
- use wast::core::WastArgCore::{RefExtern, RefNull, F32, F64, I32, I64, V128};
+ use wast::core::WastArgCore::{F32, F64, I32, I64, RefExtern, RefNull, V128};
Ok(match arg {
F32(f) => WasmValue::F32(f32::from_bits(f.bits)),
F64(f) => WasmValue::F64(f64::from_bits(f.bits)),
@@ -117,19 +117,21 @@ fn wastarg2tinywasmvalue(arg: wast::WastArg) -> Result<tinywasm_types::WasmValue
})
}
-fn wast_i128_to_i128(i: wast::core::V128Pattern) -> u128 {
- match i {
+fn wast_i128_to_i128(i: wast::core::V128Pattern) -> i128 {
+ let res: Vec<u8> = match i {
wast::core::V128Pattern::F32x4(f) => {
- f.iter().fold(0, |acc, &f| (acc << 32) | nanpattern2tinywasmvalue(f).unwrap().as_f32().unwrap() as u128)
+ f.iter().map(|v| nanpattern2tinywasmvalue(*v).unwrap().as_f32().unwrap().to_le_bytes()).flatten().collect()
}
wast::core::V128Pattern::F64x2(f) => {
- f.iter().fold(0, |acc, &f| (acc << 64) | nanpattern2tinywasmvalue(f).unwrap().as_f64().unwrap() as u128)
+ f.iter().map(|v| nanpattern2tinywasmvalue(*v).unwrap().as_f64().unwrap().to_le_bytes()).flatten().collect()
}
- wast::core::V128Pattern::I16x8(f) => f.iter().fold(0, |acc, &f| (acc << 16) | f as u128),
- wast::core::V128Pattern::I32x4(f) => f.iter().fold(0, |acc, &f| (acc << 32) | f as u128),
- wast::core::V128Pattern::I64x2(f) => f.iter().fold(0, |acc, &f| (acc << 64) | f as u128),
- wast::core::V128Pattern::I8x16(f) => f.iter().fold(0, |acc, &f| (acc << 8) | f as u128),
- }
+ wast::core::V128Pattern::I16x8(f) => f.iter().map(|v| v.to_le_bytes()).flatten().collect(),
+ wast::core::V128Pattern::I32x4(f) => f.iter().map(|v| v.to_le_bytes()).flatten().collect(),
+ wast::core::V128Pattern::I64x2(f) => f.iter().map(|v| v.to_le_bytes()).flatten().collect(),
+ wast::core::V128Pattern::I8x16(f) => f.iter().map(|v| v.to_le_bytes()).flatten().collect(),
+ };
+
+ i128::from_le_bytes(res.try_into().unwrap())
}
fn wastret2tinywasmvalue(ret: wast::WastRet) -> Result<tinywasm_types::WasmValue> {
@@ -137,7 +139,7 @@ fn wastret2tinywasmvalue(ret: wast::WastRet) -> Result<tinywasm_types::WasmValue
bail!("unsupported arg type");
};
- use wast::core::WastRetCore::{RefExtern, RefFunc, RefNull, F32, F64, I32, I64, V128};
+ use wast::core::WastRetCore::{F32, F64, I32, I64, RefExtern, RefFunc, RefNull, V128};
Ok(match ret {
F32(f) => nanpattern2tinywasmvalue(f)?,
F64(f) => nanpattern2tinywasmvalue(f)?,
diff --git a/crates/types/src/instructions.rs b/crates/types/src/instructions.rs
index 24116e8..593af2f 100644
--- a/crates/types/src/instructions.rs
+++ b/crates/types/src/instructions.rs
@@ -36,6 +36,7 @@ pub enum ConstInstruction {
I64Const(i64),
F32Const(f32),
F64Const(f64),
+ V128Const(i128),
GlobalGet(GlobalAddr),
RefFunc(Option<FuncAddr>),
RefExtern(Option<ExternAddr>),
diff --git a/crates/types/src/lib.rs b/crates/types/src/lib.rs
index d9f2234..470c631 100644
--- a/crates/types/src/lib.rs
+++ b/crates/types/src/lib.rs
@@ -259,7 +259,7 @@ pub struct WasmFunction {
#[derive(Debug, Clone, PartialEq, Default)]
#[cfg_attr(feature = "archive", derive(serde::Serialize, serde::Deserialize))]
pub struct WasmFunctionData {
- pub v128_constants: Box<[u128]>,
+ pub v128_constants: Box<[i128]>,
}
/// A WebAssembly Module Export
diff --git a/crates/types/src/value.rs b/crates/types/src/value.rs
index 01a31d5..a9498cc 100644
--- a/crates/types/src/value.rs
+++ b/crates/types/src/value.rs
@@ -17,7 +17,7 @@ pub enum WasmValue {
/// A 64-bit float.
F64(f64),
// /// A 128-bit vector
- V128(u128),
+ V128(i128),
RefExtern(ExternRef),
RefFunc(FuncRef),
@@ -112,6 +112,7 @@ impl WasmValue {
Self::I64(i) => ConstInstruction::I64Const(*i),
Self::F32(i) => ConstInstruction::F32Const(*i),
Self::F64(i) => ConstInstruction::F64Const(*i),
+ Self::V128(i) => ConstInstruction::V128Const(*i),
Self::RefFunc(i) => ConstInstruction::RefFunc(i.addr()),
_ => unimplemented!("no const_instr for {:?}", self),
}
@@ -137,6 +138,7 @@ impl WasmValue {
match (self, other) {
(Self::I32(a), Self::I32(b)) => a == b,
(Self::I64(a), Self::I64(b)) => a == b,
+ (Self::V128(a), Self::V128(b)) => a == b,
(Self::RefExtern(addr), Self::RefExtern(addr2)) => addr == addr2,
(Self::RefFunc(addr), Self::RefFunc(addr2)) => addr == addr2,
(Self::F32(a), Self::F32(b)) => {
@@ -190,7 +192,7 @@ impl WasmValue {
}
#[doc(hidden)]
- pub fn as_v128(&self) -> Option<u128> {
+ pub fn as_v128(&self) -> Option<i128> {
match self {
Self::V128(i) => Some(*i),
_ => None,
@@ -309,4 +311,4 @@ macro_rules! impl_conversion_for_wasmvalue {
}
}
-impl_conversion_for_wasmvalue! { i32 => I32, i64 => I64, f32 => F32, f64 => F64, u128 => V128, ExternRef => RefExtern, FuncRef => RefFunc }
+impl_conversion_for_wasmvalue! { i32 => I32, i64 => I64, f32 => F32, f64 => F64, i128 => V128, ExternRef => RefExtern, FuncRef => RefFunc }