Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Appearance settings
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
22 changes: 22 additions & 0 deletions 22 crates/wasm-encoder/src/core/code.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1223,6 +1223,12 @@ pub enum Instruction<'a> {
cont_type_index: u32,
tag_index: u32,
},

// Wide Arithmetic
I64Add128,
I64Sub128,
I64MulWideS,
I64MulWideU,
}

impl Encode for Instruction<'_> {
Expand Down Expand Up @@ -3757,6 +3763,22 @@ impl Encode for Instruction<'_> {
cont_type_index.encode(sink);
tag_index.encode(sink);
}
Instruction::I64Add128 => {
sink.push(0xFC);
19u32.encode(sink);
}
Instruction::I64Sub128 => {
sink.push(0xFC);
20u32.encode(sink);
}
Instruction::I64MulWideS => {
sink.push(0xFC);
21u32.encode(sink);
}
Instruction::I64MulWideU => {
sink.push(0xFC);
22u32.encode(sink);
}
}
}
}
Expand Down
8 changes: 8 additions & 0 deletions 8 crates/wasm-smith/src/config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -599,6 +599,13 @@ define_config! {
///
/// Defaults to `false`.
pub allow_invalid_funcs: bool = false,

/// Determines whether the [wide-arithmetic proposal] is enabled.
///
/// [wide-arithmetic proposal]: https://github.com/WebAssembly/wide-arithmetic
///
/// Defaults to `false`.
pub wide_arithmetic_enabled: bool = false,
}
}

Expand Down Expand Up @@ -738,6 +745,7 @@ impl<'a> Arbitrary<'a> for Config {
// Proposals that are not stage4+ are disabled by default.
memory64_enabled: false,
custom_page_sizes_enabled: false,
wide_arithmetic_enabled: false,
};
config.sanitize();
Ok(config)
Expand Down
62 changes: 62 additions & 0 deletions 62 crates/wasm-smith/src/core/code_builder.rs
Original file line number Diff line number Diff line change
Expand Up @@ -590,6 +590,10 @@ instructions! {
(Some(simd_v128_v128_on_stack_relaxed), i16x8_relaxed_q15mulr_s, VectorInt),
(Some(simd_v128_v128_on_stack_relaxed), i16x8_relaxed_dot_i8x16_i7x16_s, VectorInt),
(Some(simd_v128_v128_v128_on_stack_relaxed), i32x4_relaxed_dot_i8x16_i7x16_add_s, VectorInt),
(Some(wide_arithmetic_binop128_on_stack), i64_add128, NumericInt),
(Some(wide_arithmetic_binop128_on_stack), i64_sub128, NumericInt),
(Some(wide_arithmetic_mul_wide_on_stack), i64_mul_wide_s, NumericInt),
(Some(wide_arithmetic_mul_wide_on_stack), i64_mul_wide_u, NumericInt),
}

