Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
21 commits
Select commit Hold shift + click to select a range
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 3 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@ Refer to the [Wasmi usage guide](./docs/usage.md) to learn how properly to use [
| ✅ | [`saturating-float-to-int`] | ≥ `0.14.0` | | ✅ | [`memory64`] | [≥ `0.41.0`][(#1357)] |
| ✅ | [`sign-extension`] | ≥ `0.14.0` | | ✅ | [`wide-arithmetic`] | [≥ `0.42.0`][(#1369)] |
| ✅ | [`multi-value`] | ≥ `0.14.0` | | ✅ | [`simd`] | [≥ `0.43.0`][(#1364)] |
| ✅ | [`bulk-memory`] | [≥ `0.24.0`][(#628)] | | 📅 | [`relaxed-simd`] | [Tracking Issue][(#1431)] |
| ✅ | [`bulk-memory`] | [≥ `0.24.0`][(#628)] | | | [`relaxed-simd`] | [≥ `0.44.0`][(#1443)] |
| ✅ | [`reference-types`] | [≥ `0.24.0`][(#635)] | | 📅 | [`function-references`] | [Tracking Issue][(#774)] |
| ✅ | [`tail-calls`] | [≥ `0.28.0`][(#683)] | | 📅 | [`gc`] | [Tracking Issue][(#775)] |
| ✅ | [`extended-const`] | [≥ `0.29.0`][(#707)] | | 📅 | [`threads`] | [Tracking Issue][(#777)] |
Expand Down Expand Up @@ -113,15 +113,15 @@ Refer to the [Wasmi usage guide](./docs/usage.md) to learn how properly to use [
[(#1357)]: https://github.com/wasmi-labs/wasmi/issues/1357
[(#1364)]: https://github.com/wasmi-labs/wasmi/issues/1364
[(#1369)]: https://github.com/wasmi-labs/wasmi/issues/1369
[(#1431)]: https://github.com/wasmi-labs/wasmi/issues/1431
[(#1443)]: https://github.com/wasmi-labs/wasmi/pull/1443

## Crate Features

| Feature | Crates | Description |
|:-:|:--|:--|
| `std` | `wasmi`<br>`wasmi_core`<br>`wasmi_ir`<br>`wasmi_collections` | Enables usage of Rust's standard library. This may have some performance advantages when enabled. Disabling this feature makes Wasmi compile on platforms that do not provide Rust's standard library such as many embedded platforms. <br><br> Enabled by default. |
| `wat` | `wasmi` | Enables support to parse Wat encoded Wasm modules. <br><br> Enabled by default. |
| `simd` | `wasmi`<br>`wasmi_core`<br>`wasmi_ir`<br>`wasmi_cli` | Enables support for the Wasm `simd` proposal. Note that this may introduce execution overhead and increased memory consumption for Wasm executions that do not need Wasm `simd` functionality. <br><br> Disabled by default. |
| `simd` | `wasmi`<br>`wasmi_core`<br>`wasmi_ir`<br>`wasmi_cli` | Enables support for the Wasm `simd` and `relaxed-simd` proposals. Note that this may introduce execution overhead and increased memory consumption for Wasm executions that do not need Wasm `simd` functionality. <br><br> Disabled by default. |
| `hash-collections` | `wasmi`<br>`wasmi_collections` | Enables use of hash-map based collections in Wasmi internals. This might yield performance improvements in some use cases. <br><br> Disabled by default. |
| `prefer-btree-collections` | `wasmi`<br>`wasmi_collections` | Enforces use of btree-map based collections in Wasmi internals. This may yield performance improvements and memory consumption decreases in some use cases. Also it enables Wasmi to run on platforms that have no random source. <br><br> Disabled by default. |
| `extra-checks` | `wasmi` | Enables extra runtime checks in the Wasmi executor. Expected execution overhead is ~20%. Enable this if your focus is on safety. Disable this for maximum execution performance. <br><br> Disabled by default. |
Expand Down
71 changes: 71 additions & 0 deletions crates/core/src/simd.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
use crate::{
memory::{self, ExtendInto},
simd,
value::Float,
wasm,
TrapCode,
V128,
Expand Down Expand Up @@ -152,6 +153,14 @@ trait Lanes {
fn lanewise_binary(self, other: Self, f: impl Fn(Self::Item, Self::Item) -> Self::Item)
-> Self;

/// Apply `f` for all triplets of lane items in `self` and `other`.
fn lanewise_ternary(
self,
b: Self,
c: Self,
f: impl Fn(Self::Item, Self::Item, Self::Item) -> Self::Item,
) -> Self;

/// Apply `f` comparison for all pairs of lane items in `self` and `other`.
///
/// Storing [`Self::ALL_ONES`] if `f` evaluates to `true` or [`Self::ALL_ZEROS`] otherwise per item.
Expand Down Expand Up @@ -244,6 +253,16 @@ macro_rules! impl_lanes_for {
Self(lhs)
}

fn lanewise_ternary(self, b: Self, c: Self, f: impl Fn(Self::Item, Self::Item, Self::Item) -> Self::Item) -> Self {
let mut a = self.0;
let b = b.0;
let c = c.0;
for i in 0..Self::LANES {
a[i] = f(a[i], b[i], c[i]);
}
Self(a)
}

fn lanewise_comparison(self, other: Self, f: impl Fn(Self::Item, Self::Item) -> bool) -> Self {
self.lanewise_binary(other, |lhs, rhs| match f(lhs, rhs) {
true => Self::ALL_ONES,
Expand Down Expand Up @@ -531,6 +550,14 @@ impl V128 {
lhs.lanewise_binary(rhs, f).into_v128()
}

/// Convenience method to help implement lanewise ternary methods.
fn lanewise_ternary<T: IntoLanes>(a: Self, b: Self, c: Self, f: impl Fn(T, T, T) -> T) -> Self {
let a = <<T as IntoLanes>::Lanes>::from_v128(a);
let b = <<T as IntoLanes>::Lanes>::from_v128(b);
let c = <<T as IntoLanes>::Lanes>::from_v128(c);
a.lanewise_ternary(b, c, f).into_v128()
}

/// Convenience method to help implement lanewise comparison methods.
fn lanewise_comparison<T: IntoLanes>(lhs: Self, rhs: Self, f: impl Fn(T, T) -> bool) -> Self {
let lhs = <<T as IntoLanes>::Lanes>::from_v128(lhs);
Expand Down Expand Up @@ -1270,11 +1297,55 @@ pub fn i32x4_dot_i16x8_s(lhs: V128, rhs: V128) -> V128 {
V128::pairwise_binary(lhs, rhs, dot)
}

/// Executes a Wasm `i16x8.relaxed_dot_i8x16_i7x16_s` instruction.
pub fn i16x8_relaxed_dot_i8x16_i7x16_s(lhs: V128, rhs: V128) -> V128 {
fn dot(a: [i8; 2], b: [i8; 2]) -> i16 {
let a = a.map(i16::from);
let b = b.map(i16::from);
let dot0 = a[0].wrapping_mul(b[0]);
let dot1 = a[1].wrapping_mul(b[1]);
dot0.wrapping_add(dot1)
}
V128::pairwise_binary(lhs, rhs, dot)
}

/// Executes a Wasm `i32x4.relaxed_dot_i8x16_i7x16_add_s` instruction.
pub fn i32x4_relaxed_dot_i8x16_i7x16_add_s(lhs: V128, rhs: V128, c: V128) -> V128 {
let dot = i16x8_relaxed_dot_i8x16_i7x16_s(lhs, rhs);
let ext = i32x4_extadd_pairwise_i16x8_s(dot);
i32x4_add(ext, c)
}

/// Executes a Wasm `v128.bitselect` instruction.
pub fn v128_bitselect(v1: V128, v2: V128, c: V128) -> V128 {
simd::v128_or(simd::v128_and(v1, c), simd::v128_andnot(v2, c))
}

/// Computes the negative `mul_add`: `-(a * b) + c`
fn neg_mul_add<T>(a: T, b: T, c: T) -> T
where
T: Float + Neg<Output = T>,
{
<T as Float>::mul_add(a.neg(), b, c)
}

macro_rules! impl_ternary_for {
( $( fn $name:ident(a: V128, b: V128, c: V128) -> V128 = $lanewise_expr:expr; )* ) => {
$(
#[doc = concat!("Executes a Wasm `", stringify!($name), "` instruction.")]
pub fn $name(a: V128, b: V128, c: V128) -> V128 {
V128::lanewise_ternary(a, b, c, $lanewise_expr)
}
)*
};
}
impl_ternary_for! {
fn f32x4_relaxed_madd(a: V128, b: V128, c: V128) -> V128 = <f32 as Float>::mul_add;
fn f32x4_relaxed_nmadd(a: V128, b: V128, c: V128) -> V128 = neg_mul_add::<f32>;
fn f64x2_relaxed_madd(a: V128, b: V128, c: V128) -> V128 = <f64 as Float>::mul_add;
fn f64x2_relaxed_nmadd(a: V128, b: V128, c: V128) -> V128 = neg_mul_add::<f64>;
}

/// Executes a Wasm `v128.store` instruction.
///
/// # Errors
Expand Down
23 changes: 23 additions & 0 deletions crates/core/src/value.rs
Original file line number Diff line number Diff line change
Expand Up @@ -171,6 +171,9 @@ pub trait Float: Sized {
fn max(lhs: Self, rhs: Self) -> Self;
/// Sets sign of this value to the sign of other value.
fn copysign(lhs: Self, rhs: Self) -> Self;
/// Fused multiply-add with a single rounding error.
#[cfg(feature = "simd")]
fn mul_add(a: Self, b: Self, c: Self) -> Self;
}

macro_rules! impl_try_truncate_into {
Expand Down Expand Up @@ -394,6 +397,11 @@ macro_rules! impl_float {
fn copysign(lhs: Self, rhs: Self) -> Self {
WasmFloatExt::copysign(lhs, rhs)
}
#[inline]
#[cfg(feature = "simd")]
fn mul_add(a: Self, b: Self, c: Self) -> Self {
WasmFloatExt::mul_add(a, b, c)
}
}
};
}
Expand Down Expand Up @@ -423,6 +431,9 @@ trait WasmFloatExt {
fn nearest(self) -> Self;
/// Equivalent to the Wasm `{f32,f64}.copysign` instructions.
fn copysign(self, other: Self) -> Self;
/// Fused multiply-add with just 1 rounding error.
#[cfg(feature = "simd")]
fn mul_add(self, a: Self, b: Self) -> Self;
}

#[cfg(not(feature = "std"))]
Expand Down Expand Up @@ -474,6 +485,12 @@ macro_rules! impl_wasm_float {
fn copysign(self, other: Self) -> Self {
<libm::Libm<Self>>::copysign(self, other)
}

#[inline]
#[cfg(feature = "simd")]
fn mul_add(self, a: Self, b: Self) -> Self {
<libm::Libm<Self>>::fma(self, a, b)
}
}
};
}
Expand Down Expand Up @@ -534,6 +551,12 @@ macro_rules! impl_wasm_float {
fn copysign(self, other: Self) -> Self {
self.copysign(other)
}

#[inline]
#[cfg(feature = "simd")]
fn mul_add(self, a: Self, b: Self) -> Self {
self.mul_add(a, b)
}
}
};
}
Expand Down
9 changes: 8 additions & 1 deletion crates/fuzz/src/config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -106,12 +106,12 @@
bulk_memory_enabled: true,
reference_types_enabled: false, // TODO: re-enable reference-types for differential fuzzing
simd_enabled: true,
relaxed_simd_enabled: true,
multi_value_enabled: true,
memory64_enabled: true,
saturating_float_to_int_enabled: true,
sign_extension_ops_enabled: true,
wide_arithmetic_enabled: true,
relaxed_simd_enabled: false,
exceptions_enabled: false,
threads_enabled: false,
tail_call_enabled: true,
Expand Down Expand Up @@ -178,6 +178,13 @@
pub fn disable_simd(&mut self) {
self.inner.simd_enabled = false;
}

/// Disable the Wasm `relaxed-simd` proposal.
///
/// This is required by some supported Wasm runtime oracles.
pub fn disable_relaxed_simd(&mut self) {
self.inner.relaxed_simd_enabled = false;

Check warning on line 186 in crates/fuzz/src/config.rs

View check run for this annotation

Codecov / codecov/patch

crates/fuzz/src/config.rs#L185-L186

Added lines #L185 - L186 were not covered by tests
}
}

impl From<FuzzSmithConfig> for wasm_smith::Config {
Expand Down
1 change: 1 addition & 0 deletions crates/fuzz/src/oracle/wasmi_stack.rs
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@
config.disable_memory64();
config.disable_wide_arithmetic();
config.disable_simd();
config.disable_relaxed_simd();

Check warning on line 38 in crates/fuzz/src/oracle/wasmi_stack.rs

View check run for this annotation

Codecov / codecov/patch

crates/fuzz/src/oracle/wasmi_stack.rs#L38

Added line #L38 was not covered by tests
}

fn setup(wasm: &[u8]) -> Option<Self>
Expand Down
1 change: 1 addition & 0 deletions crates/fuzz/src/oracle/wasmtime.rs
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@
config.cranelift_regalloc_algorithm(wasmtime::RegallocAlgorithm::SinglePass);
config.wasm_custom_page_sizes(true);
config.wasm_wide_arithmetic(true);
config.relaxed_simd_deterministic(true);

Check warning on line 42 in crates/fuzz/src/oracle/wasmtime.rs

View check run for this annotation

Codecov / codecov/patch

crates/fuzz/src/oracle/wasmtime.rs#L42

Added line #L42 was not covered by tests
let engine = Engine::new(&config).unwrap();
let linker = Linker::new(&engine);
let limiter = StoreLimitsBuilder::new()
Expand Down
75 changes: 75 additions & 0 deletions crates/ir/src/for_each_op.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6221,6 +6221,81 @@ macro_rules! for_each_op_grouped {
/// The register storing the `rhs` of the instruction.
rhs: Reg,
},
/// Wasm `i32x4.relaxed_dot_i8x16_i7x8_s` instruction.
#[snake_name(i16x8_relaxed_dot_i8x16_i7x16_s)]
I16x8RelaxedDotI8x16I7x16S {
@result: Reg,
/// The register storing the `lhs` of the instruction.
lhs: Reg,
/// The register storing the `rhs` of the instruction.
rhs: Reg,
},
/// Wasm `i32x4.relaxed_dot_i8x16_i7x16_add_s` instruction.
///
/// # Encoding
///
/// Followed by an [`Instruction::Register`] encoding `c`.
#[snake_name(i32x4_relaxed_dot_i8x16_i7x16_add_s)]
I32x4RelaxedDotI8x16I7x16AddS {
@result: Reg,
/// The register storing the `lhs` of the instruction.
lhs: Reg,
/// The register storing the `rhs` of the instruction.
rhs: Reg,
},

/// Wasm `f32x4.relaxed_madd` instruction.
///
/// # Encoding
///
/// Followed by an [`Instruction::Register`] encoding `c`.
#[snake_name(f32x4_relaxed_madd)]
F32x4RelaxedMadd {
@result: Reg,
/// The register storing the `a` of the instruction.
a: Reg,
/// The register storing the `b` of the instruction.
b: Reg,
},
/// Wasm `f32x4.relaxed_nmadd` instruction.
///
/// # Encoding
///
/// Followed by an [`Instruction::Register`] encoding `c`.
#[snake_name(f32x4_relaxed_nmadd)]
F32x4RelaxedNmadd {
@result: Reg,
/// The register storing the `a` of the instruction.
a: Reg,
/// The register storing the `b` of the instruction.
b: Reg,
},
/// Wasm `f64x2.relaxed_madd` instruction.
///
/// # Encoding
///
/// Followed by an [`Instruction::Register`] encoding `c`.
#[snake_name(f64x2_relaxed_madd)]
F64x2RelaxedMadd {
@result: Reg,
/// The register storing the `a` of the instruction.
a: Reg,
/// The register storing the `b` of the instruction.
b: Reg,
},
/// Wasm `f64x2.relaxed_nmadd` instruction.
///
/// # Encoding
///
/// Followed by an [`Instruction::Register`] encoding `c`.
#[snake_name(f64x2_relaxed_nmadd)]
F64x2RelaxedNmadd {
@result: Reg,
/// The register storing the `a` of the instruction.
a: Reg,
/// The register storing the `b` of the instruction.
b: Reg,
},

/// Wasm `i8x16.neg` instruction.
#[snake_name(i8x16_neg)]
Expand Down
12 changes: 12 additions & 0 deletions crates/wasmi/src/engine/config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -185,6 +185,7 @@
features.set(WasmFeatures::MEMORY64, true);
features.set(WasmFeatures::WIDE_ARITHMETIC, false);
features.set(WasmFeatures::SIMD, cfg!(feature = "simd"));
features.set(WasmFeatures::RELAXED_SIMD, cfg!(feature = "simd"));
features
}

Expand Down Expand Up @@ -370,6 +371,17 @@
self
}

/// Enable or disable the [`relaxed-simd`] Wasm proposal for the [`Config`].
///
/// Enabled by default.
///
/// [`relaxed-simd`]: https://github.com/WebAssembly/relaxed-simd
#[cfg(feature = "simd")]
pub fn wasm_relaxed_simd(&mut self, enable: bool) -> &mut Self {
self.features.set(WasmFeatures::RELAXED_SIMD, enable);

Check warning on line 381 in crates/wasmi/src/engine/config.rs

View check run for this annotation

Codecov / codecov/patch

crates/wasmi/src/engine/config.rs#L380-L381

Added lines #L380 - L381 were not covered by tests
self
}

/// Enable or disable Wasm floating point (`f32` and `f64`) instructions and types.
///
/// Enabled by default.
Expand Down
24 changes: 24 additions & 0 deletions crates/wasmi/src/engine/executor/instrs.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2273,6 +2273,30 @@ impl<'engine> Executor<'engine> {
Instr::V128Load64LaneAt { result, address } => {
self.execute_v128_load64_lane_at(&store.inner, result, address)?
}
#[cfg(feature = "simd")]
Instr::I16x8RelaxedDotI8x16I7x16S { result, lhs, rhs } => {
self.execute_i16x8_relaxed_dot_i8x16_i7x16_s(result, lhs, rhs)
}
#[cfg(feature = "simd")]
Instr::I32x4RelaxedDotI8x16I7x16AddS { result, lhs, rhs } => {
self.execute_i32x4_relaxed_dot_i8x16_i7x16_add_s(result, lhs, rhs)
}
#[cfg(feature = "simd")]
Instr::F32x4RelaxedMadd { result, a, b } => {
self.execute_f32x4_relaxed_madd(result, a, b)
}
#[cfg(feature = "simd")]
Instr::F32x4RelaxedNmadd { result, a, b } => {
self.execute_f32x4_relaxed_nmadd(result, a, b)
}
#[cfg(feature = "simd")]
Instr::F64x2RelaxedMadd { result, a, b } => {
self.execute_f64x2_relaxed_madd(result, a, b)
}
#[cfg(feature = "simd")]
Instr::F64x2RelaxedNmadd { result, a, b } => {
self.execute_f64x2_relaxed_nmadd(result, a, b)
}
unsupported => panic!("encountered unsupported Wasmi instruction: {unsupported:?}"),
}
}
Expand Down
Loading