diff --git a/crates/types/src/lib.rs b/crates/types/src/lib.rs index 0ba5cd9539..c5940b3e58 100644 --- a/crates/types/src/lib.rs +++ b/crates/types/src/lib.rs @@ -1484,6 +1484,12 @@ pub enum ConstOp { RefI31, RefNull, RefFunc(FuncIndex), + I32Add, + I32Sub, + I32Mul, + I64Add, + I64Sub, + I64Mul, } impl ConstOp { @@ -1500,6 +1506,12 @@ impl ConstOp { O::RefFunc { function_index } => Self::RefFunc(FuncIndex::from_u32(function_index)), O::GlobalGet { global_index } => Self::GlobalGet(GlobalIndex::from_u32(global_index)), O::RefI31 => Self::RefI31, + O::I32Add => Self::I32Add, + O::I32Sub => Self::I32Sub, + O::I32Mul => Self::I32Mul, + O::I64Add => Self::I64Add, + O::I64Sub => Self::I64Sub, + O::I64Mul => Self::I64Mul, op => { return Err(wasm_unsupported!( "unsupported opcode in const expression at offset {offset:#x}: {op:?}", diff --git a/crates/wasmtime/src/config.rs b/crates/wasmtime/src/config.rs index 555c3d714f..a25cfd35ce 100644 --- a/crates/wasmtime/src/config.rs +++ b/crates/wasmtime/src/config.rs @@ -259,9 +259,6 @@ impl Config { ret.cranelift_opt_level(OptLevel::Speed); } - // Not yet implemented in Wasmtime - ret.features.set(WasmFeatures::EXTENDED_CONST, false); - // Conditionally enabled features depending on compile-time crate // features. Note that if these features are disabled then `Config` has // no way of re-enabling them. @@ -285,6 +282,7 @@ impl Config { ret.wasm_multi_value(true); ret.wasm_bulk_memory(true); ret.wasm_simd(true); + ret.wasm_extended_const(true); ret.wasm_backtrace_details(WasmBacktraceDetails::Environment); ret @@ -963,6 +961,17 @@ impl Config { self } + /// Configures whether the WebAssembly extended-const [proposal] will + /// be enabled for compilation. + /// + /// This is `true` by default. + /// + /// [proposal]: https://github.com/webassembly/extended-const + pub fn wasm_extended_const(&mut self, enable: bool) -> &mut Self { + self.features.set(WasmFeatures::EXTENDED_CONST, enable); + self + } + /// Configures whether the WebAssembly component-model [proposal] will /// be enabled for compilation. /// diff --git a/crates/wasmtime/src/runtime/vm/const_expr.rs b/crates/wasmtime/src/runtime/vm/const_expr.rs index 55a6d0a8ff..198673b930 100644 --- a/crates/wasmtime/src/runtime/vm/const_expr.rs +++ b/crates/wasmtime/src/runtime/vm/const_expr.rs @@ -78,6 +78,36 @@ impl ConstExprEvaluator { let raw = VMGcRef::from_i31(i31).as_raw_u32(); self.stack.push(ValRaw::anyref(raw)); } + wasmtime_environ::ConstOp::I32Add => { + let b = self.pop()?.get_i32(); + let a = self.pop()?.get_i32(); + self.stack.push(ValRaw::i32(a.wrapping_add(b))); + } + wasmtime_environ::ConstOp::I32Sub => { + let b = self.pop()?.get_i32(); + let a = self.pop()?.get_i32(); + self.stack.push(ValRaw::i32(a.wrapping_sub(b))); + } + wasmtime_environ::ConstOp::I32Mul => { + let b = self.pop()?.get_i32(); + let a = self.pop()?.get_i32(); + self.stack.push(ValRaw::i32(a.wrapping_mul(b))); + } + wasmtime_environ::ConstOp::I64Add => { + let b = self.pop()?.get_i64(); + let a = self.pop()?.get_i64(); + self.stack.push(ValRaw::i64(a.wrapping_add(b))); + } + wasmtime_environ::ConstOp::I64Sub => { + let b = self.pop()?.get_i64(); + let a = self.pop()?.get_i64(); + self.stack.push(ValRaw::i64(a.wrapping_sub(b))); + } + wasmtime_environ::ConstOp::I64Mul => { + let b = self.pop()?.get_i64(); + let a = self.pop()?.get_i64(); + self.stack.push(ValRaw::i64(a.wrapping_mul(b))); + } } } diff --git a/tests/wast.rs b/tests/wast.rs index 68ead32242..e4983d7d3e 100644 --- a/tests/wast.rs +++ b/tests/wast.rs @@ -74,10 +74,6 @@ fn ignore(test: &Path, strategy: Strategy) -> bool { if part == "exception-handling" { return true; } - // Not implemented in Wasmtime yet - if part == "extended-const" { - return true; - } // Wasmtime doesn't implement the table64 extension yet. if part == "memory64" { if [ @@ -219,6 +215,7 @@ fn run_wast(wast: &Path, strategy: Strategy, pooling: bool) -> anyhow::Result<() let tail_call = feature_found(wast, "tail-call") || feature_found(wast, "function-references"); let use_shared_memory = feature_found_src(&wast_bytes, "shared_memory") || feature_found_src(&wast_bytes, "shared)"); + let extended_const = feature_found(wast, "extended-const"); if pooling && use_shared_memory { log::warn!("skipping pooling test with shared memory"); @@ -240,6 +237,7 @@ fn run_wast(wast: &Path, strategy: Strategy, pooling: bool) -> anyhow::Result<() .wasm_relaxed_simd(relaxed_simd) .wasm_tail_call(tail_call) .wasm_custom_page_sizes(custom_page_sizes) + .wasm_extended_const(extended_const) .strategy(strategy); if is_cranelift {