pub(crate) struct CodeBuilderAllocations {
Expand Down Expand Up @@ -7266,3 +7270,61 @@ simd_ternop!(
I32x4RelaxedDotI8x16I7x16AddS,
i32x4_relaxed_dot_i8x16_i7x16_add_s
);

#[inline]
fn wide_arithmetic_binop128_on_stack(module: &Module, builder: &mut CodeBuilder) -> bool {
module.config.wide_arithmetic_enabled && builder.types_on_stack(module, &[ValType::I64; 4])
}

#[inline]
fn wide_arithmetic_mul_wide_on_stack(module: &Module, builder: &mut CodeBuilder) -> bool {
module.config.wide_arithmetic_enabled && builder.types_on_stack(module, &[ValType::I64; 2])
}

fn i64_add128(
_: &mut Unstructured,
module: &Module,
builder: &mut CodeBuilder,
instructions: &mut Vec<Instruction>,
) -> Result<()> {
builder.pop_operands(module, &[ValType::I64; 4]);
builder.push_operands(&[ValType::I64; 2]);
instructions.push(Instruction::I64Add128);
Ok(())
}

fn i64_sub128(
_: &mut Unstructured,
module: &Module,
builder: &mut CodeBuilder,
instructions: &mut Vec<Instruction>,
) -> Result<()> {
builder.pop_operands(module, &[ValType::I64; 4]);
builder.push_operands(&[ValType::I64; 2]);
instructions.push(Instruction::I64Sub128);
Ok(())
}

fn i64_mul_wide_s(
_: &mut Unstructured,
module: &Module,
builder: &mut CodeBuilder,
instructions: &mut Vec<Instruction>,
) -> Result<()> {
builder.pop_operands(module, &[ValType::I64; 2]);
builder.push_operands(&[ValType::I64; 2]);
instructions.push(Instruction::I64MulWideS);
Ok(())
}

fn i64_mul_wide_u(
_: &mut Unstructured,
module: &Module,
builder: &mut CodeBuilder,
instructions: &mut Vec<Instruction>,
) -> Result<()> {
builder.pop_operands(module, &[ValType::I64; 2]);
builder.push_operands(&[ValType::I64; 2]);
instructions.push(Instruction::I64MulWideU);
Ok(())
}
5 changes: 5 additions & 0 deletions 5 crates/wasmparser/src/binary_reader.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1357,6 +1357,11 @@ impl<'a> BinaryReader<'a> {
visitor.visit_memory_discard(mem)
}

0x13 => visitor.visit_i64_add128(),
0x14 => visitor.visit_i64_sub128(),
0x15 => visitor.visit_i64_mul_wide_s(),
0x16 => visitor.visit_i64_mul_wide_u(),

_ => bail!(pos, "unknown 0xfc subopcode: 0x{code:x}"),
})
}
Expand Down
2 changes: 2 additions & 0 deletions 2 crates/wasmparser/src/features.rs
Original file line number Diff line number Diff line change
Expand Up @@ -227,6 +227,8 @@ define_wasm_features! {
pub gc_types: GC_TYPES(1 << 26) = true;
/// The WebAssembly [stack-switching proposal](https://github.com/WebAssembly/stack-switching).
pub stack_switching: STACK_SWITCHING(1 << 27) = false;
/// The WebAssembly [wide-arithmetic proposal](https://github.com/WebAssembly/wide-arithmetic).
pub wide_arithmetic: WIDE_ARITHMETIC(1 << 28) = false;
}
}

Expand Down
5 changes: 5 additions & 0 deletions 5 crates/wasmparser/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -815,6 +815,11 @@ macro_rules! for_each_operator {
@stack_switching Resume { cont_type_index: u32, resume_table: $crate::ResumeTable } => visit_resume (arity 1 type -> type)
@stack_switching ResumeThrow { cont_type_index: u32, tag_index: u32, resume_table: $crate::ResumeTable } => visit_resume_throw (arity 1 tag -> type)
@stack_switching Switch { cont_type_index: u32, tag_index: u32 } => visit_switch (arity type -> ~switch)

@wide_arithmetic I64Add128 => visit_i64_add128 (arity 4 -> 2)
@wide_arithmetic I64Sub128 => visit_i64_sub128 (arity 4 -> 2)
@wide_arithmetic I64MulWideS => visit_i64_mul_wide_s (arity 2 -> 2)
@wide_arithmetic I64MulWideU => visit_i64_mul_wide_u (arity 2 -> 2)
}
};
}
Expand Down
31 changes: 31 additions & 0 deletions 31 crates/wasmparser/src/validator/operators.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1640,6 +1640,24 @@ where
.zip(ts2.iter())
.all(|(ty1, ty2)| self.resources.is_subtype(*ty1, *ty2))
}

fn check_binop128(&mut self) -> Result<()> {
self.pop_operand(Some(ValType::I64))?;
self.pop_operand(Some(ValType::I64))?;
self.pop_operand(Some(ValType::I64))?;
self.pop_operand(Some(ValType::I64))?;
self.push_operand(ValType::I64)?;
self.push_operand(ValType::I64)?;
Ok(())
}

fn check_i64_mul_wide(&mut self) -> Result<()> {
self.pop_operand(Some(ValType::I64))?;
self.pop_operand(Some(ValType::I64))?;
self.push_operand(ValType::I64)?;
self.push_operand(ValType::I64)?;
Ok(())
}
}

pub fn ty_to_str(ty: ValType) -> &'static str {
Expand Down Expand Up @@ -1704,6 +1722,7 @@ macro_rules! validate_proposal {
(desc gc) => ("gc");
(desc legacy_exceptions) => ("legacy exceptions");
(desc stack_switching) => ("stack switching");
(desc wide_arithmetic) => ("wide arithmetic");
}

impl<'a, T> VisitOperator<'a> for WasmProposalValidator<'_, '_, T>
Expand Down Expand Up @@ -5035,6 +5054,18 @@ where
}
Ok(())
}
fn visit_i64_add128(&mut self) -> Result<()> {
self.check_binop128()
}
fn visit_i64_sub128(&mut self) -> Result<()> {
self.check_binop128()
}
fn visit_i64_mul_wide_s(&mut self) -> Result<()> {
self.check_i64_mul_wide()
}
fn visit_i64_mul_wide_u(&mut self) -> Result<()> {
self.check_i64_mul_wide()
}
}

