diff --git a/CHANGELOG.md b/CHANGELOG.md index ee14315533d..654c4b5d288 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -110,6 +110,9 @@ * `UnwrapThrowExt for Result` now makes use of the required `Debug` bound to display the error as well. [#4035](https://github.com/rustwasm/wasm-bindgen/pull/4035) +* MSRV of CLI tools bumped to v1.76. This does not affect libraries like `wasm-bindgen`, `js-sys` and `web-sys`! + [#4037](https://github.com/rustwasm/wasm-bindgen/pull/4037) + ### Fixed * Copy port from headless test server when using `WASM_BINDGEN_TEST_ADDRESS`. diff --git a/crates/cli-support/Cargo.toml b/crates/cli-support/Cargo.toml index 48bb44f93f1..157c1b6c160 100644 --- a/crates/cli-support/Cargo.toml +++ b/crates/cli-support/Cargo.toml @@ -19,7 +19,7 @@ log = "0.4" rustc-demangle = "0.1.13" serde_json = "1.0" tempfile = "3.0" -walrus = "0.20.2" +walrus = "0.21" wasm-bindgen-externref-xform = { path = '../externref-xform', version = '=0.2.92' } wasm-bindgen-multi-value-xform = { path = '../multi-value-xform', version = '=0.2.92' } wasm-bindgen-shared = { path = "../shared", version = '=0.2.92' } diff --git a/crates/cli-support/src/descriptors.rs b/crates/cli-support/src/descriptors.rs index b4af4bc36a9..83617900532 100644 --- a/crates/cli-support/src/descriptors.rs +++ b/crates/cli-support/src/descriptors.rs @@ -11,10 +11,10 @@ //! functions. use crate::descriptor::{Closure, Descriptor}; -use anyhow::Error; +use anyhow::{bail, Error}; use std::borrow::Cow; -use std::collections::{HashMap, HashSet}; -use walrus::ImportId; +use std::collections::HashMap; +use walrus::{ConstExpr, ElementItems, ElementKind, ImportId, RefType}; use walrus::{CustomSection, FunctionId, Module, TypedCustomSectionId}; use wasm_bindgen_wasm_interpreter::Interpreter; @@ -87,7 +87,7 @@ impl WasmBindgenDescriptorsSection { // Find all functions which call `wbindgen_describe_closure`. These are // specially codegen'd so we know the rough structure of them. For each // one we delegate to the interpreter to figure out the actual result. - let mut element_removal_list = HashSet::new(); + let mut element_removal_list = HashMap::new(); let mut func_to_descriptor = HashMap::new(); for (id, local) in module.funcs.iter_local() { let mut find = FindDescribeClosure { @@ -106,9 +106,55 @@ impl WasmBindgenDescriptorsSection { // For all indirect functions that were closure descriptors, delete them // from the function table since we've executed them and they're not // necessary in the final binary. - for (segment, idx) in element_removal_list { - log::trace!("delete element {}", idx); - module.elements.get_mut(segment).members[idx] = None; + for (segment, idxs) in element_removal_list { + let segment = module.elements.get_mut(segment); + + let items = match &mut segment.items { + ElementItems::Functions(items) => items, + ElementItems::Expressions(_, items) => { + for idx in idxs { + log::trace!("delete element {}", idx); + items[idx] = ConstExpr::RefNull(RefType::Funcref) + } + + continue; + } + }; + + let (table, offset) = match &segment.kind { + ElementKind::Active { + table, + offset: ConstExpr::Value(Value::I32(n)), + } => (*table, *n), + _ => bail!("somehow found a closure in an unexpected element segment"), + }; + + let mut to_insert = Vec::new(); + + for idx in idxs.into_iter().rev() { + log::trace!("delete element {}", idx); + + items.remove(idx); + + // Last item, no need to do anything fancy. + if items.len() == idx { + continue; + } + + let block = items.split_off(idx); + let offset = offset + idx as i32 + 1; + let offset = ConstExpr::Value(Value::I32(offset)); + + to_insert.push((offset, block)); + } + + for (offset, block) in to_insert.into_iter().rev() { + let id = module.elements.add( + ElementKind::Active { table, offset }, + ElementItems::Functions(block), + ); + module.tables.get_mut(table).elem_segments.insert(id); + } } // And finally replace all calls of `wbindgen_describe_closure` with a diff --git a/crates/cli-support/src/externref.rs b/crates/cli-support/src/externref.rs index ef3a726ad9f..be732ceeef0 100644 --- a/crates/cli-support/src/externref.rs +++ b/crates/cli-support/src/externref.rs @@ -5,7 +5,8 @@ use crate::wit::{AdapterKind, Instruction, NonstandardWitSection}; use crate::wit::{AdapterType, InstructionData, StackChange, WasmBindgenAux}; use anyhow::Result; use std::collections::HashMap; -use walrus::{ir::Value, ElementKind, InitExpr, Module}; +use walrus::ElementItems; +use walrus::{ir::Value, ConstExpr, ElementKind, Module}; use wasm_bindgen_externref_xform::Context; pub fn process(module: &mut Module) -> Result<()> { @@ -397,11 +398,22 @@ pub fn force_contiguous_elements(module: &mut Module) -> Result<()> { // Here we take a look at all element segments in the module to see if we // need to split them. for segment in module.elements.iter_mut() { - // If this segment has all-`Some` members then it's already contiguous - // and we can skip it. - if segment.members.iter().all(|m| m.is_some()) { - continue; - } + let (ty, items) = match &mut segment.items { + ElementItems::Expressions(ty, items) => { + // If this segment has no null reference members then it's already + // contiguous and we can skip it. + if items + .iter() + .all(|item| !matches!(item, ConstExpr::RefNull(_))) + { + continue; + } + + (*ty, items) + } + // Function index segments don't have holes. + ElementItems::Functions(_) => continue, + }; // For now active segments are all we're interested in since // passive/declared have no hope of being MVP-compatible anyway. @@ -410,7 +422,7 @@ pub fn force_contiguous_elements(module: &mut Module) -> Result<()> { let (table, offset) = match &segment.kind { ElementKind::Active { table, - offset: InitExpr::Value(Value::I32(n)), + offset: ConstExpr::Value(Value::I32(n)), } => (*table, *n), _ => continue, }; @@ -425,16 +437,13 @@ pub fn force_contiguous_elements(module: &mut Module) -> Result<()> { // offset. let mut commit = |last_idx: usize, block: Vec<_>| { let new_offset = offset + (last_idx - block.len()) as i32; - let new_offset = InitExpr::Value(Value::I32(new_offset)); - new_segments.push((table, new_offset, segment.ty, block)); + let new_offset = ConstExpr::Value(Value::I32(new_offset)); + new_segments.push((table, new_offset, ty, block)); }; - for (i, id) in segment.members.iter().enumerate() { - match id { - // If we find a function, then we either start a new block or - // push it onto the existing block. - Some(id) => block.get_or_insert(Vec::new()).push(Some(*id)), - None => { - let block = match block.take() { + for (i, expr) in items.iter().enumerate() { + match expr { + ConstExpr::RefNull(_) => { + let block: Vec<_> = match block.take() { Some(b) => b, None => continue, }; @@ -449,21 +458,25 @@ pub fn force_contiguous_elements(module: &mut Module) -> Result<()> { commit(i, block); } } + // If we find a function, then we either start a new block or + // push it onto the existing block. + _ => block.get_or_insert(Vec::new()).push(*expr), } } // If there's no trailing empty slots then we commit the last block onto // the new segment list. if let Some(block) = block { - commit(segment.members.len(), block); + commit(items.len(), block); } - segment.members.truncate(truncate); + items.truncate(truncate); } for (table, offset, ty, members) in new_segments { - let id = module - .elements - .add(ElementKind::Active { table, offset }, ty, members); + let id = module.elements.add( + ElementKind::Active { table, offset }, + ElementItems::Expressions(ty, members), + ); module.tables.get_mut(table).elem_segments.insert(id); } Ok(()) diff --git a/crates/cli-support/src/multivalue.rs b/crates/cli-support/src/multivalue.rs index 4ba319685db..f6b8afb078f 100644 --- a/crates/cli-support/src/multivalue.rs +++ b/crates/cli-support/src/multivalue.rs @@ -2,7 +2,7 @@ use crate::wit::{Adapter, NonstandardWitSection}; use crate::wit::{AdapterKind, Instruction, WasmBindgenAux}; use anyhow::{anyhow, Error}; use walrus::ir::Value; -use walrus::{FunctionId, InitExpr, Module}; +use walrus::{ConstExpr, FunctionId, Module}; use wasm_bindgen_multi_value_xform as multi_value_xform; use wasm_bindgen_wasm_conventions as wasm_conventions; @@ -125,19 +125,36 @@ fn resolve_table_entry(module: &Module, func_index: u32) -> FunctionId { let elem = module.elements.get(id); let offset = match elem.kind { walrus::ElementKind::Active { offset, .. } => match offset { - InitExpr::Value(Value::I32(value)) => value as u32, + ConstExpr::Value(Value::I32(value)) => value as u32, _ => panic!("table offset was not an i32 value"), }, _ => panic!("found non-active element section for function table"), }; - elem.members.iter().enumerate().find_map(|(i, &func_id)| { + + let find = |(i, func_id): (usize, Option<&FunctionId>)| { let table_index = i as u32 + offset; if table_index == func_index { - func_id + func_id.cloned() } else { None } - }) + }; + match &elem.items { + walrus::ElementItems::Functions(items) => { + items.iter().map(Some).enumerate().find_map(find) + } + walrus::ElementItems::Expressions(_, items) => items + .iter() + .map(|expr| { + if let ConstExpr::RefFunc(id) = expr { + Some(id) + } else { + None + } + }) + .enumerate() + .find_map(find), + } }) .expect("function in function table is not initialized") } @@ -154,15 +171,31 @@ fn set_table_entry(module: &mut Module, func_index: u32, new_id: FunctionId) { let elem = module.elements.get_mut(id); let offset = match elem.kind { walrus::ElementKind::Active { offset, .. } => match offset { - InitExpr::Value(Value::I32(value)) => value as u32, + ConstExpr::Value(Value::I32(value)) => value as u32, _ => panic!("table offset was not an i32 value"), }, _ => panic!("found non-active element section for function table"), }; - for (i, func_id) in elem.members.iter_mut().enumerate() { - let table_index = i as u32 + offset; - if table_index == func_index { - *func_id = Some(new_id); + match &mut elem.items { + walrus::ElementItems::Functions(items) => { + items.iter_mut().enumerate().for_each(|(i, func_id)| { + let table_index = i as u32 + offset; + if table_index == func_index { + *func_id = new_id; + } + }) + } + walrus::ElementItems::Expressions(_, items) => { + items.iter_mut().enumerate().for_each(|(i, func_id)| { + let table_index = i as u32 + offset; + if table_index == func_index { + assert!( + matches!(func_id, ConstExpr::RefFunc(_)), + "didn't find a function at the expected position" + ); + *func_id = ConstExpr::RefFunc(new_id); + } + }) } } } diff --git a/crates/cli-support/src/wit/standard.rs b/crates/cli-support/src/wit/standard.rs index e4d7aa745c1..0be106f060d 100644 --- a/crates/cli-support/src/wit/standard.rs +++ b/crates/cli-support/src/wit/standard.rs @@ -2,7 +2,7 @@ use crate::descriptor::VectorKind; use crate::wit::{AuxImport, WasmBindgenAux}; use std::borrow::Cow; use std::collections::{HashMap, HashSet}; -use walrus::{FunctionId, ImportId, TypedCustomSectionId}; +use walrus::{FunctionId, ImportId, RefType, TypedCustomSectionId}; #[derive(Default, Debug)] pub struct NonstandardWitSection { @@ -344,8 +344,8 @@ impl AdapterType { walrus::ValType::I64 => AdapterType::I64, walrus::ValType::F32 => AdapterType::F32, walrus::ValType::F64 => AdapterType::F64, - walrus::ValType::Externref => AdapterType::Externref, - walrus::ValType::Funcref | walrus::ValType::V128 => return None, + walrus::ValType::Ref(RefType::Externref) => AdapterType::Externref, + walrus::ValType::Ref(_) | walrus::ValType::V128 => return None, }) } @@ -356,7 +356,9 @@ impl AdapterType { AdapterType::F32 => walrus::ValType::F32, AdapterType::F64 => walrus::ValType::F64, AdapterType::Enum(_) => walrus::ValType::I32, - AdapterType::Externref | AdapterType::NamedExternref(_) => walrus::ValType::Externref, + AdapterType::Externref | AdapterType::NamedExternref(_) => { + walrus::ValType::Ref(RefType::Externref) + } _ => return None, }) } diff --git a/crates/cli/Cargo.toml b/crates/cli/Cargo.toml index b4f1b2c7885..78a7915daa4 100644 --- a/crates/cli/Cargo.toml +++ b/crates/cli/Cargo.toml @@ -33,7 +33,7 @@ ureq = { version = "2.7", default-features = false, features = [ "brotli", "gzip", ] } -walrus = { version = "0.20.2", features = ['parallel'] } +walrus = { version = "0.21", features = ['parallel'] } wasm-bindgen-cli-support = { path = "../cli-support", version = "=0.2.92" } wasm-bindgen-shared = { path = "../shared", version = "=0.2.92" } @@ -43,8 +43,8 @@ diff = "0.1" predicates = "1.0.0" rayon = "1.0" tempfile = "3.0" -wasmparser = "0.102.0" -wasmprinter = "0.2.54" +wasmparser = "0.212" +wasmprinter = "0.212" [[test]] name = "reference" diff --git a/crates/cli/tests/reference/add.wat b/crates/cli/tests/reference/add.wat index b285488bd1a..62ab9c0876b 100644 --- a/crates/cli/tests/reference/add.wat +++ b/crates/cli/tests/reference/add.wat @@ -6,4 +6,6 @@ (export "memory" (memory 0)) (export "add_u32" (func $add_u32)) (export "add_i32" (func $add_i32)) + (@custom "target_features" (after code) "\02+\0fmutable-globals+\08sign-ext") ) + diff --git a/crates/cli/tests/reference/anyref-empty.wat b/crates/cli/tests/reference/anyref-empty.wat index d8de8796570..2ff9975bfff 100644 --- a/crates/cli/tests/reference/anyref-empty.wat +++ b/crates/cli/tests/reference/anyref-empty.wat @@ -6,4 +6,6 @@ (export "memory" (memory 0)) (export "__wbindgen_export_0" (table 0)) (export "__wbindgen_start" (func 0)) + (@custom "target_features" (after export) "\03+\0fmutable-globals+\08sign-ext+\0freference-types") ) + diff --git a/crates/cli/tests/reference/anyref-import-catch.wat b/crates/cli/tests/reference/anyref-import-catch.wat index 42867acbf63..fd4ba663d5e 100644 --- a/crates/cli/tests/reference/anyref-import-catch.wat +++ b/crates/cli/tests/reference/anyref-import-catch.wat @@ -19,4 +19,6 @@ (export "__wbindgen_add_to_stack_pointer" (func $__wbindgen_add_to_stack_pointer)) (export "__externref_table_dealloc" (func $__externref_table_dealloc)) (export "__wbindgen_start" (func 0)) + (@custom "target_features" (after code) "\03+\0fmutable-globals+\08sign-ext+\0freference-types") ) + diff --git a/crates/cli/tests/reference/anyref-nop.wat b/crates/cli/tests/reference/anyref-nop.wat index a410ecd9aac..5b10a28d750 100644 --- a/crates/cli/tests/reference/anyref-nop.wat +++ b/crates/cli/tests/reference/anyref-nop.wat @@ -8,4 +8,6 @@ (export "foo" (func $foo)) (export "__wbindgen_export_0" (table 0)) (export "__wbindgen_start" (func 0)) + (@custom "target_features" (after code) "\03+\0fmutable-globals+\08sign-ext+\0freference-types") ) + diff --git a/crates/cli/tests/reference/builder.wat b/crates/cli/tests/reference/builder.wat index 16a39fa1d49..47c4a031437 100644 --- a/crates/cli/tests/reference/builder.wat +++ b/crates/cli/tests/reference/builder.wat @@ -7,4 +7,6 @@ (export "memory" (memory 0)) (export "__wbg_classbuilder_free" (func $__wbg_classbuilder_free)) (export "classbuilder_builder" (func $classbuilder_builder)) + (@custom "target_features" (after code) "\02+\0fmutable-globals+\08sign-ext") ) + diff --git a/crates/cli/tests/reference/constructor.wat b/crates/cli/tests/reference/constructor.wat index 8bc0fdcb4f6..08eb4887660 100644 --- a/crates/cli/tests/reference/constructor.wat +++ b/crates/cli/tests/reference/constructor.wat @@ -7,4 +7,6 @@ (export "memory" (memory 0)) (export "__wbg_classconstructor_free" (func $__wbg_classconstructor_free)) (export "classconstructor_new" (func $classconstructor_new)) + (@custom "target_features" (after code) "\02+\0fmutable-globals+\08sign-ext") ) + diff --git a/crates/cli/tests/reference/empty.wat b/crates/cli/tests/reference/empty.wat index 78e5118949a..b2199f956b4 100644 --- a/crates/cli/tests/reference/empty.wat +++ b/crates/cli/tests/reference/empty.wat @@ -1,4 +1,6 @@ (module $reference_test.wasm (memory (;0;) 16) (export "memory" (memory 0)) + (@custom "target_features" (after export) "\02+\0fmutable-globals+\08sign-ext") ) + diff --git a/crates/cli/tests/reference/enums.wat b/crates/cli/tests/reference/enums.wat index 4928e4e4338..4c9fd212451 100644 --- a/crates/cli/tests/reference/enums.wat +++ b/crates/cli/tests/reference/enums.wat @@ -6,4 +6,6 @@ (export "memory" (memory 0)) (export "enum_echo" (func $enum_echo)) (export "option_enum_echo" (func $option_enum_echo)) + (@custom "target_features" (after code) "\02+\0fmutable-globals+\08sign-ext") ) + diff --git a/crates/cli/tests/reference/import-catch.wat b/crates/cli/tests/reference/import-catch.wat index 2c00b9253d0..2189e238a2e 100644 --- a/crates/cli/tests/reference/import-catch.wat +++ b/crates/cli/tests/reference/import-catch.wat @@ -9,4 +9,6 @@ (export "exported" (func $exported)) (export "__wbindgen_exn_store" (func $__wbindgen_exn_store)) (export "__wbindgen_add_to_stack_pointer" (func $__wbindgen_add_to_stack_pointer)) + (@custom "target_features" (after code) "\02+\0fmutable-globals+\08sign-ext") ) + diff --git a/crates/cli/tests/reference/nop.wat b/crates/cli/tests/reference/nop.wat index 27e6124af3b..211418dd944 100644 --- a/crates/cli/tests/reference/nop.wat +++ b/crates/cli/tests/reference/nop.wat @@ -4,4 +4,6 @@ (memory (;0;) 17) (export "memory" (memory 0)) (export "nop" (func $nop)) + (@custom "target_features" (after code) "\02+\0fmutable-globals+\08sign-ext") ) + diff --git a/crates/cli/tests/reference/pointers.wat b/crates/cli/tests/reference/pointers.wat index a011881f11f..5d64739088d 100644 --- a/crates/cli/tests/reference/pointers.wat +++ b/crates/cli/tests/reference/pointers.wat @@ -6,4 +6,6 @@ (export "memory" (memory 0)) (export "const_pointer" (func $const_pointer)) (export "mut_pointer" (func $mut_pointer)) + (@custom "target_features" (after code) "\02+\0fmutable-globals+\08sign-ext") ) + diff --git a/crates/cli/tests/reference/raw.wat b/crates/cli/tests/reference/raw.wat index 0b4ec6cc732..d3589ef5dba 100644 --- a/crates/cli/tests/reference/raw.wat +++ b/crates/cli/tests/reference/raw.wat @@ -11,4 +11,6 @@ (export "__wbg_test_free" (func $__wbg_test_free)) (export "test_test1" (func $test_test1)) (export "test_test2" (func $test_test2)) + (@custom "target_features" (after code) "\02+\0fmutable-globals+\08sign-ext") ) + diff --git a/crates/cli/tests/reference/result-string.wat b/crates/cli/tests/reference/result-string.wat index c887f70d2c4..c7f63576bbd 100644 --- a/crates/cli/tests/reference/result-string.wat +++ b/crates/cli/tests/reference/result-string.wat @@ -10,4 +10,6 @@ (export "exported" (func $exported)) (export "__wbindgen_add_to_stack_pointer" (func $__wbindgen_add_to_stack_pointer)) (export "__wbindgen_free" (func $__wbindgen_free)) + (@custom "target_features" (after code) "\02+\0fmutable-globals+\08sign-ext") ) + diff --git a/crates/cli/tests/reference/skip-jsdoc.wat b/crates/cli/tests/reference/skip-jsdoc.wat index c4e8b32b131..e81e8942422 100644 --- a/crates/cli/tests/reference/skip-jsdoc.wat +++ b/crates/cli/tests/reference/skip-jsdoc.wat @@ -4,4 +4,6 @@ (memory (;0;) 17) (export "memory" (memory 0)) (export "docme" (func $docme)) + (@custom "target_features" (after code) "\02+\0fmutable-globals+\08sign-ext") ) + diff --git a/crates/cli/tests/reference/string-arg.wat b/crates/cli/tests/reference/string-arg.wat index 759fe869e0b..1ce4e8ca28a 100644 --- a/crates/cli/tests/reference/string-arg.wat +++ b/crates/cli/tests/reference/string-arg.wat @@ -10,4 +10,6 @@ (export "foo" (func $foo)) (export "__wbindgen_malloc" (func $__wbindgen_malloc)) (export "__wbindgen_realloc" (func $__wbindgen_realloc)) + (@custom "target_features" (after code) "\02+\0fmutable-globals+\08sign-ext") ) + diff --git a/crates/externref-xform/Cargo.toml b/crates/externref-xform/Cargo.toml index 173967be1ee..949fdf4fb88 100644 --- a/crates/externref-xform/Cargo.toml +++ b/crates/externref-xform/Cargo.toml @@ -14,12 +14,12 @@ rust-version = "1.57" [dependencies] anyhow = "1.0" -walrus = "0.20.2" +walrus = "0.21" wasm-bindgen-wasm-conventions = { path = "../wasm-conventions", version = "=0.2.92" } [dev-dependencies] rayon = "1.0" -wasmprinter = "0.2" +wasmprinter = "0.212" wast = "21.0" wat = "1.0" diff --git a/crates/externref-xform/src/lib.rs b/crates/externref-xform/src/lib.rs index faa2b1ac1ca..df18491889a 100644 --- a/crates/externref-xform/src/lib.rs +++ b/crates/externref-xform/src/lib.rs @@ -20,12 +20,12 @@ use std::cmp; use std::collections::{BTreeMap, HashMap, HashSet}; use std::mem; -use walrus::ir::*; +use walrus::{ir::*, ElementItems, RefType}; +use walrus::{ConstExpr, FunctionId, GlobalId, Module, TableId, ValType}; use walrus::{ElementId, ExportId, ImportId, InstrLocId, TypeId}; -use walrus::{FunctionId, GlobalId, InitExpr, Module, TableId, ValType}; // must be kept in sync with src/lib.rs and EXTERNREF_HEAP_START -const DEFAULT_MIN: u32 = 128; +const DEFAULT_MIN: u64 = 128; /// State of the externref pass, used to collect information while bindings are /// generated and used eventually to actually execute the entire pass. @@ -117,10 +117,14 @@ impl Context { _ => continue, }; let offset = match offset { - walrus::InitExpr::Value(Value::I32(n)) => *n as u32, + walrus::ConstExpr::Value(Value::I32(n)) => *n as u32, other => bail!("invalid offset for segment of function table {:?}", other), }; - let max = offset + elem.members.len() as u32; + let len = match &elem.items { + ElementItems::Functions(items) => items.len(), + ElementItems::Expressions(_, items) => items.len(), + }; + let max = offset + len as u32; self.new_element_offset = cmp::max(self.new_element_offset, max); self.elements.insert(offset, *id); } @@ -131,7 +135,7 @@ impl Context { self.table = Some( module .tables - .add_local(DEFAULT_MIN, None, ValType::Externref), + .add_local(false, DEFAULT_MIN, None, RefType::Externref), ); Ok(()) @@ -195,8 +199,8 @@ impl Context { // Inject a stack pointer global which will be used for managing the // stack on the externref table. - let init = InitExpr::Value(Value::I32(DEFAULT_MIN as i32)); - let stack_pointer = module.globals.add_local(ValType::I32, true, init); + let init = ConstExpr::Value(Value::I32(DEFAULT_MIN as i32)); + let stack_pointer = module.globals.add_local(ValType::I32, true, false, init); let mut heap_alloc = None; let mut heap_dealloc = None; @@ -430,9 +434,18 @@ impl Transform<'_> { .range(..=idx) .next_back() .ok_or(anyhow!("failed to find segment defining index {}", idx))?; - let target = module.elements.get(orig_element).members[(idx - offset) as usize].ok_or( - anyhow!("function index {} not present in element segment", idx), - )?; + + let target = match &module.elements.get(orig_element).items { + ElementItems::Functions(items) => items[(idx - offset) as usize], + ElementItems::Expressions(_, items) => { + if let ConstExpr::RefFunc(target) = items[(idx - offset) as usize] { + target + } else { + bail!("function index {} not present in element segment", idx) + } + } + }; + let (shim, _externref_ty) = self.append_shim( target, &format!("closure{}", idx), @@ -441,20 +454,23 @@ impl Transform<'_> { &mut module.funcs, &mut module.locals, )?; - new_segment.push(Some(shim)); + new_segment.push(ConstExpr::RefFunc(shim)); } // ... and next update the limits of the table in case any are listed. let new_max = self.cx.new_element_offset + new_segment.len() as u32; - table.initial = cmp::max(table.initial, new_max); + table.initial = cmp::max(table.initial, u64::from(new_max)); if let Some(max) = table.maximum { - table.maximum = Some(cmp::max(max, new_max)); + table.maximum = Some(cmp::max(max, u64::from(new_max))); } let kind = walrus::ElementKind::Active { table: table.id(), - offset: InitExpr::Value(Value::I32(self.cx.new_element_offset as i32)), + offset: ConstExpr::Value(Value::I32(self.cx.new_element_offset as i32)), }; - let segment = module.elements.add(kind, ValType::Funcref, new_segment); + let segment = module.elements.add( + kind, + ElementItems::Expressions(RefType::Funcref, new_segment), + ); table.elem_segments.insert(segment); Ok(()) @@ -494,7 +510,9 @@ impl Transform<'_> { for (i, old_ty) in target_ty.params().iter().enumerate() { let is_owned = func.args.remove(&i); - let new_ty = is_owned.map(|_which| ValType::Externref).unwrap_or(*old_ty); + let new_ty = is_owned + .map(|_which| ValType::Ref(RefType::Externref)) + .unwrap_or(*old_ty); param_tys.push(new_ty); if new_ty == *old_ty { param_convert.push(Convert::None); @@ -518,7 +536,7 @@ impl Transform<'_> { let new_ret = if func.ret_externref { assert_eq!(target_ty.results(), &[ValType::I32]); - vec![ValType::Externref] + vec![ValType::Ref(RefType::Externref)] } else { target_ty.results().to_vec() }; @@ -558,7 +576,7 @@ impl Transform<'_> { // gc passes if we don't actually end up using them. let fp = locals.add(ValType::I32); let scratch_i32 = locals.add(ValType::I32); - let scratch_externref = locals.add(ValType::Externref); + let scratch_externref = locals.add(ValType::Ref(RefType::Externref)); // Update our stack pointer if there's any borrowed externref objects. if externref_stack > 0 { @@ -654,7 +672,7 @@ impl Transform<'_> { // no longer in use by our wasm instance. if externref_stack > 0 { body.local_get(fp) - .ref_null(ValType::Externref) + .ref_null(RefType::Externref) .i32_const(externref_stack) .table_fill(self.table) .local_get(fp) @@ -721,7 +739,7 @@ impl Transform<'_> { } }; - let ty = ValType::Externref; + let ty = RefType::Externref; match intrinsic { Intrinsic::TableGrow => { // Change something that looks like: diff --git a/crates/externref-xform/tests/all.rs b/crates/externref-xform/tests/all.rs index 865d8212d25..ce36dd2b0f5 100644 --- a/crates/externref-xform/tests/all.rs +++ b/crates/externref-xform/tests/all.rs @@ -152,9 +152,6 @@ impl Test { pattern.push_str(line); pattern.push('\n'); } - while pattern.ends_with('\n') { - pattern.pop(); - } if iter.next().is_some() { bail!("CHECK-ALL must be at the end of the file"); } diff --git a/crates/externref-xform/tests/anyref-param-owned.wat b/crates/externref-xform/tests/anyref-param-owned.wat index e61883d71da..a0063d05c8e 100644 --- a/crates/externref-xform/tests/anyref-param-owned.wat +++ b/crates/externref-xform/tests/anyref-param-owned.wat @@ -12,7 +12,7 @@ (type (;0;) (func (result i32))) (type (;1;) (func (param i32))) (type (;2;) (func (param externref))) - (func $#func0 (@name "foo externref shim") (;0;) (type 2) (param externref) + (func $"foo externref shim" (;0;) (type 2) (param externref) (local i32) call $alloc local.tee 1 @@ -26,6 +26,7 @@ ) (func $foo (;2;) (type 1) (param i32)) (table (;0;) 128 externref) - (export "foo" (func $#func0)) + (export "foo" (func $"foo externref shim")) + (@custom "target_features" (after code) "\01+\0freference-types") ) ;) diff --git a/crates/externref-xform/tests/anyref-param.wat b/crates/externref-xform/tests/anyref-param.wat index 715d908e892..d36133fc763 100644 --- a/crates/externref-xform/tests/anyref-param.wat +++ b/crates/externref-xform/tests/anyref-param.wat @@ -11,7 +11,7 @@ (module (type (;0;) (func (param i32))) (type (;1;) (func (param externref))) - (func $#func0 (@name "foo externref shim") (;0;) (type 1) (param externref) + (func $"foo externref shim" (;0;) (type 1) (param externref) (local i32) global.get 0 i32.const 1 @@ -35,6 +35,7 @@ (func $foo (;1;) (type 0) (param i32)) (table (;0;) 128 externref) (global (;0;) (mut i32) i32.const 128) - (export "foo" (func $#func0)) + (export "foo" (func $"foo externref shim")) + (@custom "target_features" (after code) "\01+\0freference-types") ) ;) diff --git a/crates/externref-xform/tests/clone-ref-intrinsic.wat b/crates/externref-xform/tests/clone-ref-intrinsic.wat index e62fabdc164..4fdf99a186c 100644 --- a/crates/externref-xform/tests/clone-ref-intrinsic.wat +++ b/crates/externref-xform/tests/clone-ref-intrinsic.wat @@ -17,7 +17,7 @@ (type (;1;) (func (param i32))) (type (;2;) (func (param i32) (result i32))) (type (;3;) (func (param externref) (result externref))) - (func $#func0 (@name "foo externref shim") (;0;) (type 3) (param externref) (result externref) + (func $"foo externref shim" (;0;) (type 3) (param externref) (result externref) (local i32) call $alloc local.tee 1 @@ -48,6 +48,7 @@ ) (func $dealloc (;4;) (type 1) (param i32)) (table (;0;) 128 externref) - (export "foo" (func $#func0)) + (export "foo" (func $"foo externref shim")) + (@custom "target_features" (after code) "\01+\0freference-types") ) ;) diff --git a/crates/externref-xform/tests/drop-ref-intrinsic.wat b/crates/externref-xform/tests/drop-ref-intrinsic.wat index 782c85419f8..9f17f64748d 100644 --- a/crates/externref-xform/tests/drop-ref-intrinsic.wat +++ b/crates/externref-xform/tests/drop-ref-intrinsic.wat @@ -16,7 +16,7 @@ (type (;0;) (func (result i32))) (type (;1;) (func (param i32))) (type (;2;) (func (param externref))) - (func $#func0 (@name "foo externref shim") (;0;) (type 2) (param externref) + (func $"foo externref shim" (;0;) (type 2) (param externref) (local i32) call $alloc local.tee 1 @@ -34,6 +34,7 @@ ) (func $dealloc (;3;) (type 1) (param i32)) (table (;0;) 128 externref) - (export "foo" (func $#func0)) + (export "foo" (func $"foo externref shim")) + (@custom "target_features" (after code) "\01+\0freference-types") ) ;) diff --git a/crates/externref-xform/tests/import-anyref-owned.wat b/crates/externref-xform/tests/import-anyref-owned.wat index b77bd7e7655..35563bc10ca 100644 --- a/crates/externref-xform/tests/import-anyref-owned.wat +++ b/crates/externref-xform/tests/import-anyref-owned.wat @@ -16,7 +16,7 @@ (type (;1;) (func (param i32))) (type (;2;) (func (param externref))) (import "" "a" (func $a (;0;) (type 2))) - (func $#func1 (@name "a externref shim") (;1;) (type 1) (param i32) + (func $"a externref shim" (;1;) (type 1) (param i32) local.get 0 table.get 0 local.get 0 @@ -25,10 +25,11 @@ ) (func (;2;) (type 0) i32.const 0 - call $#func1 + call $"a externref shim" ) (func $dealloc (;3;) (type 1) (param i32)) (table (;0;) 128 externref) (export "foo" (func 2)) + (@custom "target_features" (after code) "\01+\0freference-types") ) ;) diff --git a/crates/externref-xform/tests/import-anyref-ret.wat b/crates/externref-xform/tests/import-anyref-ret.wat index 14878d3444c..52c0719877c 100644 --- a/crates/externref-xform/tests/import-anyref-ret.wat +++ b/crates/externref-xform/tests/import-anyref-ret.wat @@ -14,7 +14,7 @@ (type (;0;) (func (result i32))) (type (;1;) (func (result externref))) (import "" "a" (func $a (;0;) (type 1))) - (func $#func1 (@name "a externref shim") (;1;) (type 0) (result i32) + (func $"a externref shim" (;1;) (type 0) (result i32) (local i32 externref) call $a local.set 1 @@ -25,12 +25,13 @@ local.get 0 ) (func (;2;) (type 0) (result i32) - call $#func1 + call $"a externref shim" ) (func $alloc (;3;) (type 0) (result i32) i32.const 0 ) (table (;0;) 128 externref) (export "foo" (func 2)) + (@custom "target_features" (after code) "\01+\0freference-types") ) ;) diff --git a/crates/externref-xform/tests/import-anyref.wat b/crates/externref-xform/tests/import-anyref.wat index 55fe31976bb..2ed417c0bbe 100644 --- a/crates/externref-xform/tests/import-anyref.wat +++ b/crates/externref-xform/tests/import-anyref.wat @@ -16,16 +16,17 @@ (type (;1;) (func (param i32))) (type (;2;) (func (param externref))) (import "" "a" (func $a (;0;) (type 2))) - (func $#func1 (@name "a externref shim") (;1;) (type 1) (param i32) + (func $"a externref shim" (;1;) (type 1) (param i32) local.get 0 table.get 0 call $a ) (func (;2;) (type 0) i32.const 0 - call $#func1 + call $"a externref shim" ) (table (;0;) 128 externref) (export "foo" (func 2)) + (@custom "target_features" (after code) "\01+\0freference-types") ) ;) diff --git a/crates/externref-xform/tests/mixed-export.wat b/crates/externref-xform/tests/mixed-export.wat index 02327414562..26a08f2c249 100644 --- a/crates/externref-xform/tests/mixed-export.wat +++ b/crates/externref-xform/tests/mixed-export.wat @@ -12,7 +12,7 @@ (type (;0;) (func (result i32))) (type (;1;) (func (param f32 i32 i64 i32 i32))) (type (;2;) (func (param f32 externref i64 externref i32))) - (func $#func0 (@name "a externref shim") (;0;) (type 2) (param f32 externref i64 externref i32) + (func $"a externref shim" (;0;) (type 2) (param f32 externref i64 externref i32) (local i32 i32) global.get 0 i32.const 1 @@ -47,6 +47,7 @@ (func $a (;2;) (type 1) (param f32 i32 i64 i32 i32)) (table (;0;) 128 externref) (global (;0;) (mut i32) i32.const 128) - (export "a" (func $#func0)) + (export "a" (func $"a externref shim")) + (@custom "target_features" (after code) "\01+\0freference-types") ) ;) diff --git a/crates/externref-xform/tests/mixed.wat b/crates/externref-xform/tests/mixed.wat index 5eba64fd171..edeb646f00d 100644 --- a/crates/externref-xform/tests/mixed.wat +++ b/crates/externref-xform/tests/mixed.wat @@ -21,7 +21,7 @@ (type (;2;) (func (param f32 i32 i64 i32 i32))) (type (;3;) (func (param f32 externref i64 externref i32))) (import "" "a" (func $a (;0;) (type 3))) - (func $#func1 (@name "a externref shim") (;1;) (type 2) (param f32 i32 i64 i32 i32) + (func $"a externref shim" (;1;) (type 2) (param f32 i32 i64 i32 i32) local.get 0 local.get 1 table.get 0 @@ -39,10 +39,11 @@ i64.const 3 i32.const 4 i32.const 5 - call $#func1 + call $"a externref shim" ) (func $dealloc (;3;) (type 1) (param i32)) (table (;0;) 128 externref) (export "foo" (func 2)) + (@custom "target_features" (after code) "\01+\0freference-types") ) ;) diff --git a/crates/externref-xform/tests/ret-anyref.wat b/crates/externref-xform/tests/ret-anyref.wat index 811c46b9a37..936d5d0c811 100644 --- a/crates/externref-xform/tests/ret-anyref.wat +++ b/crates/externref-xform/tests/ret-anyref.wat @@ -14,7 +14,7 @@ (type (;0;) (func (result i32))) (type (;1;) (func (result externref))) (type (;2;) (func (param i32))) - (func $#func0 (@name "foo externref shim") (;0;) (type 1) (result externref) + (func $"foo externref shim" (;0;) (type 1) (result externref) (local i32) call $foo local.tee 0 @@ -27,6 +27,7 @@ ) (func $dealloc (;2;) (type 2) (param i32)) (table (;0;) 128 externref) - (export "foo" (func $#func0)) + (export "foo" (func $"foo externref shim")) + (@custom "target_features" (after code) "\01+\0freference-types") ) ;) diff --git a/crates/externref-xform/tests/table-grow-intrinsic.wat b/crates/externref-xform/tests/table-grow-intrinsic.wat index ec7cc07ce0b..9fc963923d9 100644 --- a/crates/externref-xform/tests/table-grow-intrinsic.wat +++ b/crates/externref-xform/tests/table-grow-intrinsic.wat @@ -26,7 +26,7 @@ table.grow 0 drop ) - (func $#func1 (@name "foo externref shim") (;1;) (type 2) (param externref) + (func $"foo externref shim" (;1;) (type 2) (param externref) (local i32) call $alloc local.tee 1 @@ -39,6 +39,7 @@ i32.const 0 ) (table (;0;) 128 externref) - (export "foo" (func $#func1)) + (export "foo" (func $"foo externref shim")) + (@custom "target_features" (after code) "\01+\0freference-types") ) ;) diff --git a/crates/externref-xform/tests/table-set-null-intrinsic.wat b/crates/externref-xform/tests/table-set-null-intrinsic.wat index 3f5cf954986..4a84bb88935 100644 --- a/crates/externref-xform/tests/table-set-null-intrinsic.wat +++ b/crates/externref-xform/tests/table-set-null-intrinsic.wat @@ -16,7 +16,7 @@ (type (;0;) (func (result i32))) (type (;1;) (func (param i32))) (type (;2;) (func (param externref))) - (func $#func0 (@name "foo externref shim") (;0;) (type 2) (param externref) + (func $"foo externref shim" (;0;) (type 2) (param externref) (local i32) call $alloc local.tee 1 @@ -34,6 +34,7 @@ i32.const 0 ) (table (;0;) 128 externref) - (export "foo" (func $#func0)) + (export "foo" (func $"foo externref shim")) + (@custom "target_features" (after code) "\01+\0freference-types") ) ;) diff --git a/crates/externref-xform/tests/table.wat b/crates/externref-xform/tests/table.wat index 1acda79e6f6..3f651ddb879 100644 --- a/crates/externref-xform/tests/table.wat +++ b/crates/externref-xform/tests/table.wat @@ -14,7 +14,7 @@ (type (;0;) (func (result i32))) (type (;1;) (func (param i32))) (type (;2;) (func (param externref))) - (func $#func0 (@name "closure0 externref shim") (;0;) (type 2) (param externref) + (func $"closure0 externref shim" (;0;) (type 2) (param externref) (local i32) call $alloc local.tee 1 @@ -31,6 +31,7 @@ (table (;1;) 128 externref) (export "func" (table 0)) (elem (;0;) (i32.const 0) func $foo) - (elem (;1;) (i32.const 1) func $#func0) + (elem (;1;) (i32.const 1) funcref (ref.func $"closure0 externref shim")) + (@custom "target_features" (after code) "\01+\0freference-types") ) ;) diff --git a/crates/externref-xform/tests/tee-before-grow.wat b/crates/externref-xform/tests/tee-before-grow.wat index b73ffe083fb..2b206343d16 100644 --- a/crates/externref-xform/tests/tee-before-grow.wat +++ b/crates/externref-xform/tests/tee-before-grow.wat @@ -29,7 +29,7 @@ table.grow 0 drop ) - (func $#func1 (@name "foo externref shim") (;1;) (type 2) (param externref) + (func $"foo externref shim" (;1;) (type 2) (param externref) (local i32) call $alloc local.tee 1 @@ -42,6 +42,7 @@ i32.const 0 ) (table (;0;) 128 externref) - (export "foo" (func $#func1)) + (export "foo" (func $"foo externref shim")) + (@custom "target_features" (after code) "\01+\0freference-types") ) ;) diff --git a/crates/multi-value-xform/Cargo.toml b/crates/multi-value-xform/Cargo.toml index 6f2a807ff21..20ffe99ad72 100644 --- a/crates/multi-value-xform/Cargo.toml +++ b/crates/multi-value-xform/Cargo.toml @@ -14,12 +14,12 @@ rust-version = "1.57" [dependencies] anyhow = "1.0" -walrus = "0.20.2" +walrus = "0.21" wasm-bindgen-wasm-conventions = { path = "../wasm-conventions", version = "=0.2.92" } [dev-dependencies] rayon = "1.0" -wasmprinter = "0.2" +wasmprinter = "0.212" wast = "21.0" wat = "1.0" diff --git a/crates/multi-value-xform/src/lib.rs b/crates/multi-value-xform/src/lib.rs index 27645c8de5b..fe87d32ed46 100644 --- a/crates/multi-value-xform/src/lib.rs +++ b/crates/multi-value-xform/src/lib.rs @@ -167,7 +167,7 @@ fn xform_one( round_up_to_alignment(results_size, 8) + 8 } walrus::ValType::V128 => round_up_to_alignment(results_size, 16) + 16, - walrus::ValType::Externref | walrus::ValType::Funcref => anyhow::bail!( + walrus::ValType::Ref(_) => anyhow::bail!( "cannot multi-value transform functions that return \ reference types, since they can't go into linear memory" ), @@ -288,7 +288,7 @@ fn xform_one( ); offset += 16; } - walrus::ValType::Externref | walrus::ValType::Funcref => unreachable!(), + walrus::ValType::Ref(_) => unreachable!(), } } diff --git a/crates/multi-value-xform/tests/align.wat b/crates/multi-value-xform/tests/align.wat index 4a5b9e18a86..89c63267867 100644 --- a/crates/multi-value-xform/tests/align.wat +++ b/crates/multi-value-xform/tests/align.wat @@ -11,7 +11,7 @@ (module (type (;0;) (func (result f64 i32 i64))) (type (;1;) (func (param i32))) - (func $#func0 (@name "foo multivalue shim") (;0;) (type 0) (result f64 i32 i64) + (func $"foo multivalue shim" (;0;) (type 0) (result f64 i32 i64) (local i32) global.get 0 i32.const 32 @@ -34,6 +34,7 @@ (func $foo (;1;) (type 1) (param i32)) (memory (;0;) 1) (global (;0;) (mut i32) i32.const 0) - (export "foo" (func $#func0)) + (export "foo" (func $"foo multivalue shim")) + (@custom "target_features" (after code) "\01+\0amultivalue") ) ;) diff --git a/crates/multi-value-xform/tests/all.rs b/crates/multi-value-xform/tests/all.rs index a72b244b9db..1e14b623625 100644 --- a/crates/multi-value-xform/tests/all.rs +++ b/crates/multi-value-xform/tests/all.rs @@ -140,9 +140,6 @@ impl Test { pattern.push_str(line); pattern.push('\n'); } - while pattern.ends_with('\n') { - pattern.pop(); - } if iter.next().is_some() { bail!("CHECK-ALL must be at the end of the file"); } diff --git a/crates/multi-value-xform/tests/many.wat b/crates/multi-value-xform/tests/many.wat index 680715f4a89..c4fee08a895 100644 --- a/crates/multi-value-xform/tests/many.wat +++ b/crates/multi-value-xform/tests/many.wat @@ -11,7 +11,7 @@ (module (type (;0;) (func (result i32 f32 f64 i64))) (type (;1;) (func (param i32))) - (func $#func0 (@name "foo multivalue shim") (;0;) (type 0) (result i32 f32 f64 i64) + (func $"foo multivalue shim" (;0;) (type 0) (result i32 f32 f64 i64) (local i32) global.get 0 i32.const 32 @@ -36,6 +36,7 @@ (func $foo (;1;) (type 1) (param i32)) (memory (;0;) 1) (global (;0;) (mut i32) i32.const 0) - (export "foo" (func $#func0)) + (export "foo" (func $"foo multivalue shim")) + (@custom "target_features" (after code) "\01+\0amultivalue") ) ;) diff --git a/crates/multi-value-xform/tests/simple.wat b/crates/multi-value-xform/tests/simple.wat index 045bab590bb..b0f1c0d942a 100644 --- a/crates/multi-value-xform/tests/simple.wat +++ b/crates/multi-value-xform/tests/simple.wat @@ -20,7 +20,7 @@ (type (;2;) (func (result f32))) (type (;3;) (func (result f64))) (type (;4;) (func (param i32))) - (func $#func0 (@name "i32 multivalue shim") (;0;) (type 0) (result i32) + (func $"i32 multivalue shim" (;0;) (type 0) (result i32) (local i32) global.get 0 i32.const 16 @@ -36,7 +36,7 @@ i32.add global.set 0 ) - (func $#func1 (@name "i64 multivalue shim") (;1;) (type 1) (result i64) + (func $"i64 multivalue shim" (;1;) (type 1) (result i64) (local i32) global.get 0 i32.const 16 @@ -52,7 +52,7 @@ i32.add global.set 0 ) - (func $#func2 (@name "f32 multivalue shim") (;2;) (type 2) (result f32) + (func $"f32 multivalue shim" (;2;) (type 2) (result f32) (local i32) global.get 0 i32.const 16 @@ -68,7 +68,7 @@ i32.add global.set 0 ) - (func $#func3 (@name "f64 multivalue shim") (;3;) (type 3) (result f64) + (func $"f64 multivalue shim" (;3;) (type 3) (result f64) (local i32) global.get 0 i32.const 16 @@ -90,9 +90,10 @@ (func $f64 (;7;) (type 4) (param i32)) (memory (;0;) 1) (global (;0;) (mut i32) i32.const 0) - (export "i32" (func $#func0)) - (export "i64" (func $#func1)) - (export "f32" (func $#func2)) - (export "f64" (func $#func3)) + (export "i32" (func $"i32 multivalue shim")) + (export "i64" (func $"i64 multivalue shim")) + (export "f32" (func $"f32 multivalue shim")) + (export "f64" (func $"f64 multivalue shim")) + (@custom "target_features" (after code) "\01+\0amultivalue") ) ;) diff --git a/crates/threads-xform/Cargo.toml b/crates/threads-xform/Cargo.toml index 14edd58207e..e714207c1ce 100644 --- a/crates/threads-xform/Cargo.toml +++ b/crates/threads-xform/Cargo.toml @@ -14,13 +14,13 @@ rust-version = "1.57" [dependencies] anyhow = "1.0" -walrus = "0.20.2" +walrus = "0.21" wasm-bindgen-wasm-conventions = { path = "../wasm-conventions", version = "=0.2.92" } [dev-dependencies] rayon = "1.0" -wasmprinter = "0.2" -wasmparser = "0.82" +wasmprinter = "0.212" +wasmparser = "0.212" wat = "1.0" [[test]] diff --git a/crates/threads-xform/src/lib.rs b/crates/threads-xform/src/lib.rs index a9d0898cd33..1dd4d70c151 100644 --- a/crates/threads-xform/src/lib.rs +++ b/crates/threads-xform/src/lib.rs @@ -4,7 +4,7 @@ use std::env; use walrus::ir::Value; use walrus::FunctionBuilder; use walrus::{ - ir::MemArg, ExportItem, FunctionId, GlobalId, GlobalKind, InitExpr, InstrSeqBuilder, MemoryId, + ir::MemArg, ConstExpr, ExportItem, FunctionId, GlobalId, GlobalKind, InstrSeqBuilder, MemoryId, Module, ValType, }; use wasm_bindgen_wasm_conventions as wasm_conventions; @@ -129,7 +129,10 @@ impl Config { assert!(mem.shared); let prev_max = mem.maximum.unwrap(); assert!(mem.import.is_some()); - mem.maximum = Some(cmp::max(self.maximum_memory / PAGE_SIZE, prev_max)); + mem.maximum = Some(cmp::max( + u64::from(self.maximum_memory / PAGE_SIZE), + prev_max, + )); assert!(mem.data_segments.is_empty()); let tls = Tls { @@ -145,7 +148,7 @@ impl Config { let stack_alloc = module .globals - .add_local(ValType::I32, true, InitExpr::Value(Value::I32(0))); + .add_local(ValType::I32, true, false, ConstExpr::Value(Value::I32(0))); // Make sure the temporary stack is aligned down let temp_stack = (base + static_data_pages * PAGE_SIZE) & !(static_data_align - 1); @@ -161,7 +164,8 @@ impl Config { size: module.globals.add_local( ValType::I32, true, - InitExpr::Value(Value::I32(self.thread_stack_size as i32)), + false, + ConstExpr::Value(Value::I32(self.thread_stack_size as i32)), ), }; @@ -222,7 +226,7 @@ fn delete_synthetic_global(module: &mut Module, name: &str) -> Result bail!("`{}` must not be an imported global", name), }; match g { - InitExpr::Value(Value::I32(v)) => Ok(v as u32), + ConstExpr::Value(Value::I32(v)) => Ok(v as u32), _ => bail!("`{}` was not an `i32` constant", name), } } @@ -278,7 +282,7 @@ fn allocate_static_data( bail!("the `__heap_base` global is unexpectedly mutable"); } let offset = match &mut global.kind { - GlobalKind::Local(InitExpr::Value(Value::I32(n))) => n, + GlobalKind::Local(ConstExpr::Value(Value::I32(n))) => n, _ => bail!("`__heap_base` not a locally defined `i32`"), }; @@ -291,7 +295,7 @@ fn allocate_static_data( }; let memory = module.memories.get_mut(memory); - memory.initial += pages; + memory.initial += u64::from(pages); memory.maximum = memory.maximum.map(|m| cmp::max(m, memory.initial)); Ok((base as u32, address)) diff --git a/crates/threads-xform/tests/all.rs b/crates/threads-xform/tests/all.rs index 789346f3446..e38f377f211 100644 --- a/crates/threads-xform/tests/all.rs +++ b/crates/threads-xform/tests/all.rs @@ -28,14 +28,9 @@ fn runtest(test: &Test) -> Result { config.run(&mut module)?; walrus::passes::gc::run(&mut module); - let features = wasmparser::WasmFeatures { - threads: true, - ..Default::default() - }; + let features = wasmparser::WasmFeatures::default() | wasmparser::WasmFeatures::THREADS; - wasmparser::Validator::new() - .wasm_features(features) - .validate_all(&module.emit_wasm())?; + wasmparser::Validator::new_with_features(features).validate_all(&module.emit_wasm())?; let printed = wasmprinter::print_bytes(module.emit_wasm())?; @@ -126,9 +121,6 @@ impl Test { pattern.push_str(line); pattern.push('\n'); } - while pattern.ends_with('\n') { - pattern.pop(); - } if iter.next().is_some() { bail!("CHECK-ALL must be at the end of the file"); } diff --git a/crates/wasm-conventions/Cargo.toml b/crates/wasm-conventions/Cargo.toml index da05515c9cc..d4178ec94b2 100644 --- a/crates/wasm-conventions/Cargo.toml +++ b/crates/wasm-conventions/Cargo.toml @@ -12,8 +12,8 @@ rust-version = "1.57" [dependencies] leb128 = "0.2" -walrus = "0.20.2" +walrus = "0.21" # Matching the version `walrus` depends on. -wasmparser = "0.80" +wasmparser = "0.212" anyhow = "1.0" log = "0.4" diff --git a/crates/wasm-conventions/src/lib.rs b/crates/wasm-conventions/src/lib.rs index d7cb7279b0c..c0f25739456 100755 --- a/crates/wasm-conventions/src/lib.rs +++ b/crates/wasm-conventions/src/lib.rs @@ -10,10 +10,10 @@ use std::io::Cursor; use anyhow::{anyhow, bail, Context, Result}; use walrus::{ - ir::Value, ElementId, FunctionBuilder, FunctionId, FunctionKind, GlobalId, GlobalKind, - InitExpr, MemoryId, Module, RawCustomSection, ValType, + ir::Value, ConstExpr, ElementId, ElementItems, FunctionBuilder, FunctionId, FunctionKind, + GlobalId, GlobalKind, MemoryId, Module, RawCustomSection, ValType, }; -use wasmparser::BinaryReader; +use wasmparser::{BinaryReader, WasmFeatures}; /// Get a Wasm module's canonical linear memory. pub fn get_memory(module: &Module) -> Result { @@ -52,7 +52,7 @@ pub fn get_stack_pointer(module: &Module) -> Option { // guaranteed to have an i32 initializer, so find globals which are // locally defined, are an i32, and have a nonzero initializer .filter(|g| match g.kind { - GlobalKind::Local(InitExpr::Value(Value::I32(n))) => n != 0, + GlobalKind::Local(ConstExpr::Value(Value::I32(n))) => n != 0, _ => false, }) .collect::>(); @@ -108,18 +108,30 @@ pub fn get_function_table_entry(module: &Module, idx: u32) -> Result *n as u32, _ => continue, }; let idx = (idx - offset) as usize; - match segment.members.get(idx) { + + let slot = match &segment.items { + ElementItems::Functions(items) => items.get(idx).map(Some), + ElementItems::Expressions(_, items) => items.get(idx).map(|item| { + if let ConstExpr::RefFunc(target) = item { + Some(target) + } else { + None + } + }), + }; + + match slot { Some(slot) => { return Ok(FunctionTableEntry { element: segment.id(), idx, - func: *slot, + func: slot.cloned(), }) } None => continue, @@ -181,7 +193,7 @@ pub fn insert_target_feature(module: &mut Module, new_feature: &str) -> Result<( .as_any_mut() .downcast_mut() .context("failed to read section")?; - let mut reader = BinaryReader::new(§ion.data); + let mut reader = BinaryReader::new(§ion.data, 0, WasmFeatures::default()); // The first integer contains the target feature count. let count = reader.read_var_u32()?; @@ -189,7 +201,7 @@ pub fn insert_target_feature(module: &mut Module, new_feature: &str) -> Result<( for _ in 0..count { // First byte is the prefix. let prefix_index = reader.current_position(); - let prefix = reader.read_u8()? as u8; + let prefix = reader.read_u8()?; // Read the feature. let length = reader.read_var_u32()?; let feature = reader.read_bytes(length as usize)?; diff --git a/crates/wasm-interpreter/Cargo.toml b/crates/wasm-interpreter/Cargo.toml index 879602ec935..33c0c20eea9 100644 --- a/crates/wasm-interpreter/Cargo.toml +++ b/crates/wasm-interpreter/Cargo.toml @@ -15,7 +15,7 @@ rust-version = "1.57" [dependencies] anyhow = "1.0" log = "0.4" -walrus = "0.20.2" +walrus = "0.21" wasm-bindgen-wasm-conventions = { path = "../wasm-conventions", version = "0.2.92" } [dev-dependencies] diff --git a/crates/wasm-interpreter/src/lib.rs b/crates/wasm-interpreter/src/lib.rs index 359eb197a94..c13a23f64b8 100644 --- a/crates/wasm-interpreter/src/lib.rs +++ b/crates/wasm-interpreter/src/lib.rs @@ -18,7 +18,7 @@ #![deny(missing_docs)] -use std::collections::{BTreeMap, HashMap, HashSet}; +use std::collections::{BTreeMap, BTreeSet, HashMap}; use walrus::ir::Instr; use walrus::{ElementId, FunctionId, LocalId, Module, TableId}; @@ -157,7 +157,7 @@ impl Interpreter { &mut self, id: FunctionId, module: &Module, - entry_removal_list: &mut HashSet<(ElementId, usize)>, + entry_removal_list: &mut HashMap>, ) -> Option<&[u32]> { // Call the `id` function. This is an internal `#[inline(never)]` // whose code is completely controlled by the `wasm-bindgen` crate, so @@ -194,7 +194,10 @@ impl Interpreter { wasm_bindgen_wasm_conventions::get_function_table_entry(module, descriptor_table_idx) .expect("failed to find entry in function table"); let descriptor_id = entry.func.expect("element segment slot wasn't set"); - entry_removal_list.insert((entry.element, entry.idx)); + entry_removal_list + .entry(entry.element) + .or_default() + .insert(entry.idx); // And now execute the descriptor! self.interpret_descriptor(descriptor_id, module)