#[derive(Clone, Debug)]
Expand Down
6 changes: 5 additions & 1 deletion 6 crates/wasmprinter/src/operator.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1379,7 +1379,11 @@ macro_rules! define_visit {
(name Suspend) => ("suspend");
(name Resume) => ("resume");
(name ResumeThrow) => ("resume_throw");
(name Switch) => ("switch")
(name Switch) => ("switch");
(name I64Add128) => ("i64.add128");
(name I64Sub128) => ("i64.sub128");
(name I64MulWideS) => ("i64.mul_wide_s");
(name I64MulWideU) => ("i64.mul_wide_u");
}

impl<'a> VisitOperator<'a> for PrintOperator<'_, '_, '_, '_> {
Expand Down
6 changes: 6 additions & 0 deletions 6 crates/wast/src/core/expr.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1195,6 +1195,12 @@ instructions! {
Resume(Resume<'a>) : [0xe3] : "resume",
ResumeThrow(ResumeThrow<'a>) : [0xe4] : "resume_throw",
Switch(Switch<'a>) : [0xe5] : "switch",

// Wide arithmetic proposal
I64Add128 : [0xfc, 19] : "i64.add128",
I64Sub128 : [0xfc, 20] : "i64.sub128",
I64MulWideS : [0xfc, 21] : "i64.mul_wide_s",
I64MulWideU : [0xfc, 22] : "i64.mul_wide_u",
}
}

Expand Down
5 changes: 5 additions & 0 deletions 5 fuzz/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,7 @@ pub fn generate_valid_component(
config.memory64_enabled = u.arbitrary()?;
config.exceptions_enabled = u.arbitrary()?;
config.canonicalize_nans = u.arbitrary()?;
config.wide_arithmetic_enabled = u.arbitrary()?;

configure(&mut config, u)?;

Expand Down Expand Up @@ -111,6 +112,10 @@ pub fn validator_for_config(config: &Config) -> wasmparser::Validator {
// this point.
features.set(WasmFeatures::FUNCTION_REFERENCES, config.gc_enabled);
features.set(WasmFeatures::GC, config.gc_enabled);
features.set(
WasmFeatures::WIDE_ARITHMETIC,
config.wide_arithmetic_enabled,
);
wasmparser::Validator::new_with_features(features)
}

Expand Down
2 changes: 1 addition & 1 deletion 2 tests/cli/validate-unknown-features.wat.stderr
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
error: invalid value 'unknown' for '--features <FEATURES>': unknown feature `unknown`
Valid features: mutable-global, saturating-float-to-int, sign-extension, reference-types, multi-value, bulk-memory, simd, relaxed-simd, threads, shared-everything-threads, tail-call, floats, multi-memory, exceptions, memory64, extended-const, component-model, function-references, memory-control, gc, custom-page-sizes, component-model-values, component-model-nested-names, component-model-more-flags, component-model-multiple-returns, legacy-exceptions, gc-types, stack-switching, mvp, wasm1, wasm2, wasm3, all
Valid features: mutable-global, saturating-float-to-int, sign-extension, reference-types, multi-value, bulk-memory, simd, relaxed-simd, threads, shared-everything-threads, tail-call, floats, multi-memory, exceptions, memory64, extended-const, component-model, function-references, memory-control, gc, custom-page-sizes, component-model-values, component-model-nested-names, component-model-more-flags, component-model-multiple-returns, legacy-exceptions, gc-types, stack-switching, wide-arithmetic, mvp, wasm1, wasm2, wasm3, all

For more information, try '--help'.
47 changes: 47 additions & 0 deletions 47 tests/local/missing-features/wide-arithmetic.wast
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
(assert_invalid
(module
(func (param i64 i64 i64 i64)
local.get 0
local.get 1
local.get 2
local.get 3
i64.add128
drop
drop)
)
"wide arithmetic support is not enabled")

(assert_invalid
(module
(func (param i64 i64 i64 i64)
local.get 0
local.get 1
local.get 2
local.get 3
i64.sub128
drop
drop)
)
"wide arithmetic support is not enabled")

(assert_invalid
(module
(func (param i64 i64)
local.get 0
local.get 1
i64.mul_wide_s
drop
drop)
)
"wide arithmetic support is not enabled")

(assert_invalid
(module
(func (param i64 i64)
local.get 0
local.get 1
i64.mul_wide_u
drop
drop)
)
"wide arithmetic support is not enabled")
Loading
Morty Proxy This is a proxified and sanitized view of the page, visit original site.