diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 04a941d213..711d67bc26 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -84,6 +84,8 @@ jobs: - run: cargo check --no-default-features --features mutate - run: cargo check --no-default-features --features dump - run: cargo check --no-default-features --features objdump + - run: cargo check --no-default-features --features strip + - run: cargo check --no-default-features --features compose doc: runs-on: ubuntu-latest diff --git a/Cargo.toml b/Cargo.toml index 3270fcb5bc..2d5a004507 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,8 +1,8 @@ [package] name = "wasm-tools" -version = "1.0.10" +version = "1.0.12" authors = ["The Wasmtime Project Developers"] -edition = "2021" +edition.workspace = true description = "CLI tools for interoperating with WebAssembly files" license = "Apache-2.0 WITH LLVM-exception" documentation = "https://github.com/bytecodealliance/wasm-tools" @@ -13,49 +13,83 @@ readme = "README.md" exclude = ['tests/wabt', 'tests/testsuite', 'publish.rs'] [workspace] -members = ['crates/c-api', 'fuzz', 'crates/wasm-encoder', 'crates/fuzz-stats', 'crates/wasm-mutate-stats'] +members = [ + 'crates/c-api', + 'crates/fuzz-stats', + 'crates/wasm-mutate-stats', + 'fuzz', +] + +[workspace.package] +edition = '2021' + +[workspace.dependencies] +anyhow = "1.0.58" +arbitrary = "1.1.0" +clap = { version = "4.0.0", features = ["derive"] } +criterion = "0.3.3" +env_logger = "0.9" +indexmap = "1.9.1" +leb128 = "0.2.4" +libfuzzer-sys = "0.4.0" +log = "0.4.17" +num_cpus = "1.13" +rand = { version = "0.8.4", features = ["small_rng"] } +rayon = "1.3" +serde = { version = "1.0.137", features = ["derive"] } +wasmtime = "1.0.0" + +wasm-encoder = { version = "0.18.0", path = "crates/wasm-encoder"} +wasm-compose = { version = "0.1.3", path = "crates/wasm-compose"} +wasm-mutate = { version = "0.2.4", path = "crates/wasm-mutate" } +wasm-shrink = { version = "0.1.6", path = "crates/wasm-shrink" } +wasm-smith = { version = "0.11.2", path = "crates/wasm-smith" } +wasmparser = { version = "0.92.0", path = "crates/wasmparser" } +wasmparser-dump = { version = "0.1.4", path = "crates/dump" } +wasmprinter = { version = "0.2.36", path = "crates/wasmprinter" } +wast = { version = "47.0.1", path = "crates/wast" } +wat = { version = "1.0.44", path = "crates/wat" } [dependencies] -anyhow = "1.0" +anyhow = { workspace = true } +env_logger = { workspace = true } atty = "0.2" -env_logger = "0.9" -log = "0.4" -clap = { version = "3.1.8", features = ['derive'] } +log = { workspace = true } +clap = { workspace = true } tempfile = "3.2.0" -wat = { path = "crates/wat", version = '1.0.48' } +wat = { workspace = true } # Dependencies of `validate` -wasmparser = { path = "crates/wasmparser", optional = true, version = '0.90.0' } -rayon = { version = "1.0", optional = true } +wasmparser = { workspace = true, optional = true } +rayon = { workspace = true, optional = true } # Dependencies of `print` -wasmprinter = { path = "crates/wasmprinter", version = '0.2.39' } +wasmprinter = { workspace = true } # Dependencies of `smith` -arbitrary = { version = "1.0.0", optional = true } -serde = { version = "1", features = ['derive'], optional = true } +arbitrary = { workspace = true, optional = true } +serde = { workspace = true, optional = true } serde_json = { version = "1", optional = true } -wasm-smith = { path = "crates/wasm-smith", features = ["_internal_cli"], optional = true, version = '0.11.4' } +wasm-smith = { workspace = true, features = ["_internal_cli"], optional = true } # Dependencies of `shrink` -wasm-shrink = { path = "crates/wasm-shrink", features = ["clap"], optional = true, version = '0.1.9' } +wasm-shrink = { workspace = true, features = ["clap"], optional = true } is_executable = { version = "1.0.1", optional = true } # Dependencies of `mutate` -wasm-mutate = { path = "crates/wasm-mutate", features = ["clap"], optional = true, version = '0.2.7' } +wasm-mutate = { workspace = true, features = ["clap"], optional = true } # Dependencies of `dump` -wasmparser-dump = { path = "crates/dump", optional = true, version = '0.1.7' } +wasmparser-dump = { workspace = true, optional = true } # Dependencies of `strip` -wasm-encoder = { path = "crates/wasm-encoder", optional = true, version = '0.16.0' } +wasm-encoder = { workspace = true, optional = true } +regex = { version = "1.6.0", optional = true } # Dependencies of `compose` -wasm-compose = { path = "crates/wasm-compose", optional = true, version = '0.1.0', features = ['cli'] } +wasm-compose = { workspace = true, optional = true, features = ['cli'] } [dev-dependencies] -anyhow = "1.0" -getopts = "0.2" serde_json = "1.0" tempfile = "3.1" diff = "0.1" @@ -83,5 +117,5 @@ shrink = ['wasm-shrink', 'is_executable'] mutate = ['wasm-mutate'] dump = ['wasmparser-dump'] objdump = ['wasmparser'] -strip = ['wasm-encoder'] +strip = ['wasm-encoder', 'wasmparser', 'regex'] compose = ['wasm-compose'] diff --git a/crates/c-api/Cargo.toml b/crates/c-api/Cargo.toml index 2d38bb4a9f..19cc9ae899 100644 --- a/crates/c-api/Cargo.toml +++ b/crates/c-api/Cargo.toml @@ -3,7 +3,7 @@ name = "wasm-tools-c-api" authors = ["Addison Hart "] categories = ["development-tools", "development-tools::testing", "wasm"] description = "C API to expose wasm-tools" -edition = "2021" +edition.workspace = true license = "Apache-2.0 WITH LLVM-exception" readme = "./README.md" repository = "https://github.com/bytecodealliance/wasm-tools/tree/main/crates/c-api" @@ -18,12 +18,12 @@ test = false doctest = false [dependencies] -arbitrary = { version = "1.1.0", features = ["derive"] } -wasmparser-dump = { version = "0.1.4", path = "../dump" } -wasm-mutate = { version = "0.2.4", path = "../wasm-mutate" } -wasm-shrink = { version = "0.1.6", path = "../wasm-shrink" } -wasm-smith = { version = "0.11.2", path = "../wasm-smith" } -wasmparser = { version = "0.90.0", path = "../wasmparser" } -wasmprinter = { version = "0.2.36", path = "../wasmprinter" } -wast = { version = "46.0.0", path = "../wast" } -wat = { version = "1.0.44", path = "../wat" } +arbitrary = { workspace = true, features = ["derive"] } +wasmparser-dump = { workspace = true } +wasm-mutate = { workspace = true } +wasm-shrink = { workspace = true } +wasm-smith = { workspace = true } +wasmparser = { workspace = true } +wasmprinter = { workspace = true } +wast = { workspace = true } +wat = { workspace = true } diff --git a/crates/dump/Cargo.toml b/crates/dump/Cargo.toml index b84a3d3387..6dba8f1c8a 100644 --- a/crates/dump/Cargo.toml +++ b/crates/dump/Cargo.toml @@ -1,12 +1,12 @@ [package] name = "wasmparser-dump" -version = "0.1.7" +version = "0.1.9" authors = ["The Wasmtime Project Developers"] -edition = "2021" +edition.workspace = true license = "Apache-2.0 WITH LLVM-exception" repository = "https://github.com/bytecodealliance/wasm-tools/tree/main/crates/dump" description = "Utility to dump debug information about the wasm binary format" [dependencies] -anyhow = "1" -wasmparser = { path = "../wasmparser", version = "0.90.0" } +anyhow = { workspace = true } +wasmparser = { workspace = true } diff --git a/crates/fuzz-stats/Cargo.toml b/crates/fuzz-stats/Cargo.toml index 7cb3cb15f2..1789e13cda 100644 --- a/crates/fuzz-stats/Cargo.toml +++ b/crates/fuzz-stats/Cargo.toml @@ -1,16 +1,16 @@ [package] name = "fuzz-stats" version = "0.1.0" -edition = "2021" +edition.workspace = true publish = false [dependencies] -anyhow = "1.0" -arbitrary = "1.0" -num_cpus = "1.13" -rand = "0.8" -wasm-smith = { path = '../wasm-smith' } -wasmtime = "0.38.1" +anyhow = { workspace = true } +arbitrary = { workspace = true } +num_cpus = { workspace = true } +rand = { workspace = true } +wasm-smith = { workspace = true } +wasmtime = { workspace = true } [lib] doctest = false diff --git a/crates/wasm-compose/Cargo.toml b/crates/wasm-compose/Cargo.toml index 045b11252b..c4e59605bb 100644 --- a/crates/wasm-compose/Cargo.toml +++ b/crates/wasm-compose/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "wasm-compose" -version = "0.1.1" -edition = "2021" +version = "0.1.3" +edition.workspace = true authors = ["Peter Huene "] license = "Apache-2.0 WITH LLVM-exception" readme = "README.md" @@ -11,16 +11,16 @@ documentation = "https://docs.rs/wasm-compose" description = "A library for composing WebAssembly components." [dependencies] -wat = { version = "1.0.48", path = "../wat" } -wasm-encoder = { version = "0.16.0", path = "../wasm-encoder" } -wasmparser = { version = "0.90.0", path = "../wasmparser" } -indexmap = { version = "1.9.1", features = ["serde"] } -anyhow = "1.0.58" -serde = { version = "1.0.137", features = ["derive"] } +wat = { workspace = true } +wasm-encoder = { workspace = true } +wasmparser = { workspace = true } +indexmap = { workspace = true, features = ["serde"] } +anyhow = { workspace = true } +serde = { workspace = true } petgraph = "0.6.2" -log = "0.4.17" +log = { workspace = true } serde_yaml = "0.8.26" -clap = { version = "3.2.7", features = ["derive"], optional = true } +clap = { workspace = true, optional = true } [features] default = [] @@ -29,4 +29,4 @@ cli = ["clap"] [dev-dependencies] glob = "0.3.0" pretty_assertions = "1.2.1" -wasmprinter = { version = "0.2.39", path = "../wasmprinter" } +wasmprinter = { workspace = true } diff --git a/crates/wasm-compose/example/backend/Cargo.toml b/crates/wasm-compose/example/backend/Cargo.toml index be65e50d28..2b522c4f85 100644 --- a/crates/wasm-compose/example/backend/Cargo.toml +++ b/crates/wasm-compose/example/backend/Cargo.toml @@ -5,7 +5,7 @@ edition = "2021" publish = false [dependencies] -wit-bindgen-rust = { git = "https://github.com/bytecodealliance/wit-bindgen", default_features = false } +wit-bindgen-guest-rust = { git = "https://github.com/bytecodealliance/wit-bindgen", default_features = false } [lib] crate-type = ["cdylib"] diff --git a/crates/wasm-compose/example/middleware/Cargo.toml b/crates/wasm-compose/example/middleware/Cargo.toml index 3cc44fc35c..f9a3d34fef 100644 --- a/crates/wasm-compose/example/middleware/Cargo.toml +++ b/crates/wasm-compose/example/middleware/Cargo.toml @@ -6,7 +6,7 @@ publish = false [dependencies] flate2 = "1.0.24" -wit-bindgen-rust = { git = "https://github.com/bytecodealliance/wit-bindgen", default_features = false } +wit-bindgen-guest-rust = { git = "https://github.com/bytecodealliance/wit-bindgen", default_features = false } [lib] crate-type = ["cdylib"] diff --git a/crates/wasm-compose/example/server/Cargo.toml b/crates/wasm-compose/example/server/Cargo.toml index 679532b04b..113953e036 100644 --- a/crates/wasm-compose/example/server/Cargo.toml +++ b/crates/wasm-compose/example/server/Cargo.toml @@ -9,6 +9,6 @@ async-std = { version = "1.12.0", features = ["attributes"] } clap = { version = "3.2.16", features = ["derive"] } driftwood = "0.0.6" tide = "0.16.0" -wasmtime = { version = "0.41.0", features = ["component-model"], git = "https://github.com/bytecodealliance/wasmtime", rev = "1ce9e8aa5f32a8dad42f02c8fd84514a641c4a5c" } +wasmtime = { features = ["component-model"], git = "https://github.com/bytecodealliance/wasmtime", rev = "e45577e097b064797def3554468cffa5fdd443d3" } [workspace] diff --git a/crates/wasm-compose/example/server/src/main.rs b/crates/wasm-compose/example/server/src/main.rs index ae632d6283..633b5c4174 100644 --- a/crates/wasm-compose/example/server/src/main.rs +++ b/crates/wasm-compose/example/server/src/main.rs @@ -154,12 +154,12 @@ impl ServerApp { // Instantiate the service component and get its `execute` export let instance = linker.instantiate(&mut store, &state.component)?; let execute = instance - .get_typed_func::<(ServiceRequest,), ServiceResult, _>(&mut store, "execute")?; + .get_typed_func::<(ServiceRequest,), (ServiceResult,), _ >(&mut store, "execute")?; // Call the `execute` export with the request and translate the response execute .call(&mut store, (ServiceRequest::new(req).await?,))? - .map_err(Into::into) + .0.map_err(Into::into) .and_then(TryInto::try_into) } } diff --git a/crates/wasm-compose/example/service.wit b/crates/wasm-compose/example/service.wit index eba6406520..4bc65ac492 100644 --- a/crates/wasm-compose/example/service.wit +++ b/crates/wasm-compose/example/service.wit @@ -12,4 +12,4 @@ enum error { bad-request, } -execute: func(req: request) -> expected +execute: func(req: request) -> result diff --git a/crates/wasm-compose/example/service/Cargo.toml b/crates/wasm-compose/example/service/Cargo.toml index 75d9bc0ed1..9085a408bd 100644 --- a/crates/wasm-compose/example/service/Cargo.toml +++ b/crates/wasm-compose/example/service/Cargo.toml @@ -5,7 +5,7 @@ edition = "2021" publish = false [dependencies] -wit-bindgen-rust = { git = "https://github.com/bytecodealliance/wit-bindgen", default_features = false } +wit-bindgen-guest-rust = { git = "https://github.com/bytecodealliance/wit-bindgen", default_features = false } [lib] crate-type = ["cdylib"] diff --git a/crates/wasm-compose/src/cli.rs b/crates/wasm-compose/src/cli.rs index a22f0e9ca4..359031a2f6 100644 --- a/crates/wasm-compose/src/cli.rs +++ b/crates/wasm-compose/src/cli.rs @@ -28,6 +28,10 @@ pub struct WasmComposeCommand { #[clap(long)] pub skip_validation: bool, + /// Do not allow instance imports in the composed output component. + #[clap(long = "no-imports")] + pub disallow_imports: bool, + /// The path to the root component to compose. #[clap(value_name = "COMPONENT")] pub component: PathBuf, @@ -91,6 +95,7 @@ impl WasmComposeCommand { config.search_paths.extend(self.paths.iter().cloned()); config.skip_validation |= self.skip_validation; + config.disallow_imports |= self.disallow_imports; Ok(config) } } diff --git a/crates/wasm-compose/src/composer.rs b/crates/wasm-compose/src/composer.rs index 64b2e2ade3..8108e05fcd 100644 --- a/crates/wasm-compose/src/composer.rs +++ b/crates/wasm-compose/src/composer.rs @@ -46,7 +46,7 @@ impl Component { import_name: Option, ) -> Result { let path = path.into(); - log::debug!("parsing WebAssembly component `{}`", path.display()); + log::info!("parsing WebAssembly component `{}`", path.display()); let bytes = wat::parse_file(&path).with_context(|| { format!("failed to parse component `{path}`", path = path.display()) @@ -518,7 +518,7 @@ impl<'a> InstantiationGraphBuilder<'a> { } // Otherwise, search the paths for a valid component with the same name - log::debug!("searching for a component with name `{name}`"); + log::info!("searching for a component with name `{name}`"); for dir in std::iter::once(&self.config.dir).chain(self.config.search_paths.iter()) { if let Some(component) = Self::parse_component(index, dir, name)? { return Ok(Some(component)); @@ -537,7 +537,7 @@ impl<'a> InstantiationGraphBuilder<'a> { for ext in ["wasm", "wat"] { path.set_extension(ext); if !path.is_file() { - log::debug!("component `{path}` does not exist", path = path.display()); + log::info!("component `{path}` does not exist", path = path.display()); continue; } @@ -572,6 +572,12 @@ impl<'a> InstantiationGraphBuilder<'a> { Instance::Instantiation { component } } None => { + if self.config.disallow_imports { + bail!( + "a dependency named `{component_name}` could not be found and instance imports are not allowed", + ); + } + log::warn!("instance `{name}` will be imported because a dependency named `{component_name}` could not be found"); Instance::Import([import.unwrap()].into()) } @@ -684,7 +690,7 @@ impl<'a> InstantiationGraphBuilder<'a> { fn process_dependency(&mut self, dependency: Dependency) -> Result<(InstanceIndex, bool)> { let name = self.config.dependency_name(&dependency.instance); - log::debug!( + log::info!( "processing dependency `{name}` from instance `{dependent}` to instance `{instance}`", dependent = self .graph diff --git a/crates/wasm-compose/src/config.rs b/crates/wasm-compose/src/config.rs index 40e255483d..35d54cbdef 100644 --- a/crates/wasm-compose/src/config.rs +++ b/crates/wasm-compose/src/config.rs @@ -96,6 +96,13 @@ pub struct Config { #[serde(default)] pub skip_validation: bool, + /// Whether or not to disallow instance imports in the output component. + /// + /// Enabling this option will cause an error if a dependency cannot be + /// located. + #[serde(default)] + pub disallow_imports: bool, + /// The explicit, transitive dependencies of the root component. #[serde(default, deserialize_with = "de::index_map")] pub dependencies: IndexMap, @@ -110,7 +117,7 @@ impl Config { pub fn from_file(path: impl Into) -> Result { let path = path.into(); - log::debug!("reading configuration file `{}`", path.display()); + log::info!("reading configuration file `{}`", path.display()); let config = fs::read_to_string(&path) .with_context(|| format!("failed to read configuration file `{}`", path.display()))?; diff --git a/crates/wasm-compose/src/encoding.rs b/crates/wasm-compose/src/encoding.rs index 8796d4f163..b227ae6321 100644 --- a/crates/wasm-compose/src/encoding.rs +++ b/crates/wasm-compose/src/encoding.rs @@ -384,7 +384,7 @@ impl<'a> TypeEncoder<'a> { .iter() .map(|(name, ty)| { ( - name.as_deref(), + name.as_str(), self.component_val_type(encodable, types, *ty), ) }) @@ -404,11 +404,7 @@ impl<'a> TypeEncoder<'a> { let index = encodable.type_count(); let mut f = encodable.ty().function(); - if params.len() == 1 && params[0].0.is_none() { - f.param(params[0].1); - } else { - f.params(params.into_iter().map(|(name, ty)| (name.unwrap(), ty))); - } + f.params(params); if results.len() == 1 && results[0].0.is_none() { f.result(results[0].1); diff --git a/crates/wasm-compose/tests/compositions/component-not-valid/error.txt b/crates/wasm-compose/tests/compositions/component-not-valid/error.txt index 8c365ffc7b..a69a833403 100644 --- a/crates/wasm-compose/tests/compositions/component-not-valid/error.txt +++ b/crates/wasm-compose/tests/compositions/component-not-valid/error.txt @@ -1,4 +1,4 @@ failed to validate WebAssembly component `tests/compositions/component-not-valid/root.wat` Caused by: - unknown core function 0: function index out of bounds (at offset 0x13) + unknown core function 0: function index out of bounds (at offset 0x12) diff --git a/crates/wasm-compose/tests/compositions/conflict-on-import/b.wat b/crates/wasm-compose/tests/compositions/conflict-on-import/b.wat index bf897c5560..330f8c8c72 100644 --- a/crates/wasm-compose/tests/compositions/conflict-on-import/b.wat +++ b/crates/wasm-compose/tests/compositions/conflict-on-import/b.wat @@ -1,3 +1,3 @@ (component - (import "a" (instance (export "x" (func (param string))))) + (import "a" (instance (export "x" (func (param "x" string))))) ) diff --git a/crates/wasm-compose/tests/compositions/disallow-imports/config.yml b/crates/wasm-compose/tests/compositions/disallow-imports/config.yml new file mode 100644 index 0000000000..e537d3ed12 --- /dev/null +++ b/crates/wasm-compose/tests/compositions/disallow-imports/config.yml @@ -0,0 +1 @@ +disallow-imports: true diff --git a/crates/wasm-compose/tests/compositions/disallow-imports/error.txt b/crates/wasm-compose/tests/compositions/disallow-imports/error.txt new file mode 100644 index 0000000000..2b05e69059 --- /dev/null +++ b/crates/wasm-compose/tests/compositions/disallow-imports/error.txt @@ -0,0 +1 @@ +a dependency named `a` could not be found and instance imports are not allowed diff --git a/crates/wasm-compose/tests/compositions/disallow-imports/root.wat b/crates/wasm-compose/tests/compositions/disallow-imports/root.wat new file mode 100644 index 0000000000..6c6d721b97 --- /dev/null +++ b/crates/wasm-compose/tests/compositions/disallow-imports/root.wat @@ -0,0 +1,3 @@ +(component + (import "a" (instance)) +) diff --git a/crates/wasm-compose/tests/compositions/merged-import/b.wat b/crates/wasm-compose/tests/compositions/merged-import/b.wat index 3e4d69c0fb..403f7aeb0c 100644 --- a/crates/wasm-compose/tests/compositions/merged-import/b.wat +++ b/crates/wasm-compose/tests/compositions/merged-import/b.wat @@ -1,3 +1,3 @@ (component - (import "a" (instance (export "a" (func (param string))) (export "c" (func (param u64))))) + (import "a" (instance (export "a" (func (param "x" string))) (export "c" (func (param "y" u64))))) ) diff --git a/crates/wasm-compose/tests/compositions/merged-import/composed.wat b/crates/wasm-compose/tests/compositions/merged-import/composed.wat index a355a785ce..52c5a8310d 100644 --- a/crates/wasm-compose/tests/compositions/merged-import/composed.wat +++ b/crates/wasm-compose/tests/compositions/merged-import/composed.wat @@ -3,9 +3,9 @@ (instance (type (;0;) (func)) (export "b" (func (type 0))) - (type (;1;) (func (param u64))) + (type (;1;) (func (param "y" u64))) (export "c" (func (type 1))) - (type (;2;) (func (param string))) + (type (;2;) (func (param "x" string))) (export "a" (func (type 2))) ) ) @@ -13,9 +13,9 @@ (component (;0;) (type (;0;) (instance - (type (;0;) (func (param string))) + (type (;0;) (func (param "x" string))) (export "a" (func (type 0))) - (type (;1;) (func (param u64))) + (type (;1;) (func (param "y" u64))) (export "c" (func (type 1))) ) ) @@ -30,7 +30,7 @@ (instance (type (;0;) (func)) (export "b" (func (type 0))) - (type (;1;) (func (param u32))) + (type (;1;) (func (param "y" u32))) (export "c" (func (type 1))) ) ) diff --git a/crates/wasm-compose/tests/compositions/merged-import/root.wat b/crates/wasm-compose/tests/compositions/merged-import/root.wat index 95057e9915..3516fe2814 100644 --- a/crates/wasm-compose/tests/compositions/merged-import/root.wat +++ b/crates/wasm-compose/tests/compositions/merged-import/root.wat @@ -1,4 +1,4 @@ (component - (import "a" (instance (export "b" (func)) (export "c" (func (param u32))))) + (import "a" (instance (export "b" (func)) (export "c" (func (param "y" u32))))) (import "b" (instance)) ) diff --git a/crates/wasm-encoder/Cargo.toml b/crates/wasm-encoder/Cargo.toml index 1a8b837cf6..65fa046353 100644 --- a/crates/wasm-encoder/Cargo.toml +++ b/crates/wasm-encoder/Cargo.toml @@ -1,8 +1,8 @@ [package] name = "wasm-encoder" -version = "0.16.0" +version = "0.18.0" authors = ["Nick Fitzgerald "] -edition = "2021" +edition.workspace = true license = "Apache-2.0 WITH LLVM-exception" readme = "README.md" repository = "https://github.com/bytecodealliance/wasm-tools/tree/main/crates/wasm-encoder" @@ -13,9 +13,9 @@ A low-level WebAssembly encoder. """ [dependencies] -leb128 = "0.2.4" +leb128 = { workspace = true } [dev-dependencies] -anyhow = "1.0.38" +anyhow = { workspace = true } tempfile = "3.2.0" wasmparser = { path = "../wasmparser" } diff --git a/crates/wasm-encoder/README.md b/crates/wasm-encoder/README.md index e63248639b..5f2efbe210 100644 --- a/crates/wasm-encoder/README.md +++ b/crates/wasm-encoder/README.md @@ -16,18 +16,17 @@ ## Usage -Add this to your `Cargo.toml`: +Add `wasm-encoder` to your `Cargo.toml` -```toml -[dependencies] -wasm-encoder = "0.3" +```sh +$ cargo add wasm-encoder ``` And then you can encode WebAssembly binaries via: ```rust use wasm_encoder::{ - CodeSection, Export, ExportSection, Function, FunctionSection, Instruction, + CodeSection, ExportKind, ExportSection, Function, FunctionSection, Instruction, Module, TypeSection, ValType, }; @@ -48,17 +47,17 @@ module.section(&functions); // Encode the export section. let mut exports = ExportSection::new(); -exports.export("f", Export::Function(0)); +exports.export("f", ExportKind::Func, 0); module.section(&exports); // Encode the code section. let mut codes = CodeSection::new(); let locals = vec![]; let mut f = Function::new(locals); -f.instruction(Instruction::LocalGet(0)); -f.instruction(Instruction::LocalGet(1)); -f.instruction(Instruction::I32Add); -f.instruction(Instruction::End); +f.instruction(&Instruction::LocalGet(0)); +f.instruction(&Instruction::LocalGet(1)); +f.instruction(&Instruction::I32Add); +f.instruction(&Instruction::End); codes.function(&f); module.section(&codes); diff --git a/crates/wasm-encoder/src/component/types.rs b/crates/wasm-encoder/src/component/types.rs index b692931f3c..fbf323f3db 100644 --- a/crates/wasm-encoder/src/component/types.rs +++ b/crates/wasm-encoder/src/component/types.rs @@ -380,21 +380,8 @@ impl<'a> ComponentFuncTypeEncoder<'a> { Self(sink) } - /// Defines a single unnamed parameter. - /// - /// This method cannot be used with `params`. - /// - /// Parameters must be defined before defining results. - pub fn param(&mut self, ty: impl Into) -> &mut Self { - self.0.push(0x00); - ty.into().encode(self.0); - self - } - /// Defines named parameters. /// - /// This method cannot be used with `param`. - /// /// Parameters must be defined before defining results. pub fn params<'b, P, T>(&mut self, params: P) -> &mut Self where @@ -402,7 +389,6 @@ impl<'a> ComponentFuncTypeEncoder<'a> { P::IntoIter: ExactSizeIterator, T: Into, { - self.0.push(0x01); let params = params.into_iter(); params.len().encode(self.0); for (name, ty) in params { diff --git a/crates/wasm-encoder/src/core/code.rs b/crates/wasm-encoder/src/core/code.rs index f1f2e11163..6bc55a911f 100644 --- a/crates/wasm-encoder/src/core/code.rs +++ b/crates/wasm-encoder/src/core/code.rs @@ -325,6 +325,8 @@ pub enum Instruction<'a> { CallRef(ValType), CallIndirect { ty: u32, table: u32 }, ReturnCallRef(ValType), + ReturnCall(u32), + ReturnCallIndirect { ty: u32, table: u32 }, Throw(u32), Rethrow(u32), @@ -344,16 +346,16 @@ pub enum Instruction<'a> { I64Load(MemArg), F32Load(MemArg), F64Load(MemArg), - I32Load8_S(MemArg), - I32Load8_U(MemArg), - I32Load16_S(MemArg), - I32Load16_U(MemArg), - I64Load8_S(MemArg), - I64Load8_U(MemArg), - I64Load16_S(MemArg), - I64Load16_U(MemArg), - I64Load32_S(MemArg), - I64Load32_U(MemArg), + I32Load8S(MemArg), + I32Load8U(MemArg), + I32Load16S(MemArg), + I32Load16U(MemArg), + I64Load8S(MemArg), + I64Load8U(MemArg), + I64Load16S(MemArg), + I64Load16U(MemArg), + I64Load32S(MemArg), + I64Load32U(MemArg), I32Store(MemArg), I64Store(MemArg), F32Store(MemArg), @@ -365,9 +367,9 @@ pub enum Instruction<'a> { I64Store32(MemArg), MemorySize(u32), MemoryGrow(u32), - MemoryInit { mem: u32, data: u32 }, + MemoryInit { mem: u32, data_index: u32 }, DataDrop(u32), - MemoryCopy { src: u32, dst: u32 }, + MemoryCopy { src_mem: u32, dst_mem: u32 }, MemoryFill(u32), // Numeric instructions. @@ -520,30 +522,30 @@ pub enum Instruction<'a> { RefAsNonNull, // Bulk memory instructions. - TableInit { segment: u32, table: u32 }, - ElemDrop { segment: u32 }, - TableFill { table: u32 }, - TableSet { table: u32 }, - TableGet { table: u32 }, - TableGrow { table: u32 }, - TableSize { table: u32 }, - TableCopy { src: u32, dst: u32 }, + TableInit { elem_index: u32, table: u32 }, + ElemDrop(u32), + TableFill(u32), + TableSet(u32), + TableGet(u32), + TableGrow(u32), + TableSize(u32), + TableCopy { src_table: u32, dst_table: u32 }, // SIMD instructions. - V128Load { memarg: MemArg }, - V128Load8x8S { memarg: MemArg }, - V128Load8x8U { memarg: MemArg }, - V128Load16x4S { memarg: MemArg }, - V128Load16x4U { memarg: MemArg }, - V128Load32x2S { memarg: MemArg }, - V128Load32x2U { memarg: MemArg }, - V128Load8Splat { memarg: MemArg }, - V128Load16Splat { memarg: MemArg }, - V128Load32Splat { memarg: MemArg }, - V128Load64Splat { memarg: MemArg }, - V128Load32Zero { memarg: MemArg }, - V128Load64Zero { memarg: MemArg }, - V128Store { memarg: MemArg }, + V128Load(MemArg), + V128Load8x8S(MemArg), + V128Load8x8U(MemArg), + V128Load16x4S(MemArg), + V128Load16x4U(MemArg), + V128Load32x2S(MemArg), + V128Load32x2U(MemArg), + V128Load8Splat(MemArg), + V128Load16Splat(MemArg), + V128Load32Splat(MemArg), + V128Load64Splat(MemArg), + V128Load32Zero(MemArg), + V128Load64Zero(MemArg), + V128Store(MemArg), V128Load8Lane { memarg: MemArg, lane: Lane }, V128Load16Lane { memarg: MemArg, lane: Lane }, V128Load32Lane { memarg: MemArg, lane: Lane }, @@ -553,21 +555,21 @@ pub enum Instruction<'a> { V128Store32Lane { memarg: MemArg, lane: Lane }, V128Store64Lane { memarg: MemArg, lane: Lane }, V128Const(i128), - I8x16Shuffle { lanes: [Lane; 16] }, - I8x16ExtractLaneS { lane: Lane }, - I8x16ExtractLaneU { lane: Lane }, - I8x16ReplaceLane { lane: Lane }, - I16x8ExtractLaneS { lane: Lane }, - I16x8ExtractLaneU { lane: Lane }, - I16x8ReplaceLane { lane: Lane }, - I32x4ExtractLane { lane: Lane }, - I32x4ReplaceLane { lane: Lane }, - I64x2ExtractLane { lane: Lane }, - I64x2ReplaceLane { lane: Lane }, - F32x4ExtractLane { lane: Lane }, - F32x4ReplaceLane { lane: Lane }, - F64x2ExtractLane { lane: Lane }, - F64x2ReplaceLane { lane: Lane }, + I8x16Shuffle([Lane; 16]), + I8x16ExtractLaneS(Lane), + I8x16ExtractLaneU(Lane), + I8x16ReplaceLane(Lane), + I16x8ExtractLaneS(Lane), + I16x8ExtractLaneU(Lane), + I16x8ReplaceLane(Lane), + I32x4ExtractLane(Lane), + I32x4ReplaceLane(Lane), + I64x2ExtractLane(Lane), + I64x2ReplaceLane(Lane), + F32x4ExtractLane(Lane), + F32x4ReplaceLane(Lane), + F64x2ExtractLane(Lane), + F64x2ReplaceLane(Lane), I8x16Swizzle, I8x16Splat, I16x8Splat, @@ -771,87 +773,91 @@ pub enum Instruction<'a> { I32x4RelaxedTruncSatF32x4U, I32x4RelaxedTruncSatF64x2SZero, I32x4RelaxedTruncSatF64x2UZero, - F32x4Fma, - F32x4Fms, - F64x2Fma, - F64x2Fms, - I8x16LaneSelect, - I16x8LaneSelect, - I32x4LaneSelect, - I64x2LaneSelect, + F32x4RelaxedFma, + F32x4RelaxedFnma, + F64x2RelaxedFma, + F64x2RelaxedFnma, + I8x16RelaxedLaneselect, + I16x8RelaxedLaneselect, + I32x4RelaxedLaneselect, + I64x2RelaxedLaneselect, F32x4RelaxedMin, F32x4RelaxedMax, F64x2RelaxedMin, F64x2RelaxedMax, + I16x8RelaxedQ15mulrS, + I16x8DotI8x16I7x16S, + I32x4DotI8x16I7x16AddS, + F32x4RelaxedDotBf16x8AddF32x4, // Atomic instructions (the threads proposal) - MemoryAtomicNotify { memarg: MemArg }, - MemoryAtomicWait32 { memarg: MemArg }, - MemoryAtomicWait64 { memarg: MemArg }, + MemoryAtomicNotify(MemArg), + MemoryAtomicWait32(MemArg), + MemoryAtomicWait64(MemArg), AtomicFence, - I32AtomicLoad { memarg: MemArg }, - I64AtomicLoad { memarg: MemArg }, - I32AtomicLoad8U { memarg: MemArg }, - I32AtomicLoad16U { memarg: MemArg }, - I64AtomicLoad8U { memarg: MemArg }, - I64AtomicLoad16U { memarg: MemArg }, - I64AtomicLoad32U { memarg: MemArg }, - I32AtomicStore { memarg: MemArg }, - I64AtomicStore { memarg: MemArg }, - I32AtomicStore8 { memarg: MemArg }, - I32AtomicStore16 { memarg: MemArg }, - I64AtomicStore8 { memarg: MemArg }, - I64AtomicStore16 { memarg: MemArg }, - I64AtomicStore32 { memarg: MemArg }, - I32AtomicRmwAdd { memarg: MemArg }, - I64AtomicRmwAdd { memarg: MemArg }, - I32AtomicRmw8AddU { memarg: MemArg }, - I32AtomicRmw16AddU { memarg: MemArg }, - I64AtomicRmw8AddU { memarg: MemArg }, - I64AtomicRmw16AddU { memarg: MemArg }, - I64AtomicRmw32AddU { memarg: MemArg }, - I32AtomicRmwSub { memarg: MemArg }, - I64AtomicRmwSub { memarg: MemArg }, - I32AtomicRmw8SubU { memarg: MemArg }, - I32AtomicRmw16SubU { memarg: MemArg }, - I64AtomicRmw8SubU { memarg: MemArg }, - I64AtomicRmw16SubU { memarg: MemArg }, - I64AtomicRmw32SubU { memarg: MemArg }, - I32AtomicRmwAnd { memarg: MemArg }, - I64AtomicRmwAnd { memarg: MemArg }, - I32AtomicRmw8AndU { memarg: MemArg }, - I32AtomicRmw16AndU { memarg: MemArg }, - I64AtomicRmw8AndU { memarg: MemArg }, - I64AtomicRmw16AndU { memarg: MemArg }, - I64AtomicRmw32AndU { memarg: MemArg }, - I32AtomicRmwOr { memarg: MemArg }, - I64AtomicRmwOr { memarg: MemArg }, - I32AtomicRmw8OrU { memarg: MemArg }, - I32AtomicRmw16OrU { memarg: MemArg }, - I64AtomicRmw8OrU { memarg: MemArg }, - I64AtomicRmw16OrU { memarg: MemArg }, - I64AtomicRmw32OrU { memarg: MemArg }, - I32AtomicRmwXor { memarg: MemArg }, - I64AtomicRmwXor { memarg: MemArg }, - I32AtomicRmw8XorU { memarg: MemArg }, - I32AtomicRmw16XorU { memarg: MemArg }, - I64AtomicRmw8XorU { memarg: MemArg }, - I64AtomicRmw16XorU { memarg: MemArg }, - I64AtomicRmw32XorU { memarg: MemArg }, - I32AtomicRmwXchg { memarg: MemArg }, - I64AtomicRmwXchg { memarg: MemArg }, - I32AtomicRmw8XchgU { memarg: MemArg }, - I32AtomicRmw16XchgU { memarg: MemArg }, - I64AtomicRmw8XchgU { memarg: MemArg }, - I64AtomicRmw16XchgU { memarg: MemArg }, - I64AtomicRmw32XchgU { memarg: MemArg }, - I32AtomicRmwCmpxchg { memarg: MemArg }, - I64AtomicRmwCmpxchg { memarg: MemArg }, - I32AtomicRmw8CmpxchgU { memarg: MemArg }, - I32AtomicRmw16CmpxchgU { memarg: MemArg }, - I64AtomicRmw8CmpxchgU { memarg: MemArg }, - I64AtomicRmw16CmpxchgU { memarg: MemArg }, - I64AtomicRmw32CmpxchgU { memarg: MemArg }, + I32AtomicLoad(MemArg), + I64AtomicLoad(MemArg), + I32AtomicLoad8U(MemArg), + I32AtomicLoad16U(MemArg), + I64AtomicLoad8U(MemArg), + I64AtomicLoad16U(MemArg), + I64AtomicLoad32U(MemArg), + I32AtomicStore(MemArg), + I64AtomicStore(MemArg), + I32AtomicStore8(MemArg), + I32AtomicStore16(MemArg), + I64AtomicStore8(MemArg), + I64AtomicStore16(MemArg), + I64AtomicStore32(MemArg), + I32AtomicRmwAdd(MemArg), + I64AtomicRmwAdd(MemArg), + I32AtomicRmw8AddU(MemArg), + I32AtomicRmw16AddU(MemArg), + I64AtomicRmw8AddU(MemArg), + I64AtomicRmw16AddU(MemArg), + I64AtomicRmw32AddU(MemArg), + I32AtomicRmwSub(MemArg), + I64AtomicRmwSub(MemArg), + I32AtomicRmw8SubU(MemArg), + I32AtomicRmw16SubU(MemArg), + I64AtomicRmw8SubU(MemArg), + I64AtomicRmw16SubU(MemArg), + I64AtomicRmw32SubU(MemArg), + I32AtomicRmwAnd(MemArg), + I64AtomicRmwAnd(MemArg), + I32AtomicRmw8AndU(MemArg), + I32AtomicRmw16AndU(MemArg), + I64AtomicRmw8AndU(MemArg), + I64AtomicRmw16AndU(MemArg), + I64AtomicRmw32AndU(MemArg), + I32AtomicRmwOr(MemArg), + I64AtomicRmwOr(MemArg), + I32AtomicRmw8OrU(MemArg), + I32AtomicRmw16OrU(MemArg), + I64AtomicRmw8OrU(MemArg), + I64AtomicRmw16OrU(MemArg), + I64AtomicRmw32OrU(MemArg), + I32AtomicRmwXor(MemArg), + I64AtomicRmwXor(MemArg), + I32AtomicRmw8XorU(MemArg), + I32AtomicRmw16XorU(MemArg), + I64AtomicRmw8XorU(MemArg), + I64AtomicRmw16XorU(MemArg), + I64AtomicRmw32XorU(MemArg), + I32AtomicRmwXchg(MemArg), + I64AtomicRmwXchg(MemArg), + I32AtomicRmw8XchgU(MemArg), + I32AtomicRmw16XchgU(MemArg), + I64AtomicRmw8XchgU(MemArg), + I64AtomicRmw16XchgU(MemArg), + I64AtomicRmw32XchgU(MemArg), + I32AtomicRmwCmpxchg(MemArg), + I64AtomicRmwCmpxchg(MemArg), + I32AtomicRmw8CmpxchgU(MemArg), + I32AtomicRmw16CmpxchgU(MemArg), + I64AtomicRmw8CmpxchgU(MemArg), + I64AtomicRmw16CmpxchgU(MemArg), + I64AtomicRmw32CmpxchgU(MemArg), } impl Encode for Instruction<'_> { @@ -929,6 +935,16 @@ impl Encode for Instruction<'_> { sink.push(0x15); ty.encode(sink); } + + Instruction::ReturnCall(f) => { + sink.push(0x12); + f.encode(sink); + } + Instruction::ReturnCallIndirect { ty, table } => { + sink.push(0x13); + ty.encode(sink); + table.encode(sink); + } Instruction::Delegate(l) => { sink.push(0x18); l.encode(sink); @@ -966,11 +982,11 @@ impl Encode for Instruction<'_> { sink.push(0x24); g.encode(sink); } - Instruction::TableGet { table } => { + Instruction::TableGet(table) => { sink.push(0x25); table.encode(sink); } - Instruction::TableSet { table } => { + Instruction::TableSet(table) => { sink.push(0x26); table.encode(sink); } @@ -992,43 +1008,43 @@ impl Encode for Instruction<'_> { sink.push(0x2B); m.encode(sink); } - Instruction::I32Load8_S(m) => { + Instruction::I32Load8S(m) => { sink.push(0x2C); m.encode(sink); } - Instruction::I32Load8_U(m) => { + Instruction::I32Load8U(m) => { sink.push(0x2D); m.encode(sink); } - Instruction::I32Load16_S(m) => { + Instruction::I32Load16S(m) => { sink.push(0x2E); m.encode(sink); } - Instruction::I32Load16_U(m) => { + Instruction::I32Load16U(m) => { sink.push(0x2F); m.encode(sink); } - Instruction::I64Load8_S(m) => { + Instruction::I64Load8S(m) => { sink.push(0x30); m.encode(sink); } - Instruction::I64Load8_U(m) => { + Instruction::I64Load8U(m) => { sink.push(0x31); m.encode(sink); } - Instruction::I64Load16_S(m) => { + Instruction::I64Load16S(m) => { sink.push(0x32); m.encode(sink); } - Instruction::I64Load16_U(m) => { + Instruction::I64Load16U(m) => { sink.push(0x33); m.encode(sink); } - Instruction::I64Load32_S(m) => { + Instruction::I64Load32S(m) => { sink.push(0x34); m.encode(sink); } - Instruction::I64Load32_U(m) => { + Instruction::I64Load32U(m) => { sink.push(0x35); m.encode(sink); } @@ -1076,10 +1092,10 @@ impl Encode for Instruction<'_> { sink.push(0x40); i.encode(sink); } - Instruction::MemoryInit { mem, data } => { + Instruction::MemoryInit { mem, data_index } => { sink.push(0xfc); sink.push(0x08); - data.encode(sink); + data_index.encode(sink); mem.encode(sink); } Instruction::DataDrop(data) => { @@ -1087,11 +1103,11 @@ impl Encode for Instruction<'_> { sink.push(0x09); data.encode(sink); } - Instruction::MemoryCopy { src, dst } => { + Instruction::MemoryCopy { src_mem, dst_mem } => { sink.push(0xfc); sink.push(0x0a); - dst.encode(sink); - src.encode(sink); + dst_mem.encode(sink); + src_mem.encode(sink); } Instruction::MemoryFill(mem) => { sink.push(0xfc); @@ -1293,96 +1309,99 @@ impl Encode for Instruction<'_> { Instruction::RefAsNonNull => sink.push(0xD3), // Bulk memory instructions. - Instruction::TableInit { segment, table } => { + Instruction::TableInit { elem_index, table } => { sink.push(0xfc); sink.push(0x0c); - segment.encode(sink); + elem_index.encode(sink); table.encode(sink); } - Instruction::ElemDrop { segment } => { + Instruction::ElemDrop(segment) => { sink.push(0xfc); sink.push(0x0d); segment.encode(sink); } - Instruction::TableCopy { src, dst } => { + Instruction::TableCopy { + src_table, + dst_table, + } => { sink.push(0xfc); sink.push(0x0e); - dst.encode(sink); - src.encode(sink); + dst_table.encode(sink); + src_table.encode(sink); } - Instruction::TableGrow { table } => { + Instruction::TableGrow(table) => { sink.push(0xfc); sink.push(0x0f); table.encode(sink); } - Instruction::TableSize { table } => { + Instruction::TableSize(table) => { sink.push(0xfc); sink.push(0x10); table.encode(sink); } - Instruction::TableFill { table } => { + Instruction::TableFill(table) => { sink.push(0xfc); sink.push(0x11); table.encode(sink); } // SIMD instructions. - Instruction::V128Load { memarg } => { + Instruction::V128Load(memarg) => { sink.push(0xFD); 0x00u32.encode(sink); memarg.encode(sink); } - Instruction::V128Load8x8S { memarg } => { + Instruction::V128Load8x8S(memarg) => { sink.push(0xFD); 0x01u32.encode(sink); memarg.encode(sink); } - Instruction::V128Load8x8U { memarg } => { + Instruction::V128Load8x8U(memarg) => { sink.push(0xFD); 0x02u32.encode(sink); memarg.encode(sink); } - Instruction::V128Load16x4S { memarg } => { + Instruction::V128Load16x4S(memarg) => { sink.push(0xFD); 0x03u32.encode(sink); memarg.encode(sink); } - Instruction::V128Load16x4U { memarg } => { + Instruction::V128Load16x4U(memarg) => { sink.push(0xFD); 0x04u32.encode(sink); memarg.encode(sink); } - Instruction::V128Load32x2S { memarg } => { + Instruction::V128Load32x2S(memarg) => { sink.push(0xFD); 0x05u32.encode(sink); memarg.encode(sink); } - Instruction::V128Load32x2U { memarg } => { + Instruction::V128Load32x2U(memarg) => { sink.push(0xFD); 0x06u32.encode(sink); memarg.encode(sink); } - Instruction::V128Load8Splat { memarg } => { + Instruction::V128Load8Splat(memarg) => { sink.push(0xFD); 0x07u32.encode(sink); memarg.encode(sink); } - Instruction::V128Load16Splat { memarg } => { + Instruction::V128Load16Splat(memarg) => { sink.push(0xFD); 0x08u32.encode(sink); memarg.encode(sink); } - Instruction::V128Load32Splat { memarg } => { + Instruction::V128Load32Splat(memarg) => { sink.push(0xFD); 0x09u32.encode(sink); memarg.encode(sink); } - Instruction::V128Load64Splat { memarg } => { + Instruction::V128Load64Splat(memarg) => { sink.push(0xFD); 0x0Au32.encode(sink); memarg.encode(sink); } - Instruction::V128Store { memarg } => { + Instruction::V128Store(memarg) => { sink.push(0xFD); 0x0Bu32.encode(sink); memarg.encode(sink); @@ -1392,7 +1411,7 @@ impl Encode for Instruction<'_> { 0x0Cu32.encode(sink); sink.extend(x.to_le_bytes().iter().copied()); } - Instruction::I8x16Shuffle { lanes } => { + Instruction::I8x16Shuffle(lanes) => { sink.push(0xFD); 0x0Du32.encode(sink); assert!(lanes.iter().all(|l: &u8| *l < 32)); @@ -1426,85 +1445,85 @@ impl Encode for Instruction<'_> { sink.push(0xFD); 0x14u32.encode(sink); } - Instruction::I8x16ExtractLaneS { lane } => { + Instruction::I8x16ExtractLaneS(lane) => { sink.push(0xFD); 0x15u32.encode(sink); assert!(lane < 16); sink.push(lane); } - Instruction::I8x16ExtractLaneU { lane } => { + Instruction::I8x16ExtractLaneU(lane) => { sink.push(0xFD); 0x16u32.encode(sink); assert!(lane < 16); sink.push(lane); } - Instruction::I8x16ReplaceLane { lane } => { + Instruction::I8x16ReplaceLane(lane) => { sink.push(0xFD); 0x17u32.encode(sink); assert!(lane < 16); sink.push(lane); } - Instruction::I16x8ExtractLaneS { lane } => { + Instruction::I16x8ExtractLaneS(lane) => { sink.push(0xFD); 0x18u32.encode(sink); assert!(lane < 8); sink.push(lane); } - Instruction::I16x8ExtractLaneU { lane } => { + Instruction::I16x8ExtractLaneU(lane) => { sink.push(0xFD); 0x19u32.encode(sink); assert!(lane < 8); sink.push(lane); } - Instruction::I16x8ReplaceLane { lane } => { + Instruction::I16x8ReplaceLane(lane) => { sink.push(0xFD); 0x1Au32.encode(sink); assert!(lane < 8); sink.push(lane); } - Instruction::I32x4ExtractLane { lane } => { + Instruction::I32x4ExtractLane(lane) => { sink.push(0xFD); 0x1Bu32.encode(sink); assert!(lane < 4); sink.push(lane); } - Instruction::I32x4ReplaceLane { lane } => { + Instruction::I32x4ReplaceLane(lane) => { sink.push(0xFD); 0x1Cu32.encode(sink); assert!(lane < 4); sink.push(lane); } - Instruction::I64x2ExtractLane { lane } => { + Instruction::I64x2ExtractLane(lane) => { sink.push(0xFD); 0x1Du32.encode(sink); assert!(lane < 2); sink.push(lane); } - Instruction::I64x2ReplaceLane { lane } => { + Instruction::I64x2ReplaceLane(lane) => { sink.push(0xFD); 0x1Eu32.encode(sink); assert!(lane < 2); sink.push(lane); } - Instruction::F32x4ExtractLane { lane } => { + Instruction::F32x4ExtractLane(lane) => { sink.push(0xFD); 0x1Fu32.encode(sink); assert!(lane < 4); sink.push(lane); } - Instruction::F32x4ReplaceLane { lane } => { + Instruction::F32x4ReplaceLane(lane) => { sink.push(0xFD); 0x20u32.encode(sink); assert!(lane < 4); sink.push(lane); } - Instruction::F64x2ExtractLane { lane } => { + Instruction::F64x2ExtractLane(lane) => { sink.push(0xFD); 0x21u32.encode(sink); assert!(lane < 2); sink.push(lane); } - Instruction::F64x2ReplaceLane { lane } => { + Instruction::F64x2ReplaceLane(lane) => { sink.push(0xFD); 0x22u32.encode(sink); assert!(lane < 2); @@ -2251,12 +2270,12 @@ impl Encode for Instruction<'_> { sink.push(0xFD); 0x5Fu32.encode(sink); } - Instruction::V128Load32Zero { memarg } => { + Instruction::V128Load32Zero(memarg) => { sink.push(0xFD); 0x5Cu32.encode(sink); memarg.encode(sink); } - Instruction::V128Load64Zero { memarg } => { + Instruction::V128Load64Zero(memarg) => { sink.push(0xFD); 0x5Du32.encode(sink); memarg.encode(sink); @@ -2343,85 +2362,101 @@ impl Encode for Instruction<'_> { } Instruction::I8x16RelaxedSwizzle => { sink.push(0xFD); - 0xA2u32.encode(sink); + 0x100u32.encode(sink); } Instruction::I32x4RelaxedTruncSatF32x4S => { sink.push(0xFD); - 0xA5u32.encode(sink); + 0x101u32.encode(sink); } Instruction::I32x4RelaxedTruncSatF32x4U => { sink.push(0xFD); - 0xA6u32.encode(sink); + 0x102u32.encode(sink); } Instruction::I32x4RelaxedTruncSatF64x2SZero => { sink.push(0xFD); - 0xC5u32.encode(sink); + 0x103u32.encode(sink); } Instruction::I32x4RelaxedTruncSatF64x2UZero => { sink.push(0xFD); - 0xC6u32.encode(sink); + 0x104u32.encode(sink); } - Instruction::F32x4Fma => { + Instruction::F32x4RelaxedFma => { sink.push(0xFD); - 0xAFu32.encode(sink); + 0x105u32.encode(sink); } - Instruction::F32x4Fms => { + Instruction::F32x4RelaxedFnma => { sink.push(0xFD); - 0xB0u32.encode(sink); + 0x106u32.encode(sink); } - Instruction::F64x2Fma => { + Instruction::F64x2RelaxedFma => { sink.push(0xFD); - 0xCFu32.encode(sink); + 0x107u32.encode(sink); } - Instruction::F64x2Fms => { + Instruction::F64x2RelaxedFnma => { sink.push(0xFD); - 0xD0u32.encode(sink); + 0x108u32.encode(sink); } - Instruction::I8x16LaneSelect => { + Instruction::I8x16RelaxedLaneselect => { sink.push(0xFD); - 0xB2u32.encode(sink); + 0x109u32.encode(sink); } - Instruction::I16x8LaneSelect => { + Instruction::I16x8RelaxedLaneselect => { sink.push(0xFD); - 0xB3u32.encode(sink); + 0x10Au32.encode(sink); } - Instruction::I32x4LaneSelect => { + Instruction::I32x4RelaxedLaneselect => { sink.push(0xFD); - 0xD2u32.encode(sink); + 0x10Bu32.encode(sink); } - Instruction::I64x2LaneSelect => { + Instruction::I64x2RelaxedLaneselect => { sink.push(0xFD); - 0xD3u32.encode(sink); + 0x10Cu32.encode(sink); } Instruction::F32x4RelaxedMin => { sink.push(0xFD); - 0xB4u32.encode(sink); + 0x10Du32.encode(sink); } Instruction::F32x4RelaxedMax => { sink.push(0xFD); - 0xE2u32.encode(sink); + 0x10Eu32.encode(sink); } Instruction::F64x2RelaxedMin => { sink.push(0xFD); - 0xD4u32.encode(sink); + 0x10Fu32.encode(sink); } Instruction::F64x2RelaxedMax => { sink.push(0xFD); - 0xEEu32.encode(sink); + 0x110u32.encode(sink); + } + Instruction::I16x8RelaxedQ15mulrS => { + sink.push(0xFD); + 0x111u32.encode(sink); + } + Instruction::I16x8DotI8x16I7x16S => { + sink.push(0xFD); + 0x112u32.encode(sink); + } + Instruction::I32x4DotI8x16I7x16AddS => { + sink.push(0xFD); + 0x113u32.encode(sink); + } + Instruction::F32x4RelaxedDotBf16x8AddF32x4 => { + sink.push(0xFD); + 0x114u32.encode(sink); } // Atmoic instructions from the thread proposal - Instruction::MemoryAtomicNotify { memarg } => { + Instruction::MemoryAtomicNotify(memarg) => { sink.push(0xFE); sink.push(0x00); memarg.encode(sink); } - Instruction::MemoryAtomicWait32 { memarg } => { + Instruction::MemoryAtomicWait32(memarg) => { sink.push(0xFE); sink.push(0x01); memarg.encode(sink); } - Instruction::MemoryAtomicWait64 { memarg } => { + Instruction::MemoryAtomicWait64(memarg) => { sink.push(0xFE); sink.push(0x02); memarg.encode(sink); @@ -2431,317 +2466,317 @@ impl Encode for Instruction<'_> { sink.push(0x03); sink.push(0x00); } - Instruction::I32AtomicLoad { memarg } => { + Instruction::I32AtomicLoad(memarg) => { sink.push(0xFE); sink.push(0x10); memarg.encode(sink); } - Instruction::I64AtomicLoad { memarg } => { + Instruction::I64AtomicLoad(memarg) => { sink.push(0xFE); sink.push(0x11); memarg.encode(sink); } - Instruction::I32AtomicLoad8U { memarg } => { + Instruction::I32AtomicLoad8U(memarg) => { sink.push(0xFE); sink.push(0x12); memarg.encode(sink); } - Instruction::I32AtomicLoad16U { memarg } => { + Instruction::I32AtomicLoad16U(memarg) => { sink.push(0xFE); sink.push(0x13); memarg.encode(sink); } - Instruction::I64AtomicLoad8U { memarg } => { + Instruction::I64AtomicLoad8U(memarg) => { sink.push(0xFE); sink.push(0x14); memarg.encode(sink); } - Instruction::I64AtomicLoad16U { memarg } => { + Instruction::I64AtomicLoad16U(memarg) => { sink.push(0xFE); sink.push(0x15); memarg.encode(sink); } - Instruction::I64AtomicLoad32U { memarg } => { + Instruction::I64AtomicLoad32U(memarg) => { sink.push(0xFE); sink.push(0x16); memarg.encode(sink); } - Instruction::I32AtomicStore { memarg } => { + Instruction::I32AtomicStore(memarg) => { sink.push(0xFE); sink.push(0x17); memarg.encode(sink); } - Instruction::I64AtomicStore { memarg } => { + Instruction::I64AtomicStore(memarg) => { sink.push(0xFE); sink.push(0x18); memarg.encode(sink); } - Instruction::I32AtomicStore8 { memarg } => { + Instruction::I32AtomicStore8(memarg) => { sink.push(0xFE); sink.push(0x19); memarg.encode(sink); } - Instruction::I32AtomicStore16 { memarg } => { + Instruction::I32AtomicStore16(memarg) => { sink.push(0xFE); sink.push(0x1A); memarg.encode(sink); } - Instruction::I64AtomicStore8 { memarg } => { + Instruction::I64AtomicStore8(memarg) => { sink.push(0xFE); sink.push(0x1B); memarg.encode(sink); } - Instruction::I64AtomicStore16 { memarg } => { + Instruction::I64AtomicStore16(memarg) => { sink.push(0xFE); sink.push(0x1C); memarg.encode(sink); } - Instruction::I64AtomicStore32 { memarg } => { + Instruction::I64AtomicStore32(memarg) => { sink.push(0xFE); sink.push(0x1D); memarg.encode(sink); } - Instruction::I32AtomicRmwAdd { memarg } => { + Instruction::I32AtomicRmwAdd(memarg) => { sink.push(0xFE); sink.push(0x1E); memarg.encode(sink); } - Instruction::I64AtomicRmwAdd { memarg } => { + Instruction::I64AtomicRmwAdd(memarg) => { sink.push(0xFE); sink.push(0x1F); memarg.encode(sink); } - Instruction::I32AtomicRmw8AddU { memarg } => { + Instruction::I32AtomicRmw8AddU(memarg) => { sink.push(0xFE); sink.push(0x20); memarg.encode(sink); } - Instruction::I32AtomicRmw16AddU { memarg } => { + Instruction::I32AtomicRmw16AddU(memarg) => { sink.push(0xFE); sink.push(0x21); memarg.encode(sink); } - Instruction::I64AtomicRmw8AddU { memarg } => { + Instruction::I64AtomicRmw8AddU(memarg) => { sink.push(0xFE); sink.push(0x22); memarg.encode(sink); } - Instruction::I64AtomicRmw16AddU { memarg } => { + Instruction::I64AtomicRmw16AddU(memarg) => { sink.push(0xFE); sink.push(0x23); memarg.encode(sink); } - Instruction::I64AtomicRmw32AddU { memarg } => { + Instruction::I64AtomicRmw32AddU(memarg) => { sink.push(0xFE); sink.push(0x24); memarg.encode(sink); } - Instruction::I32AtomicRmwSub { memarg } => { + Instruction::I32AtomicRmwSub(memarg) => { sink.push(0xFE); sink.push(0x25); memarg.encode(sink); } - Instruction::I64AtomicRmwSub { memarg } => { + Instruction::I64AtomicRmwSub(memarg) => { sink.push(0xFE); sink.push(0x26); memarg.encode(sink); } - Instruction::I32AtomicRmw8SubU { memarg } => { + Instruction::I32AtomicRmw8SubU(memarg) => { sink.push(0xFE); sink.push(0x27); memarg.encode(sink); } - Instruction::I32AtomicRmw16SubU { memarg } => { + Instruction::I32AtomicRmw16SubU(memarg) => { sink.push(0xFE); sink.push(0x28); memarg.encode(sink); } - Instruction::I64AtomicRmw8SubU { memarg } => { + Instruction::I64AtomicRmw8SubU(memarg) => { sink.push(0xFE); sink.push(0x29); memarg.encode(sink); } - Instruction::I64AtomicRmw16SubU { memarg } => { + Instruction::I64AtomicRmw16SubU(memarg) => { sink.push(0xFE); sink.push(0x2A); memarg.encode(sink); } - Instruction::I64AtomicRmw32SubU { memarg } => { + Instruction::I64AtomicRmw32SubU(memarg) => { sink.push(0xFE); sink.push(0x2B); memarg.encode(sink); } - Instruction::I32AtomicRmwAnd { memarg } => { + Instruction::I32AtomicRmwAnd(memarg) => { sink.push(0xFE); sink.push(0x2C); memarg.encode(sink); } - Instruction::I64AtomicRmwAnd { memarg } => { + Instruction::I64AtomicRmwAnd(memarg) => { sink.push(0xFE); sink.push(0x2D); memarg.encode(sink); } - Instruction::I32AtomicRmw8AndU { memarg } => { + Instruction::I32AtomicRmw8AndU(memarg) => { sink.push(0xFE); sink.push(0x2E); memarg.encode(sink); } - Instruction::I32AtomicRmw16AndU { memarg } => { + Instruction::I32AtomicRmw16AndU(memarg) => { sink.push(0xFE); sink.push(0x2F); memarg.encode(sink); } - Instruction::I64AtomicRmw8AndU { memarg } => { + Instruction::I64AtomicRmw8AndU(memarg) => { sink.push(0xFE); sink.push(0x30); memarg.encode(sink); } - Instruction::I64AtomicRmw16AndU { memarg } => { + Instruction::I64AtomicRmw16AndU(memarg) => { sink.push(0xFE); sink.push(0x31); memarg.encode(sink); } - Instruction::I64AtomicRmw32AndU { memarg } => { + Instruction::I64AtomicRmw32AndU(memarg) => { sink.push(0xFE); sink.push(0x32); memarg.encode(sink); } - Instruction::I32AtomicRmwOr { memarg } => { + Instruction::I32AtomicRmwOr(memarg) => { sink.push(0xFE); sink.push(0x33); memarg.encode(sink); } - Instruction::I64AtomicRmwOr { memarg } => { + Instruction::I64AtomicRmwOr(memarg) => { sink.push(0xFE); sink.push(0x34); memarg.encode(sink); } - Instruction::I32AtomicRmw8OrU { memarg } => { + Instruction::I32AtomicRmw8OrU(memarg) => { sink.push(0xFE); sink.push(0x35); memarg.encode(sink); } - Instruction::I32AtomicRmw16OrU { memarg } => { + Instruction::I32AtomicRmw16OrU(memarg) => { sink.push(0xFE); sink.push(0x36); memarg.encode(sink); } - Instruction::I64AtomicRmw8OrU { memarg } => { + Instruction::I64AtomicRmw8OrU(memarg) => { sink.push(0xFE); sink.push(0x37); memarg.encode(sink); } - Instruction::I64AtomicRmw16OrU { memarg } => { + Instruction::I64AtomicRmw16OrU(memarg) => { sink.push(0xFE); sink.push(0x38); memarg.encode(sink); } - Instruction::I64AtomicRmw32OrU { memarg } => { + Instruction::I64AtomicRmw32OrU(memarg) => { sink.push(0xFE); sink.push(0x39); memarg.encode(sink); } - Instruction::I32AtomicRmwXor { memarg } => { + Instruction::I32AtomicRmwXor(memarg) => { sink.push(0xFE); sink.push(0x3A); memarg.encode(sink); } - Instruction::I64AtomicRmwXor { memarg } => { + Instruction::I64AtomicRmwXor(memarg) => { sink.push(0xFE); sink.push(0x3B); memarg.encode(sink); } - Instruction::I32AtomicRmw8XorU { memarg } => { + Instruction::I32AtomicRmw8XorU(memarg) => { sink.push(0xFE); sink.push(0x3C); memarg.encode(sink); } - Instruction::I32AtomicRmw16XorU { memarg } => { + Instruction::I32AtomicRmw16XorU(memarg) => { sink.push(0xFE); sink.push(0x3D); memarg.encode(sink); } - Instruction::I64AtomicRmw8XorU { memarg } => { + Instruction::I64AtomicRmw8XorU(memarg) => { sink.push(0xFE); sink.push(0x3E); memarg.encode(sink); } - Instruction::I64AtomicRmw16XorU { memarg } => { + Instruction::I64AtomicRmw16XorU(memarg) => { sink.push(0xFE); sink.push(0x3F); memarg.encode(sink); } - Instruction::I64AtomicRmw32XorU { memarg } => { + Instruction::I64AtomicRmw32XorU(memarg) => { sink.push(0xFE); sink.push(0x40); memarg.encode(sink); } - Instruction::I32AtomicRmwXchg { memarg } => { + Instruction::I32AtomicRmwXchg(memarg) => { sink.push(0xFE); sink.push(0x41); memarg.encode(sink); } - Instruction::I64AtomicRmwXchg { memarg } => { + Instruction::I64AtomicRmwXchg(memarg) => { sink.push(0xFE); sink.push(0x42); memarg.encode(sink); } - Instruction::I32AtomicRmw8XchgU { memarg } => { + Instruction::I32AtomicRmw8XchgU(memarg) => { sink.push(0xFE); sink.push(0x43); memarg.encode(sink); } - Instruction::I32AtomicRmw16XchgU { memarg } => { + Instruction::I32AtomicRmw16XchgU(memarg) => { sink.push(0xFE); sink.push(0x44); memarg.encode(sink); } - Instruction::I64AtomicRmw8XchgU { memarg } => { + Instruction::I64AtomicRmw8XchgU(memarg) => { sink.push(0xFE); sink.push(0x45); memarg.encode(sink); } - Instruction::I64AtomicRmw16XchgU { memarg } => { + Instruction::I64AtomicRmw16XchgU(memarg) => { sink.push(0xFE); sink.push(0x46); memarg.encode(sink); } - Instruction::I64AtomicRmw32XchgU { memarg } => { + Instruction::I64AtomicRmw32XchgU(memarg) => { sink.push(0xFE); sink.push(0x47); memarg.encode(sink); } - Instruction::I32AtomicRmwCmpxchg { memarg } => { + Instruction::I32AtomicRmwCmpxchg(memarg) => { sink.push(0xFE); sink.push(0x48); memarg.encode(sink); } - Instruction::I64AtomicRmwCmpxchg { memarg } => { + Instruction::I64AtomicRmwCmpxchg(memarg) => { sink.push(0xFE); sink.push(0x49); memarg.encode(sink); } - Instruction::I32AtomicRmw8CmpxchgU { memarg } => { + Instruction::I32AtomicRmw8CmpxchgU(memarg) => { sink.push(0xFE); sink.push(0x4A); memarg.encode(sink); } - Instruction::I32AtomicRmw16CmpxchgU { memarg } => { + Instruction::I32AtomicRmw16CmpxchgU(memarg) => { sink.push(0xFE); sink.push(0x4B); memarg.encode(sink); } - Instruction::I64AtomicRmw8CmpxchgU { memarg } => { + Instruction::I64AtomicRmw8CmpxchgU(memarg) => { sink.push(0xFE); sink.push(0x4C); memarg.encode(sink); } - Instruction::I64AtomicRmw16CmpxchgU { memarg } => { + Instruction::I64AtomicRmw16CmpxchgU(memarg) => { sink.push(0xFE); sink.push(0x4D); memarg.encode(sink); } - Instruction::I64AtomicRmw32CmpxchgU { memarg } => { + Instruction::I64AtomicRmw32CmpxchgU(memarg) => { sink.push(0xFE); sink.push(0x4E); memarg.encode(sink); diff --git a/crates/wasm-mutate-stats/Cargo.toml b/crates/wasm-mutate-stats/Cargo.toml index f961ccc803..41e4e2731c 100644 --- a/crates/wasm-mutate-stats/Cargo.toml +++ b/crates/wasm-mutate-stats/Cargo.toml @@ -1,22 +1,22 @@ [package] name = "wasm-mutate-stats" version = "0.1.0" -edition = "2021" +edition.workspace = true publish = false [dependencies] -anyhow = "1.0" -arbitrary = "1.0" -num_cpus = "1.13" -rand = { version = "0.8.0", features = ["small_rng"] } -wasm-mutate = { path = '../wasm-mutate' } -wasmprinter = { path = '../wasmprinter' } -wasmparser = { path = "../wasmparser" } -wasmtime = "0.38.1" -env_logger = "0.9" +anyhow = { workspace = true } +arbitrary = { workspace = true } +num_cpus = { workspace = true } +rand = { workspace = true } +wasm-mutate = { workspace = true } +wasmprinter = { workspace = true } +wasmparser = { workspace = true } +wasmtime = { workspace = true } +env_logger = { workspace = true } itertools = "0.10.0" -clap = { version = "3.0", features = ['derive'] } -log = "0.4" +clap = { workspace = true } +log = { workspace = true } [lib] doctest = false diff --git a/crates/wasm-mutate-stats/src/bin/wasm-mutate-stats.rs b/crates/wasm-mutate-stats/src/bin/wasm-mutate-stats.rs index b5bceb4dba..800d213885 100644 --- a/crates/wasm-mutate-stats/src/bin/wasm-mutate-stats.rs +++ b/crates/wasm-mutate-stats/src/bin/wasm-mutate-stats.rs @@ -81,7 +81,7 @@ struct Options { /// List of engine configurations. /// Allowed values: [O0, O2, Os] /// If it is not set, the default configuration of wasmtime will be used - #[clap(short = 'c', long = "compilation-configs", parse(try_from_str=parse_optimization_types) )] + #[clap(short = 'c', long = "compilation-configs", value_parser = parse_optimization_types)] configs: Option>, /// Target triple during compilation, e.g. "x86_64-apple-darwin" #[clap(short = 'a', long = "triple")] diff --git a/crates/wasm-mutate/Cargo.toml b/crates/wasm-mutate/Cargo.toml index 33119537a2..c56fece75c 100644 --- a/crates/wasm-mutate/Cargo.toml +++ b/crates/wasm-mutate/Cargo.toml @@ -1,22 +1,22 @@ [package] name = "wasm-mutate" -version = "0.2.7" -edition = "2021" +version = "0.2.9" +edition.workspace = true license = "Apache-2.0 WITH LLVM-exception" repository = "https://github.com/bytecodealliance/wasm-tools/tree/main/crates/wasm-mutate" description = "A WebAssembly test case mutator" [dependencies] -clap = { optional = true, version = "3.0", features = ['derive'] } +clap = { workspace = true, optional = true } thiserror = "1.0.28" -wasmparser = { version = "0.90.0", path = "../wasmparser" } -wasm-encoder = { version = "0.16.0", path = "../wasm-encoder"} -rand = { version = "0.8.0", features = ["small_rng"] } -log = "0.4.14" +wasmparser = { workspace = true } +wasm-encoder = { workspace = true } +rand = { workspace = true } +log = { workspace = true } egg = "0.6.0" [dev-dependencies] -anyhow = "1" +anyhow = { workspace = true } wat = { path = "../wat" } wasmprinter = { path = "../wasmprinter" } -env_logger = "0.9" +env_logger = { workspace = true } diff --git a/crates/wasm-mutate/README.md b/crates/wasm-mutate/README.md index d0dbc7aab6..3eb29d0bdb 100644 --- a/crates/wasm-mutate/README.md +++ b/crates/wasm-mutate/README.md @@ -20,17 +20,16 @@ ## Usage -Add this to your `Cargo.toml`: +Add `wasm-mutate` to your `Cargo.toml`: -```toml -[dependencies] -wasm-mutate = "0.2.0" +```shell +$ cargo add wasm-mutate ``` -You can mutate a WebAssembly binary by using the cli tool: +You can also mutate a WebAssembly binary by using the cli tool: ```bash -./wasm-mutate original.wasm --seed 0 -o out.wasm --preserve-semantics +wasm-tools mutate original.wasm --seed 0 -o out.wasm --preserve-semantics ``` ## Features diff --git a/crates/wasm-mutate/src/lib.rs b/crates/wasm-mutate/src/lib.rs index 39b9b04a9c..0f61104c74 100644 --- a/crates/wasm-mutate/src/lib.rs +++ b/crates/wasm-mutate/src/lib.rs @@ -26,7 +26,7 @@ use crate::mutators::{ use info::ModuleInfo; use mutators::Mutator; use rand::{rngs::SmallRng, Rng, SeedableRng}; -use std::{cell::Cell, sync::Arc}; +use std::sync::Arc; #[cfg(feature = "clap")] use clap::Parser; @@ -174,10 +174,9 @@ pub struct WasmMutate<'wasm> { short, long, default_value = "18446744073709551615", // u64::MAX - parse(try_from_str = parse_fuel), ) )] - fuel: Cell, + fuel: u64, /// Only perform size-reducing transformations on the Wasm module. This /// allows `wasm-mutate` to be used as a test case reducer. @@ -196,11 +195,6 @@ pub struct WasmMutate<'wasm> { info: Option>, } -#[cfg(feature = "clap")] -fn parse_fuel(s: &str) -> Result, String> { - s.parse::().map(Cell::new).map_err(|s| s.to_string()) -} - impl Default for WasmMutate<'_> { fn default() -> Self { let seed = 3; @@ -209,7 +203,7 @@ impl Default for WasmMutate<'_> { preserve_semantics: false, reduce: false, raw_mutate_func: None, - fuel: Cell::new(u64::MAX), + fuel: u64::MAX, rng: None, info: None, } @@ -235,7 +229,7 @@ impl<'wasm> WasmMutate<'wasm> { /// Configure the fuel used during the mutation pub fn fuel(&mut self, fuel: u64) -> &mut Self { - self.fuel = Cell::new(fuel); + self.fuel = fuel; self } @@ -269,12 +263,12 @@ impl<'wasm> WasmMutate<'wasm> { self } - pub(crate) fn consume_fuel(&self, qt: u64) -> Result<()> { - if qt > self.fuel.get() { + pub(crate) fn consume_fuel(&mut self, qt: u64) -> Result<()> { + if qt > self.fuel { log::info!("Out of fuel"); return Err(Error::out_of_fuel()); } - self.fuel.set(self.fuel.get() - qt); + self.fuel -= qt; Ok(()) } diff --git a/crates/wasm-mutate/src/mutators/codemotion/ir.rs b/crates/wasm-mutate/src/mutators/codemotion/ir.rs index 9e6522b5bf..a41c4569b0 100644 --- a/crates/wasm-mutate/src/mutators/codemotion/ir.rs +++ b/crates/wasm-mutate/src/mutators/codemotion/ir.rs @@ -271,14 +271,14 @@ impl AstBuilder { for (idx, (operator, _)) in operators.iter().enumerate() { match operator { - Operator::If { ty } => { + Operator::If { blockty } => { // push current code first if !parse_context.current_code_is_empty() { parse_context.push_current_code_as_node(); } parse_context.reset_code_range_at(idx + 1); parse_context.push_state(); - parse_context.push_frame(State::If, Some(*ty), idx); + parse_context.push_frame(State::If, Some(*blockty), idx); } Operator::Else => { if !parse_context.current_code_is_empty() { @@ -288,21 +288,21 @@ impl AstBuilder { parse_context.push_state(); parse_context.push_frame(State::Else, None, idx); } - Operator::Block { ty } => { + Operator::Block { blockty } => { if !parse_context.current_code_is_empty() { parse_context.push_current_code_as_node(); } parse_context.reset_code_range_at(idx + 1); parse_context.push_state(); - parse_context.push_frame(State::Block, Some(*ty), idx); + parse_context.push_frame(State::Block, Some(*blockty), idx); } - Operator::Loop { ty } => { + Operator::Loop { blockty } => { if !parse_context.current_code_is_empty() { parse_context.push_current_code_as_node(); } parse_context.reset_code_range_at(idx + 1); parse_context.push_state(); - parse_context.push_frame(State::Loop, Some(*ty), idx); + parse_context.push_frame(State::Loop, Some(*blockty), idx); } Operator::End => { if !parse_context.current_code_is_empty() { diff --git a/crates/wasm-mutate/src/mutators/codemotion/loop_unrolling.rs b/crates/wasm-mutate/src/mutators/codemotion/loop_unrolling.rs index 9c167455c7..9eb1b86e61 100644 --- a/crates/wasm-mutate/src/mutators/codemotion/loop_unrolling.rs +++ b/crates/wasm-mutate/src/mutators/codemotion/loop_unrolling.rs @@ -94,9 +94,9 @@ impl LoopUnrollWriter { to_fix.insert(idx, Instruction::BrIf(relative_depth + 1)); } } - Operator::BrTable { table } => { + Operator::BrTable { targets } => { let mut jmpfix = vec![]; - for i in table.targets() { + for i in targets.targets() { let d = i?; if d > current_depth { // Out jump...annotate for fixing @@ -106,7 +106,7 @@ impl LoopUnrollWriter { } } - let mut def = table.default(); + let mut def = targets.default(); if def > current_depth { def += 1; } diff --git a/crates/wasm-mutate/src/mutators/modify_const_exprs.rs b/crates/wasm-mutate/src/mutators/modify_const_exprs.rs index 95e2e129c6..84e7cb9dd1 100644 --- a/crates/wasm-mutate/src/mutators/modify_const_exprs.rs +++ b/crates/wasm-mutate/src/mutators/modify_const_exprs.rs @@ -98,12 +98,14 @@ impl<'cfg, 'wasm> Translator for InitTranslator<'cfg, 'wasm> { T::F32 if should_zero => CE::f32_const(0.0), T::F64 if should_zero => CE::f64_const(0.0), T::I32 => CE::i32_const(if let O::I32Const { value } = op { - self.config.rng().gen_range(0..value) + let range = if value < 0 { value..0 } else { 0..value }; + self.config.rng().gen_range(range) } else { self.config.rng().gen() }), T::I64 => CE::i64_const(if let O::I64Const { value } = op { - self.config.rng().gen_range(0..value) + let range = if value < 0 { value..0 } else { 0..value }; + self.config.rng().gen_range(range) } else { self.config.rng().gen() }), diff --git a/crates/wasm-mutate/src/mutators/peephole.rs b/crates/wasm-mutate/src/mutators/peephole.rs index c2ea89a674..6c62446d0f 100644 --- a/crates/wasm-mutate/src/mutators/peephole.rs +++ b/crates/wasm-mutate/src/mutators/peephole.rs @@ -36,7 +36,7 @@ use self::{ use super::{Mutator, OperatorAndByteOffset}; use crate::{ module::{map_type, PrimitiveTypeInfo}, - Error, ModuleInfo, Result, WasmMutate, + Error, ErrorKind, ModuleInfo, Result, WasmMutate, }; use egg::{Rewrite, Runner}; use rand::{prelude::SmallRng, Rng}; @@ -229,8 +229,6 @@ impl PeepholeMutator { // In theory this will return the Id of the operator eterm let root = egraph.add_expr(&start); let startcmp = start.clone(); - // Since this construction is expensive then more fuel is consumed - let config4fuel = config.clone(); // If the number of nodes in the egraph is not large, then // continue the search @@ -274,6 +272,8 @@ impl PeepholeMutator { .map(move |expr| { log::trace!("Yielding expression:\n{}", expr.pretty(60)); + config.consume_fuel(1)?; + let mut newfunc = self.copy_locals(reader)?; let needed_resources = Encoder::build_function( config, @@ -407,10 +407,14 @@ impl PeepholeMutator { false }, ); + Ok(module) }) - // Consume fuel for each returned expression and it is expensive - .take_while(move |_| config4fuel.consume_fuel(1).is_ok()); + .map_while(|module: Result| match module { + Ok(module) => Some(Ok(module)), + Err(e) if matches!(e.kind(), ErrorKind::OutOfFuel) => None, + Err(e) => Some(Err(e)), + }); return Ok(Box::new(iterator)); } @@ -633,8 +637,8 @@ mod tests { (type (;0;) (func (result i32))) (func (;0;) (type 0) (result i32) (local i32 i32) - i32.const -1985698784 - i32.const 1985698840 + i32.const 1697131274 + i32.const -1697131218 i32.add) (export "exported_func" (func 0))) "#, diff --git a/crates/wasm-mutate/src/mutators/peephole/dfg.rs b/crates/wasm-mutate/src/mutators/peephole/dfg.rs index f7bcd61bf6..d822bd2d7e 100644 --- a/crates/wasm-mutate/src/mutators/peephole/dfg.rs +++ b/crates/wasm-mutate/src/mutators/peephole/dfg.rs @@ -663,15 +663,15 @@ impl<'a> DFGBuilder { self.push_node(Lang::TableSize(*table), idx); } - Operator::DataDrop { segment } => { - self.empty_node(Lang::DataDrop(*segment), idx); + Operator::DataDrop { data_index } => { + self.empty_node(Lang::DataDrop(*data_index), idx); } - Operator::ElemDrop { segment } => { - self.empty_node(Lang::ElemDrop(*segment), idx); + Operator::ElemDrop { elem_index } => { + self.empty_node(Lang::ElemDrop(*elem_index), idx); } - Operator::MemoryInit { mem, segment } => { + Operator::MemoryInit { mem, data_index } => { let a = Id::from(self.pop_operand(idx, false)); let b = Id::from(self.pop_operand(idx, false)); let c = Id::from(self.pop_operand(idx, false)); @@ -679,22 +679,22 @@ impl<'a> DFGBuilder { Lang::MemoryInit( MemoryInit { memory: *mem, - segment: *segment, + segment: *data_index, }, [c, b, a], ), idx, ); } - Operator::MemoryCopy { src, dst } => { + Operator::MemoryCopy { src_mem, dst_mem } => { let a = Id::from(self.pop_operand(idx, false)); let b = Id::from(self.pop_operand(idx, false)); let c = Id::from(self.pop_operand(idx, false)); self.empty_node( Lang::MemoryCopy( MemoryCopy { - src: *src, - dst: *dst, + src: *src_mem, + dst: *dst_mem, }, [c, b, a], ), @@ -709,7 +709,7 @@ impl<'a> DFGBuilder { self.empty_node(Lang::MemoryFill(*mem, [c, b, a]), idx); } - Operator::TableInit { table, segment } => { + Operator::TableInit { table, elem_index } => { let a = Id::from(self.pop_operand(idx, false)); let b = Id::from(self.pop_operand(idx, false)); let c = Id::from(self.pop_operand(idx, false)); @@ -717,7 +717,7 @@ impl<'a> DFGBuilder { Lang::TableInit( TableInit { table: *table, - segment: *segment, + segment: *elem_index, }, [c, b, a], ), @@ -762,12 +762,12 @@ impl<'a> DFGBuilder { } Operator::RefNull { - ty: wasmparser::HeapType::Extern, + hty: wasmparser::HeapType::Extern, } => { self.push_node(Lang::RefNull(RefType::Extern), idx); } Operator::RefNull { - ty: wasmparser::HeapType::Func, + hty: wasmparser::HeapType::Func, } => { self.push_node(Lang::RefNull(RefType::Func), idx); } diff --git a/crates/wasm-mutate/src/mutators/peephole/eggsy/encoder/expr2wasm.rs b/crates/wasm-mutate/src/mutators/peephole/eggsy/encoder/expr2wasm.rs index 822c39a51a..0f481087b5 100644 --- a/crates/wasm-mutate/src/mutators/peephole/eggsy/encoder/expr2wasm.rs +++ b/crates/wasm-mutate/src/mutators/peephole/eggsy/encoder/expr2wasm.rs @@ -106,16 +106,16 @@ pub fn expr2wasm( Lang::I64Load(memarg, _) => insn(Instruction::I64Load(memarg.into())), Lang::F32Load(memarg, _) => insn(Instruction::F32Load(memarg.into())), Lang::F64Load(memarg, _) => insn(Instruction::F64Load(memarg.into())), - Lang::I32Load8U(memarg, _) => insn(Instruction::I32Load8_U(memarg.into())), - Lang::I32Load8S(memarg, _) => insn(Instruction::I32Load8_S(memarg.into())), - Lang::I32Load16U(memarg, _) => insn(Instruction::I32Load16_U(memarg.into())), - Lang::I32Load16S(memarg, _) => insn(Instruction::I32Load16_S(memarg.into())), - Lang::I64Load8U(memarg, _) => insn(Instruction::I64Load8_U(memarg.into())), - Lang::I64Load8S(memarg, _) => insn(Instruction::I64Load8_S(memarg.into())), - Lang::I64Load16U(memarg, _) => insn(Instruction::I64Load16_U(memarg.into())), - Lang::I64Load16S(memarg, _) => insn(Instruction::I64Load16_S(memarg.into())), - Lang::I64Load32U(memarg, _) => insn(Instruction::I64Load32_U(memarg.into())), - Lang::I64Load32S(memarg, _) => insn(Instruction::I64Load32_S(memarg.into())), + Lang::I32Load8U(memarg, _) => insn(Instruction::I32Load8U(memarg.into())), + Lang::I32Load8S(memarg, _) => insn(Instruction::I32Load8S(memarg.into())), + Lang::I32Load16U(memarg, _) => insn(Instruction::I32Load16U(memarg.into())), + Lang::I32Load16S(memarg, _) => insn(Instruction::I32Load16S(memarg.into())), + Lang::I64Load8U(memarg, _) => insn(Instruction::I64Load8U(memarg.into())), + Lang::I64Load8S(memarg, _) => insn(Instruction::I64Load8S(memarg.into())), + Lang::I64Load16U(memarg, _) => insn(Instruction::I64Load16U(memarg.into())), + Lang::I64Load16S(memarg, _) => insn(Instruction::I64Load16S(memarg.into())), + Lang::I64Load32U(memarg, _) => insn(Instruction::I64Load32U(memarg.into())), + Lang::I64Load32S(memarg, _) => insn(Instruction::I64Load32S(memarg.into())), Lang::RandI32 => insn(Instruction::I32Const(config.rng().gen())), Lang::RandI64 => insn(Instruction::I64Const(config.rng().gen())), Lang::RandF32 => { @@ -328,13 +328,13 @@ pub fn expr2wasm( Lang::MemoryInit(init, _) => { newfunc.instruction(&Instruction::MemoryInit { mem: init.memory, - data: init.segment, + data_index: init.segment, }); } Lang::MemoryCopy(cp, _) => { newfunc.instruction(&Instruction::MemoryCopy { - src: cp.src, - dst: cp.dst, + src_mem: cp.src, + dst_mem: cp.dst, }); } Lang::MemoryFill(mem, _) => insn(Instruction::MemoryFill(*mem)), @@ -342,21 +342,21 @@ pub fn expr2wasm( Lang::TableInit(init, _) => { newfunc.instruction(&Instruction::TableInit { table: init.table, - segment: init.segment, + elem_index: init.segment, }); } Lang::TableCopy(cp, _) => { newfunc.instruction(&Instruction::TableCopy { - src: cp.src, - dst: cp.dst, + src_table: cp.src, + dst_table: cp.dst, }); } - Lang::TableFill(table, _) => insn(Instruction::TableFill { table: *table }), - Lang::ElemDrop(idx) => insn(Instruction::ElemDrop { segment: *idx }), - Lang::TableGrow(table, _) => insn(Instruction::TableGrow { table: *table }), - Lang::TableSize(table) => insn(Instruction::TableSize { table: *table }), - Lang::TableGet(table, _) => insn(Instruction::TableGet { table: *table }), - Lang::TableSet(table, _) => insn(Instruction::TableSet { table: *table }), + Lang::TableFill(table, _) => insn(Instruction::TableFill(*table)), + Lang::ElemDrop(idx) => insn(Instruction::ElemDrop(*idx)), + Lang::TableGrow(table, _) => insn(Instruction::TableGrow(*table)), + Lang::TableSize(table) => insn(Instruction::TableSize(*table)), + Lang::TableGet(table, _) => insn(Instruction::TableGet(*table)), + Lang::TableSet(table, _) => insn(Instruction::TableSet(*table)), Lang::I32UseGlobal(_) => { // Request a new global let request = ResourceRequest::Global { @@ -419,74 +419,46 @@ pub fn expr2wasm( Lang::V128Bitselect(_) => insn(Instruction::V128Bitselect), Lang::V128Load(memarg, _) => { - newfunc.instruction(&Instruction::V128Load { - memarg: memarg.into(), - }); + newfunc.instruction(&Instruction::V128Load(memarg.into())); } Lang::V128Load8x8S(memarg, _) => { - newfunc.instruction(&Instruction::V128Load8x8S { - memarg: memarg.into(), - }); + newfunc.instruction(&Instruction::V128Load8x8S(memarg.into())); } Lang::V128Load8x8U(memarg, _) => { - newfunc.instruction(&Instruction::V128Load8x8U { - memarg: memarg.into(), - }); + newfunc.instruction(&Instruction::V128Load8x8U(memarg.into())); } Lang::V128Load16x4S(memarg, _) => { - newfunc.instruction(&Instruction::V128Load16x4S { - memarg: memarg.into(), - }); + newfunc.instruction(&Instruction::V128Load16x4S(memarg.into())); } Lang::V128Load16x4U(memarg, _) => { - newfunc.instruction(&Instruction::V128Load16x4U { - memarg: memarg.into(), - }); + newfunc.instruction(&Instruction::V128Load16x4U(memarg.into())); } Lang::V128Load32x2S(memarg, _) => { - newfunc.instruction(&Instruction::V128Load32x2S { - memarg: memarg.into(), - }); + newfunc.instruction(&Instruction::V128Load32x2S(memarg.into())); } Lang::V128Load32x2U(memarg, _) => { - newfunc.instruction(&Instruction::V128Load32x2U { - memarg: memarg.into(), - }); + newfunc.instruction(&Instruction::V128Load32x2U(memarg.into())); } Lang::V128Load8Splat(memarg, _) => { - newfunc.instruction(&Instruction::V128Load8Splat { - memarg: memarg.into(), - }); + newfunc.instruction(&Instruction::V128Load8Splat(memarg.into())); } Lang::V128Load16Splat(memarg, _) => { - newfunc.instruction(&Instruction::V128Load16Splat { - memarg: memarg.into(), - }); + newfunc.instruction(&Instruction::V128Load16Splat(memarg.into())); } Lang::V128Load32Splat(memarg, _) => { - newfunc.instruction(&Instruction::V128Load32Splat { - memarg: memarg.into(), - }); + newfunc.instruction(&Instruction::V128Load32Splat(memarg.into())); } Lang::V128Load64Splat(memarg, _) => { - newfunc.instruction(&Instruction::V128Load64Splat { - memarg: memarg.into(), - }); + newfunc.instruction(&Instruction::V128Load64Splat(memarg.into())); } Lang::V128Load32Zero(memarg, _) => { - newfunc.instruction(&Instruction::V128Load32Zero { - memarg: memarg.into(), - }); + newfunc.instruction(&Instruction::V128Load32Zero(memarg.into())); } Lang::V128Load64Zero(memarg, _) => { - newfunc.instruction(&Instruction::V128Load64Zero { - memarg: memarg.into(), - }); + newfunc.instruction(&Instruction::V128Load64Zero(memarg.into())); } Lang::V128Store(memarg, _) => { - newfunc.instruction(&Instruction::V128Store { - memarg: memarg.into(), - }); + newfunc.instruction(&Instruction::V128Store(memarg.into())); } Lang::V128Load8Lane(memarg, _) => { newfunc.instruction(&Instruction::V128Load8Lane { @@ -537,48 +509,20 @@ pub fn expr2wasm( }); } - Lang::I8x16ExtractLaneS(lane, _) => { - insn(Instruction::I8x16ExtractLaneS { lane: *lane }) - } - Lang::I8x16ExtractLaneU(lane, _) => { - insn(Instruction::I8x16ExtractLaneU { lane: *lane }) - } - Lang::I8x16ReplaceLane(lane, _) => { - insn(Instruction::I8x16ReplaceLane { lane: *lane }) - } - Lang::I16x8ExtractLaneS(lane, _) => { - insn(Instruction::I16x8ExtractLaneS { lane: *lane }) - } - Lang::I16x8ExtractLaneU(lane, _) => { - insn(Instruction::I16x8ExtractLaneU { lane: *lane }) - } - Lang::I16x8ReplaceLane(lane, _) => { - insn(Instruction::I16x8ReplaceLane { lane: *lane }) - } - Lang::I32x4ExtractLane(lane, _) => { - insn(Instruction::I32x4ExtractLane { lane: *lane }) - } - Lang::I32x4ReplaceLane(lane, _) => { - insn(Instruction::I32x4ReplaceLane { lane: *lane }) - } - Lang::I64x2ExtractLane(lane, _) => { - insn(Instruction::I64x2ExtractLane { lane: *lane }) - } - Lang::I64x2ReplaceLane(lane, _) => { - insn(Instruction::I64x2ReplaceLane { lane: *lane }) - } - Lang::F32x4ExtractLane(lane, _) => { - insn(Instruction::F32x4ExtractLane { lane: *lane }) - } - Lang::F32x4ReplaceLane(lane, _) => { - insn(Instruction::F32x4ReplaceLane { lane: *lane }) - } - Lang::F64x2ExtractLane(lane, _) => { - insn(Instruction::F64x2ExtractLane { lane: *lane }) - } - Lang::F64x2ReplaceLane(lane, _) => { - insn(Instruction::F64x2ReplaceLane { lane: *lane }) - } + Lang::I8x16ExtractLaneS(lane, _) => insn(Instruction::I8x16ExtractLaneS(*lane)), + Lang::I8x16ExtractLaneU(lane, _) => insn(Instruction::I8x16ExtractLaneU(*lane)), + Lang::I8x16ReplaceLane(lane, _) => insn(Instruction::I8x16ReplaceLane(*lane)), + Lang::I16x8ExtractLaneS(lane, _) => insn(Instruction::I16x8ExtractLaneS(*lane)), + Lang::I16x8ExtractLaneU(lane, _) => insn(Instruction::I16x8ExtractLaneU(*lane)), + Lang::I16x8ReplaceLane(lane, _) => insn(Instruction::I16x8ReplaceLane(*lane)), + Lang::I32x4ExtractLane(lane, _) => insn(Instruction::I32x4ExtractLane(*lane)), + Lang::I32x4ReplaceLane(lane, _) => insn(Instruction::I32x4ReplaceLane(*lane)), + Lang::I64x2ExtractLane(lane, _) => insn(Instruction::I64x2ExtractLane(*lane)), + Lang::I64x2ReplaceLane(lane, _) => insn(Instruction::I64x2ReplaceLane(*lane)), + Lang::F32x4ExtractLane(lane, _) => insn(Instruction::F32x4ExtractLane(*lane)), + Lang::F32x4ReplaceLane(lane, _) => insn(Instruction::F32x4ReplaceLane(*lane)), + Lang::F64x2ExtractLane(lane, _) => insn(Instruction::F64x2ExtractLane(*lane)), + Lang::F64x2ReplaceLane(lane, _) => insn(Instruction::F64x2ReplaceLane(*lane)), Lang::I8x16Swizzle(_) => insn(Instruction::I8x16Swizzle), Lang::I8x16Splat(_) => insn(Instruction::I8x16Splat), diff --git a/crates/wasm-mutate/src/mutators/snip_function.rs b/crates/wasm-mutate/src/mutators/snip_function.rs index 3e6d89520d..ffa75cde98 100644 --- a/crates/wasm-mutate/src/mutators/snip_function.rs +++ b/crates/wasm-mutate/src/mutators/snip_function.rs @@ -24,7 +24,8 @@ impl Mutator for SnipMutator { let function_to_mutate = config.rng().gen_range(0..count); let ftype = config .info() - .get_functype_idx(function_to_mutate + config.info().num_imported_functions()); + .get_functype_idx(function_to_mutate + config.info().num_imported_functions()) + .clone(); for i in 0..count { config.consume_fuel(1)?; @@ -40,7 +41,7 @@ impl Mutator for SnipMutator { let locals = vec![]; let mut f = Function::new(locals); - match ftype { + match &ftype { TypeInfo::Func(t) => { for primitive in t.returns.iter() { match primitive { diff --git a/crates/wasm-mutate/src/mutators/translate.rs b/crates/wasm-mutate/src/mutators/translate.rs index fd98c42d7f..d132cef365 100644 --- a/crates/wasm-mutate/src/mutators/translate.rs +++ b/crates/wasm-mutate/src/mutators/translate.rs @@ -218,7 +218,7 @@ pub fn const_expr( match op { Operator::RefFunc { .. } | Operator::RefNull { - ty: wasmparser::HeapType::Func, + hty: wasmparser::HeapType::Func, .. } | Operator::GlobalGet { .. } => {} @@ -287,663 +287,87 @@ pub fn element( Ok(()) } -/// This is a pretty gnarly function that translates from `wasmparser` -/// operators to `wasm_encoder` operators. It's quite large because there's -/// quite a few wasm instructions. The theory though is that at least each -/// individual case is pretty self-contained. +#[allow(unused_variables)] pub fn op(t: &mut dyn Translator, op: &Operator<'_>) -> Result> { use wasm_encoder::Instruction as I; - use wasmparser::Operator as O; - Ok(match op { - O::Unreachable => I::Unreachable, - O::Nop => I::Nop, - - O::Block { ty } => I::Block(t.translate_block_type(ty)?), - O::Loop { ty } => I::Loop(t.translate_block_type(ty)?), - O::If { ty } => I::If(t.translate_block_type(ty)?), - O::Else => I::Else, - - O::Try { ty } => I::Try(t.translate_block_type(ty)?), - O::Catch { index } => I::Catch(t.remap(Item::Tag, *index)?), - O::Throw { index } => I::Throw(t.remap(Item::Tag, *index)?), - O::Rethrow { relative_depth } => I::Rethrow(*relative_depth), - O::End => I::End, - O::Br { relative_depth } => I::Br(*relative_depth), - O::BrIf { relative_depth } => I::BrIf(*relative_depth), - O::BrTable { table } => I::BrTable( - table + + macro_rules! translate { + ($( @$proposal:ident $op:ident $({ $($arg:ident: $argty:ty),* })? => $visit:ident)*) => { + Ok(match op { + $( + wasmparser::Operator::$op $({ $($arg),* })? => { + $( + $(let $arg = translate!(map $arg $arg);)* + )? + translate!(build $op $($($arg)*)?) + } + )* + }) + }; + + // This case is used to map, based on the name of the field, from the + // wasmparser payload type to the wasm-encoder payload type through + // `Translator` as applicable. + (map $arg:ident tag_index) => (t.remap(Item::Tag, *$arg)?); + (map $arg:ident function_index) => (t.remap(Item::Function, *$arg)?); + (map $arg:ident table) => (t.remap(Item::Table, *$arg)?); + (map $arg:ident table_index) => (t.remap(Item::Table, *$arg)?); + (map $arg:ident table) => (t.remap(Item::Table, *$arg)?); + (map $arg:ident dst_table) => (t.remap(Item::Table, *$arg)?); + (map $arg:ident src_table) => (t.remap(Item::Table, *$arg)?); + (map $arg:ident type_index) => (t.remap(Item::Type, *$arg)?); + (map $arg:ident global_index) => (t.remap(Item::Global, *$arg)?); + (map $arg:ident mem) => (t.remap(Item::Memory, *$arg)?); + (map $arg:ident src_mem) => (t.remap(Item::Memory, *$arg)?); + (map $arg:ident dst_mem) => (t.remap(Item::Memory, *$arg)?); + (map $arg:ident data_index) => (t.remap(Item::Data, *$arg)?); + (map $arg:ident elem_index) => (t.remap(Item::Element, *$arg)?); + (map $arg:ident blockty) => (t.translate_block_type($arg)?); + (map $arg:ident relative_depth) => (*$arg); + (map $arg:ident targets) => (( + $arg .targets() .collect::, wasmparser::BinaryReaderError>>()? .into(), - table.default(), - ), - O::BrOnNull { relative_depth } => I::BrOnNull(*relative_depth), - O::BrOnNonNull { relative_depth } => I::BrOnNonNull(*relative_depth), - - O::Return => I::Return, - O::Call { function_index } => I::Call(t.remap(Item::Function, *function_index)?), - O::CallRef { ty } => I::CallRef(t.translate_heapty(ty)?), - O::CallIndirect { - index, - table_index, - table_byte: _, - } => I::CallIndirect { - ty: t.remap(Item::Type, *index)?, - table: t.remap(Item::Table, *table_index)?, - }, - O::ReturnCallRef { ty } => I::ReturnCallRef(t.translate_heapty(ty)?), - O::Delegate { relative_depth } => I::Delegate(*relative_depth), - O::CatchAll => I::CatchAll, - O::Drop => I::Drop, - O::Select => I::Select, - O::TypedSelect { ty } => I::TypedSelect(t.translate_ty(ty)?), - - O::LocalGet { local_index } => I::LocalGet(*local_index), - O::LocalSet { local_index } => I::LocalSet(*local_index), - O::LocalTee { local_index } => I::LocalTee(*local_index), - - O::GlobalGet { global_index } => I::GlobalGet(t.remap(Item::Global, *global_index)?), - O::GlobalSet { global_index } => I::GlobalSet(t.remap(Item::Global, *global_index)?), - - O::I32Load { memarg } => I::I32Load(t.translate_memarg(memarg)?), - O::I64Load { memarg } => I::I64Load(t.translate_memarg(memarg)?), - O::F32Load { memarg } => I::F32Load(t.translate_memarg(memarg)?), - O::F64Load { memarg } => I::F64Load(t.translate_memarg(memarg)?), - O::I32Load8S { memarg } => I::I32Load8_S(t.translate_memarg(memarg)?), - O::I32Load8U { memarg } => I::I32Load8_U(t.translate_memarg(memarg)?), - O::I32Load16S { memarg } => I::I32Load16_S(t.translate_memarg(memarg)?), - O::I32Load16U { memarg } => I::I32Load16_U(t.translate_memarg(memarg)?), - O::I64Load8S { memarg } => I::I64Load8_S(t.translate_memarg(memarg)?), - O::I64Load8U { memarg } => I::I64Load8_U(t.translate_memarg(memarg)?), - O::I64Load16S { memarg } => I::I64Load16_S(t.translate_memarg(memarg)?), - O::I64Load16U { memarg } => I::I64Load16_U(t.translate_memarg(memarg)?), - O::I64Load32S { memarg } => I::I64Load32_S(t.translate_memarg(memarg)?), - O::I64Load32U { memarg } => I::I64Load32_U(t.translate_memarg(memarg)?), - O::I32Store { memarg } => I::I32Store(t.translate_memarg(memarg)?), - O::I64Store { memarg } => I::I64Store(t.translate_memarg(memarg)?), - O::F32Store { memarg } => I::F32Store(t.translate_memarg(memarg)?), - O::F64Store { memarg } => I::F64Store(t.translate_memarg(memarg)?), - O::I32Store8 { memarg } => I::I32Store8(t.translate_memarg(memarg)?), - O::I32Store16 { memarg } => I::I32Store16(t.translate_memarg(memarg)?), - O::I64Store8 { memarg } => I::I64Store8(t.translate_memarg(memarg)?), - O::I64Store16 { memarg } => I::I64Store16(t.translate_memarg(memarg)?), - O::I64Store32 { memarg } => I::I64Store32(t.translate_memarg(memarg)?), - - O::MemorySize { mem, .. } => I::MemorySize(t.remap(Item::Memory, *mem)?), - O::MemoryGrow { mem, .. } => I::MemoryGrow(t.remap(Item::Memory, *mem)?), - - O::I32Const { value } => I::I32Const(*value), - O::I64Const { value } => I::I64Const(*value), - O::F32Const { value } => I::F32Const(f32::from_bits(value.bits())), - O::F64Const { value } => I::F64Const(f64::from_bits(value.bits())), - - O::RefNull { ty } => I::RefNull(t.translate_heapty(ty)?), - O::RefIsNull => I::RefIsNull, - O::RefFunc { function_index } => I::RefFunc(t.remap(Item::Function, *function_index)?), - O::RefAsNonNull => I::RefAsNonNull, - - O::I32Eqz => I::I32Eqz, - O::I32Eq => I::I32Eq, - O::I32Ne => I::I32Ne, - O::I32LtS => I::I32LtS, - O::I32LtU => I::I32LtU, - O::I32GtS => I::I32GtS, - O::I32GtU => I::I32GtU, - O::I32LeS => I::I32LeS, - O::I32LeU => I::I32LeU, - O::I32GeS => I::I32GeS, - O::I32GeU => I::I32GeU, - O::I64Eqz => I::I64Eqz, - O::I64Eq => I::I64Eq, - O::I64Ne => I::I64Ne, - O::I64LtS => I::I64LtS, - O::I64LtU => I::I64LtU, - O::I64GtS => I::I64GtS, - O::I64GtU => I::I64GtU, - O::I64LeS => I::I64LeS, - O::I64LeU => I::I64LeU, - O::I64GeS => I::I64GeS, - O::I64GeU => I::I64GeU, - O::F32Eq => I::F32Eq, - O::F32Ne => I::F32Ne, - O::F32Lt => I::F32Lt, - O::F32Gt => I::F32Gt, - O::F32Le => I::F32Le, - O::F32Ge => I::F32Ge, - O::F64Eq => I::F64Eq, - O::F64Ne => I::F64Ne, - O::F64Lt => I::F64Lt, - O::F64Gt => I::F64Gt, - O::F64Le => I::F64Le, - O::F64Ge => I::F64Ge, - O::I32Clz => I::I32Clz, - O::I32Ctz => I::I32Ctz, - O::I32Popcnt => I::I32Popcnt, - O::I32Add => I::I32Add, - O::I32Sub => I::I32Sub, - O::I32Mul => I::I32Mul, - O::I32DivS => I::I32DivS, - O::I32DivU => I::I32DivU, - O::I32RemS => I::I32RemS, - O::I32RemU => I::I32RemU, - O::I32And => I::I32And, - O::I32Or => I::I32Or, - O::I32Xor => I::I32Xor, - O::I32Shl => I::I32Shl, - O::I32ShrS => I::I32ShrS, - O::I32ShrU => I::I32ShrU, - O::I32Rotl => I::I32Rotl, - O::I32Rotr => I::I32Rotr, - O::I64Clz => I::I64Clz, - O::I64Ctz => I::I64Ctz, - O::I64Popcnt => I::I64Popcnt, - O::I64Add => I::I64Add, - O::I64Sub => I::I64Sub, - O::I64Mul => I::I64Mul, - O::I64DivS => I::I64DivS, - O::I64DivU => I::I64DivU, - O::I64RemS => I::I64RemS, - O::I64RemU => I::I64RemU, - O::I64And => I::I64And, - O::I64Or => I::I64Or, - O::I64Xor => I::I64Xor, - O::I64Shl => I::I64Shl, - O::I64ShrS => I::I64ShrS, - O::I64ShrU => I::I64ShrU, - O::I64Rotl => I::I64Rotl, - O::I64Rotr => I::I64Rotr, - O::F32Abs => I::F32Abs, - O::F32Neg => I::F32Neg, - O::F32Ceil => I::F32Ceil, - O::F32Floor => I::F32Floor, - O::F32Trunc => I::F32Trunc, - O::F32Nearest => I::F32Nearest, - O::F32Sqrt => I::F32Sqrt, - O::F32Add => I::F32Add, - O::F32Sub => I::F32Sub, - O::F32Mul => I::F32Mul, - O::F32Div => I::F32Div, - O::F32Min => I::F32Min, - O::F32Max => I::F32Max, - O::F32Copysign => I::F32Copysign, - O::F64Abs => I::F64Abs, - O::F64Neg => I::F64Neg, - O::F64Ceil => I::F64Ceil, - O::F64Floor => I::F64Floor, - O::F64Trunc => I::F64Trunc, - O::F64Nearest => I::F64Nearest, - O::F64Sqrt => I::F64Sqrt, - O::F64Add => I::F64Add, - O::F64Sub => I::F64Sub, - O::F64Mul => I::F64Mul, - O::F64Div => I::F64Div, - O::F64Min => I::F64Min, - O::F64Max => I::F64Max, - O::F64Copysign => I::F64Copysign, - O::I32WrapI64 => I::I32WrapI64, - O::I32TruncF32S => I::I32TruncF32S, - O::I32TruncF32U => I::I32TruncF32U, - O::I32TruncF64S => I::I32TruncF64S, - O::I32TruncF64U => I::I32TruncF64U, - O::I64ExtendI32S => I::I64ExtendI32S, - O::I64ExtendI32U => I::I64ExtendI32U, - O::I64TruncF32S => I::I64TruncF32S, - O::I64TruncF32U => I::I64TruncF32U, - O::I64TruncF64S => I::I64TruncF64S, - O::I64TruncF64U => I::I64TruncF64U, - O::F32ConvertI32S => I::F32ConvertI32S, - O::F32ConvertI32U => I::F32ConvertI32U, - O::F32ConvertI64S => I::F32ConvertI64S, - O::F32ConvertI64U => I::F32ConvertI64U, - O::F32DemoteF64 => I::F32DemoteF64, - O::F64ConvertI32S => I::F64ConvertI32S, - O::F64ConvertI32U => I::F64ConvertI32U, - O::F64ConvertI64S => I::F64ConvertI64S, - O::F64ConvertI64U => I::F64ConvertI64U, - O::F64PromoteF32 => I::F64PromoteF32, - O::I32ReinterpretF32 => I::I32ReinterpretF32, - O::I64ReinterpretF64 => I::I64ReinterpretF64, - O::F32ReinterpretI32 => I::F32ReinterpretI32, - O::F64ReinterpretI64 => I::F64ReinterpretI64, - O::I32Extend8S => I::I32Extend8S, - O::I32Extend16S => I::I32Extend16S, - O::I64Extend8S => I::I64Extend8S, - O::I64Extend16S => I::I64Extend16S, - O::I64Extend32S => I::I64Extend32S, - - O::I32TruncSatF32S => I::I32TruncSatF32S, - O::I32TruncSatF32U => I::I32TruncSatF32U, - O::I32TruncSatF64S => I::I32TruncSatF64S, - O::I32TruncSatF64U => I::I32TruncSatF64U, - O::I64TruncSatF32S => I::I64TruncSatF32S, - O::I64TruncSatF32U => I::I64TruncSatF32U, - O::I64TruncSatF64S => I::I64TruncSatF64S, - O::I64TruncSatF64U => I::I64TruncSatF64U, - - O::MemoryInit { segment, mem } => I::MemoryInit { - data: t.remap(Item::Data, *segment)?, - mem: t.remap(Item::Memory, *mem)?, - }, - O::DataDrop { segment } => I::DataDrop(t.remap(Item::Data, *segment)?), - O::MemoryCopy { src, dst } => I::MemoryCopy { - src: t.remap(Item::Memory, *src)?, - dst: t.remap(Item::Memory, *dst)?, - }, - O::MemoryFill { mem, .. } => I::MemoryFill(t.remap(Item::Memory, *mem)?), - - O::TableInit { segment, table } => I::TableInit { - segment: t.remap(Item::Element, *segment)?, - table: t.remap(Item::Table, *table)?, - }, - O::ElemDrop { segment } => I::ElemDrop { - segment: t.remap(Item::Element, *segment)?, - }, - O::TableCopy { - dst_table, - src_table, - } => I::TableCopy { - dst: t.remap(Item::Table, *dst_table)?, - src: t.remap(Item::Table, *src_table)?, - }, - O::TableFill { table } => I::TableFill { - table: t.remap(Item::Table, *table)?, - }, - O::TableGet { table } => I::TableGet { - table: t.remap(Item::Table, *table)?, - }, - O::TableSet { table } => I::TableSet { - table: t.remap(Item::Table, *table)?, - }, - O::TableGrow { table } => I::TableGrow { - table: t.remap(Item::Table, *table)?, - }, - O::TableSize { table } => I::TableSize { - table: t.remap(Item::Table, *table)?, - }, - - O::V128Load { memarg } => I::V128Load { - memarg: t.translate_memarg(memarg)?, - }, - O::V128Load8x8S { memarg } => I::V128Load8x8S { - memarg: t.translate_memarg(memarg)?, - }, - O::V128Load8x8U { memarg } => I::V128Load8x8U { - memarg: t.translate_memarg(memarg)?, - }, - O::V128Load16x4S { memarg } => I::V128Load16x4S { - memarg: t.translate_memarg(memarg)?, - }, - O::V128Load16x4U { memarg } => I::V128Load16x4U { - memarg: t.translate_memarg(memarg)?, - }, - O::V128Load32x2S { memarg } => I::V128Load32x2S { - memarg: t.translate_memarg(memarg)?, - }, - O::V128Load32x2U { memarg } => I::V128Load32x2U { - memarg: t.translate_memarg(memarg)?, - }, - O::V128Load8Splat { memarg } => I::V128Load8Splat { - memarg: t.translate_memarg(memarg)?, - }, - O::V128Load16Splat { memarg } => I::V128Load16Splat { - memarg: t.translate_memarg(memarg)?, - }, - O::V128Load32Splat { memarg } => I::V128Load32Splat { - memarg: t.translate_memarg(memarg)?, - }, - O::V128Load64Splat { memarg } => I::V128Load64Splat { - memarg: t.translate_memarg(memarg)?, - }, - O::V128Load32Zero { memarg } => I::V128Load32Zero { - memarg: t.translate_memarg(memarg)?, - }, - O::V128Load64Zero { memarg } => I::V128Load64Zero { - memarg: t.translate_memarg(memarg)?, - }, - O::V128Store { memarg } => I::V128Store { - memarg: t.translate_memarg(memarg)?, - }, - O::V128Load8Lane { memarg, lane } => I::V128Load8Lane { - memarg: t.translate_memarg(memarg)?, - lane: *lane, - }, - O::V128Load16Lane { memarg, lane } => I::V128Load16Lane { - memarg: t.translate_memarg(memarg)?, - lane: *lane, - }, - O::V128Load32Lane { memarg, lane } => I::V128Load32Lane { - memarg: t.translate_memarg(memarg)?, - lane: *lane, - }, - O::V128Load64Lane { memarg, lane } => I::V128Load64Lane { - memarg: t.translate_memarg(memarg)?, - lane: *lane, - }, - O::V128Store8Lane { memarg, lane } => I::V128Store8Lane { - memarg: t.translate_memarg(memarg)?, - lane: *lane, - }, - O::V128Store16Lane { memarg, lane } => I::V128Store16Lane { - memarg: t.translate_memarg(memarg)?, - lane: *lane, - }, - O::V128Store32Lane { memarg, lane } => I::V128Store32Lane { - memarg: t.translate_memarg(memarg)?, - lane: *lane, - }, - O::V128Store64Lane { memarg, lane } => I::V128Store64Lane { - memarg: t.translate_memarg(memarg)?, - lane: *lane, - }, + $arg.default(), + )); + (map $arg:ident table_byte) => (()); + (map $arg:ident mem_byte) => (()); + (map $arg:ident flags) => (()); + (map $arg:ident ty) => (t.translate_ty($arg)?); + (map $arg:ident hty) => (t.translate_heapty($arg)?); + (map $arg:ident memarg) => (t.translate_memarg($arg)?); + (map $arg:ident local_index) => (*$arg); + (map $arg:ident value) => ($arg); + (map $arg:ident lane) => (*$arg); + (map $arg:ident lanes) => (*$arg); + + // This case takes the arguments of a wasmparser instruction and creates + // a wasm-encoder instruction. There are a few special cases for where + // the structure of a wasmparser instruction differs from that of + // wasm-encoder. + (build $op:ident) => (I::$op); + (build BrTable $arg:ident) => (I::BrTable($arg.0, $arg.1)); + (build I32Const $arg:ident) => (I::I32Const(*$arg)); + (build I64Const $arg:ident) => (I::I64Const(*$arg)); + (build F32Const $arg:ident) => (I::F32Const(f32::from_bits($arg.bits()))); + (build F64Const $arg:ident) => (I::F64Const(f64::from_bits($arg.bits()))); + (build V128Const $arg:ident) => (I::V128Const($arg.i128())); + (build $op:ident $arg:ident) => (I::$op($arg)); + (build CallIndirect $ty:ident $table:ident $_:ident) => (I::CallIndirect { + ty: $ty, + table: $table, + }); + (build ReturnCallIndirect $ty:ident $table:ident) => (I::ReturnCallIndirect { + ty: $ty, + table: $table, + }); + (build MemoryGrow $mem:ident $_:ident) => (I::MemoryGrow($mem)); + (build MemorySize $mem:ident $_:ident) => (I::MemorySize($mem)); + (build $op:ident $($arg:ident)*) => (I::$op { $($arg),* }); + } - O::V128Const { value } => I::V128Const(value.i128()), - O::I8x16Shuffle { lanes } => I::I8x16Shuffle { lanes: *lanes }, - O::I8x16ExtractLaneS { lane } => I::I8x16ExtractLaneS { lane: *lane }, - O::I8x16ExtractLaneU { lane } => I::I8x16ExtractLaneU { lane: *lane }, - O::I8x16ReplaceLane { lane } => I::I8x16ReplaceLane { lane: *lane }, - O::I16x8ExtractLaneS { lane } => I::I16x8ExtractLaneS { lane: *lane }, - O::I16x8ExtractLaneU { lane } => I::I16x8ExtractLaneU { lane: *lane }, - O::I16x8ReplaceLane { lane } => I::I16x8ReplaceLane { lane: *lane }, - O::I32x4ExtractLane { lane } => I::I32x4ExtractLane { lane: *lane }, - O::I32x4ReplaceLane { lane } => I::I32x4ReplaceLane { lane: *lane }, - O::I64x2ExtractLane { lane } => I::I64x2ExtractLane { lane: *lane }, - O::I64x2ReplaceLane { lane } => I::I64x2ReplaceLane { lane: *lane }, - O::F32x4ExtractLane { lane } => I::F32x4ExtractLane { lane: *lane }, - O::F32x4ReplaceLane { lane } => I::F32x4ReplaceLane { lane: *lane }, - O::F64x2ExtractLane { lane } => I::F64x2ExtractLane { lane: *lane }, - O::F64x2ReplaceLane { lane } => I::F64x2ReplaceLane { lane: *lane }, - - O::I8x16Swizzle => I::I8x16Swizzle, - O::I8x16Splat => I::I8x16Splat, - O::I16x8Splat => I::I16x8Splat, - O::I32x4Splat => I::I32x4Splat, - O::I64x2Splat => I::I64x2Splat, - O::F32x4Splat => I::F32x4Splat, - O::F64x2Splat => I::F64x2Splat, - O::I8x16Eq => I::I8x16Eq, - O::I8x16Ne => I::I8x16Ne, - O::I8x16LtS => I::I8x16LtS, - O::I8x16LtU => I::I8x16LtU, - O::I8x16GtS => I::I8x16GtS, - O::I8x16GtU => I::I8x16GtU, - O::I8x16LeS => I::I8x16LeS, - O::I8x16LeU => I::I8x16LeU, - O::I8x16GeS => I::I8x16GeS, - O::I8x16GeU => I::I8x16GeU, - O::I16x8Eq => I::I16x8Eq, - O::I16x8Ne => I::I16x8Ne, - O::I16x8LtS => I::I16x8LtS, - O::I16x8LtU => I::I16x8LtU, - O::I16x8GtS => I::I16x8GtS, - O::I16x8GtU => I::I16x8GtU, - O::I16x8LeS => I::I16x8LeS, - O::I16x8LeU => I::I16x8LeU, - O::I16x8GeS => I::I16x8GeS, - O::I16x8GeU => I::I16x8GeU, - O::I32x4Eq => I::I32x4Eq, - O::I32x4Ne => I::I32x4Ne, - O::I32x4LtS => I::I32x4LtS, - O::I32x4LtU => I::I32x4LtU, - O::I32x4GtS => I::I32x4GtS, - O::I32x4GtU => I::I32x4GtU, - O::I32x4LeS => I::I32x4LeS, - O::I32x4LeU => I::I32x4LeU, - O::I32x4GeS => I::I32x4GeS, - O::I32x4GeU => I::I32x4GeU, - O::I64x2Eq => I::I64x2Eq, - O::I64x2Ne => I::I64x2Ne, - O::I64x2LtS => I::I64x2LtS, - O::I64x2GtS => I::I64x2GtS, - O::I64x2LeS => I::I64x2LeS, - O::I64x2GeS => I::I64x2GeS, - O::F32x4Eq => I::F32x4Eq, - O::F32x4Ne => I::F32x4Ne, - O::F32x4Lt => I::F32x4Lt, - O::F32x4Gt => I::F32x4Gt, - O::F32x4Le => I::F32x4Le, - O::F32x4Ge => I::F32x4Ge, - O::F64x2Eq => I::F64x2Eq, - O::F64x2Ne => I::F64x2Ne, - O::F64x2Lt => I::F64x2Lt, - O::F64x2Gt => I::F64x2Gt, - O::F64x2Le => I::F64x2Le, - O::F64x2Ge => I::F64x2Ge, - O::V128Not => I::V128Not, - O::V128And => I::V128And, - O::V128AndNot => I::V128AndNot, - O::V128Or => I::V128Or, - O::V128Xor => I::V128Xor, - O::V128Bitselect => I::V128Bitselect, - O::V128AnyTrue => I::V128AnyTrue, - O::I8x16Abs => I::I8x16Abs, - O::I8x16Neg => I::I8x16Neg, - O::I8x16Popcnt => I::I8x16Popcnt, - O::I8x16AllTrue => I::I8x16AllTrue, - O::I8x16Bitmask => I::I8x16Bitmask, - O::I8x16NarrowI16x8S => I::I8x16NarrowI16x8S, - O::I8x16NarrowI16x8U => I::I8x16NarrowI16x8U, - O::I8x16Shl => I::I8x16Shl, - O::I8x16ShrS => I::I8x16ShrS, - O::I8x16ShrU => I::I8x16ShrU, - O::I8x16Add => I::I8x16Add, - O::I8x16AddSatS => I::I8x16AddSatS, - O::I8x16AddSatU => I::I8x16AddSatU, - O::I8x16Sub => I::I8x16Sub, - O::I8x16SubSatS => I::I8x16SubSatS, - O::I8x16SubSatU => I::I8x16SubSatU, - O::I8x16MinS => I::I8x16MinS, - O::I8x16MinU => I::I8x16MinU, - O::I8x16MaxS => I::I8x16MaxS, - O::I8x16MaxU => I::I8x16MaxU, - O::I8x16RoundingAverageU => I::I8x16RoundingAverageU, - O::I16x8ExtAddPairwiseI8x16S => I::I16x8ExtAddPairwiseI8x16S, - O::I16x8ExtAddPairwiseI8x16U => I::I16x8ExtAddPairwiseI8x16U, - O::I16x8Abs => I::I16x8Abs, - O::I16x8Neg => I::I16x8Neg, - O::I16x8Q15MulrSatS => I::I16x8Q15MulrSatS, - O::I16x8AllTrue => I::I16x8AllTrue, - O::I16x8Bitmask => I::I16x8Bitmask, - O::I16x8NarrowI32x4S => I::I16x8NarrowI32x4S, - O::I16x8NarrowI32x4U => I::I16x8NarrowI32x4U, - O::I16x8ExtendLowI8x16S => I::I16x8ExtendLowI8x16S, - O::I16x8ExtendHighI8x16S => I::I16x8ExtendHighI8x16S, - O::I16x8ExtendLowI8x16U => I::I16x8ExtendLowI8x16U, - O::I16x8ExtendHighI8x16U => I::I16x8ExtendHighI8x16U, - O::I16x8Shl => I::I16x8Shl, - O::I16x8ShrS => I::I16x8ShrS, - O::I16x8ShrU => I::I16x8ShrU, - O::I16x8Add => I::I16x8Add, - O::I16x8AddSatS => I::I16x8AddSatS, - O::I16x8AddSatU => I::I16x8AddSatU, - O::I16x8Sub => I::I16x8Sub, - O::I16x8SubSatS => I::I16x8SubSatS, - O::I16x8SubSatU => I::I16x8SubSatU, - O::I16x8Mul => I::I16x8Mul, - O::I16x8MinS => I::I16x8MinS, - O::I16x8MinU => I::I16x8MinU, - O::I16x8MaxS => I::I16x8MaxS, - O::I16x8MaxU => I::I16x8MaxU, - O::I16x8RoundingAverageU => I::I16x8RoundingAverageU, - O::I16x8ExtMulLowI8x16S => I::I16x8ExtMulLowI8x16S, - O::I16x8ExtMulHighI8x16S => I::I16x8ExtMulHighI8x16S, - O::I16x8ExtMulLowI8x16U => I::I16x8ExtMulLowI8x16U, - O::I16x8ExtMulHighI8x16U => I::I16x8ExtMulHighI8x16U, - O::I32x4ExtAddPairwiseI16x8S => I::I32x4ExtAddPairwiseI16x8S, - O::I32x4ExtAddPairwiseI16x8U => I::I32x4ExtAddPairwiseI16x8U, - O::I32x4Abs => I::I32x4Abs, - O::I32x4Neg => I::I32x4Neg, - O::I32x4AllTrue => I::I32x4AllTrue, - O::I32x4Bitmask => I::I32x4Bitmask, - O::I32x4ExtendLowI16x8S => I::I32x4ExtendLowI16x8S, - O::I32x4ExtendHighI16x8S => I::I32x4ExtendHighI16x8S, - O::I32x4ExtendLowI16x8U => I::I32x4ExtendLowI16x8U, - O::I32x4ExtendHighI16x8U => I::I32x4ExtendHighI16x8U, - O::I32x4Shl => I::I32x4Shl, - O::I32x4ShrS => I::I32x4ShrS, - O::I32x4ShrU => I::I32x4ShrU, - O::I32x4Add => I::I32x4Add, - O::I32x4Sub => I::I32x4Sub, - O::I32x4Mul => I::I32x4Mul, - O::I32x4MinS => I::I32x4MinS, - O::I32x4MinU => I::I32x4MinU, - O::I32x4MaxS => I::I32x4MaxS, - O::I32x4MaxU => I::I32x4MaxU, - O::I32x4DotI16x8S => I::I32x4DotI16x8S, - O::I32x4ExtMulLowI16x8S => I::I32x4ExtMulLowI16x8S, - O::I32x4ExtMulHighI16x8S => I::I32x4ExtMulHighI16x8S, - O::I32x4ExtMulLowI16x8U => I::I32x4ExtMulLowI16x8U, - O::I32x4ExtMulHighI16x8U => I::I32x4ExtMulHighI16x8U, - O::I64x2Abs => I::I64x2Abs, - O::I64x2Neg => I::I64x2Neg, - O::I64x2AllTrue => I::I64x2AllTrue, - O::I64x2Bitmask => I::I64x2Bitmask, - O::I64x2ExtendLowI32x4S => I::I64x2ExtendLowI32x4S, - O::I64x2ExtendHighI32x4S => I::I64x2ExtendHighI32x4S, - O::I64x2ExtendLowI32x4U => I::I64x2ExtendLowI32x4U, - O::I64x2ExtendHighI32x4U => I::I64x2ExtendHighI32x4U, - O::I64x2Shl => I::I64x2Shl, - O::I64x2ShrS => I::I64x2ShrS, - O::I64x2ShrU => I::I64x2ShrU, - O::I64x2Add => I::I64x2Add, - O::I64x2Sub => I::I64x2Sub, - O::I64x2Mul => I::I64x2Mul, - O::I64x2ExtMulLowI32x4S => I::I64x2ExtMulLowI32x4S, - O::I64x2ExtMulHighI32x4S => I::I64x2ExtMulHighI32x4S, - O::I64x2ExtMulLowI32x4U => I::I64x2ExtMulLowI32x4U, - O::I64x2ExtMulHighI32x4U => I::I64x2ExtMulHighI32x4U, - O::F32x4Ceil => I::F32x4Ceil, - O::F32x4Floor => I::F32x4Floor, - O::F32x4Trunc => I::F32x4Trunc, - O::F32x4Nearest => I::F32x4Nearest, - O::F32x4Abs => I::F32x4Abs, - O::F32x4Neg => I::F32x4Neg, - O::F32x4Sqrt => I::F32x4Sqrt, - O::F32x4Add => I::F32x4Add, - O::F32x4Sub => I::F32x4Sub, - O::F32x4Mul => I::F32x4Mul, - O::F32x4Div => I::F32x4Div, - O::F32x4Min => I::F32x4Min, - O::F32x4Max => I::F32x4Max, - O::F32x4PMin => I::F32x4PMin, - O::F32x4PMax => I::F32x4PMax, - O::F64x2Ceil => I::F64x2Ceil, - O::F64x2Floor => I::F64x2Floor, - O::F64x2Trunc => I::F64x2Trunc, - O::F64x2Nearest => I::F64x2Nearest, - O::F64x2Abs => I::F64x2Abs, - O::F64x2Neg => I::F64x2Neg, - O::F64x2Sqrt => I::F64x2Sqrt, - O::F64x2Add => I::F64x2Add, - O::F64x2Sub => I::F64x2Sub, - O::F64x2Mul => I::F64x2Mul, - O::F64x2Div => I::F64x2Div, - O::F64x2Min => I::F64x2Min, - O::F64x2Max => I::F64x2Max, - O::F64x2PMin => I::F64x2PMin, - O::F64x2PMax => I::F64x2PMax, - O::I32x4TruncSatF32x4S => I::I32x4TruncSatF32x4S, - O::I32x4TruncSatF32x4U => I::I32x4TruncSatF32x4U, - O::F32x4ConvertI32x4S => I::F32x4ConvertI32x4S, - O::F32x4ConvertI32x4U => I::F32x4ConvertI32x4U, - O::I32x4TruncSatF64x2SZero => I::I32x4TruncSatF64x2SZero, - O::I32x4TruncSatF64x2UZero => I::I32x4TruncSatF64x2UZero, - O::F64x2ConvertLowI32x4S => I::F64x2ConvertLowI32x4S, - O::F64x2ConvertLowI32x4U => I::F64x2ConvertLowI32x4U, - O::F32x4DemoteF64x2Zero => I::F32x4DemoteF64x2Zero, - O::F64x2PromoteLowF32x4 => I::F64x2PromoteLowF32x4, - O::I8x16RelaxedSwizzle => I::I8x16RelaxedSwizzle, - O::I32x4RelaxedTruncSatF32x4S => I::I32x4RelaxedTruncSatF32x4S, - O::I32x4RelaxedTruncSatF32x4U => I::I32x4RelaxedTruncSatF32x4U, - O::I32x4RelaxedTruncSatF64x2SZero => I::I32x4RelaxedTruncSatF64x2SZero, - O::I32x4RelaxedTruncSatF64x2UZero => I::I32x4RelaxedTruncSatF64x2UZero, - O::F32x4Fma => I::F32x4Fma, - O::F32x4Fms => I::F32x4Fms, - O::F64x2Fma => I::F64x2Fma, - O::F64x2Fms => I::F64x2Fms, - O::I8x16LaneSelect => I::I8x16LaneSelect, - O::I16x8LaneSelect => I::I16x8LaneSelect, - O::I32x4LaneSelect => I::I32x4LaneSelect, - O::I64x2LaneSelect => I::I64x2LaneSelect, - O::F32x4RelaxedMin => I::F32x4RelaxedMin, - O::F32x4RelaxedMax => I::F32x4RelaxedMax, - O::F64x2RelaxedMin => I::F64x2RelaxedMin, - O::F64x2RelaxedMax => I::F64x2RelaxedMax, - - // Note that these cases are not supported in `wasm_encoder` yet, - // and in general `wasmparser` often parses more things than - // `wasm_encoder` supports. If these are seen we simply say that - // this mutation isn't applicable because `wasm-encoder` can't - // create the new function anyway. - O::MemoryAtomicNotify { .. } - | O::MemoryAtomicWait32 { .. } - | O::MemoryAtomicWait64 { .. } - | O::I32AtomicLoad { .. } - | O::I64AtomicLoad { .. } - | O::I32AtomicLoad8U { .. } - | O::I32AtomicLoad16U { .. } - | O::I64AtomicLoad8U { .. } - | O::I64AtomicLoad16U { .. } - | O::I64AtomicLoad32U { .. } - | O::I32AtomicStore { .. } - | O::I64AtomicStore { .. } - | O::I32AtomicStore8 { .. } - | O::I32AtomicStore16 { .. } - | O::I64AtomicStore8 { .. } - | O::I64AtomicStore16 { .. } - | O::I64AtomicStore32 { .. } - | O::I32AtomicRmwAdd { .. } - | O::I64AtomicRmwAdd { .. } - | O::I32AtomicRmw8AddU { .. } - | O::I32AtomicRmw16AddU { .. } - | O::I64AtomicRmw8AddU { .. } - | O::I64AtomicRmw16AddU { .. } - | O::I64AtomicRmw32AddU { .. } - | O::I32AtomicRmwSub { .. } - | O::I64AtomicRmwSub { .. } - | O::I32AtomicRmw8SubU { .. } - | O::I32AtomicRmw16SubU { .. } - | O::I64AtomicRmw8SubU { .. } - | O::I64AtomicRmw16SubU { .. } - | O::I64AtomicRmw32SubU { .. } - | O::I32AtomicRmwAnd { .. } - | O::I64AtomicRmwAnd { .. } - | O::I32AtomicRmw8AndU { .. } - | O::I32AtomicRmw16AndU { .. } - | O::I64AtomicRmw8AndU { .. } - | O::I64AtomicRmw16AndU { .. } - | O::I64AtomicRmw32AndU { .. } - | O::I32AtomicRmwOr { .. } - | O::I64AtomicRmwOr { .. } - | O::I32AtomicRmw8OrU { .. } - | O::I32AtomicRmw16OrU { .. } - | O::I64AtomicRmw8OrU { .. } - | O::I64AtomicRmw16OrU { .. } - | O::I64AtomicRmw32OrU { .. } - | O::I32AtomicRmwXor { .. } - | O::I64AtomicRmwXor { .. } - | O::I32AtomicRmw8XorU { .. } - | O::I32AtomicRmw16XorU { .. } - | O::I64AtomicRmw8XorU { .. } - | O::I64AtomicRmw16XorU { .. } - | O::I64AtomicRmw32XorU { .. } - | O::I32AtomicRmwXchg { .. } - | O::I64AtomicRmwXchg { .. } - | O::I32AtomicRmw8XchgU { .. } - | O::I32AtomicRmw16XchgU { .. } - | O::I64AtomicRmw8XchgU { .. } - | O::I64AtomicRmw16XchgU { .. } - | O::I64AtomicRmw32XchgU { .. } - | O::I32AtomicRmwCmpxchg { .. } - | O::I64AtomicRmwCmpxchg { .. } - | O::I32AtomicRmw8CmpxchgU { .. } - | O::I32AtomicRmw16CmpxchgU { .. } - | O::I64AtomicRmw8CmpxchgU { .. } - | O::I64AtomicRmw16CmpxchgU { .. } - | O::I64AtomicRmw32CmpxchgU { .. } - | O::ReturnCall { .. } - | O::ReturnCallIndirect { .. } - | O::AtomicFence { .. } => return Err(Error::no_mutations_applicable()), - }) + wasmparser::for_each_operator!(translate) } pub fn block_type(t: &mut dyn Translator, ty: &wasmparser::BlockType) -> Result { diff --git a/crates/wasm-mutate/tests/tests.rs b/crates/wasm-mutate/tests/tests.rs index 9fba9466c0..6d97df157c 100644 --- a/crates/wasm-mutate/tests/tests.rs +++ b/crates/wasm-mutate/tests/tests.rs @@ -45,6 +45,7 @@ fn integration_test() { Ok(it) => it, Err(e) => match e.kind() { ErrorKind::NoMutationsApplicable => continue, + ErrorKind::OutOfFuel => break, _ => panic!("{}", e), }, }; diff --git a/crates/wasm-shrink/Cargo.toml b/crates/wasm-shrink/Cargo.toml index 8f6050b41d..c480a1b7a3 100644 --- a/crates/wasm-shrink/Cargo.toml +++ b/crates/wasm-shrink/Cargo.toml @@ -2,24 +2,24 @@ authors = ["Nick Fitzgerald "] categories = ["command-line-utilities", "development-tools", "development-tools::testing", "wasm"] description = "A WebAssembly test case shrinker" -edition = "2021" +edition.workspace = true keywords = ["reducer", "reduce", "bug", "crash"] license = "Apache-2.0 WITH LLVM-exception" readme = "./README.md" repository = "https://github.com/bytecodealliance/wasm-tools/tree/main/crates/wasm-shrink" name = "wasm-shrink" -version = "0.1.9" +version = "0.1.11" [dependencies] -anyhow = "1" +anyhow = { workspace = true } blake3 = "1.2.0" -log = "0.4" -rand = { version = "0.8.4", features = ["small_rng"] } -clap = { version = "3.0", optional = true, features = ['derive'] } -wasm-mutate = { version = "0.2.7", path = "../wasm-mutate" } -wasmparser = { version = "0.90.0", path = "../wasmparser" } +log = { workspace = true } +rand = { workspace = true } +clap = { workspace = true, optional = true } +wasm-mutate = { workspace = true } +wasmparser = { workspace = true } [dev-dependencies] -env_logger = "0.9" +env_logger = { workspace = true } wasmprinter = { path = "../wasmprinter" } wat = { path = "../wat" } diff --git a/crates/wasm-shrink/README.md b/crates/wasm-shrink/README.md index 629884a65c..d860556475 100644 --- a/crates/wasm-shrink/README.md +++ b/crates/wasm-shrink/README.md @@ -24,7 +24,7 @@ compiler). ### Install ``` -$ cargo install --git https://github.com/bytecodealliance/wasm-tools.git +$ cargo install wasm-tools ``` ### Writing a Predicate Script @@ -65,10 +65,10 @@ and non-zero if there is *not* any match. This is useful for predicate scripts. ### Run -To run `wasm-shrink` pass it the predicate and the initial test case: +To run `wasm-tools shrink` pass it the predicate and the initial test case: ```bash -$ wasm-shrink predicate.sh test-case.wasm -o shrunken.wasm +$ wasm-tools shrink predicate.sh test-case.wasm -o shrunken.wasm ``` The shrunken Wasm file will be written to `shrunken.wasm` in this case, but if @@ -78,7 +78,7 @@ case's name. You can see all options by passing `--help`: ```bash -$ wasm-shrink --help +$ wasm-tools shrink --help ``` ## Embed as a Library @@ -88,9 +88,8 @@ allow programmatic usage. First, add a dependency to your `Cargo.toml`: -```toml -[dependencies] -wasm-shrink = "0.1.0" +```sh +$ cargo add wasm-shrink ``` Then use the `wasm_shrink::WasmShrink` builder to configure and run a shrinking diff --git a/crates/wasm-smith/Cargo.toml b/crates/wasm-smith/Cargo.toml index 10d19e55f9..c5f223f1d4 100644 --- a/crates/wasm-smith/Cargo.toml +++ b/crates/wasm-smith/Cargo.toml @@ -3,12 +3,12 @@ authors = ["Nick Fitzgerald "] categories = ["command-line-utilities", "development-tools", "development-tools::testing", "wasm"] description = "A WebAssembly test case generator" documentation = "https://docs.rs/wasm-smith" -edition = "2021" +edition.workspace = true license = "Apache-2.0 WITH LLVM-exception" name = "wasm-smith" readme = "./README.md" repository = "https://github.com/bytecodealliance/wasm-tools/tree/main/crates/wasm-smith" -version = "0.11.4" +version = "0.11.6" exclude = ["/benches/corpus"] [[bench]] @@ -16,18 +16,18 @@ name = "corpus" harness = false [dependencies] -arbitrary = { version = "1.1.0", features = ["derive"] } +arbitrary = { workspace = true, features = ["derive"] } flagset = "0.4" -indexmap = "1.6" -leb128 = "0.2.4" -serde = { version = "1", features = ['derive'], optional = true } -wasm-encoder = { version = "0.16.0", path = "../wasm-encoder" } -wasmparser = { version = "0.90.0", path = "../wasmparser" } +indexmap = { workspace = true } +leb128 = { workspace = true } +serde = { workspace = true, optional = true } +wasm-encoder = { workspace = true } +wasmparser = { workspace = true } [dev-dependencies] -criterion = "0.3.3" -libfuzzer-sys = "0.4.0" -rand = { version = "0.8.0", features = ["small_rng"] } +criterion = { workspace = true } +libfuzzer-sys = { workspace = true } +rand = { workspace = true } wasmprinter = { path = "../wasmprinter" } wat = { path = "../wat" } diff --git a/crates/wasm-smith/README.md b/crates/wasm-smith/README.md index a841bd1c84..720472ebb6 100644 --- a/crates/wasm-smith/README.md +++ b/crates/wasm-smith/README.md @@ -46,11 +46,8 @@ $ cargo fuzz add my_wasm_smith_fuzz_target Next, add `wasm-smith` to your dependencies: -```toml -# fuzz/Cargo.toml - -[dependencies] -wasm-smith = "0.4.0" +```shell +$ cargo add wasm-smith ``` Then, define your fuzz target so that it takes arbitrary `wasm_smith::Module`s @@ -88,13 +85,13 @@ $ cargo fuzz run my_wasm_smith_fuzz_target Install the CLI tool via `cargo`: ```shell -$ cargo install --git https://github.com/bytecodealliance/wasm-tools +$ cargo install wasm-tools ``` Convert some arbitrary input into a valid Wasm module: ```shell -$ head -c 100 /dev/urandom | wasm-smith -o test.wasm +$ head -c 100 /dev/urandom | wasm-tools smith -o test.wasm ``` Finally, run your tool on the generated Wasm module: diff --git a/crates/wasm-smith/src/component.rs b/crates/wasm-smith/src/component.rs index d89a358459..90f328c8a4 100644 --- a/crates/wasm-smith/src/component.rs +++ b/crates/wasm-smith/src/component.rs @@ -729,6 +729,7 @@ impl ComponentBuilder { "memory".into(), crate::core::EntityType::Memory(self.arbitrary_core_memory_type(u)?), )); + exports.insert("memory".into()); counts.memories += 1; has_memory = true; } @@ -1079,20 +1080,20 @@ impl ComponentBuilder { u: &mut Unstructured, exports: &mut HashSet, type_fuel: &mut u32, - ) -> Result { + ) -> Result { let mut choices: Vec< fn( &mut ComponentBuilder, &mut HashSet, &mut Unstructured, &mut u32, - ) -> Result, + ) -> Result, > = Vec::with_capacity(3); // Export. if self.current_type_scope().can_ref_type() { choices.push(|me, exports, u, _type_fuel| { - Ok(InstanceTypeDef::Export { + Ok(InstanceTypeDecl::Export { name: crate::unique_string(100, exports, u)?, ty: me.arbitrary_type_ref(u, false, true)?.unwrap(), }) @@ -1118,7 +1119,7 @@ impl ComponentBuilder { } => me.current_type_scope_mut().push_core(ty.clone()), _ => unreachable!(), }; - Ok(InstanceTypeDef::Alias(alias)) + Ok(InstanceTypeDecl::Alias(alias)) }); } @@ -1126,15 +1127,17 @@ impl ComponentBuilder { choices.push(|me, _exports, u, type_fuel| { let ty = me.arbitrary_core_type(u, type_fuel)?; me.current_type_scope_mut().push_core(ty.clone()); - Ok(InstanceTypeDef::CoreType(ty)) + Ok(InstanceTypeDecl::CoreType(ty)) }); // Type definition. - choices.push(|me, _exports, u, type_fuel| { - let ty = me.arbitrary_type(u, type_fuel)?; - me.current_type_scope_mut().push(ty.clone()); - Ok(InstanceTypeDef::Type(ty)) - }); + if self.types.len() < self.config.max_nesting_depth() { + choices.push(|me, _exports, u, type_fuel| { + let ty = me.arbitrary_type(u, type_fuel)?; + me.current_type_scope_mut().push(ty.clone()); + Ok(InstanceTypeDecl::Type(ty)) + }); + } let f = u.choose(&choices)?; f(self, exports, u, type_fuel) @@ -1218,41 +1221,6 @@ impl ComponentBuilder { let mut results = Vec::new(); let mut names = HashSet::new(); - fn push( - b: &ComponentBuilder, - u: &mut Unstructured, - type_fuel: &mut u32, - names: &mut HashSet, - items: &mut Vec<(Option, ComponentValType)>, - ) -> Result { - *type_fuel = type_fuel.saturating_sub(1); - if *type_fuel == 0 { - return Ok(false); - } - - // If the collection is empty (i.e. first push), then arbitrarily give it a name. - // Otherwise, all of the items must be named. - let name = if items.is_empty() { - // Most of the time we should have named parameters/results. - u.ratio::(99, 100)? - .then(|| crate::unique_non_empty_string(100, names, u)) - .transpose()? - } else { - Some(crate::unique_non_empty_string(100, names, u)?) - }; - - let ty = b.arbitrary_component_val_type(u)?; - - items.push((name, ty)); - - // There can be only one unnamed parameter/result. - if items.len() == 1 && items[0].0.is_none() { - return Ok(false); - } - - Ok(true) - } - // Note: parameters are currently limited to a maximum of 16 // because any additional parameters will require indirect access // via a pointer argument; when this occurs, validation of any @@ -1263,7 +1231,17 @@ impl ComponentBuilder { // we should increase this maximum to test indirect parameter // passing. arbitrary_loop(u, 0, 16, |u| { - push(self, u, type_fuel, &mut names, &mut params) + *type_fuel = type_fuel.saturating_sub(1); + if *type_fuel == 0 { + return Ok(false); + } + + let name = crate::unique_non_empty_string(100, &mut names, u)?; + let ty = self.arbitrary_component_val_type(u)?; + + params.push((name, ty)); + + Ok(true) })?; names.clear(); @@ -1272,7 +1250,32 @@ impl ComponentBuilder { // required. When the memory option is implemented, this restriction // should be relaxed. arbitrary_loop(u, 0, 1, |u| { - push(self, u, type_fuel, &mut names, &mut results) + *type_fuel = type_fuel.saturating_sub(1); + if *type_fuel == 0 { + return Ok(false); + } + + // If the result list is empty (i.e. first push), then arbitrarily give + // the result a name. Otherwise, all of the subsequent items must be named. + let name = if results.is_empty() { + // Most of the time we should have a single, unnamed result. + u.ratio::(10, 100)? + .then(|| crate::unique_non_empty_string(100, &mut names, u)) + .transpose()? + } else { + Some(crate::unique_non_empty_string(100, &mut names, u)?) + }; + + let ty = self.arbitrary_component_val_type(u)?; + + results.push((name, ty)); + + // There can be only one unnamed result. + if results.len() == 1 && results[0].0.is_none() { + return Ok(false); + } + + Ok(true) })?; Ok(Rc::new(FuncType { params, results })) @@ -1835,11 +1838,7 @@ fn inverse_scalar_canonical_abi_for( for core_ty in &core_func_ty.params { params.push(( - if core_func_ty.params.len() > 1 || u.arbitrary()? { - Some(crate::unique_non_empty_string(100, &mut names, u)?) - } else { - None - }, + crate::unique_non_empty_string(100, &mut names, u)?, from_core_ty(u, *core_ty)?, )); } @@ -1998,24 +1997,24 @@ enum ComponentTypeDef { Export { name: String, ty: ComponentTypeRef }, } -impl From for ComponentTypeDef { - fn from(def: InstanceTypeDef) -> Self { +impl From for ComponentTypeDef { + fn from(def: InstanceTypeDecl) -> Self { match def { - InstanceTypeDef::CoreType(t) => Self::CoreType(t), - InstanceTypeDef::Type(t) => Self::Type(t), - InstanceTypeDef::Export { name, ty } => Self::Export { name, ty }, - InstanceTypeDef::Alias(a) => Self::Alias(a), + InstanceTypeDecl::CoreType(t) => Self::CoreType(t), + InstanceTypeDecl::Type(t) => Self::Type(t), + InstanceTypeDecl::Export { name, ty } => Self::Export { name, ty }, + InstanceTypeDecl::Alias(a) => Self::Alias(a), } } } #[derive(Clone, Debug, PartialEq, Eq, Hash)] struct InstanceType { - defs: Vec, + defs: Vec, } #[derive(Clone, Debug, PartialEq, Eq, Hash)] -enum InstanceTypeDef { +enum InstanceTypeDecl { CoreType(Rc), Type(Rc), Alias(Alias), @@ -2024,21 +2023,11 @@ enum InstanceTypeDef { #[derive(Clone, Debug, PartialEq, Eq, Hash)] struct FuncType { - params: Vec<(Option, ComponentValType)>, + params: Vec<(String, ComponentValType)>, results: Vec<(Option, ComponentValType)>, } impl FuncType { - fn unnamed_param_ty(&self) -> Option { - if self.params.len() == 1 { - let (name, ty) = &self.params[0]; - if name.is_none() { - return Some(*ty); - } - } - None - } - fn unnamed_result_ty(&self) -> Option { if self.results.len() == 1 { let (name, ty) = &self.results[0]; diff --git a/crates/wasm-smith/src/component/encode.rs b/crates/wasm-smith/src/component/encode.rs index b19e8f4622..db4c97c899 100644 --- a/crates/wasm-smith/src/component/encode.rs +++ b/crates/wasm-smith/src/component/encode.rs @@ -159,16 +159,7 @@ impl Type { Self::Func(func_ty) => { let mut f = enc.function(); - if let Some(ty) = func_ty.unnamed_param_ty() { - f.param(ty); - } else { - f.params( - func_ty - .params - .iter() - .map(|(name, ty)| (name.as_deref().unwrap(), *ty)), - ); - } + f.params(func_ty.params.iter().map(|(name, ty)| (name.as_str(), *ty))); if let Some(ty) = func_ty.unnamed_result_ty() { f.result(ty); @@ -220,30 +211,30 @@ impl Type { let mut enc_inst_ty = wasm_encoder::InstanceType::new(); for def in &inst_ty.defs { match def { - InstanceTypeDef::CoreType(ty) => { + InstanceTypeDecl::CoreType(ty) => { ty.encode(enc_inst_ty.core_type()); } - InstanceTypeDef::Type(ty) => { + InstanceTypeDecl::Type(ty) => { ty.encode(enc_inst_ty.ty()); } - InstanceTypeDef::Export { name, ty } => { + InstanceTypeDecl::Export { name, ty } => { enc_inst_ty.export(name, *ty); } - InstanceTypeDef::Alias(Alias::Outer { + InstanceTypeDecl::Alias(Alias::Outer { count, i, kind: OuterAliasKind::Type(_), }) => { enc_inst_ty.alias_outer_type(*count, *i); } - InstanceTypeDef::Alias(Alias::Outer { + InstanceTypeDecl::Alias(Alias::Outer { count, i, kind: OuterAliasKind::CoreType(_), }) => { enc_inst_ty.alias_outer_core_type(*count, *i); } - InstanceTypeDef::Alias(_) => unreachable!(), + InstanceTypeDecl::Alias(_) => unreachable!(), } } enc.instance(&enc_inst_ty); diff --git a/crates/wasm-smith/src/core/code_builder.rs b/crates/wasm-smith/src/core/code_builder.rs index ccb66bee85..ac9cc71a07 100644 --- a/crates/wasm-smith/src/core/code_builder.rs +++ b/crates/wasm-smith/src/core/code_builder.rs @@ -545,13 +545,17 @@ instructions! { (Some(simd_v128_on_stack_relaxed), i32x4_relaxed_trunc_sat_f64x2s_zero, Vector), (Some(simd_v128_on_stack_relaxed), i32x4_relaxed_trunc_sat_f64x2u_zero, Vector), (Some(simd_v128_v128_v128_on_stack_relaxed), f32x4_fma, Vector), - (Some(simd_v128_v128_v128_on_stack_relaxed), f32x4_fms, Vector), + (Some(simd_v128_v128_v128_on_stack_relaxed), f32x4_fnma, Vector), (Some(simd_v128_v128_v128_on_stack_relaxed), f64x2_fma, Vector), - (Some(simd_v128_v128_v128_on_stack_relaxed), f64x2_fms, Vector), + (Some(simd_v128_v128_v128_on_stack_relaxed), f64x2_fnma, Vector), (Some(simd_v128_v128_on_stack_relaxed), f32x4_relaxed_min, Vector), (Some(simd_v128_v128_on_stack_relaxed), f32x4_relaxed_max, Vector), (Some(simd_v128_v128_on_stack_relaxed), f64x2_relaxed_min, Vector), (Some(simd_v128_v128_on_stack_relaxed), f64x2_relaxed_max, Vector), + (Some(simd_v128_v128_on_stack_relaxed), i16x8_relaxed_q15mulr_s, Vector), + (Some(simd_v128_v128_on_stack_relaxed), i16x8_dot_i8x16_i7x16_s, Vector), + (Some(simd_v128_v128_v128_on_stack_relaxed), i32x4_dot_i8x16_i7x16_add_s, Vector), + (Some(simd_v128_v128_v128_on_stack_relaxed), f32x4_relaxed_dot_bf16x8_add_f32x4, Vector), } pub(crate) struct CodeBuilderAllocations { @@ -1742,7 +1746,7 @@ fn i32_load_8_s( ) -> Result { let memarg = mem_arg(u, module, builder, &[0])?; builder.allocs.operands.push(Some(ValType::I32)); - Ok(Instruction::I32Load8_S(memarg)) + Ok(Instruction::I32Load8S(memarg)) } fn i32_load_8_u( @@ -1752,7 +1756,7 @@ fn i32_load_8_u( ) -> Result { let memarg = mem_arg(u, module, builder, &[0])?; builder.allocs.operands.push(Some(ValType::I32)); - Ok(Instruction::I32Load8_U(memarg)) + Ok(Instruction::I32Load8U(memarg)) } fn i32_load_16_s( @@ -1762,7 +1766,7 @@ fn i32_load_16_s( ) -> Result { let memarg = mem_arg(u, module, builder, &[0, 1])?; builder.allocs.operands.push(Some(ValType::I32)); - Ok(Instruction::I32Load16_S(memarg)) + Ok(Instruction::I32Load16S(memarg)) } fn i32_load_16_u( @@ -1772,7 +1776,7 @@ fn i32_load_16_u( ) -> Result { let memarg = mem_arg(u, module, builder, &[0, 1])?; builder.allocs.operands.push(Some(ValType::I32)); - Ok(Instruction::I32Load16_U(memarg)) + Ok(Instruction::I32Load16U(memarg)) } fn i64_load_8_s( @@ -1782,7 +1786,7 @@ fn i64_load_8_s( ) -> Result { let memarg = mem_arg(u, module, builder, &[0])?; builder.allocs.operands.push(Some(ValType::I64)); - Ok(Instruction::I64Load8_S(memarg)) + Ok(Instruction::I64Load8S(memarg)) } fn i64_load_16_s( @@ -1792,7 +1796,7 @@ fn i64_load_16_s( ) -> Result { let memarg = mem_arg(u, module, builder, &[0, 1])?; builder.allocs.operands.push(Some(ValType::I64)); - Ok(Instruction::I64Load16_S(memarg)) + Ok(Instruction::I64Load16S(memarg)) } fn i64_load_32_s( @@ -1802,7 +1806,7 @@ fn i64_load_32_s( ) -> Result { let memarg = mem_arg(u, module, builder, &[0, 1, 2])?; builder.allocs.operands.push(Some(ValType::I64)); - Ok(Instruction::I64Load32_S(memarg)) + Ok(Instruction::I64Load32S(memarg)) } fn i64_load_8_u( @@ -1812,7 +1816,7 @@ fn i64_load_8_u( ) -> Result { let memarg = mem_arg(u, module, builder, &[0])?; builder.allocs.operands.push(Some(ValType::I64)); - Ok(Instruction::I64Load8_U(memarg)) + Ok(Instruction::I64Load8U(memarg)) } fn i64_load_16_u( @@ -1822,7 +1826,7 @@ fn i64_load_16_u( ) -> Result { let memarg = mem_arg(u, module, builder, &[0, 1])?; builder.allocs.operands.push(Some(ValType::I64)); - Ok(Instruction::I64Load16_U(memarg)) + Ok(Instruction::I64Load16U(memarg)) } fn i64_load_32_u( @@ -1832,7 +1836,7 @@ fn i64_load_32_u( ) -> Result { let memarg = mem_arg(u, module, builder, &[0, 1, 2])?; builder.allocs.operands.push(Some(ValType::I64)); - Ok(Instruction::I64Load32_U(memarg)) + Ok(Instruction::I64Load32U(memarg)) } #[inline] @@ -2010,9 +2014,9 @@ fn memory_init( ValType::I64 }; let mem = memory_index(u, builder, ty)?; - let data = data_index(u, module)?; + let data_index = data_index(u, module)?; builder.pop_operands(&[ty]); - Ok(Instruction::MemoryInit { mem, data }) + Ok(Instruction::MemoryInit { mem, data_index }) } #[inline] @@ -2075,7 +2079,8 @@ fn memory_copy( _module: &Module, builder: &mut CodeBuilder, ) -> Result { - let (src, dst) = if builder.types_on_stack(&[ValType::I64, ValType::I64, ValType::I64]) { + let (src_mem, dst_mem) = if builder.types_on_stack(&[ValType::I64, ValType::I64, ValType::I64]) + { builder.pop_operands(&[ValType::I64, ValType::I64, ValType::I64]); ( memory_index(u, builder, ValType::I64)?, @@ -2102,7 +2107,7 @@ fn memory_copy( } else { unreachable!() }; - Ok(Instruction::MemoryCopy { dst, src }) + Ok(Instruction::MemoryCopy { dst_mem, src_mem }) } #[inline] @@ -3298,7 +3303,7 @@ fn table_fill( let ty = pop_reference_type(builder); builder.pop_operands(&[ValType::I32]); let table = table_index(ty, u, module)?; - Ok(Instruction::TableFill { table }) + Ok(Instruction::TableFill(table)) } #[inline] @@ -3318,7 +3323,7 @@ fn table_set( let ty = pop_reference_type(builder); builder.pop_operands(&[ValType::I32]); let table = table_index(ty, u, module)?; - Ok(Instruction::TableSet { table }) + Ok(Instruction::TableSet(table)) } #[inline] @@ -3337,7 +3342,7 @@ fn table_get( let idx = u.int_in_range(0..=module.tables.len() - 1)?; let ty = module.tables[idx].element_type; builder.push_operands(&[ty]); - Ok(Instruction::TableGet { table: idx as u32 }) + Ok(Instruction::TableGet(idx as u32)) } #[inline] @@ -3352,7 +3357,7 @@ fn table_size( ) -> Result { let table = u.int_in_range(0..=module.tables.len() - 1)? as u32; builder.push_operands(&[ValType::I32]); - Ok(Instruction::TableSize { table }) + Ok(Instruction::TableSize(table)) } #[inline] @@ -3373,7 +3378,7 @@ fn table_grow( let ty = pop_reference_type(builder); let table = table_index(ty, u, module)?; builder.push_operands(&[ValType::I32]); - Ok(Instruction::TableGrow { table }) + Ok(Instruction::TableGrow(table)) } #[inline] @@ -3389,9 +3394,12 @@ fn table_copy( builder: &mut CodeBuilder, ) -> Result { builder.pop_operands(&[ValType::I32, ValType::I32, ValType::I32]); - let src = u.int_in_range(0..=module.tables.len() - 1)? as u32; - let dst = table_index(module.tables[src as usize].element_type, u, module)?; - Ok(Instruction::TableCopy { src, dst }) + let src_table = u.int_in_range(0..=module.tables.len() - 1)? as u32; + let dst_table = table_index(module.tables[src_table as usize].element_type, u, module)?; + Ok(Instruction::TableCopy { + src_table, + dst_table, + }) } #[inline] @@ -3417,7 +3425,7 @@ fn table_init( let segment = *u.choose(&segments)?; let table = table_index(module.elems[segment].ty, u, module)?; Ok(Instruction::TableInit { - segment: segment as u32, + elem_index: segment as u32, table, }) } @@ -3433,7 +3441,7 @@ fn elem_drop( _builder: &mut CodeBuilder, ) -> Result { let segment = u.int_in_range(0..=module.elems.len() - 1)? as u32; - Ok(Instruction::ElemDrop { segment }) + Ok(Instruction::ElemDrop(segment)) } fn pop_reference_type(builder: &mut CodeBuilder) -> ValType { @@ -3562,7 +3570,7 @@ macro_rules! simd_load { ) -> Result { let memarg = mem_arg(u, module, builder, $alignments)?; builder.push_operands(&[ValType::V128]); - Ok(Instruction::$instruction { memarg }) + Ok(Instruction::$instruction(memarg)) } }; } @@ -3588,7 +3596,7 @@ fn v128_store( ) -> Result { builder.pop_operands(&[ValType::V128]); let memarg = mem_arg(u, module, builder, &[0, 1, 2, 3, 4])?; - Ok(Instruction::V128Store { memarg }) + Ok(Instruction::V128Store(memarg)) } macro_rules! simd_load_lane { @@ -3653,7 +3661,7 @@ fn i8x16_shuffle( for i in 0..16 { lanes[i] = u.int_in_range(0..=31)?; } - Ok(Instruction::I8x16Shuffle { lanes }) + Ok(Instruction::I8x16Shuffle(lanes)) } macro_rules! simd_lane_access { @@ -3665,9 +3673,7 @@ macro_rules! simd_lane_access { ) -> Result { builder.pop_operands($in_types); builder.push_operands($out_types); - Ok(Instruction::$instruction { - lane: lane_index(u, $number_of_lanes)?, - }) + Ok(Instruction::$instruction(lane_index(u, $number_of_lanes)?)) } }; } @@ -3956,15 +3962,22 @@ simd_unop!( I32x4RelaxedTruncSatF64x2UZero, i32x4_relaxed_trunc_sat_f64x2u_zero ); -simd_ternop!(F32x4Fma, f32x4_fma); -simd_ternop!(F32x4Fms, f32x4_fms); -simd_ternop!(F64x2Fma, f64x2_fma); -simd_ternop!(F64x2Fms, f64x2_fms); -simd_ternop!(I8x16LaneSelect, i8x16_laneselect); -simd_ternop!(I16x8LaneSelect, i16x8_laneselect); -simd_ternop!(I32x4LaneSelect, i32x4_laneselect); -simd_ternop!(I64x2LaneSelect, i64x2_laneselect); +simd_ternop!(F32x4RelaxedFma, f32x4_fma); +simd_ternop!(F32x4RelaxedFnma, f32x4_fnma); +simd_ternop!(F64x2RelaxedFma, f64x2_fma); +simd_ternop!(F64x2RelaxedFnma, f64x2_fnma); +simd_ternop!(I8x16RelaxedLaneselect, i8x16_laneselect); +simd_ternop!(I16x8RelaxedLaneselect, i16x8_laneselect); +simd_ternop!(I32x4RelaxedLaneselect, i32x4_laneselect); +simd_ternop!(I64x2RelaxedLaneselect, i64x2_laneselect); simd_binop!(F32x4RelaxedMin, f32x4_relaxed_min); simd_binop!(F32x4RelaxedMax, f32x4_relaxed_max); simd_binop!(F64x2RelaxedMin, f64x2_relaxed_min); simd_binop!(F64x2RelaxedMax, f64x2_relaxed_max); +simd_binop!(I16x8RelaxedQ15mulrS, i16x8_relaxed_q15mulr_s); +simd_binop!(I16x8DotI8x16I7x16S, i16x8_dot_i8x16_i7x16_s); +simd_ternop!(I32x4DotI8x16I7x16AddS, i32x4_dot_i8x16_i7x16_add_s); +simd_ternop!( + F32x4RelaxedDotBf16x8AddF32x4, + f32x4_relaxed_dot_bf16x8_add_f32x4 +); diff --git a/crates/wasm-smith/src/core/no_traps.rs b/crates/wasm-smith/src/core/no_traps.rs index ba57487b13..096a18a750 100755 --- a/crates/wasm-smith/src/core/no_traps.rs +++ b/crates/wasm-smith/src/core/no_traps.rs @@ -157,7 +157,7 @@ impl Module { ValType::V128 if can_store_args_to_memory => { new_insts.push(address.clone()); new_insts.push(Instruction::LocalGet(val_to_store)); - new_insts.push(Instruction::V128Store { memarg }); + new_insts.push(Instruction::V128Store(memarg)); } _ => { new_insts.push(Instruction::Drop); @@ -177,29 +177,29 @@ impl Module { | Instruction::I64Load(memarg) | Instruction::F32Load(memarg) | Instruction::F64Load(memarg) - | Instruction::I32Load8_S(memarg) - | Instruction::I32Load8_U(memarg) - | Instruction::I32Load16_S(memarg) - | Instruction::I32Load16_U(memarg) - | Instruction::I64Load8_S(memarg) - | Instruction::I64Load8_U(memarg) - | Instruction::I64Load16_S(memarg) - | Instruction::I64Load16_U(memarg) - | Instruction::I64Load32_S(memarg) - | Instruction::I64Load32_U(memarg) - | Instruction::V128Load { memarg } - | Instruction::V128Load8x8S { memarg } - | Instruction::V128Load8x8U { memarg } - | Instruction::V128Load16x4S { memarg } - | Instruction::V128Load16x4U { memarg } - | Instruction::V128Load32x2S { memarg } - | Instruction::V128Load32x2U { memarg } - | Instruction::V128Load8Splat { memarg } - | Instruction::V128Load16Splat { memarg } - | Instruction::V128Load32Splat { memarg } - | Instruction::V128Load64Splat { memarg } - | Instruction::V128Load32Zero { memarg } - | Instruction::V128Load64Zero { memarg } => { + | Instruction::I32Load8S(memarg) + | Instruction::I32Load8U(memarg) + | Instruction::I32Load16S(memarg) + | Instruction::I32Load16U(memarg) + | Instruction::I64Load8S(memarg) + | Instruction::I64Load8U(memarg) + | Instruction::I64Load16S(memarg) + | Instruction::I64Load16U(memarg) + | Instruction::I64Load32S(memarg) + | Instruction::I64Load32U(memarg) + | Instruction::V128Load(memarg) + | Instruction::V128Load8x8S(memarg) + | Instruction::V128Load8x8U(memarg) + | Instruction::V128Load16x4S(memarg) + | Instruction::V128Load16x4U(memarg) + | Instruction::V128Load32x2S(memarg) + | Instruction::V128Load32x2U(memarg) + | Instruction::V128Load8Splat(memarg) + | Instruction::V128Load16Splat(memarg) + | Instruction::V128Load32Splat(memarg) + | Instruction::V128Load64Splat(memarg) + | Instruction::V128Load32Zero(memarg) + | Instruction::V128Load64Zero(memarg) => { let memory = &self.memories[memarg.memory_index as usize]; let address_type = if memory.memory64 { ValType::I64 @@ -280,7 +280,7 @@ impl Module { | Instruction::I64Store8(memarg) | Instruction::I64Store16(memarg) | Instruction::I64Store32(memarg) - | Instruction::V128Store { memarg } => { + | Instruction::V128Store(memarg) => { let memory = &self.memories[memarg.memory_index as usize]; let address_type = if memory.memory64 { ValType::I64 @@ -347,11 +347,15 @@ impl Module { return Err(NotSupported { opcode: inst }) } - Instruction::MemoryCopy { src: _, dst: _ } - | Instruction::MemoryFill(_) - | Instruction::MemoryInit { mem: _, data: _ } => { - return Err(NotSupported { opcode: inst }) + Instruction::MemoryCopy { + src_mem: _, + dst_mem: _, } + | Instruction::MemoryFill(_) + | Instruction::MemoryInit { + mem: _, + data_index: _, + } => return Err(NotSupported { opcode: inst }), // Unsigned integer division and remainder will trap when // the divisor is 0. To avoid the trap, we will set any 0 @@ -521,16 +525,17 @@ impl Module { // [input_or_0:conv_type] new_insts.push(inst); } - Instruction::TableFill { table: _ } - | Instruction::TableSet { table: _ } - | Instruction::TableGet { table: _ } + Instruction::TableFill(_) + | Instruction::TableSet(_) + | Instruction::TableGet(_) | Instruction::TableInit { - segment: _, + elem_index: _, table: _, } - | Instruction::TableCopy { src: _, dst: _ } => { - return Err(NotSupported { opcode: inst }) - } + | Instruction::TableCopy { + src_table: _, + dst_table: _, + } => return Err(NotSupported { opcode: inst }), // None of the other instructions can trap, so just copy them over. inst => new_insts.push(inst), @@ -692,21 +697,21 @@ fn type_of_float_conversion(inst: &Instruction) -> ValType { fn type_of_memory_access(inst: &Instruction) -> ValType { match inst { Instruction::I32Load(_) - | Instruction::I32Load8_S(_) - | Instruction::I32Load8_U(_) - | Instruction::I32Load16_S(_) - | Instruction::I32Load16_U(_) + | Instruction::I32Load8S(_) + | Instruction::I32Load8U(_) + | Instruction::I32Load16S(_) + | Instruction::I32Load16U(_) | Instruction::I32Store(_) | Instruction::I32Store8(_) | Instruction::I32Store16(_) => ValType::I32, Instruction::I64Load(_) - | Instruction::I64Load8_S(_) - | Instruction::I64Load8_U(_) - | Instruction::I64Load16_S(_) - | Instruction::I64Load16_U(_) - | Instruction::I64Load32_S(_) - | Instruction::I64Load32_U(_) + | Instruction::I64Load8S(_) + | Instruction::I64Load8U(_) + | Instruction::I64Load16S(_) + | Instruction::I64Load16U(_) + | Instruction::I64Load32S(_) + | Instruction::I64Load32U(_) | Instruction::I64Store(_) | Instruction::I64Store8(_) | Instruction::I64Store16(_) @@ -716,20 +721,20 @@ fn type_of_memory_access(inst: &Instruction) -> ValType { Instruction::F64Load(_) | Instruction::F64Store(_) => ValType::F64, - Instruction::V128Load { .. } - | Instruction::V128Load8x8S { .. } - | Instruction::V128Load8x8U { .. } - | Instruction::V128Load16x4S { .. } - | Instruction::V128Load16x4U { .. } - | Instruction::V128Load32x2S { .. } - | Instruction::V128Load32x2U { .. } - | Instruction::V128Load8Splat { .. } - | Instruction::V128Load16Splat { .. } - | Instruction::V128Load32Splat { .. } - | Instruction::V128Load64Splat { .. } - | Instruction::V128Load32Zero { .. } - | Instruction::V128Load64Zero { .. } - | Instruction::V128Store { .. } => ValType::V128, + Instruction::V128Load(_) + | Instruction::V128Load8x8S(_) + | Instruction::V128Load8x8U(_) + | Instruction::V128Load16x4S(_) + | Instruction::V128Load16x4U(_) + | Instruction::V128Load32x2S(_) + | Instruction::V128Load32x2U(_) + | Instruction::V128Load8Splat(_) + | Instruction::V128Load16Splat(_) + | Instruction::V128Load32Splat(_) + | Instruction::V128Load64Splat(_) + | Instruction::V128Load32Zero(_) + | Instruction::V128Load64Zero(_) + | Instruction::V128Store(_) => ValType::V128, _ => panic!("not a memory access instruction"), } diff --git a/crates/wasm-smith/src/lib.rs b/crates/wasm-smith/src/lib.rs index 95a3ebd346..22cc50b5eb 100644 --- a/crates/wasm-smith/src/lib.rs +++ b/crates/wasm-smith/src/lib.rs @@ -11,11 +11,8 @@ //! //! Next, add `wasm-smith` to your dependencies: //! -//! ```toml -//! # fuzz/Cargo.toml -//! -//! [dependencies] -//! wasm-smith = "0.4.0" +//! ```shell +//! $ cargo add wasm-smith //! ``` //! //! Then, define your fuzz target so that it takes arbitrary @@ -68,8 +65,7 @@ pub use crate::core::{ use arbitrary::{Result, Unstructured}; pub use component::{Component, ConfiguredComponent}; pub use config::{Config, DefaultConfig, SwarmConfig}; - -use std::{collections::HashSet, str}; +use std::{collections::HashSet, fmt::Write, str}; /// Do something an arbitrary number of times. /// @@ -132,7 +128,7 @@ pub(crate) fn unique_string( ) -> Result { let mut name = limited_string(max_size, u)?; while names.contains(&name) { - name.push_str(&format!("{}", names.len())); + write!(&mut name, "{}", names.len()).unwrap(); } names.insert(name.clone()); Ok(name) @@ -145,7 +141,6 @@ pub(crate) fn unique_non_empty_string( ) -> Result { let mut s = unique_string(max_size, names, u)?; while s.is_empty() || names.contains(&s) { - use std::fmt::Write; write!(&mut s, "{}", names.len()).unwrap(); } names.insert(s.clone()); diff --git a/crates/wasmparser/Cargo.toml b/crates/wasmparser/Cargo.toml index 661fd8161f..b566162528 100644 --- a/crates/wasmparser/Cargo.toml +++ b/crates/wasmparser/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "wasmparser" -version = "0.90.0" +version = "0.92.0" authors = ["Yury Delendik "] license = "Apache-2.0 WITH LLVM-exception" repository = "https://github.com/bytecodealliance/wasm-tools/tree/main/crates/wasmparser" @@ -9,19 +9,18 @@ keywords = ["parser", "WebAssembly", "wasm"] description = """ A simple event-driven library for parsing WebAssembly binary files. """ -edition = "2021" +edition.workspace = true exclude = ["benches/*.wasm"] [dependencies] -indexmap = "1.8.0" +indexmap = { workspace = true } [dev-dependencies] -anyhow = "1.0" -criterion = "0.3" -getopts = "0.2" +anyhow = { workspace = true } +criterion = { workspace = true } wat = { path = "../wat" } wast = { path = "../wast" } -rayon = "1.3" +rayon = { workspace = true } wasmparser-dump = { path = "../dump" } once_cell = "1.13.0" diff --git a/crates/wasmparser/benches/benchmark.rs b/crates/wasmparser/benches/benchmark.rs index 86178d3125..8a2392422a 100644 --- a/crates/wasmparser/benches/benchmark.rs +++ b/crates/wasmparser/benches/benchmark.rs @@ -1,16 +1,10 @@ -#[macro_use] -extern crate criterion; - use anyhow::Result; -use criterion::Criterion; +use criterion::{criterion_group, criterion_main, Criterion}; use once_cell::unsync::Lazy; use std::fs; use std::path::Path; use std::path::PathBuf; -use wasmparser::{ - BlockType, BrTable, DataKind, ElementKind, HeapType, Ieee32, Ieee64, MemArg, Parser, Payload, - ValType, Validator, VisitOperator, WasmFeatures, V128, -}; +use wasmparser::{DataKind, ElementKind, HeapType, Parser, Payload, ValType, Validator, VisitOperator, WasmFeatures}; /// A benchmark input. pub struct BenchmarkInput { diff --git a/crates/wasmparser/src/binary_reader.rs b/crates/wasmparser/src/binary_reader.rs index da40ca01e7..4333e48389 100644 --- a/crates/wasmparser/src/binary_reader.rs +++ b/crates/wasmparser/src/binary_reader.rs @@ -142,6 +142,7 @@ impl<'a> BinaryReader<'a> { } /// Gets the original position of the binary reader. + #[inline] pub fn original_position(&self) -> usize { self.original_offset + self.position } @@ -324,8 +325,7 @@ impl<'a> BinaryReader<'a> { 0x40 => ComponentType::Func(ComponentFuncType { params: self .read_type_vec(MAX_WASM_FUNCTION_PARAMS, "component function parameters")?, - results: self - .read_type_vec(MAX_WASM_FUNCTION_RETURNS, "component function results")?, + results: self.read_component_func_result()?, }), 0x41 => { let size = @@ -355,21 +355,27 @@ impl<'a> BinaryReader<'a> { }) } - pub(crate) fn read_type_vec(&mut self, max: usize, desc: &str) -> Result> { + pub(crate) fn read_component_func_result(&mut self) -> Result> { Ok(match self.read_u8()? { - 0x00 => TypeVec::Unnamed(self.read_component_val_type()?), - 0x01 => { - let size = self.read_size(max, desc)?; - TypeVec::Named( - (0..size) - .map(|_| Ok((self.read_string()?, self.read_component_val_type()?))) - .collect::>()?, - ) - } - x => return self.invalid_leading_byte(x, desc), + 0x00 => ComponentFuncResult::Unnamed(self.read_component_val_type()?), + 0x01 => ComponentFuncResult::Named( + self.read_type_vec(MAX_WASM_FUNCTION_RETURNS, "component function results")?, + ), + x => return self.invalid_leading_byte(x, "component function results"), }) } + pub(crate) fn read_type_vec( + &mut self, + max: usize, + desc: &str, + ) -> Result> { + let size = self.read_size(max, desc)?; + (0..size) + .map(|_| Ok((self.read_string()?, self.read_component_val_type()?))) + .collect::>() + } + pub(crate) fn read_module_type_decl(&mut self) -> Result> { Ok(match self.read_u8()? { 0x00 => ModuleTypeDeclaration::Import(self.read_import()?), @@ -857,7 +863,7 @@ impl<'a> BinaryReader<'a> { fn read_size(&mut self, limit: usize, desc: &str) -> Result { let size = self.read_var_u32()? as usize; if size > limit { - bail!(self.original_position() - 4, "{desc} size is out of bounds",); + bail!(self.original_position() - 4, "{desc} size is out of bounds"); } Ok(size) } @@ -946,16 +952,19 @@ impl<'a> BinaryReader<'a> { } /// Returns whether the `BinaryReader` has reached the end of the file. + #[inline] pub fn eof(&self) -> bool { self.position >= self.buffer.len() } /// Returns the `BinaryReader`'s current position. + #[inline] pub fn current_position(&self) -> usize { self.position } /// Returns the number of bytes remaining in the `BinaryReader`. + #[inline] pub fn bytes_remaining(&self) -> usize { self.buffer.len() - self.position } @@ -1945,12 +1954,9 @@ impl<'a> BinaryReader<'a> { 0x9e => visitor.visit_i16x8_extmul_low_i8x16_u(pos), 0x9f => visitor.visit_i16x8_extmul_high_i8x16_u(pos), 0xa0 => visitor.visit_i32x4_abs(pos), - 0xa2 => visitor.visit_i8x16_relaxed_swizzle(pos), 0xa1 => visitor.visit_i32x4_neg(pos), 0xa3 => visitor.visit_i32x4_all_true(pos), 0xa4 => visitor.visit_i32x4_bitmask(pos), - 0xa5 => visitor.visit_i32x4_relaxed_trunc_sat_f32x4_s(pos), - 0xa6 => visitor.visit_i32x4_relaxed_trunc_sat_f32x4_u(pos), 0xa7 => visitor.visit_i32x4_extend_low_i16x8_s(pos), 0xa8 => visitor.visit_i32x4_extend_high_i16x8_s(pos), 0xa9 => visitor.visit_i32x4_extend_low_i16x8_u(pos), @@ -1959,12 +1965,7 @@ impl<'a> BinaryReader<'a> { 0xac => visitor.visit_i32x4_shr_s(pos), 0xad => visitor.visit_i32x4_shr_u(pos), 0xae => visitor.visit_i32x4_add(pos), - 0xaf => visitor.visit_f32x4_fma(pos), - 0xb0 => visitor.visit_f32x4_fms(pos), 0xb1 => visitor.visit_i32x4_sub(pos), - 0xb2 => visitor.visit_i8x16_laneselect(pos), - 0xb3 => visitor.visit_i16x8_laneselect(pos), - 0xb4 => visitor.visit_f32x4_relaxed_min(pos), 0xb5 => visitor.visit_i32x4_mul(pos), 0xb6 => visitor.visit_i32x4_min_s(pos), 0xb7 => visitor.visit_i32x4_min_u(pos), @@ -1979,8 +1980,6 @@ impl<'a> BinaryReader<'a> { 0xc1 => visitor.visit_i64x2_neg(pos), 0xc3 => visitor.visit_i64x2_all_true(pos), 0xc4 => visitor.visit_i64x2_bitmask(pos), - 0xc5 => visitor.visit_i32x4_relaxed_trunc_sat_f64x2_s_zero(pos), - 0xc6 => visitor.visit_i32x4_relaxed_trunc_sat_f64x2_u_zero(pos), 0xc7 => visitor.visit_i64x2_extend_low_i32x4_s(pos), 0xc8 => visitor.visit_i64x2_extend_high_i32x4_s(pos), 0xc9 => visitor.visit_i64x2_extend_low_i32x4_u(pos), @@ -1989,12 +1988,7 @@ impl<'a> BinaryReader<'a> { 0xcc => visitor.visit_i64x2_shr_s(pos), 0xcd => visitor.visit_i64x2_shr_u(pos), 0xce => visitor.visit_i64x2_add(pos), - 0xcf => visitor.visit_f64x2_fma(pos), - 0xd0 => visitor.visit_f64x2_fms(pos), 0xd1 => visitor.visit_i64x2_sub(pos), - 0xd2 => visitor.visit_i32x4_laneselect(pos), - 0xd3 => visitor.visit_i64x2_laneselect(pos), - 0xd4 => visitor.visit_f64x2_relaxed_min(pos), 0xd5 => visitor.visit_i64x2_mul(pos), 0xd6 => visitor.visit_i64x2_eq(pos), 0xd7 => visitor.visit_i64x2_ne(pos), @@ -2008,7 +2002,6 @@ impl<'a> BinaryReader<'a> { 0xdf => visitor.visit_i64x2_extmul_high_i32x4_u(pos), 0xe0 => visitor.visit_f32x4_abs(pos), 0xe1 => visitor.visit_f32x4_neg(pos), - 0xe2 => visitor.visit_f32x4_relaxed_max(pos), 0xe3 => visitor.visit_f32x4_sqrt(pos), 0xe4 => visitor.visit_f32x4_add(pos), 0xe5 => visitor.visit_f32x4_sub(pos), @@ -2020,7 +2013,6 @@ impl<'a> BinaryReader<'a> { 0xeb => visitor.visit_f32x4_pmax(pos), 0xec => visitor.visit_f64x2_abs(pos), 0xed => visitor.visit_f64x2_neg(pos), - 0xee => visitor.visit_f64x2_relaxed_max(pos), 0xef => visitor.visit_f64x2_sqrt(pos), 0xf0 => visitor.visit_f64x2_add(pos), 0xf1 => visitor.visit_f64x2_sub(pos), @@ -2038,6 +2030,27 @@ impl<'a> BinaryReader<'a> { 0xfd => visitor.visit_i32x4_trunc_sat_f64x2_u_zero(pos), 0xfe => visitor.visit_f64x2_convert_low_i32x4_s(pos), 0xff => visitor.visit_f64x2_convert_low_i32x4_u(pos), + 0x100 => visitor.visit_i8x16_relaxed_swizzle(pos), + 0x101 => visitor.visit_i32x4_relaxed_trunc_sat_f32x4_s(pos), + 0x102 => visitor.visit_i32x4_relaxed_trunc_sat_f32x4_u(pos), + 0x103 => visitor.visit_i32x4_relaxed_trunc_sat_f64x2_s_zero(pos), + 0x104 => visitor.visit_i32x4_relaxed_trunc_sat_f64x2_u_zero(pos), + 0x105 => visitor.visit_f32x4_relaxed_fma(pos), + 0x106 => visitor.visit_f32x4_relaxed_fnma(pos), + 0x107 => visitor.visit_f64x2_relaxed_fma(pos), + 0x108 => visitor.visit_f64x2_relaxed_fnma(pos), + 0x109 => visitor.visit_i8x16_relaxed_laneselect(pos), + 0x10a => visitor.visit_i16x8_relaxed_laneselect(pos), + 0x10b => visitor.visit_i32x4_relaxed_laneselect(pos), + 0x10c => visitor.visit_i64x2_relaxed_laneselect(pos), + 0x10d => visitor.visit_f32x4_relaxed_min(pos), + 0x10e => visitor.visit_f32x4_relaxed_max(pos), + 0x10f => visitor.visit_f64x2_relaxed_min(pos), + 0x110 => visitor.visit_f64x2_relaxed_max(pos), + 0x111 => visitor.visit_i16x8_relaxed_q15mulr_s(pos), + 0x112 => visitor.visit_i16x8_dot_i8x16_i7x16_s(pos), + 0x113 => visitor.visit_i32x4_dot_i8x16_i7x16_add_s(pos), + 0x114 => visitor.visit_f32x4_relaxed_dot_bf16x8_add_f32x4(pos), _ => bail!(pos, "unknown 0xfd subopcode: 0x{code:x}"), }) @@ -2056,7 +2069,12 @@ impl<'a> BinaryReader<'a> { 0x00 => visitor.visit_memory_atomic_notify(pos, self.read_memarg_of_align(2)?), 0x01 => visitor.visit_memory_atomic_wait32(pos, self.read_memarg_of_align(2)?), 0x02 => visitor.visit_memory_atomic_wait64(pos, self.read_memarg_of_align(3)?), - 0x03 => visitor.visit_atomic_fence(pos, self.read_u8()? as u8), + 0x03 => { + if self.read_u8()? != 0 { + bail!(pos, "nonzero byte after `atomic.fence`"); + } + visitor.visit_atomic_fence(pos) + } 0x10 => visitor.visit_i32_atomic_load(pos, self.read_memarg_of_align(2)?), 0x11 => visitor.visit_i64_atomic_load(pos, self.read_memarg_of_align(3)?), 0x12 => visitor.visit_i32_atomic_load8_u(pos, self.read_memarg_of_align(0)?), @@ -2258,8 +2276,8 @@ impl<'a> BrTable<'a> { /// let buf = [0x0e, 0x02, 0x01, 0x02, 0x00]; /// let mut reader = wasmparser::BinaryReader::new(&buf); /// let op = reader.read_operator().unwrap(); - /// if let wasmparser::Operator::BrTable { table } = op { - /// let targets = table.targets().collect::, _>>().unwrap(); + /// if let wasmparser::Operator::BrTable { targets } = op { + /// let targets = targets.targets().collect::, _>>().unwrap(); /// assert_eq!(targets, [1, 2]); /// } /// ``` diff --git a/crates/wasmparser/src/lib.rs b/crates/wasmparser/src/lib.rs index aa59c1f4f9..186a205c8c 100644 --- a/crates/wasmparser/src/lib.rs +++ b/crates/wasmparser/src/lib.rs @@ -41,10 +41,10 @@ /// /// - `@mvp`: Denoting a Wasm operator from the initial Wasm MVP version. /// - `@exceptions`: [Wasm `expection-handling` proposal] -/// - `@tail_calls`: [Wasm `tail-calls` proposal] +/// - `@tail_call`: [Wasm `tail-calls` proposal] /// - `@reference_types`: [Wasm `reference-types` proposal] -/// - `@sign_ext_ops`: [Wasm `sign-extension-ops` proposal] -/// - `@non_trapping_f2i_conversions`: [Wasm `non_trapping_float-to-int-conversions` proposal] +/// - `@sign_extension`: [Wasm `sign-extension-ops` proposal] +/// - `@saturating_float_to_int`: [Wasm `non_trapping_float-to-int-conversions` proposal] /// - `@bulk_memory `:[Wasm `bulk-memory` proposal] /// - `@threads`: [Wasm `threads` proposal] /// - `@simd`: [Wasm `simd` proposal] @@ -78,10 +78,6 @@ /// https://github.com/WebAssembly/relaxed-simd /// /// ``` -/// // These names are referred to by the types of each payload and must -/// // be imported into the module using the `for_each_operator!` macro. -/// use wasmparser::{HeapType, V128, MemArg, BlockType, ValType, BrTable, Ieee32, Ieee64}; -/// /// macro_rules! define_visit_operator { /// // The outer layer of repetition represents how all operators are /// // provided to the macro at the same time. @@ -122,63 +118,63 @@ macro_rules! for_each_operator { $mac! { @mvp Unreachable => visit_unreachable @mvp Nop => visit_nop - @mvp Block { ty: BlockType } => visit_block - @mvp Loop { ty: BlockType } => visit_loop - @mvp If { ty: BlockType } => visit_if + @mvp Block { blockty: $crate::BlockType } => visit_block + @mvp Loop { blockty: $crate::BlockType } => visit_loop + @mvp If { blockty: $crate::BlockType } => visit_if @mvp Else => visit_else - @expections Try { ty: BlockType } => visit_try - @expections Catch { index: u32 } => visit_catch - @expections Throw { index: u32 } => visit_throw - @expections Rethrow { relative_depth: u32 } => visit_rethrow + @exceptions Try { blockty: $crate::BlockType } => visit_try + @exceptions Catch { tag_index: u32 } => visit_catch + @exceptions Throw { tag_index: u32 } => visit_throw + @exceptions Rethrow { relative_depth: u32 } => visit_rethrow @mvp End => visit_end @mvp Br { relative_depth: u32 } => visit_br @mvp BrIf { relative_depth: u32 } => visit_br_if - @mvp BrTable { table: BrTable<'a> } => visit_br_table + @mvp BrTable { targets: $crate::BrTable<'a> } => visit_br_table @mvp Return => visit_return @mvp Call { function_index: u32 } => visit_call - @mvp CallIndirect { index: u32, table_index: u32, table_byte: u8 } => visit_call_indirect - @tail_calls ReturnCall { function_index: u32 } => visit_return_call - @tail_calls ReturnCallIndirect { index: u32, table_index: u32 } => visit_return_call_indirect - @expections Delegate { relative_depth: u32 } => visit_delegate - @expections CatchAll => visit_catch_all + @mvp CallIndirect { type_index: u32, table_index: u32, table_byte: u8 } => visit_call_indirect + @tail_call ReturnCall { function_index: u32 } => visit_return_call + @tail_call ReturnCallIndirect { type_index: u32, table_index: u32 } => visit_return_call_indirect + @exceptions Delegate { relative_depth: u32 } => visit_delegate + @exceptions CatchAll => visit_catch_all @mvp Drop => visit_drop @mvp Select => visit_select - @reference_types TypedSelect { ty: ValType } => visit_typed_select + @reference_types TypedSelect { ty: $crate::ValType } => visit_typed_select @mvp LocalGet { local_index: u32 } => visit_local_get @mvp LocalSet { local_index: u32 } => visit_local_set @mvp LocalTee { local_index: u32 } => visit_local_tee @mvp GlobalGet { global_index: u32 } => visit_global_get @mvp GlobalSet { global_index: u32 } => visit_global_set - @mvp I32Load { memarg: MemArg } => visit_i32_load - @mvp I64Load { memarg: MemArg } => visit_i64_load - @mvp F32Load { memarg: MemArg } => visit_f32_load - @mvp F64Load { memarg: MemArg } => visit_f64_load - @mvp I32Load8S { memarg: MemArg } => visit_i32_load8_s - @mvp I32Load8U { memarg: MemArg } => visit_i32_load8_u - @mvp I32Load16S { memarg: MemArg } => visit_i32_load16_s - @mvp I32Load16U { memarg: MemArg } => visit_i32_load16_u - @mvp I64Load8S { memarg: MemArg } => visit_i64_load8_s - @mvp I64Load8U { memarg: MemArg } => visit_i64_load8_u - @mvp I64Load16S { memarg: MemArg } => visit_i64_load16_s - @mvp I64Load16U { memarg: MemArg } => visit_i64_load16_u - @mvp I64Load32S { memarg: MemArg } => visit_i64_load32_s - @mvp I64Load32U { memarg: MemArg } => visit_i64_load32_u - @mvp I32Store { memarg: MemArg } => visit_i32_store - @mvp I64Store { memarg: MemArg } => visit_i64_store - @mvp F32Store { memarg: MemArg } => visit_f32_store - @mvp F64Store { memarg: MemArg } => visit_f64_store - @mvp I32Store8 { memarg: MemArg } => visit_i32_store8 - @mvp I32Store16 { memarg: MemArg } => visit_i32_store16 - @mvp I64Store8 { memarg: MemArg } => visit_i64_store8 - @mvp I64Store16 { memarg: MemArg } => visit_i64_store16 - @mvp I64Store32 { memarg: MemArg } => visit_i64_store32 + @mvp I32Load { memarg: $crate::MemArg } => visit_i32_load + @mvp I64Load { memarg: $crate::MemArg } => visit_i64_load + @mvp F32Load { memarg: $crate::MemArg } => visit_f32_load + @mvp F64Load { memarg: $crate::MemArg } => visit_f64_load + @mvp I32Load8S { memarg: $crate::MemArg } => visit_i32_load8_s + @mvp I32Load8U { memarg: $crate::MemArg } => visit_i32_load8_u + @mvp I32Load16S { memarg: $crate::MemArg } => visit_i32_load16_s + @mvp I32Load16U { memarg: $crate::MemArg } => visit_i32_load16_u + @mvp I64Load8S { memarg: $crate::MemArg } => visit_i64_load8_s + @mvp I64Load8U { memarg: $crate::MemArg } => visit_i64_load8_u + @mvp I64Load16S { memarg: $crate::MemArg } => visit_i64_load16_s + @mvp I64Load16U { memarg: $crate::MemArg } => visit_i64_load16_u + @mvp I64Load32S { memarg: $crate::MemArg } => visit_i64_load32_s + @mvp I64Load32U { memarg: $crate::MemArg } => visit_i64_load32_u + @mvp I32Store { memarg: $crate::MemArg } => visit_i32_store + @mvp I64Store { memarg: $crate::MemArg } => visit_i64_store + @mvp F32Store { memarg: $crate::MemArg } => visit_f32_store + @mvp F64Store { memarg: $crate::MemArg } => visit_f64_store + @mvp I32Store8 { memarg: $crate::MemArg } => visit_i32_store8 + @mvp I32Store16 { memarg: $crate::MemArg } => visit_i32_store16 + @mvp I64Store8 { memarg: $crate::MemArg } => visit_i64_store8 + @mvp I64Store16 { memarg: $crate::MemArg } => visit_i64_store16 + @mvp I64Store32 { memarg: $crate::MemArg } => visit_i64_store32 @mvp MemorySize { mem: u32, mem_byte: u8 } => visit_memory_size @mvp MemoryGrow { mem: u32, mem_byte: u8 } => visit_memory_grow @mvp I32Const { value: i32 } => visit_i32_const @mvp I64Const { value: i64 } => visit_i64_const - @mvp F32Const { value: Ieee32 } => visit_f32_const - @mvp F64Const { value: Ieee64 } => visit_f64_const - @reference_types RefNull { ty: HeapType } => visit_ref_null + @mvp F32Const { value: $crate::Ieee32 } => visit_f32_const + @mvp F64Const { value: $crate::Ieee64 } => visit_f64_const + @reference_types RefNull { hty: $crate::HeapType } => visit_ref_null @reference_types RefIsNull => visit_ref_is_null @reference_types RefFunc { function_index: u32 } => visit_ref_func @mvp I32Eqz => visit_i32_eqz @@ -304,133 +300,142 @@ macro_rules! for_each_operator { @mvp I64ReinterpretF64 => visit_i64_reinterpret_f64 @mvp F32ReinterpretI32 => visit_f32_reinterpret_i32 @mvp F64ReinterpretI64 => visit_f64_reinterpret_i64 - @sign_ext_ops I32Extend8S => visit_i32_extend8_s - @sign_ext_ops I32Extend16S => visit_i32_extend16_s - @sign_ext_ops I64Extend8S => visit_i64_extend8_s - @sign_ext_ops I64Extend16S => visit_i64_extend16_s - @sign_ext_ops I64Extend32S => visit_i64_extend32_s + @sign_extension I32Extend8S => visit_i32_extend8_s + @sign_extension I32Extend16S => visit_i32_extend16_s + @sign_extension I64Extend8S => visit_i64_extend8_s + @sign_extension I64Extend16S => visit_i64_extend16_s + @sign_extension I64Extend32S => visit_i64_extend32_s // 0xFC operators // Non-trapping Float-to-int Conversions - @non_trapping_f2i_conversions I32TruncSatF32S => visit_i32_trunc_sat_f32_s - @non_trapping_f2i_conversions I32TruncSatF32U => visit_i32_trunc_sat_f32_u - @non_trapping_f2i_conversions I32TruncSatF64S => visit_i32_trunc_sat_f64_s - @non_trapping_f2i_conversions I32TruncSatF64U => visit_i32_trunc_sat_f64_u - @non_trapping_f2i_conversions I64TruncSatF32S => visit_i64_trunc_sat_f32_s - @non_trapping_f2i_conversions I64TruncSatF32U => visit_i64_trunc_sat_f32_u - @non_trapping_f2i_conversions I64TruncSatF64S => visit_i64_trunc_sat_f64_s - @non_trapping_f2i_conversions I64TruncSatF64U => visit_i64_trunc_sat_f64_u + // https://github.com/WebAssembly/nontrapping-float-to-int-conversions + @saturating_float_to_int I32TruncSatF32S => visit_i32_trunc_sat_f32_s + @saturating_float_to_int I32TruncSatF32U => visit_i32_trunc_sat_f32_u + @saturating_float_to_int I32TruncSatF64S => visit_i32_trunc_sat_f64_s + @saturating_float_to_int I32TruncSatF64U => visit_i32_trunc_sat_f64_u + @saturating_float_to_int I64TruncSatF32S => visit_i64_trunc_sat_f32_s + @saturating_float_to_int I64TruncSatF32U => visit_i64_trunc_sat_f32_u + @saturating_float_to_int I64TruncSatF64S => visit_i64_trunc_sat_f64_s + @saturating_float_to_int I64TruncSatF64U => visit_i64_trunc_sat_f64_u - // 0xFC operators - // bulk memory https://github.com/WebAssembly/bulk-memory-operations/blob/master/proposals/bulk-memory-operations/Overview.md - @bulk_memory MemoryInit { segment: u32, mem: u32 } => visit_memory_init - @bulk_memory DataDrop { segment: u32 } => visit_data_drop - @bulk_memory MemoryCopy { dst: u32, src: u32 } => visit_memory_copy + // 0xFC prefixed operators + // bulk memory operations + // https://github.com/WebAssembly/bulk-memory-operations + @bulk_memory MemoryInit { data_index: u32, mem: u32 } => visit_memory_init + @bulk_memory DataDrop { data_index: u32 } => visit_data_drop + @bulk_memory MemoryCopy { dst_mem: u32, src_mem: u32 } => visit_memory_copy @bulk_memory MemoryFill { mem: u32 } => visit_memory_fill - @bulk_memory TableInit { segment: u32, table: u32 } => visit_table_init - @bulk_memory ElemDrop { segment: u32 } => visit_elem_drop + @bulk_memory TableInit { elem_index: u32, table: u32 } => visit_table_init + @bulk_memory ElemDrop { elem_index: u32 } => visit_elem_drop @bulk_memory TableCopy { dst_table: u32, src_table: u32 } => visit_table_copy - @bulk_memory TableFill { table: u32 } => visit_table_fill - @bulk_memory TableGet { table: u32 } => visit_table_get - @bulk_memory TableSet { table: u32 } => visit_table_set - @bulk_memory TableGrow { table: u32 } => visit_table_grow - @bulk_memory TableSize { table: u32 } => visit_table_size - // 0xFE operators - // https://github.com/WebAssembly/threads/blob/master/proposals/threads/Overview.md - @threads MemoryAtomicNotify { memarg: MemArg } => visit_memory_atomic_notify - @threads MemoryAtomicWait32 { memarg: MemArg } => visit_memory_atomic_wait32 - @threads MemoryAtomicWait64 { memarg: MemArg } => visit_memory_atomic_wait64 - @threads AtomicFence { flags: u8 } => visit_atomic_fence - @threads I32AtomicLoad { memarg: MemArg } => visit_i32_atomic_load - @threads I64AtomicLoad { memarg: MemArg } => visit_i64_atomic_load - @threads I32AtomicLoad8U { memarg: MemArg } => visit_i32_atomic_load8_u - @threads I32AtomicLoad16U { memarg: MemArg } => visit_i32_atomic_load16_u - @threads I64AtomicLoad8U { memarg: MemArg } => visit_i64_atomic_load8_u - @threads I64AtomicLoad16U { memarg: MemArg } => visit_i64_atomic_load16_u - @threads I64AtomicLoad32U { memarg: MemArg } => visit_i64_atomic_load32_u - @threads I32AtomicStore { memarg: MemArg } => visit_i32_atomic_store - @threads I64AtomicStore { memarg: MemArg } => visit_i64_atomic_store - @threads I32AtomicStore8 { memarg: MemArg } => visit_i32_atomic_store8 - @threads I32AtomicStore16 { memarg: MemArg } => visit_i32_atomic_store16 - @threads I64AtomicStore8 { memarg: MemArg } => visit_i64_atomic_store8 - @threads I64AtomicStore16 { memarg: MemArg } => visit_i64_atomic_store16 - @threads I64AtomicStore32 { memarg: MemArg } => visit_i64_atomic_store32 - @threads I32AtomicRmwAdd { memarg: MemArg } => visit_i32_atomic_rmw_add - @threads I64AtomicRmwAdd { memarg: MemArg } => visit_i64_atomic_rmw_add - @threads I32AtomicRmw8AddU { memarg: MemArg } => visit_i32_atomic_rmw8_add_u - @threads I32AtomicRmw16AddU { memarg: MemArg } => visit_i32_atomic_rmw16_add_u - @threads I64AtomicRmw8AddU { memarg: MemArg } => visit_i64_atomic_rmw8_add_u - @threads I64AtomicRmw16AddU { memarg: MemArg } => visit_i64_atomic_rmw16_add_u - @threads I64AtomicRmw32AddU { memarg: MemArg } => visit_i64_atomic_rmw32_add_u - @threads I32AtomicRmwSub { memarg: MemArg } => visit_i32_atomic_rmw_sub - @threads I64AtomicRmwSub { memarg: MemArg } => visit_i64_atomic_rmw_sub - @threads I32AtomicRmw8SubU { memarg: MemArg } => visit_i32_atomic_rmw8_sub_u - @threads I32AtomicRmw16SubU { memarg: MemArg } => visit_i32_atomic_rmw16_sub_u - @threads I64AtomicRmw8SubU { memarg: MemArg } => visit_i64_atomic_rmw8_sub_u - @threads I64AtomicRmw16SubU { memarg: MemArg } => visit_i64_atomic_rmw16_sub_u - @threads I64AtomicRmw32SubU { memarg: MemArg } => visit_i64_atomic_rmw32_sub_u - @threads I32AtomicRmwAnd { memarg: MemArg } => visit_i32_atomic_rmw_and - @threads I64AtomicRmwAnd { memarg: MemArg } => visit_i64_atomic_rmw_and - @threads I32AtomicRmw8AndU { memarg: MemArg } => visit_i32_atomic_rmw8_and_u - @threads I32AtomicRmw16AndU { memarg: MemArg } => visit_i32_atomic_rmw16_and_u - @threads I64AtomicRmw8AndU { memarg: MemArg } => visit_i64_atomic_rmw8_and_u - @threads I64AtomicRmw16AndU { memarg: MemArg } => visit_i64_atomic_rmw16_and_u - @threads I64AtomicRmw32AndU { memarg: MemArg } => visit_i64_atomic_rmw32_and_u - @threads I32AtomicRmwOr { memarg: MemArg } => visit_i32_atomic_rmw_or - @threads I64AtomicRmwOr { memarg: MemArg } => visit_i64_atomic_rmw_or - @threads I32AtomicRmw8OrU { memarg: MemArg } => visit_i32_atomic_rmw8_or_u - @threads I32AtomicRmw16OrU { memarg: MemArg } => visit_i32_atomic_rmw16_or_u - @threads I64AtomicRmw8OrU { memarg: MemArg } => visit_i64_atomic_rmw8_or_u - @threads I64AtomicRmw16OrU { memarg: MemArg } => visit_i64_atomic_rmw16_or_u - @threads I64AtomicRmw32OrU { memarg: MemArg } => visit_i64_atomic_rmw32_or_u - @threads I32AtomicRmwXor { memarg: MemArg } => visit_i32_atomic_rmw_xor - @threads I64AtomicRmwXor { memarg: MemArg } => visit_i64_atomic_rmw_xor - @threads I32AtomicRmw8XorU { memarg: MemArg } => visit_i32_atomic_rmw8_xor_u - @threads I32AtomicRmw16XorU { memarg: MemArg } => visit_i32_atomic_rmw16_xor_u - @threads I64AtomicRmw8XorU { memarg: MemArg } => visit_i64_atomic_rmw8_xor_u - @threads I64AtomicRmw16XorU { memarg: MemArg } => visit_i64_atomic_rmw16_xor_u - @threads I64AtomicRmw32XorU { memarg: MemArg } => visit_i64_atomic_rmw32_xor_u - @threads I32AtomicRmwXchg { memarg: MemArg } => visit_i32_atomic_rmw_xchg - @threads I64AtomicRmwXchg { memarg: MemArg } => visit_i64_atomic_rmw_xchg - @threads I32AtomicRmw8XchgU { memarg: MemArg } => visit_i32_atomic_rmw8_xchg_u - @threads I32AtomicRmw16XchgU { memarg: MemArg } => visit_i32_atomic_rmw16_xchg_u - @threads I64AtomicRmw8XchgU { memarg: MemArg } => visit_i64_atomic_rmw8_xchg_u - @threads I64AtomicRmw16XchgU { memarg: MemArg } => visit_i64_atomic_rmw16_xchg_u - @threads I64AtomicRmw32XchgU { memarg: MemArg } => visit_i64_atomic_rmw32_xchg_u - @threads I32AtomicRmwCmpxchg { memarg: MemArg } => visit_i32_atomic_rmw_cmpxchg - @threads I64AtomicRmwCmpxchg { memarg: MemArg } => visit_i64_atomic_rmw_cmpxchg - @threads I32AtomicRmw8CmpxchgU { memarg: MemArg } => visit_i32_atomic_rmw8_cmpxchg_u - @threads I32AtomicRmw16CmpxchgU { memarg: MemArg } => visit_i32_atomic_rmw16_cmpxchg_u - @threads I64AtomicRmw8CmpxchgU { memarg: MemArg } => visit_i64_atomic_rmw8_cmpxchg_u - @threads I64AtomicRmw16CmpxchgU { memarg: MemArg } => visit_i64_atomic_rmw16_cmpxchg_u - @threads I64AtomicRmw32CmpxchgU { memarg: MemArg } => visit_i64_atomic_rmw32_cmpxchg_u + // 0xFC prefixed operators + // reference-types + // https://github.com/WebAssembly/reference-types + @reference_types TableFill { table: u32 } => visit_table_fill + @reference_types TableGet { table: u32 } => visit_table_get + @reference_types TableSet { table: u32 } => visit_table_set + @reference_types TableGrow { table: u32 } => visit_table_grow + @reference_types TableSize { table: u32 } => visit_table_size + + // 0xFE prefixed operators + // threads + // https://github.com/WebAssembly/threads + @threads MemoryAtomicNotify { memarg: $crate::MemArg } => visit_memory_atomic_notify + @threads MemoryAtomicWait32 { memarg: $crate::MemArg } => visit_memory_atomic_wait32 + @threads MemoryAtomicWait64 { memarg: $crate::MemArg } => visit_memory_atomic_wait64 + @threads AtomicFence => visit_atomic_fence + @threads I32AtomicLoad { memarg: $crate::MemArg } => visit_i32_atomic_load + @threads I64AtomicLoad { memarg: $crate::MemArg } => visit_i64_atomic_load + @threads I32AtomicLoad8U { memarg: $crate::MemArg } => visit_i32_atomic_load8_u + @threads I32AtomicLoad16U { memarg: $crate::MemArg } => visit_i32_atomic_load16_u + @threads I64AtomicLoad8U { memarg: $crate::MemArg } => visit_i64_atomic_load8_u + @threads I64AtomicLoad16U { memarg: $crate::MemArg } => visit_i64_atomic_load16_u + @threads I64AtomicLoad32U { memarg: $crate::MemArg } => visit_i64_atomic_load32_u + @threads I32AtomicStore { memarg: $crate::MemArg } => visit_i32_atomic_store + @threads I64AtomicStore { memarg: $crate::MemArg } => visit_i64_atomic_store + @threads I32AtomicStore8 { memarg: $crate::MemArg } => visit_i32_atomic_store8 + @threads I32AtomicStore16 { memarg: $crate::MemArg } => visit_i32_atomic_store16 + @threads I64AtomicStore8 { memarg: $crate::MemArg } => visit_i64_atomic_store8 + @threads I64AtomicStore16 { memarg: $crate::MemArg } => visit_i64_atomic_store16 + @threads I64AtomicStore32 { memarg: $crate::MemArg } => visit_i64_atomic_store32 + @threads I32AtomicRmwAdd { memarg: $crate::MemArg } => visit_i32_atomic_rmw_add + @threads I64AtomicRmwAdd { memarg: $crate::MemArg } => visit_i64_atomic_rmw_add + @threads I32AtomicRmw8AddU { memarg: $crate::MemArg } => visit_i32_atomic_rmw8_add_u + @threads I32AtomicRmw16AddU { memarg: $crate::MemArg } => visit_i32_atomic_rmw16_add_u + @threads I64AtomicRmw8AddU { memarg: $crate::MemArg } => visit_i64_atomic_rmw8_add_u + @threads I64AtomicRmw16AddU { memarg: $crate::MemArg } => visit_i64_atomic_rmw16_add_u + @threads I64AtomicRmw32AddU { memarg: $crate::MemArg } => visit_i64_atomic_rmw32_add_u + @threads I32AtomicRmwSub { memarg: $crate::MemArg } => visit_i32_atomic_rmw_sub + @threads I64AtomicRmwSub { memarg: $crate::MemArg } => visit_i64_atomic_rmw_sub + @threads I32AtomicRmw8SubU { memarg: $crate::MemArg } => visit_i32_atomic_rmw8_sub_u + @threads I32AtomicRmw16SubU { memarg: $crate::MemArg } => visit_i32_atomic_rmw16_sub_u + @threads I64AtomicRmw8SubU { memarg: $crate::MemArg } => visit_i64_atomic_rmw8_sub_u + @threads I64AtomicRmw16SubU { memarg: $crate::MemArg } => visit_i64_atomic_rmw16_sub_u + @threads I64AtomicRmw32SubU { memarg: $crate::MemArg } => visit_i64_atomic_rmw32_sub_u + @threads I32AtomicRmwAnd { memarg: $crate::MemArg } => visit_i32_atomic_rmw_and + @threads I64AtomicRmwAnd { memarg: $crate::MemArg } => visit_i64_atomic_rmw_and + @threads I32AtomicRmw8AndU { memarg: $crate::MemArg } => visit_i32_atomic_rmw8_and_u + @threads I32AtomicRmw16AndU { memarg: $crate::MemArg } => visit_i32_atomic_rmw16_and_u + @threads I64AtomicRmw8AndU { memarg: $crate::MemArg } => visit_i64_atomic_rmw8_and_u + @threads I64AtomicRmw16AndU { memarg: $crate::MemArg } => visit_i64_atomic_rmw16_and_u + @threads I64AtomicRmw32AndU { memarg: $crate::MemArg } => visit_i64_atomic_rmw32_and_u + @threads I32AtomicRmwOr { memarg: $crate::MemArg } => visit_i32_atomic_rmw_or + @threads I64AtomicRmwOr { memarg: $crate::MemArg } => visit_i64_atomic_rmw_or + @threads I32AtomicRmw8OrU { memarg: $crate::MemArg } => visit_i32_atomic_rmw8_or_u + @threads I32AtomicRmw16OrU { memarg: $crate::MemArg } => visit_i32_atomic_rmw16_or_u + @threads I64AtomicRmw8OrU { memarg: $crate::MemArg } => visit_i64_atomic_rmw8_or_u + @threads I64AtomicRmw16OrU { memarg: $crate::MemArg } => visit_i64_atomic_rmw16_or_u + @threads I64AtomicRmw32OrU { memarg: $crate::MemArg } => visit_i64_atomic_rmw32_or_u + @threads I32AtomicRmwXor { memarg: $crate::MemArg } => visit_i32_atomic_rmw_xor + @threads I64AtomicRmwXor { memarg: $crate::MemArg } => visit_i64_atomic_rmw_xor + @threads I32AtomicRmw8XorU { memarg: $crate::MemArg } => visit_i32_atomic_rmw8_xor_u + @threads I32AtomicRmw16XorU { memarg: $crate::MemArg } => visit_i32_atomic_rmw16_xor_u + @threads I64AtomicRmw8XorU { memarg: $crate::MemArg } => visit_i64_atomic_rmw8_xor_u + @threads I64AtomicRmw16XorU { memarg: $crate::MemArg } => visit_i64_atomic_rmw16_xor_u + @threads I64AtomicRmw32XorU { memarg: $crate::MemArg } => visit_i64_atomic_rmw32_xor_u + @threads I32AtomicRmwXchg { memarg: $crate::MemArg } => visit_i32_atomic_rmw_xchg + @threads I64AtomicRmwXchg { memarg: $crate::MemArg } => visit_i64_atomic_rmw_xchg + @threads I32AtomicRmw8XchgU { memarg: $crate::MemArg } => visit_i32_atomic_rmw8_xchg_u + @threads I32AtomicRmw16XchgU { memarg: $crate::MemArg } => visit_i32_atomic_rmw16_xchg_u + @threads I64AtomicRmw8XchgU { memarg: $crate::MemArg } => visit_i64_atomic_rmw8_xchg_u + @threads I64AtomicRmw16XchgU { memarg: $crate::MemArg } => visit_i64_atomic_rmw16_xchg_u + @threads I64AtomicRmw32XchgU { memarg: $crate::MemArg } => visit_i64_atomic_rmw32_xchg_u + @threads I32AtomicRmwCmpxchg { memarg: $crate::MemArg } => visit_i32_atomic_rmw_cmpxchg + @threads I64AtomicRmwCmpxchg { memarg: $crate::MemArg } => visit_i64_atomic_rmw_cmpxchg + @threads I32AtomicRmw8CmpxchgU { memarg: $crate::MemArg } => visit_i32_atomic_rmw8_cmpxchg_u + @threads I32AtomicRmw16CmpxchgU { memarg: $crate::MemArg } => visit_i32_atomic_rmw16_cmpxchg_u + @threads I64AtomicRmw8CmpxchgU { memarg: $crate::MemArg } => visit_i64_atomic_rmw8_cmpxchg_u + @threads I64AtomicRmw16CmpxchgU { memarg: $crate::MemArg } => visit_i64_atomic_rmw16_cmpxchg_u + @threads I64AtomicRmw32CmpxchgU { memarg: $crate::MemArg } => visit_i64_atomic_rmw32_cmpxchg_u // 0xFD operators - // SIMD https://webassembly.github.io/simd/core/binary/instructions.html - @simd V128Load { memarg: MemArg } => visit_v128_load - @simd V128Load8x8S { memarg: MemArg } => visit_v128_load8x8_s - @simd V128Load8x8U { memarg: MemArg } => visit_v128_load8x8_u - @simd V128Load16x4S { memarg: MemArg } => visit_v128_load16x4_s - @simd V128Load16x4U { memarg: MemArg } => visit_v128_load16x4_u - @simd V128Load32x2S { memarg: MemArg } => visit_v128_load32x2_s - @simd V128Load32x2U { memarg: MemArg } => visit_v128_load32x2_u - @simd V128Load8Splat { memarg: MemArg } => visit_v128_load8_splat - @simd V128Load16Splat { memarg: MemArg } => visit_v128_load16_splat - @simd V128Load32Splat { memarg: MemArg } => visit_v128_load32_splat - @simd V128Load64Splat { memarg: MemArg } => visit_v128_load64_splat - @simd V128Load32Zero { memarg: MemArg } => visit_v128_load32_zero - @simd V128Load64Zero { memarg: MemArg } => visit_v128_load64_zero - @simd V128Store { memarg: MemArg } => visit_v128_store - @simd V128Load8Lane { memarg: MemArg, lane: u8 } => visit_v128_load8_lane - @simd V128Load16Lane { memarg: MemArg, lane: u8 } => visit_v128_load16_lane - @simd V128Load32Lane { memarg: MemArg, lane: u8 } => visit_v128_load32_lane - @simd V128Load64Lane { memarg: MemArg, lane: u8 } => visit_v128_load64_lane - @simd V128Store8Lane { memarg: MemArg, lane: u8 } => visit_v128_store8_lane - @simd V128Store16Lane { memarg: MemArg, lane: u8 } => visit_v128_store16_lane - @simd V128Store32Lane { memarg: MemArg, lane: u8 } => visit_v128_store32_lane - @simd V128Store64Lane { memarg: MemArg, lane: u8 } => visit_v128_store64_lane - @simd V128Const { value: V128 } => visit_v128_const + // 128-bit SIMD + // - https://github.com/webassembly/simd + // - https://webassembly.github.io/simd/core/binary/instructions.html + @simd V128Load { memarg: $crate::MemArg } => visit_v128_load + @simd V128Load8x8S { memarg: $crate::MemArg } => visit_v128_load8x8_s + @simd V128Load8x8U { memarg: $crate::MemArg } => visit_v128_load8x8_u + @simd V128Load16x4S { memarg: $crate::MemArg } => visit_v128_load16x4_s + @simd V128Load16x4U { memarg: $crate::MemArg } => visit_v128_load16x4_u + @simd V128Load32x2S { memarg: $crate::MemArg } => visit_v128_load32x2_s + @simd V128Load32x2U { memarg: $crate::MemArg } => visit_v128_load32x2_u + @simd V128Load8Splat { memarg: $crate::MemArg } => visit_v128_load8_splat + @simd V128Load16Splat { memarg: $crate::MemArg } => visit_v128_load16_splat + @simd V128Load32Splat { memarg: $crate::MemArg } => visit_v128_load32_splat + @simd V128Load64Splat { memarg: $crate::MemArg } => visit_v128_load64_splat + @simd V128Load32Zero { memarg: $crate::MemArg } => visit_v128_load32_zero + @simd V128Load64Zero { memarg: $crate::MemArg } => visit_v128_load64_zero + @simd V128Store { memarg: $crate::MemArg } => visit_v128_store + @simd V128Load8Lane { memarg: $crate::MemArg, lane: u8 } => visit_v128_load8_lane + @simd V128Load16Lane { memarg: $crate::MemArg, lane: u8 } => visit_v128_load16_lane + @simd V128Load32Lane { memarg: $crate::MemArg, lane: u8 } => visit_v128_load32_lane + @simd V128Load64Lane { memarg: $crate::MemArg, lane: u8 } => visit_v128_load64_lane + @simd V128Store8Lane { memarg: $crate::MemArg, lane: u8 } => visit_v128_store8_lane + @simd V128Store16Lane { memarg: $crate::MemArg, lane: u8 } => visit_v128_store16_lane + @simd V128Store32Lane { memarg: $crate::MemArg, lane: u8 } => visit_v128_store32_lane + @simd V128Store64Lane { memarg: $crate::MemArg, lane: u8 } => visit_v128_store64_lane + @simd V128Const { value: $crate::V128 } => visit_v128_const @simd I8x16Shuffle { lanes: [u8; 16] } => visit_i8x16_shuffle @simd I8x16ExtractLaneS { lane: u8 } => visit_i8x16_extract_lane_s @simd I8x16ExtractLaneU { lane: u8 } => visit_i8x16_extract_lane_u @@ -646,31 +651,35 @@ macro_rules! for_each_operator { @simd F64x2PromoteLowF32x4 => visit_f64x2_promote_low_f32x4 // Relaxed SIMD operators + // https://github.com/WebAssembly/relaxed-simd @relaxed_simd I8x16RelaxedSwizzle => visit_i8x16_relaxed_swizzle @relaxed_simd I32x4RelaxedTruncSatF32x4S => visit_i32x4_relaxed_trunc_sat_f32x4_s @relaxed_simd I32x4RelaxedTruncSatF32x4U => visit_i32x4_relaxed_trunc_sat_f32x4_u @relaxed_simd I32x4RelaxedTruncSatF64x2SZero => visit_i32x4_relaxed_trunc_sat_f64x2_s_zero @relaxed_simd I32x4RelaxedTruncSatF64x2UZero => visit_i32x4_relaxed_trunc_sat_f64x2_u_zero - @relaxed_simd F32x4Fma => visit_f32x4_fma - @relaxed_simd F32x4Fms => visit_f32x4_fms - @relaxed_simd F64x2Fma => visit_f64x2_fma - @relaxed_simd F64x2Fms => visit_f64x2_fms - @relaxed_simd I8x16LaneSelect => visit_i8x16_laneselect - @relaxed_simd I16x8LaneSelect => visit_i16x8_laneselect - @relaxed_simd I32x4LaneSelect => visit_i32x4_laneselect - @relaxed_simd I64x2LaneSelect => visit_i64x2_laneselect + @relaxed_simd F32x4RelaxedFma => visit_f32x4_relaxed_fma + @relaxed_simd F32x4RelaxedFnma => visit_f32x4_relaxed_fnma + @relaxed_simd F64x2RelaxedFma => visit_f64x2_relaxed_fma + @relaxed_simd F64x2RelaxedFnma => visit_f64x2_relaxed_fnma + @relaxed_simd I8x16RelaxedLaneselect => visit_i8x16_relaxed_laneselect + @relaxed_simd I16x8RelaxedLaneselect => visit_i16x8_relaxed_laneselect + @relaxed_simd I32x4RelaxedLaneselect => visit_i32x4_relaxed_laneselect + @relaxed_simd I64x2RelaxedLaneselect => visit_i64x2_relaxed_laneselect @relaxed_simd F32x4RelaxedMin => visit_f32x4_relaxed_min @relaxed_simd F32x4RelaxedMax => visit_f32x4_relaxed_max @relaxed_simd F64x2RelaxedMin => visit_f64x2_relaxed_min @relaxed_simd F64x2RelaxedMax => visit_f64x2_relaxed_max + @relaxed_simd I16x8RelaxedQ15mulrS => visit_i16x8_relaxed_q15mulr_s + @relaxed_simd I16x8DotI8x16I7x16S => visit_i16x8_dot_i8x16_i7x16_s + @relaxed_simd I32x4DotI8x16I7x16AddS => visit_i32x4_dot_i8x16_i7x16_add_s + @relaxed_simd F32x4RelaxedDotBf16x8AddF32x4 => visit_f32x4_relaxed_dot_bf16x8_add_f32x4 // Typed Function references - @function_references CallRef { ty: HeapType } => visit_call_ref - @function_references ReturnCallRef { ty: HeapType } => visit_return_call_ref + @function_references CallRef { hty: $crate::HeapType } => visit_call_ref + @function_references ReturnCallRef { hty: $crate::HeapType } => visit_return_call_ref @function_references RefAsNonNull => visit_ref_as_non_null @function_references BrOnNull { relative_depth: u32 } => visit_br_on_null @function_references BrOnNonNull { relative_depth: u32 } => visit_br_on_non_null - } }; } diff --git a/crates/wasmparser/src/parser.rs b/crates/wasmparser/src/parser.rs index f23e7f894c..a29cb57e47 100644 --- a/crates/wasmparser/src/parser.rs +++ b/crates/wasmparser/src/parser.rs @@ -5,8 +5,8 @@ use crate::{ ComponentInstanceSectionReader, ComponentStartSectionReader, ComponentTypeSectionReader, CustomSectionReader, DataSectionReader, ElementSectionReader, ExportSectionReader, FunctionBody, FunctionSectionReader, GlobalSectionReader, ImportSectionReader, - InstanceSectionReader, MemorySectionReader, Result, TableSectionReader, TagSectionReader, - TypeSectionReader, + InstanceSectionReader, MemorySectionReader, Result, SectionReader, TableSectionReader, + TagSectionReader, TypeSectionReader, }; use std::convert::TryInto; use std::fmt; @@ -281,6 +281,33 @@ pub enum Payload<'a> { End(usize), } +const CUSTOM_SECTION: u8 = 0; +const TYPE_SECTION: u8 = 1; +const IMPORT_SECTION: u8 = 2; +const FUNCTION_SECTION: u8 = 3; +const TABLE_SECTION: u8 = 4; +const MEMORY_SECTION: u8 = 5; +const GLOBAL_SECTION: u8 = 6; +const EXPORT_SECTION: u8 = 7; +const START_SECTION: u8 = 8; +const ELEMENT_SECTION: u8 = 9; +const CODE_SECTION: u8 = 10; +const DATA_SECTION: u8 = 11; +const DATA_COUNT_SECTION: u8 = 12; +const TAG_SECTION: u8 = 13; + +const COMPONENT_MODULE_SECTION: u8 = 1; +const COMPONENT_CORE_INSTANCE_SECTION: u8 = 2; +const COMPONENT_CORE_TYPE_SECTION: u8 = 3; +const COMPONENT_SECTION: u8 = 4; +const COMPONENT_INSTANCE_SECTION: u8 = 5; +const COMPONENT_ALIAS_SECTION: u8 = 6; +const COMPONENT_TYPE_SECTION: u8 = 7; +const COMPONENT_CANONICAL_SECTION: u8 = 8; +const COMPONENT_START_SECTION: u8 = 9; +const COMPONENT_IMPORT_SECTION: u8 = 10; +const COMPONENT_EXPORT_SECTION: u8 = 11; + impl Parser { /// Creates a new parser. /// @@ -541,35 +568,35 @@ impl Parser { (_, 0) => section(reader, len, CustomSectionReader::new, CustomSection), // Module sections - (Encoding::Module, 1) => { + (Encoding::Module, TYPE_SECTION) => { section(reader, len, TypeSectionReader::new, TypeSection) } - (Encoding::Module, 2) => { + (Encoding::Module, IMPORT_SECTION) => { section(reader, len, ImportSectionReader::new, ImportSection) } - (Encoding::Module, 3) => { + (Encoding::Module, FUNCTION_SECTION) => { section(reader, len, FunctionSectionReader::new, FunctionSection) } - (Encoding::Module, 4) => { + (Encoding::Module, TABLE_SECTION) => { section(reader, len, TableSectionReader::new, TableSection) } - (Encoding::Module, 5) => { + (Encoding::Module, MEMORY_SECTION) => { section(reader, len, MemorySectionReader::new, MemorySection) } - (Encoding::Module, 6) => { + (Encoding::Module, GLOBAL_SECTION) => { section(reader, len, GlobalSectionReader::new, GlobalSection) } - (Encoding::Module, 7) => { + (Encoding::Module, EXPORT_SECTION) => { section(reader, len, ExportSectionReader::new, ExportSection) } - (Encoding::Module, 8) => { + (Encoding::Module, START_SECTION) => { let (func, range) = single_u32(reader, len, "start")?; Ok(StartSection { func, range }) } - (Encoding::Module, 9) => { + (Encoding::Module, ELEMENT_SECTION) => { section(reader, len, ElementSectionReader::new, ElementSection) } - (Encoding::Module, 10) => { + (Encoding::Module, CODE_SECTION) => { let start = reader.original_position(); let count = delimited(reader, &mut len, |r| r.read_var_u32())?; let range = start..reader.original_position() + len as usize; @@ -583,20 +610,20 @@ impl Parser { size: len, }) } - (Encoding::Module, 11) => { + (Encoding::Module, DATA_SECTION) => { section(reader, len, DataSectionReader::new, DataSection) } - (Encoding::Module, 12) => { + (Encoding::Module, DATA_COUNT_SECTION) => { let (count, range) = single_u32(reader, len, "data count")?; Ok(DataCountSection { count, range }) } - (Encoding::Module, 13) => { + (Encoding::Module, TAG_SECTION) => { section(reader, len, TagSectionReader::new, TagSection) } // Component sections - (Encoding::Component, 1 /* module */) - | (Encoding::Component, 4 /* component */) => { + (Encoding::Component, COMPONENT_MODULE_SECTION) + | (Encoding::Component, COMPONENT_SECTION) => { if len as usize > MAX_WASM_MODULE_SIZE { bail!( len_pos, @@ -618,50 +645,49 @@ impl Parser { _ => unreachable!(), }) } - (Encoding::Component, 2) => { + (Encoding::Component, COMPONENT_CORE_INSTANCE_SECTION) => { section(reader, len, InstanceSectionReader::new, InstanceSection) } - (Encoding::Component, 3) => { + (Encoding::Component, COMPONENT_CORE_TYPE_SECTION) => { section(reader, len, CoreTypeSectionReader::new, CoreTypeSection) } - // Section 5 handled above - (Encoding::Component, 5) => section( + (Encoding::Component, COMPONENT_INSTANCE_SECTION) => section( reader, len, ComponentInstanceSectionReader::new, ComponentInstanceSection, ), - (Encoding::Component, 6) => section( + (Encoding::Component, COMPONENT_ALIAS_SECTION) => section( reader, len, ComponentAliasSectionReader::new, ComponentAliasSection, ), - (Encoding::Component, 7) => section( + (Encoding::Component, COMPONENT_TYPE_SECTION) => section( reader, len, ComponentTypeSectionReader::new, ComponentTypeSection, ), - (Encoding::Component, 8) => section( + (Encoding::Component, COMPONENT_CANONICAL_SECTION) => section( reader, len, ComponentCanonicalSectionReader::new, ComponentCanonicalSection, ), - (Encoding::Component, 9) => section( + (Encoding::Component, COMPONENT_START_SECTION) => section( reader, len, ComponentStartSectionReader::new, ComponentStartSection, ), - (Encoding::Component, 10) => section( + (Encoding::Component, COMPONENT_IMPORT_SECTION) => section( reader, len, ComponentImportSectionReader::new, ComponentImportSection, ), - (Encoding::Component, 11) => section( + (Encoding::Component, COMPONENT_EXPORT_SECTION) => section( reader, len, ComponentExportSectionReader::new, @@ -930,6 +956,62 @@ impl Default for Parser { } } +impl Payload<'_> { + /// If this `Payload` represents a section in the original wasm module then + /// the section's id and range within the original wasm binary are returned. + /// + /// Not all payloads refer to entire sections, such as the `Version` and + /// `CodeSectionEntry` variants. These variants will return `None` from this + /// function. + /// + /// Otherwise this function will return `Some` where the first element is + /// the byte identifier for the section and the second element is the range + /// of the contents of the section within the original wasm binary. + /// + /// The purpose of this method is to enable tools to easily iterate over + /// entire sections if necessary and handle sections uniformly, for example + /// dropping custom sections while preserving all other sections. + pub fn as_section(&self) -> Option<(u8, Range)> { + use Payload::*; + + match self { + Version { .. } => None, + TypeSection(s) => Some((TYPE_SECTION, s.range())), + ImportSection(s) => Some((IMPORT_SECTION, s.range())), + FunctionSection(s) => Some((FUNCTION_SECTION, s.range())), + TableSection(s) => Some((TABLE_SECTION, s.range())), + MemorySection(s) => Some((MEMORY_SECTION, s.range())), + TagSection(s) => Some((TAG_SECTION, s.range())), + GlobalSection(s) => Some((GLOBAL_SECTION, s.range())), + ExportSection(s) => Some((EXPORT_SECTION, s.range())), + ElementSection(s) => Some((ELEMENT_SECTION, s.range())), + DataSection(s) => Some((DATA_SECTION, s.range())), + StartSection { range, .. } => Some((START_SECTION, range.clone())), + DataCountSection { range, .. } => Some((DATA_COUNT_SECTION, range.clone())), + CodeSectionStart { range, .. } => Some((CODE_SECTION, range.clone())), + CodeSectionEntry(_) => None, + + ModuleSection { range, .. } => Some((COMPONENT_MODULE_SECTION, range.clone())), + InstanceSection(s) => Some((COMPONENT_CORE_INSTANCE_SECTION, s.range())), + CoreTypeSection(s) => Some((COMPONENT_CORE_TYPE_SECTION, s.range())), + ComponentSection { range, .. } => Some((COMPONENT_SECTION, range.clone())), + ComponentInstanceSection(s) => Some((COMPONENT_INSTANCE_SECTION, s.range())), + ComponentAliasSection(s) => Some((COMPONENT_ALIAS_SECTION, s.range())), + ComponentTypeSection(s) => Some((COMPONENT_TYPE_SECTION, s.range())), + ComponentCanonicalSection(s) => Some((COMPONENT_CANONICAL_SECTION, s.range())), + ComponentStartSection(s) => Some((COMPONENT_START_SECTION, s.range())), + ComponentImportSection(s) => Some((COMPONENT_IMPORT_SECTION, s.range())), + ComponentExportSection(s) => Some((COMPONENT_EXPORT_SECTION, s.range())), + + CustomSection(c) => Some((CUSTOM_SECTION, c.range())), + + UnknownSection { id, range, .. } => Some((*id, range.clone())), + + End(_) => None, + } + } +} + impl fmt::Debug for Payload<'_> { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { use Payload::*; diff --git a/crates/wasmparser/src/readers/component/types.rs b/crates/wasmparser/src/readers/component/types.rs index 157ad01e0e..bf891556ab 100644 --- a/crates/wasmparser/src/readers/component/types.rs +++ b/crates/wasmparser/src/readers/component/types.rs @@ -259,31 +259,25 @@ pub enum InstanceTypeDeclaration<'a> { }, } -/// Represents the vector of types in a component function's -/// parameters or results. +/// Represents the result type of a component function. #[derive(Debug, Clone)] -pub enum TypeVec<'a> { - /// The type vector contains a single, unnamed type. +pub enum ComponentFuncResult<'a> { + /// The function returns a singular, unnamed type. Unnamed(ComponentValType), - /// The type vector contains zero or more named types. + /// The function returns zero or more named types. Named(Box<[(&'a str, ComponentValType)]>), } -impl TypeVec<'_> { - /// Gets the type vector's length. - pub fn len(&self) -> usize { +impl ComponentFuncResult<'_> { + /// Gets the count of types returned by the function. + pub fn type_count(&self) -> usize { match self { Self::Unnamed(_) => 1, Self::Named(vec) => vec.len(), } } - /// Determines if the type vector is empty. - pub fn is_empty(&self) -> bool { - self.len() == 0 - } - - /// Iterates over the types in the type vector. + /// Iterates over the types returned by the function. pub fn iter(&self) -> impl Iterator, &ComponentValType)> { enum Either { Left(L), @@ -316,9 +310,9 @@ impl TypeVec<'_> { #[derive(Debug, Clone)] pub struct ComponentFuncType<'a> { /// The function parameters. - pub params: TypeVec<'a>, - /// The function results. - pub results: TypeVec<'a>, + pub params: Box<[(&'a str, ComponentValType)]>, + /// The function result. + pub results: ComponentFuncResult<'a>, } /// Represents a case in a variant type. @@ -392,7 +386,7 @@ impl<'a> ComponentTypeSectionReader<'a> { /// # Examples /// ``` /// use wasmparser::ComponentTypeSectionReader; - /// let data: &[u8] = &[0x01, 0x40, 0x01, 0x01, 0x03, b'f', b'o', b'o', 0x73, 0x00, 0x73]; + /// let data: &[u8] = &[0x01, 0x40, 0x01, 0x03, b'f', b'o', b'o', 0x73, 0x00, 0x73]; /// let mut reader = ComponentTypeSectionReader::new(data, 0).unwrap(); /// for _ in 0..reader.get_count() { /// let ty = reader.read().expect("type"); @@ -439,7 +433,7 @@ impl<'a> IntoIterator for ComponentTypeSectionReader<'a> { /// # Examples /// ``` /// use wasmparser::ComponentTypeSectionReader; - /// let data: &[u8] = &[0x01, 0x40, 0x01, 0x01, 0x03, b'f', b'o', b'o', 0x73, 0x00, 0x73]; + /// let data: &[u8] = &[0x01, 0x40, 0x01, 0x03, b'f', b'o', b'o', 0x73, 0x00, 0x73]; /// let mut reader = ComponentTypeSectionReader::new(data, 0).unwrap(); /// for ty in reader { /// println!("Type {:?}", ty.expect("type")); diff --git a/crates/wasmparser/src/readers/core/operators.rs b/crates/wasmparser/src/readers/core/operators.rs index fc1e33c82a..0448927d70 100644 --- a/crates/wasmparser/src/readers/core/operators.rs +++ b/crates/wasmparser/src/readers/core/operators.rs @@ -13,7 +13,7 @@ * limitations under the License. */ -use crate::{BinaryReader, BinaryReaderError, HeapType, Result, ValType}; +use crate::{BinaryReader, BinaryReaderError, Result, ValType}; /// Represents a block type. #[derive(Debug, Copy, Clone, PartialEq, Eq)] diff --git a/crates/wasmparser/src/readers/core/types.rs b/crates/wasmparser/src/readers/core/types.rs index c93a4634a4..600b12c3b1 100644 --- a/crates/wasmparser/src/readers/core/types.rs +++ b/crates/wasmparser/src/readers/core/types.rs @@ -100,7 +100,7 @@ pub enum Type { pub struct FuncType { /// The combined parameters and result types. params_results: Box<[ValType]>, - /// The number of paramter types. + /// The number of parameter types. len_params: usize, } diff --git a/crates/wasmparser/src/validator.rs b/crates/wasmparser/src/validator.rs index 1cb21d1899..5983941530 100644 --- a/crates/wasmparser/src/validator.rs +++ b/crates/wasmparser/src/validator.rs @@ -55,7 +55,7 @@ use self::component::*; pub use self::core::ValidatorResources; use self::core::*; use self::types::{TypeList, Types, TypesRef}; -pub use func::FuncValidator; +pub use func::{FuncToValidate, FuncValidator, FuncValidatorAllocations}; pub use operators::{Frame, FrameKind}; fn check_max(cur_len: usize, amt_added: u32, max: usize, desc: &str, offset: usize) -> Result<()> { @@ -311,7 +311,7 @@ pub enum ValidPayload<'a> { /// of the currently-used parser until this returned one ends. Parser(Parser), /// A function was found to be validate. - Func(FuncValidator, FunctionBody<'a>), + Func(FuncToValidate, FunctionBody<'a>), /// The end payload was validated and the types known to the validator /// are provided. End(Types), @@ -370,8 +370,11 @@ impl Validator { } } - for (mut validator, body) in functions_to_validate { + let mut allocs = FuncValidatorAllocations::default(); + for (func, body) in functions_to_validate { + let mut validator = func.into_validator(allocs); validator.validate(&body)?; + allocs = validator.into_allocations(); } Ok(last_types.unwrap()) @@ -844,37 +847,33 @@ impl Validator { /// Validates [`Payload::CodeSectionEntry`](crate::Payload). /// - /// This function will prepare a [`FuncValidator`] which can be used to - /// validate the function. The function body provided will be parsed only - /// enough to create the function validation context. After this the - /// [`OperatorsReader`](crate::readers::OperatorsReader) returned can be used to read the - /// opcodes of the function as well as feed information into the validator. + /// This function will prepare a [`FuncToValidate`] which can be used to + /// create a [`FuncValidator`] to validate the function. The function body + /// provided will not be parsed or validated by this function. /// - /// Note that the returned [`FuncValidator`] is "connected" to this + /// Note that the returned [`FuncToValidate`] is "connected" to this /// [`Validator`] in that it uses the internal context of this validator for - /// validating the function. The [`FuncValidator`] can be sent to - /// another thread, for example, to offload actual processing of functions + /// validating the function. The [`FuncToValidate`] can be sent to another + /// thread, for example, to offload actual processing of functions /// elsewhere. /// /// This method should only be called when parsing a module. pub fn code_section_entry( &mut self, body: &crate::FunctionBody, - ) -> Result> { + ) -> Result> { let offset = body.range().start; self.state.ensure_module("code", offset)?; let state = self.module.as_mut().unwrap(); let (index, ty) = state.next_code_index_and_type(offset)?; - Ok(FuncValidator::new( + Ok(FuncToValidate::new( index, ty, - 0, ValidatorResources(state.module.arc().clone()), &self.features, - ) - .unwrap()) + )) } /// Validates [`Payload::DataSection`](crate::Payload). @@ -887,13 +886,7 @@ impl Validator { "data", |state, _, _, count, offset| { state.data_segment_count = count; - check_max( - state.module.data_count.unwrap_or(0) as usize, - count, - MAX_WASM_DATA_SEGMENTS, - "data segments", - offset, - ) + check_max(0, count, MAX_WASM_DATA_SEGMENTS, "data segments", offset) }, |state, features, types, d, offset| state.add_data_segment(d, features, types, offset), ) @@ -1455,4 +1448,45 @@ mod tests { Ok(()) } + + #[test] + fn test_type_id_aliasing() -> Result<()> { + let bytes = wat::parse_str( + r#" + (component + (type $T (list string)) + (alias outer 0 $T (type $A1)) + (alias outer 0 $T (type $A2)) + ) + "#, + )?; + + let mut validator = Validator::new_with_features(WasmFeatures { + component_model: true, + ..Default::default() + }); + + let types = validator.validate_all(&bytes)?; + + let t_id = types.id_from_type_index(0, false).unwrap(); + let a1_id = types.id_from_type_index(1, false).unwrap(); + let a2_id = types.id_from_type_index(2, false).unwrap(); + + // The ids should all be different + assert!(t_id != a1_id); + assert!(t_id != a2_id); + assert!(a1_id != a2_id); + + // However, they should all point to the same type + assert!(std::ptr::eq( + types.type_from_id(t_id).unwrap(), + types.type_from_id(a1_id).unwrap() + )); + assert!(std::ptr::eq( + types.type_from_id(t_id).unwrap(), + types.type_from_id(a2_id).unwrap() + )); + + Ok(()) + } } diff --git a/crates/wasmparser/src/validator/component.rs b/crates/wasmparser/src/validator/component.rs index 5ce0e12c08..b2acb467bf 100644 --- a/crates/wasmparser/src/validator/component.rs +++ b/crates/wasmparser/src/validator/component.rs @@ -87,6 +87,8 @@ impl ComponentState { current.core_types.push(TypeId { type_size: ty.type_size(), index: types.len(), + type_index: Some(current.core_types.len()), + is_core: true, }); types.push(ty); @@ -113,6 +115,8 @@ impl ComponentState { self.core_modules.push(TypeId { type_size: ty.type_size(), index: types.len(), + type_index: None, + is_core: true, }); types.push(ty); @@ -182,6 +186,8 @@ impl ComponentState { current.types.push(TypeId { type_size: ty.type_size(), index: types.len(), + type_index: Some(current.types.len()), + is_core: false, }); types.push(ty); @@ -327,6 +333,8 @@ impl ComponentState { self.core_funcs.push(TypeId { type_size: lowered_ty.type_size(), index: types.len(), + type_index: None, + is_core: true, }); types.push(lowered_ty); @@ -344,6 +352,8 @@ impl ComponentState { self.components.push(TypeId { type_size: ty.type_size(), index: types.len(), + type_index: None, + is_core: false, }); types.push(ty); @@ -863,21 +873,20 @@ impl ComponentState { ) -> Result { let mut type_size = 1; - let mut set = HashSet::with_capacity(std::cmp::max(ty.params.len(), ty.results.len())); + let mut set = + HashSet::with_capacity(std::cmp::max(ty.params.len(), ty.results.type_count())); let params = ty .params .iter() .map(|(name, ty)| { - if let Some(name) = name { - Self::check_name(name, "function parameter", offset)?; - if !set.insert(name) { - return Err(BinaryReaderError::new("duplicate parameter name", offset)); - } + Self::check_name(name, "function parameter", offset)?; + if !set.insert(*name) { + return Err(BinaryReaderError::new("duplicate parameter name", offset)); } let ty = self.create_component_val_type(*ty, types, offset)?; type_size = combine_type_sizes(type_size, ty.type_size(), offset)?; - Ok((name.map(ToOwned::to_owned), ty)) + Ok((name.to_string(), ty)) }) .collect::>()?; @@ -1010,6 +1019,8 @@ impl ComponentState { let id = TypeId { type_size: ty.type_size(), index: types.len(), + type_index: None, + is_core: true, }; types.push(ty); @@ -1145,6 +1156,8 @@ impl ComponentState { let id = TypeId { type_size: ty.type_size(), index: types.len(), + type_index: None, + is_core: false, }; types.push(ty); @@ -1246,6 +1259,8 @@ impl ComponentState { let id = TypeId { type_size: ty.type_size(), index: types.len(), + type_index: None, + is_core: false, }; types.push(ty); @@ -1332,6 +1347,8 @@ impl ComponentState { let id = TypeId { type_size: ty.type_size(), index: types.len(), + type_index: None, + is_core: true, }; types.push(ty); @@ -1545,7 +1562,13 @@ impl ComponentState { let current = components.last_mut().unwrap(); check_max(current.type_count(), 1, MAX_WASM_TYPES, "types", offset)?; - current.core_types.push(ty); + current.core_types.push(TypeId { + type_size: ty.type_size, + index: ty.index, + type_index: Some(current.core_types.len()), + is_core: true, + }); + Ok(()) } @@ -1556,7 +1579,13 @@ impl ComponentState { let current = components.last_mut().unwrap(); check_max(current.type_count(), 1, MAX_WASM_TYPES, "types", offset)?; - current.types.push(ty); + current.types.push(TypeId { + type_size: ty.type_size, + index: ty.index, + type_index: Some(current.types.len()), + is_core: false, + }); + Ok(()) } diff --git a/crates/wasmparser/src/validator/core.rs b/crates/wasmparser/src/validator/core.rs index fc6d9c306f..116bc85824 100644 --- a/crates/wasmparser/src/validator/core.rs +++ b/crates/wasmparser/src/validator/core.rs @@ -2,17 +2,17 @@ //! use super::{ check_max, combine_type_sizes, - operators::OperatorValidator, + operators::{OperatorValidator, OperatorValidatorAllocations}, types::{EntityType, Type, TypeId, TypeList}, }; use crate::validator::core::arc::MaybeOwned; use crate::{ - limits::*, BinaryReaderError, BlockType, BrTable, ConstExpr, Data, DataKind, Element, - ElementItem, ElementKind, ExternalKind, FuncType, Global, GlobalType, HeapType, Ieee32, Ieee64, - MemArg, MemoryType, RefType, Result, TableType, TagType, TypeRef, ValType, VisitOperator, - WasmFeatures, WasmFuncType, WasmModuleResources, FUNC_REF, V128, + limits::*, BinaryReaderError, ConstExpr, Data, DataKind, Element, ElementItem, ElementKind, + ExternalKind, FuncType, Global, GlobalType, HeapType, MemoryType, RefType, Result, TableType, TagType, TypeRef, + ValType, VisitOperator, WasmFeatures, WasmFuncType, WasmModuleResources, FUNC_REF, }; use indexmap::IndexMap; +use std::mem; use std::{collections::HashSet, sync::Arc}; // Section order for WebAssembly modules. @@ -65,6 +65,8 @@ pub(crate) struct ModuleState { /// function being validated). pub expected_code_bodies: Option, + const_expr_allocs: OperatorValidatorAllocations, + /// When parsing the code section, represents the current index in the section. code_section_index: Option, } @@ -247,7 +249,11 @@ impl ModuleState { let mut validator = VisitConstOperator { order: self.order, uninserted_funcref: false, - ops: OperatorValidator::new_const_expr(features, expected_ty), + ops: OperatorValidator::new_const_expr( + features, + expected_ty, + mem::take(&mut self.const_expr_allocs), + ), resources: OperatorValidatorResources { types, module: &mut self.module, @@ -263,6 +269,8 @@ impl ModuleState { // See comment in `RefFunc` below for why this is an assert. assert!(!validator.uninserted_funcref); + self.const_expr_allocs = validator.ops.into_allocations(); + return Ok(()); struct VisitConstOperator<'a> { @@ -479,6 +487,8 @@ impl Module { self.types.push(TypeId { type_size: ty.type_size(), index: types.len(), + type_index: Some(self.types.len()), + is_core: true, }); types.push(ty); Ok(()) diff --git a/crates/wasmparser/src/validator/func.rs b/crates/wasmparser/src/validator/func.rs index 41ed3a31c8..f25afc00bc 100644 --- a/crates/wasmparser/src/validator/func.rs +++ b/crates/wasmparser/src/validator/func.rs @@ -1,44 +1,90 @@ -use super::operators::{Frame, OperatorValidator}; -use crate::{BinaryReader, HeapType, Result, ValType}; +use super::operators::{Frame, OperatorValidator, OperatorValidatorAllocations}; +use crate::{BinaryReader, Result, ValType, VisitOperator}; use crate::{FunctionBody, Operator, WasmFeatures, WasmModuleResources}; -/// Validation context for a WebAssembly function. +/// Resources necessary to perform validation of a function. /// /// This structure is created by -/// [`Validator::code_section_entry`](crate::Validator::code_section_entry) -/// and is created per-function in a WebAssembly module. This structure is -/// suitable for sending to other threads while the original +/// [`Validator::code_section_entry`](crate::Validator::code_section_entry) and +/// is created per-function in a WebAssembly module. This structure is suitable +/// for sending to other threads while the original /// [`Validator`](crate::Validator) continues processing other functions. -pub struct FuncValidator { - validator: OperatorValidator, +pub struct FuncToValidate { resources: T, index: u32, + ty: u32, + features: WasmFeatures, } -impl FuncValidator { - /// Creates a new `FuncValidator`. +impl FuncToValidate { + /// Creates a new function to validate which will have the specified + /// configuration parameters: /// - /// The returned `FuncValidator` can be used to validate a function with - /// the type `ty` specified. The `resources` indicate what the containing - /// module has for the function to use, and the `features` configure what - /// WebAssembly proposals are enabled for this function. + /// * `index` - the core wasm function index being validated + /// * `ty` - the core wasm type index of the function being validated, + /// defining the results and parameters to the function. + /// * `resources` - metadata and type information about the module that + /// this function is validated within. + /// * `features` - enabled WebAssembly features. + pub fn new(index: u32, ty: u32, resources: T, features: &WasmFeatures) -> FuncToValidate { + FuncToValidate { + resources, + index, + ty, + features: *features, + } + } + + /// Converts this [`FuncToValidate`] into a [`FuncValidator`] using the + /// `allocs` provided. + /// + /// This method, in conjunction with [`FuncValidator::into_allocations`], + /// provides a means to reuse allocations across validation of each + /// individual function. Note that it is also sufficient to call this + /// method with `Default::default()` if no prior allocations are + /// available. /// - /// The returned validator can be used to then parse a [`FunctionBody`], for - /// example, to read locals and validate operators. - pub fn new( - index: u32, - ty: u32, - offset: usize, - resources: T, - features: &WasmFeatures, - ) -> Result> { - Ok(FuncValidator { - validator: OperatorValidator::new_func(ty, offset, features, &resources)?, + /// # Panics + /// + /// If a `FuncToValidate` was created with an invalid `ty` index then this + /// function will panic. + pub fn into_validator(self, allocs: FuncValidatorAllocations) -> FuncValidator { + let FuncToValidate { resources, index, - }) + ty, + features, + } = self; + let validator = + OperatorValidator::new_func(ty, 0, &features, &resources, allocs.0).unwrap(); + FuncValidator { + validator, + resources, + index, + } } +} +/// Validation context for a WebAssembly function. +/// +/// This is a finalized validator which is ready to process a [`FunctionBody`]. +/// This is created from the [`FuncToValidate::into_validator`] method. +pub struct FuncValidator { + validator: OperatorValidator, + resources: T, + index: u32, +} + +/// External handle to the internal allocations used during function validation. +/// +/// This is created with either the `Default` implementation or with +/// [`FuncValidator::into_allocations`]. It is then passed as an argument to +/// [`FuncToValidate::into_validator`] to provide a means of reusing allocations +/// between each function. +#[derive(Default)] +pub struct FuncValidatorAllocations(OperatorValidatorAllocations); + +impl FuncValidator { /// Convenience function to validate an entire function's body. /// /// You may not end up using this in final implementations because you'll @@ -53,7 +99,7 @@ impl FuncValidator { self.finish(reader.original_position()) } - /// Reads the local defintions from the given `BinaryReader`, often sourced + /// Reads the local definitions from the given `BinaryReader`, often sourced /// from a `FunctionBody`. /// /// This function will automatically advance the `BinaryReader` forward, @@ -140,7 +186,7 @@ impl FuncValidator { /// # Note /// /// A `depth` of 0 will refer to the last operand on the stack. - pub fn get_operand_type(&self, depth: usize) -> Option { + pub fn get_operand_type(&self, depth: usize) -> Option> { self.validator.peek_operand_at(depth) } @@ -163,6 +209,16 @@ impl FuncValidator { pub fn get_control_frame(&self, depth: usize) -> Option<&Frame> { self.validator.get_frame(depth) } + + /// Consumes this validator and returns the underlying allocations that + /// were used during the validation process. + /// + /// The returned value here can be paired with + /// [`FuncToValidate::into_validator`] to reuse the allocations already + /// created by this validator. + pub fn into_allocations(self) -> FuncValidatorAllocations { + FuncValidatorAllocations(self.validator.into_allocations()) + } } #[cfg(test)] @@ -240,7 +296,8 @@ mod tests { #[test] fn operand_stack_height() { - let mut v = FuncValidator::new(0, 0, 0, &EmptyResources, &Default::default()).unwrap(); + let mut v = FuncToValidate::new(0, 0, EmptyResources, &Default::default()) + .into_validator(Default::default()); // Initially zero values on the stack. assert_eq!(v.operand_stack_height(), 0); @@ -254,7 +311,7 @@ mod tests { .op( 1, &Operator::Block { - ty: crate::BlockType::Empty + blockty: crate::BlockType::Empty } ) .is_ok()); @@ -266,8 +323,6 @@ mod tests { } } -use crate::{BlockType, BrTable, Ieee32, Ieee64, MemArg, VisitOperator, V128}; - macro_rules! define_visit_operator { ($(@$proposal:ident $op:ident $({ $($arg:ident: $argty:ty),* })? => $visit:ident)*) => { $( diff --git a/crates/wasmparser/src/validator/operators.rs b/crates/wasmparser/src/validator/operators.rs index c7ca9dc04f..d58a79caab 100644 --- a/crates/wasmparser/src/validator/operators.rs +++ b/crates/wasmparser/src/validator/operators.rs @@ -37,12 +37,12 @@ pub(crate) struct OperatorValidator { pub(crate) features: WasmFeatures, // Temporary storage used during the validation of `br_table`. - br_table_tmp: Vec, + br_table_tmp: Vec>, /// The `control` list is the list of blocks that we're currently in. control: Vec, /// The `operands` is the current type stack. - operands: Vec, + operands: Vec>, /// Offset of the `end` instruction which emptied the `control` stack, which /// must be the end of the function. @@ -53,7 +53,6 @@ pub(crate) struct OperatorValidator { // it if you so like. const MAX_LOCALS_TO_TRACK: usize = 50; -#[derive(Default)] pub(super) struct Locals { // Total number of locals in the function. num_locals: u32, @@ -132,7 +131,43 @@ struct OperatorValidatorTemp<'validator, 'resources, T> { resources: &'resources T, } +#[derive(Default)] +pub struct OperatorValidatorAllocations { + br_table_tmp: Vec>, + control: Vec, + operands: Vec>, + locals_first: Vec, + locals_all: Vec<(u32, ValType)>, +} + impl OperatorValidator { + fn new(features: &WasmFeatures, allocs: OperatorValidatorAllocations) -> Self { + let OperatorValidatorAllocations { + br_table_tmp, + control, + operands, + locals_first, + locals_all, + } = allocs; + debug_assert!(br_table_tmp.is_empty()); + debug_assert!(control.is_empty()); + debug_assert!(operands.is_empty()); + debug_assert!(locals_first.is_empty()); + debug_assert!(locals_all.is_empty()); + OperatorValidator { + locals: Locals { + num_locals: 0, + first: locals_first, + all: locals_all, + }, + features: *features, + br_table_tmp, + operands, + control, + end_which_emptied_control: None, + } + } + /// Creates a new operator validator which will be used to validate a /// function whose type is the `ty` index specified. /// @@ -143,23 +178,18 @@ impl OperatorValidator { offset: usize, features: &WasmFeatures, resources: &T, + allocs: OperatorValidatorAllocations, ) -> Result where T: WasmModuleResources, { - let mut ret = OperatorValidator { - locals: Locals::default(), - features: *features, - br_table_tmp: Vec::new(), - operands: Vec::new(), - control: vec![Frame { - kind: FrameKind::Block, - block_type: BlockType::FuncType(ty), - height: 0, - unreachable: false, - }], - end_which_emptied_control: None, - }; + let mut ret = OperatorValidator::new(features, allocs); + ret.control.push(Frame { + kind: FrameKind::Block, + block_type: BlockType::FuncType(ty), + height: 0, + unreachable: false, + }); let params = OperatorValidatorTemp { inner: &mut ret, resources, @@ -175,20 +205,19 @@ impl OperatorValidator { /// Creates a new operator validator which will be used to validate an /// `init_expr` constant expression which should result in the `ty` /// specified. - pub fn new_const_expr(features: &WasmFeatures, ty: ValType) -> Self { - OperatorValidator { - locals: Locals::default(), - features: *features, - br_table_tmp: Vec::new(), - operands: Vec::new(), - control: vec![Frame { - kind: FrameKind::Block, - block_type: BlockType::Type(ty), - height: 0, - unreachable: false, - }], - end_which_emptied_control: None, - } + pub fn new_const_expr( + features: &WasmFeatures, + ty: ValType, + allocs: OperatorValidatorAllocations, + ) -> Self { + let mut ret = OperatorValidator::new(features, allocs); + ret.control.push(Frame { + kind: FrameKind::Block, + block_type: BlockType::Type(ty), + height: 0, + unreachable: false, + }); + ret } pub fn define_locals( @@ -239,7 +268,7 @@ impl OperatorValidator { /// # Note /// /// A `depth` of 0 will refer to the last operand on the stack. - pub fn peek_operand_at(&self, depth: usize) -> Option { + pub fn peek_operand_at(&self, depth: usize) -> Option> { self.operands.iter().rev().nth(depth).copied() } @@ -261,10 +290,10 @@ impl OperatorValidator { T: WasmModuleResources, 'resources: 'validator, { - OperatorValidatorTemp { + WasmProposalValidator(OperatorValidatorTemp { inner: self, resources, - } + }) } pub fn finish(&mut self, offset: usize) -> Result<()> { @@ -288,6 +317,20 @@ impl OperatorValidator { fn err_beyond_end(&self, offset: usize) -> BinaryReaderError { format_err!(offset, "operators remaining after end of function") } + + pub fn into_allocations(self) -> OperatorValidatorAllocations { + fn truncate(mut tmp: Vec) -> Vec { + tmp.truncate(0); + tmp + } + OperatorValidatorAllocations { + br_table_tmp: truncate(self.br_table_tmp), + control: truncate(self.control), + operands: truncate(self.operands), + locals_first: truncate(self.locals.first), + locals_all: truncate(self.locals.all), + } + } } impl Deref for OperatorValidatorTemp<'_, '_, R> { @@ -299,7 +342,7 @@ impl Deref for OperatorValidatorTemp<'_, '_, R> { impl DerefMut for OperatorValidatorTemp<'_, '_, R> { fn deref_mut(&mut self) -> &mut OperatorValidator { - &mut self.inner + self.inner } } @@ -309,8 +352,12 @@ impl<'resources, R: WasmModuleResources> OperatorValidatorTemp<'_, 'resources, R /// This is used by instructions to represent a value that is pushed to the /// operand stack. This can fail, but only if `Type` is feature gated. /// Otherwise the push operation always succeeds. - fn push_operand(&mut self, ty: ValType) -> Result<()> { - self.operands.push(ty); + fn push_operand(&mut self, ty: T) -> Result<()> + where + T: Into> + { + let maybe_ty = ty.into(); + self.operands.push(maybe_ty); Ok(()) } @@ -331,7 +378,7 @@ impl<'resources, R: WasmModuleResources> OperatorValidatorTemp<'_, 'resources, R /// If `Some(T)` is returned then `T` was popped from the operand stack and /// matches `expected`. If `Bot` is returned then it means that `None` was /// expected and the current block is unreachable. - fn pop_operand(&mut self, offset: usize, expected: Option) -> Result { + fn pop_operand(&mut self, offset: usize, expected: Option) -> Result> { // This method is one of the hottest methods in the validator so to // improve codegen this method contains a fast-path success case where // if the top operand on the stack is as expected it's returned @@ -344,12 +391,10 @@ impl<'resources, R: WasmModuleResources> OperatorValidatorTemp<'_, 'resources, R // pop it. If we shouldn't have popped it then it's passed to the slow // path to get pushed back onto the stack. let popped = if let Some(actual_ty) = self.operands.pop() { - if let Some(expected) = expected { - if actual_ty == expected { - if let Some(control) = self.control.last() { - if self.operands.len() >= control.height { - return Ok(actual_ty); - } + if actual_ty == expected { + if let Some(control) = self.control.last() { + if self.operands.len() >= control.height { + return Ok(actual_ty); } } } @@ -369,20 +414,20 @@ impl<'resources, R: WasmModuleResources> OperatorValidatorTemp<'_, 'resources, R &mut self, offset: usize, expected: Option, - popped: Option, - ) -> Result { + popped: Option>, + ) -> Result> { self.operands.extend(popped); let control = match self.control.last() { Some(c) => c, None => return Err(self.err_beyond_end(offset)), }; - let actual_ty = if self.operands.len() == control.height && control.unreachable { - ValType::Bot + let actual = if self.operands.len() == control.height && control.unreachable { + None } else { if self.operands.len() == control.height { let desc = match expected { Some(ty) => ty_to_str(ty), - None => "a type".into(), + None => "a type", }; bail!( offset, @@ -392,36 +437,31 @@ impl<'resources, R: WasmModuleResources> OperatorValidatorTemp<'_, 'resources, R self.operands.pop().unwrap() } }; - let actual = match expected { - None => actual_ty, - Some(expected_ty) => { - if !self.resources.matches(actual_ty, expected_ty) { + if let (Some(actual_ty), Some(expected_ty)) = (actual, expected) { + if !self.resources.matches(actual_ty, expected_ty) { bail!( offset, "type mismatch: expected {}, found {}", ty_to_str(expected_ty), ty_to_str(actual_ty) ); - } else { - actual_ty - } } - }; + } Ok(actual) } fn pop_ref(&mut self, offset: usize) -> Result { match self.pop_operand(offset, None)? { - ValType::Bot => Ok(RefType { + None | Some(ValType::Bot) => Ok(RefType { nullable: false, heap_type: HeapType::Bot, }), - ValType::Ref(rt) => Ok(rt), - ty => bail!( + Some(ValType::Ref(rt)) => Ok(rt), + Some(ty) => bail!( offset, "type mismatch: expected ref but found {}", ty_to_str(ty) - ), + ) } } @@ -524,9 +564,6 @@ impl<'resources, R: WasmModuleResources> OperatorValidatorTemp<'_, 'resources, R /// Validates that `memory_index` is valid in this module, and returns the /// type of address used to index the memory specified. fn check_memory_index(&self, offset: usize, memory_index: u32) -> Result { - if memory_index > 0 && !self.features.multi_memory { - bail!(offset, "multi-memory support is not enabled"); - } match self.resources.memory_at(memory_index) { Some(mem) => Ok(mem.index_type()), None => bail!(offset, "unknown memory {}", memory_index), @@ -555,39 +592,6 @@ impl<'resources, R: WasmModuleResources> OperatorValidatorTemp<'_, 'resources, R Ok(()) } - fn check_threads_enabled(&self, offset: usize) -> Result<()> { - if !self.features.threads { - bail!(offset, "threads support is not enabled") - } - Ok(()) - } - - fn check_reference_types_enabled(&self, offset: usize) -> Result<()> { - if !self.features.reference_types { - bail!(offset, "reference types support is not enabled") - } - Ok(()) - } - - /// Checks if Wasm proposal `saturating_float_to_int` is enabled. - fn check_saturating_float_to_int_enabled(&self, offset: usize) -> Result<()> { - if !self.features.saturating_float_to_int { - bail!( - offset, - "saturating float to int conversions support is not enabled" - ); - } - Ok(()) - } - - /// Checks if Wasm proposal `sign_extension` is enabled. - fn check_sign_extension_enabled(&self, offset: usize) -> Result<()> { - if !self.features.sign_extension { - bail!(offset, "sign extension operations support is not enabled"); - } - Ok(()) - } - fn check_function_references_enabled(&self, offset: usize) -> Result<()> { if !self.features.function_references { bail!(offset, "function references support is not enabled",); @@ -602,37 +606,6 @@ impl<'resources, R: WasmModuleResources> OperatorValidatorTemp<'_, 'resources, R Ok(()) } - fn check_simd_enabled(&self, offset: usize) -> Result<()> { - if !self.features.simd { - bail!(offset, "SIMD support is not enabled"); - } - Ok(()) - } - - fn check_relaxed_simd_enabled(&self, offset: usize) -> Result<()> { - // Relaxed SIMD operators make sense only with SIMD and be non-deterministic. - self.check_non_deterministic_enabled(offset)?; - self.check_simd_enabled(offset)?; - if !self.features.relaxed_simd { - bail!(offset, "Relaxed SIMD support is not enabled"); - } - Ok(()) - } - - fn check_exceptions_enabled(&self, offset: usize) -> Result<()> { - if !self.features.exceptions { - bail!(offset, "Exceptions support is not enabled"); - } - Ok(()) - } - - fn check_bulk_memory_enabled(&self, offset: usize) -> Result<()> { - if !self.features.bulk_memory { - bail!(offset, "bulk memory support is not enabled"); - } - Ok(()) - } - fn check_shared_memarg_wo_align(&self, offset: usize, memarg: MemArg) -> Result { self.check_memory_index(offset, memarg.memory) } @@ -799,7 +772,6 @@ impl<'resources, R: WasmModuleResources> OperatorValidatorTemp<'_, 'resources, R /// Checks the validity of an atomic load operator. fn check_atomic_load(&mut self, offset: usize, memarg: MemArg, load_ty: ValType) -> Result<()> { - self.check_threads_enabled(offset)?; let ty = self.check_shared_memarg_wo_align(offset, memarg)?; self.pop_operand(offset, Some(ty))?; self.push_operand(load_ty)?; @@ -813,7 +785,6 @@ impl<'resources, R: WasmModuleResources> OperatorValidatorTemp<'_, 'resources, R memarg: MemArg, store_ty: ValType, ) -> Result<()> { - self.check_threads_enabled(offset)?; let ty = self.check_shared_memarg_wo_align(offset, memarg)?; self.pop_operand(offset, Some(store_ty))?; self.pop_operand(offset, Some(ty))?; @@ -827,7 +798,6 @@ impl<'resources, R: WasmModuleResources> OperatorValidatorTemp<'_, 'resources, R memarg: MemArg, op_ty: ValType, ) -> Result<()> { - self.check_threads_enabled(offset)?; let ty = self.check_shared_memarg_wo_align(offset, memarg)?; self.pop_operand(offset, Some(op_ty))?; self.pop_operand(offset, Some(ty))?; @@ -842,7 +812,6 @@ impl<'resources, R: WasmModuleResources> OperatorValidatorTemp<'_, 'resources, R memarg: MemArg, op_ty: ValType, ) -> Result<()> { - self.check_threads_enabled(offset)?; let ty = self.check_shared_memarg_wo_align(offset, memarg)?; self.pop_operand(offset, Some(op_ty))?; self.pop_operand(offset, Some(op_ty))?; @@ -853,7 +822,6 @@ impl<'resources, R: WasmModuleResources> OperatorValidatorTemp<'_, 'resources, R /// Checks a [`V128`] splat operator. fn check_v128_splat(&mut self, offset: usize, src_ty: ValType) -> Result<()> { - self.check_simd_enabled(offset)?; self.pop_operand(offset, Some(src_ty))?; self.push_operand(ValType::V128)?; Ok(()) @@ -861,7 +829,6 @@ impl<'resources, R: WasmModuleResources> OperatorValidatorTemp<'_, 'resources, R /// Checks a [`V128`] binary operator. fn check_v128_binary_op(&mut self, offset: usize) -> Result<()> { - self.check_simd_enabled(offset)?; self.pop_operand(offset, Some(ValType::V128))?; self.pop_operand(offset, Some(ValType::V128))?; self.push_operand(ValType::V128)?; @@ -876,7 +843,6 @@ impl<'resources, R: WasmModuleResources> OperatorValidatorTemp<'_, 'resources, R /// Checks a [`V128`] binary operator. fn check_v128_relaxed_binary_op(&mut self, offset: usize) -> Result<()> { - self.check_relaxed_simd_enabled(offset)?; self.pop_operand(offset, Some(ValType::V128))?; self.pop_operand(offset, Some(ValType::V128))?; self.push_operand(ValType::V128)?; @@ -885,7 +851,6 @@ impl<'resources, R: WasmModuleResources> OperatorValidatorTemp<'_, 'resources, R /// Checks a [`V128`] binary operator. fn check_v128_unary_op(&mut self, offset: usize) -> Result<()> { - self.check_simd_enabled(offset)?; self.pop_operand(offset, Some(ValType::V128))?; self.push_operand(ValType::V128)?; Ok(()) @@ -899,7 +864,6 @@ impl<'resources, R: WasmModuleResources> OperatorValidatorTemp<'_, 'resources, R /// Checks a [`V128`] binary operator. fn check_v128_relaxed_unary_op(&mut self, offset: usize) -> Result<()> { - self.check_relaxed_simd_enabled(offset)?; self.pop_operand(offset, Some(ValType::V128))?; self.push_operand(ValType::V128)?; Ok(()) @@ -907,7 +871,6 @@ impl<'resources, R: WasmModuleResources> OperatorValidatorTemp<'_, 'resources, R /// Checks a [`V128`] relaxed ternary operator. fn check_v128_relaxed_ternary_op(&mut self, offset: usize) -> Result<()> { - self.check_relaxed_simd_enabled(offset)?; self.pop_operand(offset, Some(ValType::V128))?; self.pop_operand(offset, Some(ValType::V128))?; self.pop_operand(offset, Some(ValType::V128))?; @@ -917,7 +880,6 @@ impl<'resources, R: WasmModuleResources> OperatorValidatorTemp<'_, 'resources, R /// Checks a [`V128`] relaxed ternary operator. fn check_v128_bitmask_op(&mut self, offset: usize) -> Result<()> { - self.check_simd_enabled(offset)?; self.pop_operand(offset, Some(ValType::V128))?; self.push_operand(ValType::I32)?; Ok(()) @@ -925,7 +887,6 @@ impl<'resources, R: WasmModuleResources> OperatorValidatorTemp<'_, 'resources, R /// Checks a [`V128`] relaxed ternary operator. fn check_v128_shift_op(&mut self, offset: usize) -> Result<()> { - self.check_simd_enabled(offset)?; self.pop_operand(offset, Some(ValType::I32))?; self.pop_operand(offset, Some(ValType::V128))?; self.push_operand(ValType::V128)?; @@ -934,7 +895,6 @@ impl<'resources, R: WasmModuleResources> OperatorValidatorTemp<'_, 'resources, R /// Checks a [`V128`] common load operator. fn check_v128_load_op(&mut self, offset: usize, memarg: MemArg) -> Result<()> { - self.check_simd_enabled(offset)?; let idx = self.check_memarg(memarg, 3, offset)?; self.pop_operand(offset, Some(idx))?; self.push_operand(ValType::V128)?; @@ -1026,6 +986,63 @@ fn ty_to_str(ty: ValType) -> &'static str { } } +/// A wrapper "visitor" around the real operator validator internally which +/// exists to check that the required wasm feature is enabled to proceed with +/// validation. +/// +/// This validator is macro-generated to ensure that the proposal listed in this +/// crate's macro matches the one that's validated here. Each instruction's +/// visit method validates the specified proposal is enabled and then delegates +/// to `OperatorValidatorTemp` to perform the actual opcode validation. +struct WasmProposalValidator<'validator, 'resources, T>( + OperatorValidatorTemp<'validator, 'resources, T>, +); + +impl WasmProposalValidator<'_, '_, T> { + fn check_enabled(&self, offset: usize, flag: bool, desc: &str) -> Result<()> { + if flag { + return Ok(()); + } + bail!(offset, "{desc} support is not enabled"); + } +} + +macro_rules! validate_proposal { + ($( @$proposal:ident $op:ident $({ $($arg:ident: $argty:ty),* })? => $visit:ident)*) => { + $( + fn $visit(&mut self, offset: usize $($(,$arg: $argty)*)?) -> Result<()> { + validate_proposal!(validate self offset $proposal); + self.0.$visit(offset $( $(,$arg)* )?) + } + )* + }; + + (validate self offset mvp) => {}; + (validate $self:ident $offset:ident $proposal:ident) => { + $self.check_enabled($offset, $self.0.features.$proposal, validate_proposal!(desc $proposal))? + }; + + (desc simd) => ("SIMD"); + (desc relaxed_simd) => ("relaxed SIMD"); + (desc threads) => ("threads"); + (desc saturating_float_to_int) => ("saturating float to int conversions"); + (desc reference_types) => ("reference types"); + (desc bulk_memory) => ("bulk memory"); + (desc sign_extension) => ("sign extension operations"); + (desc exceptions) => ("exceptions"); + (desc tail_call) => ("tail calls"); + (desc function_references) => ("function references"); +} + +impl<'a, T> VisitOperator<'a> for WasmProposalValidator<'_, '_, T> +where + T: WasmModuleResources, +{ + type Output = Result<()>; + + for_each_operator!(validate_proposal); +} + impl<'a, T> VisitOperator<'a> for OperatorValidatorTemp<'_, '_, T> where T: WasmModuleResources, @@ -1073,7 +1090,6 @@ where Ok(()) } fn visit_try(&mut self, offset: usize, ty: BlockType) -> Self::Output { - self.check_exceptions_enabled(offset)?; self.check_block_type(offset, ty)?; for ty in self.params(offset, ty)?.rev() { self.pop_operand(offset, Some(ty))?; @@ -1082,7 +1098,6 @@ where Ok(()) } fn visit_catch(&mut self, offset: usize, index: u32) -> Self::Output { - self.check_exceptions_enabled(offset)?; let frame = self.pop_ctrl(offset)?; if frame.kind != FrameKind::Try && frame.kind != FrameKind::Catch { bail!(offset, "catch found outside of an `try` block"); @@ -1103,7 +1118,6 @@ where Ok(()) } fn visit_throw(&mut self, offset: usize, index: u32) -> Self::Output { - self.check_exceptions_enabled(offset)?; // Check values associated with the exception. let ty = self.tag_at(index, offset)?; for ty in ty.inputs().rev() { @@ -1116,7 +1130,6 @@ where Ok(()) } fn visit_rethrow(&mut self, offset: usize, relative_depth: u32) -> Self::Output { - self.check_exceptions_enabled(offset)?; // This is not a jump, but we need to check that the `rethrow` // targets an actual `catch` to get the exception. let (_, kind) = self.jump(offset, relative_depth)?; @@ -1130,7 +1143,6 @@ where Ok(()) } fn visit_delegate(&mut self, offset: usize, relative_depth: u32) -> Self::Output { - self.check_exceptions_enabled(offset)?; let frame = self.pop_ctrl(offset)?; if frame.kind != FrameKind::Try { bail!(offset, "delegate found outside of an `try` block"); @@ -1144,7 +1156,6 @@ where Ok(()) } fn visit_catch_all(&mut self, offset: usize) -> Self::Output { - self.check_exceptions_enabled(offset)?; let frame = self.pop_ctrl(offset)?; if frame.kind == FrameKind::CatchAll { bail!(offset, "only one catch_all allowed per `try` block"); @@ -1243,12 +1254,12 @@ where self.check_return(offset)?; Ok(()) } - fn visit_call_ref(&mut self, offset: usize, ty: HeapType) -> Self::Output { + fn visit_call_ref(&mut self, offset: usize, hty: HeapType) -> Self::Output { self.check_function_references_enabled(offset)?; let rt = self.pop_ref(offset)?; let expected = RefType { nullable: true, - heap_type: ty, + heap_type: hty, }; if !self .resources @@ -1259,7 +1270,7 @@ where "type mismatch: funcref on stack does not match specified type", ); } - match ty { + match hty { HeapType::Index(type_index) => self.check_call_ty(offset, type_index)?, HeapType::Bot => (), _ => bail!( @@ -1269,9 +1280,9 @@ where } Ok(()) } - fn visit_return_call_ref(&mut self, offset: usize, ty: HeapType) -> Self::Output { + fn visit_return_call_ref(&mut self, offset: usize, hty: HeapType) -> Self::Output { self.check_tail_call_enabled(offset)?; - self.visit_call_ref(offset, ty)?; + self.visit_call_ref(offset, hty)?; self.check_return(offset) } fn visit_call_indirect( @@ -1306,27 +1317,27 @@ where self.pop_operand(offset, Some(ValType::I32))?; let ty1 = self.pop_operand(offset, None)?; let ty2 = self.pop_operand(offset, None)?; - fn is_num(ty: ValType) -> bool { + fn is_num(ty: Option) -> bool { matches!( ty, - ValType::I32 - | ValType::I64 - | ValType::F32 - | ValType::F64 - | ValType::V128 - | ValType::Bot + Some(ValType::I32) + | Some(ValType::I64) + | Some(ValType::F32) + | Some(ValType::F64) + | Some(ValType::V128) + | None ) } if !is_num(ty1) || !is_num(ty2) { bail!(offset, "type mismatch: select only takes integral types") } - if ty1 != ty2 && ty1 != ValType::Bot && ty2 != ValType::Bot { + if ty1 != ty2 && ty1 != Some(ValType::Bot) && ty2 != Some(ValType::Bot) { bail!( offset, "type mismatch: select operands have different types" ); } - self.push_operand(if ty1 == ValType::Bot { ty2 } else { ty1 })?; + self.push_operand(if ty1 == Some(ValType::Bot) { ty2 } else { ty1 })?; Ok(()) } fn visit_typed_select(&mut self, offset: usize, ty: ValType) -> Self::Output { @@ -1912,55 +1923,42 @@ where self.check_fconversion_op(offset, ValType::F64, ValType::I64) } fn visit_i32_trunc_sat_f32_s(&mut self, offset: usize) -> Self::Output { - self.check_saturating_float_to_int_enabled(offset)?; self.check_conversion_op(offset, ValType::I32, ValType::F32) } fn visit_i32_trunc_sat_f32_u(&mut self, offset: usize) -> Self::Output { - self.check_saturating_float_to_int_enabled(offset)?; self.check_conversion_op(offset, ValType::I32, ValType::F32) } fn visit_i32_trunc_sat_f64_s(&mut self, offset: usize) -> Self::Output { - self.check_saturating_float_to_int_enabled(offset)?; self.check_conversion_op(offset, ValType::I32, ValType::F64) } fn visit_i32_trunc_sat_f64_u(&mut self, offset: usize) -> Self::Output { - self.check_saturating_float_to_int_enabled(offset)?; self.check_conversion_op(offset, ValType::I32, ValType::F64) } fn visit_i64_trunc_sat_f32_s(&mut self, offset: usize) -> Self::Output { - self.check_saturating_float_to_int_enabled(offset)?; self.check_conversion_op(offset, ValType::I64, ValType::F32) } fn visit_i64_trunc_sat_f32_u(&mut self, offset: usize) -> Self::Output { - self.check_saturating_float_to_int_enabled(offset)?; self.check_conversion_op(offset, ValType::I64, ValType::F32) } fn visit_i64_trunc_sat_f64_s(&mut self, offset: usize) -> Self::Output { - self.check_saturating_float_to_int_enabled(offset)?; self.check_conversion_op(offset, ValType::I64, ValType::F64) } fn visit_i64_trunc_sat_f64_u(&mut self, offset: usize) -> Self::Output { - self.check_saturating_float_to_int_enabled(offset)?; self.check_conversion_op(offset, ValType::I64, ValType::F64) } fn visit_i32_extend8_s(&mut self, offset: usize) -> Self::Output { - self.check_sign_extension_enabled(offset)?; self.check_unary_op(offset, ValType::I32) } fn visit_i32_extend16_s(&mut self, offset: usize) -> Self::Output { - self.check_sign_extension_enabled(offset)?; self.check_unary_op(offset, ValType::I32) } fn visit_i64_extend8_s(&mut self, offset: usize) -> Self::Output { - self.check_sign_extension_enabled(offset)?; self.check_unary_op(offset, ValType::I64) } fn visit_i64_extend16_s(&mut self, offset: usize) -> Self::Output { - self.check_sign_extension_enabled(offset)?; self.check_unary_op(offset, ValType::I64) } fn visit_i64_extend32_s(&mut self, offset: usize) -> Self::Output { - self.check_sign_extension_enabled(offset)?; self.check_unary_op(offset, ValType::I64) } fn visit_i32_atomic_load(&mut self, offset: usize, memarg: MemArg) -> Self::Output { @@ -2156,7 +2154,6 @@ where self.check_atomic_binary_op(offset, memarg, ValType::I32) } fn visit_memory_atomic_wait32(&mut self, offset: usize, memarg: MemArg) -> Self::Output { - self.check_threads_enabled(offset)?; let ty = self.check_shared_memarg_wo_align(offset, memarg)?; self.pop_operand(offset, Some(ValType::I64))?; self.pop_operand(offset, Some(ValType::I32))?; @@ -2165,7 +2162,6 @@ where Ok(()) } fn visit_memory_atomic_wait64(&mut self, offset: usize, memarg: MemArg) -> Self::Output { - self.check_threads_enabled(offset)?; let ty = self.check_shared_memarg_wo_align(offset, memarg)?; self.pop_operand(offset, Some(ValType::I64))?; self.pop_operand(offset, Some(ValType::I64))?; @@ -2173,15 +2169,10 @@ where self.push_operand(ValType::I32)?; Ok(()) } - fn visit_atomic_fence(&mut self, offset: usize, flags: u8) -> Self::Output { - self.check_threads_enabled(offset)?; - if flags != 0 { - bail!(offset, "non-zero flags for fence not supported yet"); - } + fn visit_atomic_fence(&mut self, _offset: usize) -> Self::Output { Ok(()) } fn visit_ref_null(&mut self, offset: usize, heap_type: HeapType) -> Self::Output { - self.check_reference_types_enabled(offset)?; match heap_type { HeapType::Extern | HeapType::Func | HeapType::Bot => {} HeapType::Index(_) => self.check_function_references_enabled(offset)?, @@ -2258,13 +2249,11 @@ where Ok(()) } fn visit_ref_is_null(&mut self, offset: usize) -> Self::Output { - self.check_reference_types_enabled(offset)?; self.pop_ref(offset)?; self.push_operand(ValType::I32)?; Ok(()) } fn visit_ref_func(&mut self, offset: usize, function_index: u32) -> Self::Output { - self.check_reference_types_enabled(offset)?; let type_index = match self.resources.type_index_of_function(function_index) { Some(idx) => idx, None => bail!( @@ -2283,21 +2272,18 @@ where Ok(()) } fn visit_v128_load(&mut self, offset: usize, memarg: MemArg) -> Self::Output { - self.check_simd_enabled(offset)?; let ty = self.check_memarg(memarg, 4, offset)?; self.pop_operand(offset, Some(ty))?; self.push_operand(ValType::V128)?; Ok(()) } fn visit_v128_store(&mut self, offset: usize, memarg: MemArg) -> Self::Output { - self.check_simd_enabled(offset)?; let ty = self.check_memarg(memarg, 4, offset)?; self.pop_operand(offset, Some(ValType::V128))?; self.pop_operand(offset, Some(ty))?; Ok(()) } - fn visit_v128_const(&mut self, offset: usize, _value: V128) -> Self::Output { - self.check_simd_enabled(offset)?; + fn visit_v128_const(&mut self, _offset: usize, _value: V128) -> Self::Output { self.push_operand(ValType::V128)?; Ok(()) } @@ -2322,7 +2308,6 @@ where self.check_v128_splat(offset, ValType::F64) } fn visit_i8x16_extract_lane_s(&mut self, offset: usize, lane: u8) -> Self::Output { - self.check_simd_enabled(offset)?; self.check_simd_lane_index(offset, lane, 16)?; self.pop_operand(offset, Some(ValType::V128))?; self.push_operand(ValType::I32)?; @@ -2332,7 +2317,6 @@ where self.visit_i8x16_extract_lane_s(input, lane) } fn visit_i16x8_extract_lane_s(&mut self, offset: usize, lane: u8) -> Self::Output { - self.check_simd_enabled(offset)?; self.check_simd_lane_index(offset, lane, 8)?; self.pop_operand(offset, Some(ValType::V128))?; self.push_operand(ValType::I32)?; @@ -2342,14 +2326,12 @@ where self.visit_i16x8_extract_lane_s(input, lane) } fn visit_i32x4_extract_lane(&mut self, offset: usize, lane: u8) -> Self::Output { - self.check_simd_enabled(offset)?; self.check_simd_lane_index(offset, lane, 4)?; self.pop_operand(offset, Some(ValType::V128))?; self.push_operand(ValType::I32)?; Ok(()) } fn visit_i8x16_replace_lane(&mut self, offset: usize, lane: u8) -> Self::Output { - self.check_simd_enabled(offset)?; self.check_simd_lane_index(offset, lane, 16)?; self.pop_operand(offset, Some(ValType::I32))?; self.pop_operand(offset, Some(ValType::V128))?; @@ -2357,7 +2339,6 @@ where Ok(()) } fn visit_i16x8_replace_lane(&mut self, offset: usize, lane: u8) -> Self::Output { - self.check_simd_enabled(offset)?; self.check_simd_lane_index(offset, lane, 8)?; self.pop_operand(offset, Some(ValType::I32))?; self.pop_operand(offset, Some(ValType::V128))?; @@ -2365,7 +2346,6 @@ where Ok(()) } fn visit_i32x4_replace_lane(&mut self, offset: usize, lane: u8) -> Self::Output { - self.check_simd_enabled(offset)?; self.check_simd_lane_index(offset, lane, 4)?; self.pop_operand(offset, Some(ValType::I32))?; self.pop_operand(offset, Some(ValType::V128))?; @@ -2373,14 +2353,12 @@ where Ok(()) } fn visit_i64x2_extract_lane(&mut self, offset: usize, lane: u8) -> Self::Output { - self.check_simd_enabled(offset)?; self.check_simd_lane_index(offset, lane, 2)?; self.pop_operand(offset, Some(ValType::V128))?; self.push_operand(ValType::I64)?; Ok(()) } fn visit_i64x2_replace_lane(&mut self, offset: usize, lane: u8) -> Self::Output { - self.check_simd_enabled(offset)?; self.check_simd_lane_index(offset, lane, 2)?; self.pop_operand(offset, Some(ValType::I64))?; self.pop_operand(offset, Some(ValType::V128))?; @@ -2389,7 +2367,6 @@ where } fn visit_f32x4_extract_lane(&mut self, offset: usize, lane: u8) -> Self::Output { self.check_non_deterministic_enabled(offset)?; - self.check_simd_enabled(offset)?; self.check_simd_lane_index(offset, lane, 4)?; self.pop_operand(offset, Some(ValType::V128))?; self.push_operand(ValType::F32)?; @@ -2397,7 +2374,6 @@ where } fn visit_f32x4_replace_lane(&mut self, offset: usize, lane: u8) -> Self::Output { self.check_non_deterministic_enabled(offset)?; - self.check_simd_enabled(offset)?; self.check_simd_lane_index(offset, lane, 4)?; self.pop_operand(offset, Some(ValType::F32))?; self.pop_operand(offset, Some(ValType::V128))?; @@ -2406,7 +2382,6 @@ where } fn visit_f64x2_extract_lane(&mut self, offset: usize, lane: u8) -> Self::Output { self.check_non_deterministic_enabled(offset)?; - self.check_simd_enabled(offset)?; self.check_simd_lane_index(offset, lane, 2)?; self.pop_operand(offset, Some(ValType::V128))?; self.push_operand(ValType::F64)?; @@ -2414,7 +2389,6 @@ where } fn visit_f64x2_replace_lane(&mut self, offset: usize, lane: u8) -> Self::Output { self.check_non_deterministic_enabled(offset)?; - self.check_simd_enabled(offset)?; self.check_simd_lane_index(offset, lane, 2)?; self.pop_operand(offset, Some(ValType::F64))?; self.pop_operand(offset, Some(ValType::V128))?; @@ -2517,6 +2491,12 @@ where fn visit_f64x2_relaxed_max(&mut self, offset: usize) -> Self::Output { self.check_v128_relaxed_binary_op(offset) } + fn visit_i16x8_relaxed_q15mulr_s(&mut self, offset: usize) -> Self::Output { + self.check_v128_relaxed_binary_op(offset) + } + fn visit_i16x8_dot_i8x16_i7x16_s(&mut self, offset: usize) -> Self::Output { + self.check_v128_relaxed_binary_op(offset) + } fn visit_i8x16_eq(&mut self, offset: usize) -> Self::Output { self.check_v128_binary_op(offset) } @@ -2953,35 +2933,40 @@ where self.check_v128_relaxed_unary_op(offset) } fn visit_v128_bitselect(&mut self, offset: usize) -> Self::Output { - self.check_simd_enabled(offset)?; self.pop_operand(offset, Some(ValType::V128))?; self.pop_operand(offset, Some(ValType::V128))?; self.pop_operand(offset, Some(ValType::V128))?; self.push_operand(ValType::V128)?; Ok(()) } - fn visit_f32x4_fma(&mut self, offset: usize) -> Self::Output { + fn visit_f32x4_relaxed_fma(&mut self, offset: usize) -> Self::Output { self.check_v128_relaxed_ternary_op(offset) } - fn visit_f32x4_fms(&mut self, offset: usize) -> Self::Output { + fn visit_f32x4_relaxed_fnma(&mut self, offset: usize) -> Self::Output { self.check_v128_relaxed_ternary_op(offset) } - fn visit_f64x2_fma(&mut self, offset: usize) -> Self::Output { + fn visit_f64x2_relaxed_fma(&mut self, offset: usize) -> Self::Output { self.check_v128_relaxed_ternary_op(offset) } - fn visit_f64x2_fms(&mut self, offset: usize) -> Self::Output { + fn visit_f64x2_relaxed_fnma(&mut self, offset: usize) -> Self::Output { self.check_v128_relaxed_ternary_op(offset) } - fn visit_i8x16_laneselect(&mut self, offset: usize) -> Self::Output { + fn visit_i8x16_relaxed_laneselect(&mut self, offset: usize) -> Self::Output { self.check_v128_relaxed_ternary_op(offset) } - fn visit_i16x8_laneselect(&mut self, offset: usize) -> Self::Output { + fn visit_i16x8_relaxed_laneselect(&mut self, offset: usize) -> Self::Output { self.check_v128_relaxed_ternary_op(offset) } - fn visit_i32x4_laneselect(&mut self, offset: usize) -> Self::Output { + fn visit_i32x4_relaxed_laneselect(&mut self, offset: usize) -> Self::Output { self.check_v128_relaxed_ternary_op(offset) } - fn visit_i64x2_laneselect(&mut self, offset: usize) -> Self::Output { + fn visit_i64x2_relaxed_laneselect(&mut self, offset: usize) -> Self::Output { + self.check_v128_relaxed_ternary_op(offset) + } + fn visit_i32x4_dot_i8x16_i7x16_add_s(&mut self, offset: usize) -> Self::Output { + self.check_v128_relaxed_ternary_op(offset) + } + fn visit_f32x4_relaxed_dot_bf16x8_add_f32x4(&mut self, offset: usize) -> Self::Output { self.check_v128_relaxed_ternary_op(offset) } fn visit_v128_any_true(&mut self, offset: usize) -> Self::Output { @@ -3048,21 +3033,18 @@ where self.check_v128_shift_op(offset) } fn visit_i8x16_swizzle(&mut self, offset: usize) -> Self::Output { - self.check_simd_enabled(offset)?; self.pop_operand(offset, Some(ValType::V128))?; self.pop_operand(offset, Some(ValType::V128))?; self.push_operand(ValType::V128)?; Ok(()) } fn visit_i8x16_relaxed_swizzle(&mut self, offset: usize) -> Self::Output { - self.check_relaxed_simd_enabled(offset)?; self.pop_operand(offset, Some(ValType::V128))?; self.pop_operand(offset, Some(ValType::V128))?; self.push_operand(ValType::V128)?; Ok(()) } fn visit_i8x16_shuffle(&mut self, offset: usize, lanes: [u8; 16]) -> Self::Output { - self.check_simd_enabled(offset)?; self.pop_operand(offset, Some(ValType::V128))?; self.pop_operand(offset, Some(ValType::V128))?; for i in lanes { @@ -3072,21 +3054,18 @@ where Ok(()) } fn visit_v128_load8_splat(&mut self, offset: usize, memarg: MemArg) -> Self::Output { - self.check_simd_enabled(offset)?; let ty = self.check_memarg(memarg, 0, offset)?; self.pop_operand(offset, Some(ty))?; self.push_operand(ValType::V128)?; Ok(()) } fn visit_v128_load16_splat(&mut self, offset: usize, memarg: MemArg) -> Self::Output { - self.check_simd_enabled(offset)?; let ty = self.check_memarg(memarg, 1, offset)?; self.pop_operand(offset, Some(ty))?; self.push_operand(ValType::V128)?; Ok(()) } fn visit_v128_load32_splat(&mut self, offset: usize, memarg: MemArg) -> Self::Output { - self.check_simd_enabled(offset)?; let ty = self.check_memarg(memarg, 2, offset)?; self.pop_operand(offset, Some(ty))?; self.push_operand(ValType::V128)?; @@ -3120,7 +3099,6 @@ where self.check_v128_load_op(offset, memarg) } fn visit_v128_load8_lane(&mut self, offset: usize, memarg: MemArg, lane: u8) -> Self::Output { - self.check_simd_enabled(offset)?; let idx = self.check_memarg(memarg, 0, offset)?; self.check_simd_lane_index(offset, lane, 16)?; self.pop_operand(offset, Some(ValType::V128))?; @@ -3129,7 +3107,6 @@ where Ok(()) } fn visit_v128_load16_lane(&mut self, offset: usize, memarg: MemArg, lane: u8) -> Self::Output { - self.check_simd_enabled(offset)?; let idx = self.check_memarg(memarg, 1, offset)?; self.check_simd_lane_index(offset, lane, 8)?; self.pop_operand(offset, Some(ValType::V128))?; @@ -3138,7 +3115,6 @@ where Ok(()) } fn visit_v128_load32_lane(&mut self, offset: usize, memarg: MemArg, lane: u8) -> Self::Output { - self.check_simd_enabled(offset)?; let idx = self.check_memarg(memarg, 2, offset)?; self.check_simd_lane_index(offset, lane, 4)?; self.pop_operand(offset, Some(ValType::V128))?; @@ -3147,7 +3123,6 @@ where Ok(()) } fn visit_v128_load64_lane(&mut self, offset: usize, memarg: MemArg, lane: u8) -> Self::Output { - self.check_simd_enabled(offset)?; let idx = self.check_memarg(memarg, 3, offset)?; self.check_simd_lane_index(offset, lane, 2)?; self.pop_operand(offset, Some(ValType::V128))?; @@ -3156,7 +3131,6 @@ where Ok(()) } fn visit_v128_store8_lane(&mut self, offset: usize, memarg: MemArg, lane: u8) -> Self::Output { - self.check_simd_enabled(offset)?; let idx = self.check_memarg(memarg, 0, offset)?; self.check_simd_lane_index(offset, lane, 16)?; self.pop_operand(offset, Some(ValType::V128))?; @@ -3164,7 +3138,6 @@ where Ok(()) } fn visit_v128_store16_lane(&mut self, offset: usize, memarg: MemArg, lane: u8) -> Self::Output { - self.check_simd_enabled(offset)?; let idx = self.check_memarg(memarg, 1, offset)?; self.check_simd_lane_index(offset, lane, 8)?; self.pop_operand(offset, Some(ValType::V128))?; @@ -3172,7 +3145,6 @@ where Ok(()) } fn visit_v128_store32_lane(&mut self, offset: usize, memarg: MemArg, lane: u8) -> Self::Output { - self.check_simd_enabled(offset)?; let idx = self.check_memarg(memarg, 2, offset)?; self.check_simd_lane_index(offset, lane, 4)?; self.pop_operand(offset, Some(ValType::V128))?; @@ -3180,7 +3152,6 @@ where Ok(()) } fn visit_v128_store64_lane(&mut self, offset: usize, memarg: MemArg, lane: u8) -> Self::Output { - self.check_simd_enabled(offset)?; let idx = self.check_memarg(memarg, 3, offset)?; self.check_simd_lane_index(offset, lane, 2)?; self.pop_operand(offset, Some(ValType::V128))?; @@ -3188,7 +3159,6 @@ where Ok(()) } fn visit_memory_init(&mut self, offset: usize, segment: u32, mem: u32) -> Self::Output { - self.check_bulk_memory_enabled(offset)?; let ty = self.check_memory_index(offset, mem)?; match self.resources.data_count() { None => bail!(offset, "data count section required"), @@ -3201,7 +3171,6 @@ where Ok(()) } fn visit_data_drop(&mut self, offset: usize, segment: u32) -> Self::Output { - self.check_bulk_memory_enabled(offset)?; match self.resources.data_count() { None => bail!(offset, "data count section required"), Some(count) if segment < count => {} @@ -3210,7 +3179,6 @@ where Ok(()) } fn visit_memory_copy(&mut self, offset: usize, dst: u32, src: u32) -> Self::Output { - self.check_bulk_memory_enabled(offset)?; let dst_ty = self.check_memory_index(offset, dst)?; let src_ty = self.check_memory_index(offset, src)?; @@ -3231,7 +3199,6 @@ where Ok(()) } fn visit_memory_fill(&mut self, offset: usize, mem: u32) -> Self::Output { - self.check_bulk_memory_enabled(offset)?; let ty = self.check_memory_index(offset, mem)?; self.pop_operand(offset, Some(ty))?; self.pop_operand(offset, Some(ValType::I32))?; @@ -3239,10 +3206,7 @@ where Ok(()) } fn visit_table_init(&mut self, offset: usize, segment: u32, table: u32) -> Self::Output { - self.check_bulk_memory_enabled(offset)?; - if table > 0 { - self.check_reference_types_enabled(offset)?; - } + if table > 0 {} let table = match self.resources.table_at(table) { Some(table) => table, None => bail!(offset, "unknown table {}: table index out of bounds", table), @@ -3264,7 +3228,6 @@ where Ok(()) } fn visit_elem_drop(&mut self, offset: usize, segment: u32) -> Self::Output { - self.check_bulk_memory_enabled(offset)?; if segment >= self.resources.element_count() { bail!( offset, @@ -3275,10 +3238,7 @@ where Ok(()) } fn visit_table_copy(&mut self, offset: usize, dst_table: u32, src_table: u32) -> Self::Output { - self.check_bulk_memory_enabled(offset)?; - if src_table > 0 || dst_table > 0 { - self.check_reference_types_enabled(offset)?; - } + if src_table > 0 || dst_table > 0 {} let (src, dst) = match ( self.resources.table_at(src_table), self.resources.table_at(dst_table), @@ -3298,7 +3258,6 @@ where Ok(()) } fn visit_table_get(&mut self, offset: usize, table: u32) -> Self::Output { - self.check_reference_types_enabled(offset)?; let ty = match self.resources.table_at(table) { Some(ty) => ty.element_type, None => bail!(offset, "table index out of bounds"), @@ -3308,7 +3267,6 @@ where Ok(()) } fn visit_table_set(&mut self, offset: usize, table: u32) -> Self::Output { - self.check_reference_types_enabled(offset)?; let ty = match self.resources.table_at(table) { Some(ty) => ty.element_type, None => bail!(offset, "table index out of bounds"), @@ -3318,7 +3276,6 @@ where Ok(()) } fn visit_table_grow(&mut self, offset: usize, table: u32) -> Self::Output { - self.check_reference_types_enabled(offset)?; let ty = match self.resources.table_at(table) { Some(ty) => ty.element_type, None => bail!(offset, "table index out of bounds"), @@ -3329,7 +3286,6 @@ where Ok(()) } fn visit_table_size(&mut self, offset: usize, table: u32) -> Self::Output { - self.check_reference_types_enabled(offset)?; if self.resources.table_at(table).is_none() { bail!(offset, "table index out of bounds"); } @@ -3337,7 +3293,6 @@ where Ok(()) } fn visit_table_fill(&mut self, offset: usize, table: u32) -> Self::Output { - self.check_bulk_memory_enabled(offset)?; let ty = match self.resources.table_at(table) { Some(ty) => ty.element_type, None => bail!(offset, "table index out of bounds"), diff --git a/crates/wasmparser/src/validator/types.rs b/crates/wasmparser/src/validator/types.rs index 36d917b1fc..c2d653fd20 100644 --- a/crates/wasmparser/src/validator/types.rs +++ b/crates/wasmparser/src/validator/types.rs @@ -141,6 +141,14 @@ pub struct TypeId { pub(crate) type_size: usize, /// The index into the global list of types. pub(crate) index: usize, + /// The original type index. + /// + /// This will be `None` for implicitly defined types, e.g. types for + /// modules definitions, component definitions, instantiations, and function + /// lowerings. + pub(crate) type_index: Option, + /// Whether or not the type is a core type. + pub(crate) is_core: bool, } /// A unified type definition for validating WebAssembly modules and components. @@ -706,7 +714,7 @@ pub struct ComponentFuncType { /// The effective type size for the component function type. pub(crate) type_size: usize, /// The function parameters. - pub params: Box<[(Option, ComponentValType)]>, + pub params: Box<[(String, ComponentValType)]>, /// The function's results. pub results: Box<[(Option, ComponentValType)]>, } diff --git a/crates/wasmprinter/Cargo.toml b/crates/wasmprinter/Cargo.toml index b78352bde5..3a0e5d24e3 100644 --- a/crates/wasmprinter/Cargo.toml +++ b/crates/wasmprinter/Cargo.toml @@ -1,8 +1,8 @@ [package] name = "wasmprinter" -version = "0.2.39" +version = "0.2.41" authors = ["Alex Crichton "] -edition = "2021" +edition.workspace = true license = "Apache-2.0 WITH LLVM-exception" readme = "README.md" repository = "https://github.com/bytecodealliance/wasm-tools/tree/main/crates/wasmprinter" @@ -13,13 +13,12 @@ Rust converter from the WebAssembly binary format to the text format. """ [dependencies] -anyhow = "1.0" -wasmparser = { path = '../wasmparser', version = '0.90.0' } +anyhow = { workspace = true } +wasmparser = { workspace = true } [dev-dependencies] diff = "0.1" -getopts = "0.2" -rayon = "1.0" +rayon = { workspace = true } tempfile = "3.0" wat = { path = "../wat" } wast = { path = "../wast" } diff --git a/crates/wasmprinter/README.md b/crates/wasmprinter/README.md index ee31c4cd2c..fe9dc460c5 100644 --- a/crates/wasmprinter/README.md +++ b/crates/wasmprinter/README.md @@ -16,11 +16,10 @@ ## Usage -This crate is published on `crates.io`, so you can depend on it with: +Add `wasmprinter` to your `Cargo.toml` -```toml -[dependencies] -wasmprinter = "0.2.0" +```sh +$ cargo add wasmprinter ``` You can then convert wasm binaries to strings like so: diff --git a/crates/wasmprinter/src/lib.rs b/crates/wasmprinter/src/lib.rs index 3ca6e2187e..8d4a80f5f5 100644 --- a/crates/wasmprinter/src/lib.rs +++ b/crates/wasmprinter/src/lib.rs @@ -1648,10 +1648,8 @@ impl Printer { for (name, ty) in ty.params.iter() { self.result.push(' '); self.start_group("param "); - if let Some(name) = name { - self.print_str(name)?; - self.result.push(' '); - } + self.print_str(name)?; + self.result.push(' '); self.print_component_val_type(state, ty)?; self.end_group() } diff --git a/crates/wasmprinter/src/operator.rs b/crates/wasmprinter/src/operator.rs index c697d02b77..22051a2fee 100644 --- a/crates/wasmprinter/src/operator.rs +++ b/crates/wasmprinter/src/operator.rs @@ -29,7 +29,11 @@ impl<'a, 'b> PrintOperator<'a, 'b> { } fn print_blockty(&mut self, ty: &BlockType) -> Result<()> { - self.printer.print_blockty(self.state, ty, self.cur_depth()) + // Note that 1 is added to the current depth here since if a block type + // is being printed then a block is being created which will increase + // the label depth of the block itself. + self.printer + .print_blockty(self.state, ty, self.cur_depth() + 1) } fn cur_depth(&self) -> u32 { @@ -1100,7 +1104,7 @@ impl<'a> VisitOperator<'a> for PrintOperator<'_, '_> { self.mem_instr("i64.atomic.rmw32.cmpxchg_u", &memarg, 4) } - fn visit_atomic_fence(&mut self, _pos: usize, _flags: u8) -> Self::Output { + fn visit_atomic_fence(&mut self, _pos: usize) -> Self::Output { self.instr("atomic.fence") } @@ -1299,6 +1303,12 @@ impl<'a> VisitOperator<'a> for PrintOperator<'_, '_> { fn visit_f64x2_relaxed_max(&mut self, _pos: usize) -> Self::Output { self.instr("f64x2.relaxed_max") } + fn visit_i16x8_relaxed_q15mulr_s(&mut self, _pos: usize) -> Self::Output { + self.instr("i16x8.relaxed_q15mulr_s") + } + fn visit_i16x8_dot_i8x16_i7x16_s(&mut self, _pos: usize) -> Self::Output { + self.instr("i16x8.dot_i8x16_i7x16_s") + } fn visit_i8x16_eq(&mut self, _pos: usize) -> Self::Output { self.instr("i8x16.eq") @@ -1751,29 +1761,35 @@ impl<'a> VisitOperator<'a> for PrintOperator<'_, '_> { fn visit_v128_bitselect(&mut self, _pos: usize) -> Self::Output { self.instr("v128.bitselect") } - fn visit_f32x4_fma(&mut self, _pos: usize) -> Self::Output { - self.instr("f32x4.fma") + fn visit_f32x4_relaxed_fma(&mut self, _pos: usize) -> Self::Output { + self.instr("f32x4.relaxed_fma") + } + fn visit_f32x4_relaxed_fnma(&mut self, _pos: usize) -> Self::Output { + self.instr("f32x4.relaxed_fnma") + } + fn visit_f64x2_relaxed_fma(&mut self, _pos: usize) -> Self::Output { + self.instr("f64x2.relaxed_fma") } - fn visit_f32x4_fms(&mut self, _pos: usize) -> Self::Output { - self.instr("f32x4.fms") + fn visit_f64x2_relaxed_fnma(&mut self, _pos: usize) -> Self::Output { + self.instr("f64x2.relaxed_fnma") } - fn visit_f64x2_fma(&mut self, _pos: usize) -> Self::Output { - self.instr("f64x2.fma") + fn visit_i8x16_relaxed_laneselect(&mut self, _pos: usize) -> Self::Output { + self.instr("i8x16.relaxed_laneselect") } - fn visit_f64x2_fms(&mut self, _pos: usize) -> Self::Output { - self.instr("f64x2.fms") + fn visit_i16x8_relaxed_laneselect(&mut self, _pos: usize) -> Self::Output { + self.instr("i16x8.relaxed_laneselect") } - fn visit_i8x16_laneselect(&mut self, _pos: usize) -> Self::Output { - self.instr("i8x16.laneselect") + fn visit_i32x4_relaxed_laneselect(&mut self, _pos: usize) -> Self::Output { + self.instr("i32x4.relaxed_laneselect") } - fn visit_i16x8_laneselect(&mut self, _pos: usize) -> Self::Output { - self.instr("i16x8.laneselect") + fn visit_i64x2_relaxed_laneselect(&mut self, _pos: usize) -> Self::Output { + self.instr("i64x2.relaxed_laneselect") } - fn visit_i32x4_laneselect(&mut self, _pos: usize) -> Self::Output { - self.instr("i32x4.laneselect") + fn visit_i32x4_dot_i8x16_i7x16_add_s(&mut self, _pos: usize) -> Self::Output { + self.instr("i32x4.dot_i8x16_i7x16_add_s") } - fn visit_i64x2_laneselect(&mut self, _pos: usize) -> Self::Output { - self.instr("i64x2.laneselect") + fn visit_f32x4_relaxed_dot_bf16x8_add_f32x4(&mut self, _pos: usize) -> Self::Output { + self.instr("f32x4.relaxed_dot_bf16x8_add_f32x4") } fn visit_v128_any_true(&mut self, _pos: usize) -> Self::Output { self.instr("v128.any_true") diff --git a/crates/wast/Cargo.toml b/crates/wast/Cargo.toml index 0c2bb35c26..55d4b42e7b 100644 --- a/crates/wast/Cargo.toml +++ b/crates/wast/Cargo.toml @@ -1,8 +1,8 @@ [package] name = "wast" -version = "46.0.0" +version = "47.0.1" authors = ["Alex Crichton "] -edition = "2021" +edition.workspace = true license = "Apache-2.0 WITH LLVM-exception" readme = "README.md" repository = "https://github.com/bytecodealliance/wasm-tools/tree/main/crates/wast" @@ -13,14 +13,14 @@ Customizable Rust parsers for the WebAssembly Text formats WAT and WAST """ [dependencies] -leb128 = "0.2" +leb128 = { workspace = true } unicode-width = "0.1.9" memchr = "2.4.1" -wasm-encoder = { version = "0.16.0", path = "../wasm-encoder" } +wasm-encoder = { workspace = true } [dev-dependencies] -anyhow = "1.0" -rayon = "1.0" +anyhow = { workspace = true } +rayon = { workspace = true } wasmparser = { path = "../wasmparser" } wat = { path = "../wat" } diff --git a/crates/wast/README.md b/crates/wast/README.md index 548a3630e8..b52a992eda 100644 --- a/crates/wast/README.md +++ b/crates/wast/README.md @@ -17,11 +17,10 @@ ## Usage -Add this to your `Cargo.toml`: +Add `wast` to your `Cargo.toml` -```toml -[dependencies] -wast = "22.0" +```sh +$ cargo add wast ``` The intent of this crate is to provide utilities, combinators, and built-in @@ -45,9 +44,8 @@ crate, however, to parse simply an s-expression wasm-related format (like only include a lexer, the parsing framework, and a few basic token-related parsers. -```toml -[dependencies] -wast = { version = "22.0", default-features = false } +```sh +$ cargo add wast --no-default-features ``` # License diff --git a/crates/wast/src/component/binary.rs b/crates/wast/src/component/binary.rs index 2084f2f15c..13799a2f06 100644 --- a/crates/wast/src/component/binary.rs +++ b/crates/wast/src/component/binary.rs @@ -78,11 +78,7 @@ fn encode_type(encoder: ComponentTypeEncoder, ty: &TypeDef) { } TypeDef::Func(f) => { let mut encoder = encoder.function(); - if f.params.len() == 1 && f.params[0].name.is_none() { - encoder.param(&f.params[0].ty); - } else { - encoder.params(f.params.iter().map(|p| (p.name.unwrap_or(""), &p.ty))); - } + encoder.params(f.params.iter().map(|p| (p.name, &p.ty))); if f.results.len() == 1 && f.results[0].name.is_none() { encoder.result(&f.results[0].ty); diff --git a/crates/wast/src/component/types.rs b/crates/wast/src/component/types.rs index 6c4e99516a..607607236e 100644 --- a/crates/wast/src/component/types.rs +++ b/crates/wast/src/component/types.rs @@ -698,8 +698,8 @@ impl<'a> Parse<'a> for ComponentFunctionType<'a> { /// A parameter of a [`ComponentFunctionType`]. #[derive(Debug)] pub struct ComponentFunctionParam<'a> { - /// An optionally-specified name of this parameter - pub name: Option<&'a str>, + /// The name of the parameter + pub name: &'a str, /// The type of the parameter. pub ty: ComponentValType<'a>, } diff --git a/crates/wast/src/core/binary.rs b/crates/wast/src/core/binary.rs index 917dcb9e7a..7d475102c5 100644 --- a/crates/wast/src/core/binary.rs +++ b/crates/wast/src/core/binary.rs @@ -202,7 +202,7 @@ impl Encode for Rec<'_> { return; } - e.push(0x45); + e.push(0x4f); self.types.len().encode(e); for ty in &self.types { ty.encode(e); diff --git a/crates/wast/src/core/expr.rs b/crates/wast/src/core/expr.rs index b149244869..9d358373e6 100644 --- a/crates/wast/src/core/expr.rs +++ b/crates/wast/src/core/expr.rs @@ -1139,23 +1139,27 @@ instructions! { CatchAll : [0x19] : "catch_all", // Relaxed SIMD proposal - I8x16RelaxedSwizzle : [0xfd, 0xa2]: "i8x16.relaxed_swizzle", - I32x4RelaxedTruncF32x4S : [0xfd, 0xa5]: "i32x4.relaxed_trunc_f32x4_s", - I32x4RelaxedTruncF32x4U : [0xfd, 0xa6]: "i32x4.relaxed_trunc_f32x4_u", - I32x4RelaxedTruncF64x2SZero : [0xfd, 0xc5]: "i32x4.relaxed_trunc_f64x2_s_zero", - I32x4RelaxedTruncF64x2UZero : [0xfd, 0xc6]: "i32x4.relaxed_trunc_f64x2_u_zero", - F32x4Fma : [0xfd, 0xaf]: "f32x4.fma", - F32x4Fms : [0xfd, 0xb0]: "f32x4.fms", - F64x4Fma : [0xfd, 0xcf]: "f64x2.fma", - F64x4Fms : [0xfd, 0xd0]: "f64x2.fms", - I8x16LaneSelect : [0xfd, 0xb2]: "i8x16.laneselect", - I16x8LaneSelect : [0xfd, 0xb3]: "i16x8.laneselect", - I32x4LaneSelect : [0xfd, 0xd2]: "i32x4.laneselect", - I64x2LaneSelect : [0xfd, 0xd3]: "i64x2.laneselect", - F32x4RelaxedMin : [0xfd, 0xb4]: "f32x4.relaxed_min", - F32x4RelaxedMax : [0xfd, 0xe2]: "f32x4.relaxed_max", - F64x2RelaxedMin : [0xfd, 0xd4]: "f64x2.relaxed_min", - F64x2RelaxedMax : [0xfd, 0xee]: "f64x2.relaxed_max", + I8x16RelaxedSwizzle : [0xfd, 0x100]: "i8x16.relaxed_swizzle", + I32x4RelaxedTruncF32x4S : [0xfd, 0x101]: "i32x4.relaxed_trunc_f32x4_s", + I32x4RelaxedTruncF32x4U : [0xfd, 0x102]: "i32x4.relaxed_trunc_f32x4_u", + I32x4RelaxedTruncF64x2SZero : [0xfd, 0x103]: "i32x4.relaxed_trunc_f64x2_s_zero", + I32x4RelaxedTruncF64x2UZero : [0xfd, 0x104]: "i32x4.relaxed_trunc_f64x2_u_zero", + F32x4RelaxedFma : [0xfd, 0x105]: "f32x4.relaxed_fma", + F32x4RelaxedFnma : [0xfd, 0x106]: "f32x4.relaxed_fnma", + F64x2RelaxedFma : [0xfd, 0x107]: "f64x2.relaxed_fma", + F64x2RelaxedFnma : [0xfd, 0x108]: "f64x2.relaxed_fnma", + I8x16RelaxedLaneselect : [0xfd, 0x109]: "i8x16.relaxed_laneselect", + I16x8RelaxedLaneselect : [0xfd, 0x10A]: "i16x8.relaxed_laneselect", + I32x4RelaxedLaneselect : [0xfd, 0x10B]: "i32x4.relaxed_laneselect", + I64x2RelaxedLaneselect : [0xfd, 0x10C]: "i64x2.relaxed_laneselect", + F32x4RelaxedMin : [0xfd, 0x10D]: "f32x4.relaxed_min", + F32x4RelaxedMax : [0xfd, 0x10E]: "f32x4.relaxed_max", + F64x2RelaxedMin : [0xfd, 0x10F]: "f64x2.relaxed_min", + F64x2RelaxedMax : [0xfd, 0x110]: "f64x2.relaxed_max", + I16x8RelaxedQ15mulrS: [0xfd, 0x111]: "i16x8.relaxed_q15mulr_s", + I16x8DotI8x16I7x16S: [0xfd, 0x112]: "i16x8.dot_i8x16_i7x16_s", + I32x4DotI8x16I7x16AddS: [0xfd, 0x113]: "i32x4.dot_i8x16_i7x16_add_s", + F32x4RelaxedDotBf16x8AddF32x4: [0xfd, 0x114]: "f32x4.relaxed_dot_bf16x8_add_f32x4", } } diff --git a/crates/wast/src/core/resolve/names.rs b/crates/wast/src/core/resolve/names.rs index 85adb120de..8edc6e5bf5 100644 --- a/crates/wast/src/core/resolve/names.rs +++ b/crates/wast/src/core/resolve/names.rs @@ -646,9 +646,7 @@ impl<'a, 'b> ExprResolver<'a, 'b> { self.resolver.resolve(&mut a.src_array, Ns::Type)?; } - RefNull(ty) | CallRef(ty) | ReturnCallRef(ty) => { - self.resolver.resolve_heaptype(ty)? - } + RefNull(ty) | CallRef(ty) | ReturnCallRef(ty) => self.resolver.resolve_heaptype(ty)?, _ => {} } diff --git a/crates/wast/src/core/wast.rs b/crates/wast/src/core/wast.rs index 5780b9de4f..41437e02d8 100644 --- a/crates/wast/src/core/wast.rs +++ b/crates/wast/src/core/wast.rs @@ -76,6 +76,8 @@ pub enum WastRetCore<'a> { RefExtern(u32), /// A non-null funcref is expected. RefFunc(Option>), + + Either(Vec>), } static RETS: &[(&str, fn(Parser<'_>) -> Result>)] = { @@ -89,6 +91,14 @@ static RETS: &[(&str, fn(Parser<'_>) -> Result>)] = { ("ref.null", |p| Ok(RefNull(p.parse()?))), ("ref.extern", |p| Ok(RefExtern(p.parse()?))), ("ref.func", |p| Ok(RefFunc(p.parse()?))), + ("either", |p| { + p.depth_check()?; + let mut cases = Vec::new(); + while !p.is_empty() { + cases.push(p.parens(|p| p.parse())?); + } + Ok(Either(cases)) + }), ] }; diff --git a/crates/wast/src/lexer.rs b/crates/wast/src/lexer.rs index ee40807f8d..a4f8f128c7 100644 --- a/crates/wast/src/lexer.rs +++ b/crates/wast/src/lexer.rs @@ -90,6 +90,12 @@ pub enum Token<'a> { Float(Float<'a>), } +enum ReservedKind<'a> { + String(Cow<'a, [u8]>), + Idchars, + Reserved, +} + /// Errors that can be generated while lexing. /// /// All lexing errors have line/colum/position information as well as a @@ -354,37 +360,51 @@ impl<'a> Lexer<'a> { b')' => Ok(Some(Token::RParen(self.split_first_byte()))), - b'"' => { - let val = self.string()?; - let src = &self.input[pos..self.cur()]; - return Ok(Some(Token::String(WasmString(Box::new(WasmStringInner { - val, - src, - }))))); - } - // https://webassembly.github.io/spec/core/text/lexical.html#white-space b' ' | b'\n' | b'\r' | b'\t' => Ok(Some(Token::Whitespace(self.split_ws()))), - c @ idchars!() => { - let reserved = self.split_while(|b| matches!(b, idchars!())); - - // https://webassembly.github.io/spec/core/text/values.html#integers - if let Some(number) = self.number(reserved) { - Ok(Some(number)) - // https://webassembly.github.io/spec/core/text/values.html#text-id - } else if *c == b'$' && reserved.len() > 1 { - Ok(Some(Token::Id(reserved))) - // https://webassembly.github.io/spec/core/text/lexical.html#text-keyword - } else if b'a' <= *c && *c <= b'z' { - Ok(Some(Token::Keyword(reserved))) - } else { - Ok(Some(Token::Reserved(reserved))) + c @ (idchars!() | b'"') => { + let (kind, src) = self.split_reserved()?; + match kind { + // If the reserved token was simply a single string then + // that is converted to a standalone string token + ReservedKind::String(val) => { + return Ok(Some(Token::String(WasmString(Box::new(WasmStringInner { + val, + src, + }))))); + } + + // If only idchars were consumed then this could be a + // specific kind of standalone token we're interested in. + ReservedKind::Idchars => { + // https://webassembly.github.io/spec/core/text/values.html#integers + if let Some(number) = self.number(src) { + return Ok(Some(number)); + // https://webassembly.github.io/spec/core/text/values.html#text-id + } else if *c == b'$' && src.len() > 1 { + return Ok(Some(Token::Id(src))); + // https://webassembly.github.io/spec/core/text/lexical.html#text-keyword + } else if b'a' <= *c && *c <= b'z' { + return Ok(Some(Token::Keyword(src))); + } + } + + // ... otherwise this was a conglomeration of idchars, + // strings, or just idchars that don't match a prior rule, + // meaning this falls through to the fallback `Reserved` + // token. + ReservedKind::Reserved => {} } + + Ok(Some(Token::Reserved(src))) } // This could be a line comment, otherwise `;` is a reserved token. // The second byte is checked to see if it's a `;;` line comment + // + // Note that this character being considered as part of a + // `reserved` token is part of the annotations proposal. b';' => match self.remaining.as_bytes().get(1) { Some(b';') => { let comment = self.split_until(b'\n'); @@ -395,6 +415,9 @@ impl<'a> Lexer<'a> { }, // Other known reserved tokens other than `;` + // + // Note that these characters being considered as part of a + // `reserved` token is part of the annotations proposal. b',' | b'[' | b']' | b'{' | b'}' => Ok(Some(Token::Reserved(self.split_first_byte()))), _ => { @@ -466,16 +489,74 @@ impl<'a> Lexer<'a> { ret } - fn split_while(&mut self, f: impl Fn(u8) -> bool) -> &'a str { - let pos = self - .remaining - .as_bytes() - .iter() - .position(|b| !f(*b)) - .unwrap_or(self.remaining.len()); + /// Splits off a "reserved" token which is then further processed later on + /// to figure out which kind of token it is `depending on `ReservedKind`. + /// + /// For more information on this method see the clarification at + /// https://github.com/WebAssembly/spec/pull/1499 but the general gist is + /// that this is parsing the grammar: + /// + /// ```text + /// reserved := (idchar | string)+ + /// ``` + /// + /// which means that it is eating any number of adjacent string/idchar + /// tokens (e.g. `a"b"c`) and returning the classification of what was + /// eaten. The classification assists in determining what the actual token + /// here eaten looks like. + fn split_reserved(&mut self) -> Result<(ReservedKind<'a>, &'a str), Error> { + let mut idchars = false; + let mut strings = 0u32; + let mut last_string_val = None; + let mut pos = 0; + while let Some(byte) = self.remaining.as_bytes().get(pos) { + match byte { + // Normal `idchars` production which appends to the reserved + // token that's being produced. + idchars!() => { + idchars = true; + pos += 1; + } + + // https://webassembly.github.io/spec/core/text/values.html#text-string + b'"' => { + strings += 1; + pos += 1; + let mut it = self.remaining[pos..].chars(); + let result = Lexer::parse_str(&mut it, self.allow_confusing_unicode); + pos = self.remaining.len() - it.as_str().len(); + match result { + Ok(s) => last_string_val = Some(s), + Err(e) => { + let start = self.input.len() - self.remaining.len(); + self.remaining = &self.remaining[pos..]; + let err_pos = match &e { + LexError::UnexpectedEof => self.input.len(), + _ => { + self.input[..start + pos] + .char_indices() + .next_back() + .unwrap() + .0 + } + }; + return Err(self.error(err_pos, e)); + } + } + } + + // Nothing else is considered part of a reserved token + _ => break, + } + } let (ret, remaining) = self.remaining.split_at(pos); self.remaining = remaining; - ret + Ok(match (idchars, strings) { + (false, 0) => unreachable!(), + (false, 1) => (ReservedKind::String(last_string_val.unwrap()), ret), + (true, 0) => (ReservedKind::Idchars, ret), + _ => (ReservedKind::Reserved, ret), + }) } fn number(&self, src: &'a str) -> Option> { @@ -688,24 +769,6 @@ impl<'a> Lexer<'a> { Ok(()) } - /// Reads everything for a literal string except the leading `"`. Returns - /// the string value that has been read. - /// - /// https://webassembly.github.io/spec/core/text/values.html#text-string - fn string(&mut self) -> Result, Error> { - let mut it = self.remaining[1..].chars(); - let result = Lexer::parse_str(&mut it, self.allow_confusing_unicode); - let end = self.input.len() - it.as_str().len(); - self.remaining = &self.input[end..]; - result.map_err(|e| { - let err_pos = match &e { - LexError::UnexpectedEof => self.input.len(), - _ => self.input[..end].char_indices().next_back().unwrap().0, - }; - self.error(err_pos, e) - }) - } - fn parse_str( it: &mut str::Chars<'a>, allow_confusing_unicode: bool, diff --git a/crates/wast/src/names.rs b/crates/wast/src/names.rs index b6cf06f443..7cbfc5d9ca 100644 --- a/crates/wast/src/names.rs +++ b/crates/wast/src/names.rs @@ -81,6 +81,6 @@ pub fn resolve_error(id: Id<'_>, ns: &str) -> Error { ); Error::new( id.span(), - format!("failed to find {} named `${}`", ns, id.name()), + format!("unknown {ns}: failed to find name `${}`", id.name()), ) } diff --git a/crates/wast/tests/parse-fail/bad-index.wat.err b/crates/wast/tests/parse-fail/bad-index.wat.err index 717d46017b..f380bddec1 100644 --- a/crates/wast/tests/parse-fail/bad-index.wat.err +++ b/crates/wast/tests/parse-fail/bad-index.wat.err @@ -1,4 +1,4 @@ -failed to find label named `$s` +unknown label: failed to find name `$s` --> tests/parse-fail/bad-index.wat:1:18 | 1 | (func br_on_null $s) diff --git a/crates/wat/Cargo.toml b/crates/wat/Cargo.toml index a3db6a1cb7..e68d90d563 100644 --- a/crates/wat/Cargo.toml +++ b/crates/wat/Cargo.toml @@ -1,8 +1,8 @@ [package] name = "wat" -version = "1.0.48" +version = "1.0.49" authors = ["Alex Crichton "] -edition = "2021" +edition.workspace = true license = "Apache-2.0 WITH LLVM-exception" readme = "README.md" repository = "https://github.com/bytecodealliance/wasm-tools/tree/main/crates/wat" @@ -13,4 +13,4 @@ Rust parser for the WebAssembly Text format, WAT """ [dependencies] -wast = { path = '../wast', version = '46.0.0' } +wast = { workspace = true } diff --git a/crates/wat/README.md b/crates/wat/README.md index d9f4e0fe43..f104162720 100644 --- a/crates/wat/README.md +++ b/crates/wat/README.md @@ -17,11 +17,10 @@ ## Usage -Add this to your `Cargo.toml`: +Add `wat` to your `Cargo.toml` -```toml -[dependencies] -wat = "1.0" +```sh +$ cargo add wat ``` And then you can parse WAT to binary WebAssembly via: diff --git a/crates/wat/src/lib.rs b/crates/wat/src/lib.rs index f48f0526f4..bd0bafcb71 100644 --- a/crates/wat/src/lib.rs +++ b/crates/wat/src/lib.rs @@ -216,9 +216,9 @@ pub fn parse_str(wat: impl AsRef) -> Result> { } fn _parse_str(wat: &str) -> Result> { - let buf = ParseBuffer::new(&wat).map_err(|e| Error::cvt(e, wat))?; + let buf = ParseBuffer::new(wat).map_err(|e| Error::cvt(e, wat))?; let mut ast = parser::parse::(&buf).map_err(|e| Error::cvt(e, wat))?; - Ok(ast.encode().map_err(|e| Error::cvt(e, wat))?) + ast.encode().map_err(|e| Error::cvt(e, wat)) } /// A convenience type definition for `Result` where the error is [`Error`] diff --git a/fuzz/Cargo.toml b/fuzz/Cargo.toml index ce01922302..29c3b67099 100644 --- a/fuzz/Cargo.toml +++ b/fuzz/Cargo.toml @@ -2,23 +2,23 @@ name = "wasm-tools-fuzz" version = "0.0.1" publish = false -edition = "2021" +edition.workspace = true [package.metadata] cargo-fuzz = true [dependencies] -anyhow = "1" -arbitrary = "1" -env_logger = "0.9" -libfuzzer-sys = "0.4.0" -log = "0.4" +anyhow = { workspace = true } +arbitrary = { workspace = true } +env_logger = { workspace = true } +libfuzzer-sys = { workspace = true } +log = { workspace = true } tempfile = "3.0" wasm-mutate = { path = "../crates/wasm-mutate" } wasm-smith = { path = "../crates/wasm-smith" } wasmparser = { path = "../crates/wasmparser" } wasmprinter = { path = "../crates/wasmprinter" } -wasmtime = { version = "0.38.1", optional = true } +wasmtime = { workspace = true, optional = true } wast = { path = "../crates/wast" } wat = { path = "../crates/wat" } diff --git a/publish.rs b/publish.rs index 9fb968333f..b67fdadbc0 100644 --- a/publish.rs +++ b/publish.rs @@ -35,8 +35,8 @@ const CRATES_TO_PUBLISH: &[&str] = &[ "wasm-smith", "wasm-mutate", "wasm-shrink", - "wasm-tools", "wasm-compose", + "wasm-tools", ]; #[derive(Clone)] diff --git a/src/bin/wasm-tools/main.rs b/src/bin/wasm-tools/main.rs index 0c04c30de2..a12fb4a3b1 100644 --- a/src/bin/wasm-tools/main.rs +++ b/src/bin/wasm-tools/main.rs @@ -2,6 +2,7 @@ use anyhow::Result; use clap::Parser; use std::io; use std::process::ExitCode; +use wasm_tools::Verbosity; macro_rules! subcommands { ($(($name:ident, $string:tt))*) => { @@ -19,6 +20,9 @@ macro_rules! subcommands { $name { #[clap(flatten)] opts: $name::Opts, + + #[clap(flatten)] + verbosity: Verbosity, }, )* } @@ -28,7 +32,10 @@ macro_rules! subcommands { match self { $( #[cfg(feature = $string)] - WasmTools::$name { opts } => opts.run(), + Self::$name { opts, verbosity } => { + verbosity.init_logger(); + opts.run() + } )* } } @@ -50,10 +57,6 @@ subcommands! { } fn main() -> ExitCode { - env_logger::Builder::from_env(env_logger::Env::default().default_filter_or("warn")) - .format_target(false) - .init(); - let err = match ::parse().run() { Ok(()) => return ExitCode::SUCCESS, Err(e) => e, @@ -71,3 +74,9 @@ fn main() -> ExitCode { eprintln!("Error: {:?}", err); ExitCode::FAILURE } + +#[test] +fn verify_cli() { + use clap::CommandFactory; + WasmTools::command().debug_assert() +} diff --git a/src/bin/wasm-tools/smith.rs b/src/bin/wasm-tools/smith.rs index 7a1af22020..d9a6a3394a 100644 --- a/src/bin/wasm-tools/smith.rs +++ b/src/bin/wasm-tools/smith.rs @@ -38,7 +38,6 @@ pub struct Opts { /// The arbitrary input seed. /// /// `stdin` is used if this argument is not supplied. - #[clap(parse(from_os_str))] input: Option, #[clap(flatten)] @@ -70,7 +69,7 @@ pub struct Opts { fuel: Option, /// JSON configuration file with settings to control the wasm output. - #[clap(short = 'c', long = "config", parse(from_os_str))] + #[clap(short = 'c', long = "config")] config: Option, #[clap(flatten)] diff --git a/src/bin/wasm-tools/strip.rs b/src/bin/wasm-tools/strip.rs index f9a9e3d704..45e1b17aef 100644 --- a/src/bin/wasm-tools/strip.rs +++ b/src/bin/wasm-tools/strip.rs @@ -1,7 +1,6 @@ -use anyhow::{bail, Result}; -use std::ops::Range; -use wasm_encoder::{RawSection, SectionId}; -use wasmparser::{Encoding, Parser, Payload::*, SectionReader}; +use anyhow::{Result}; +use wasm_encoder::RawSection; +use wasmparser::{Parser, Payload::*}; /// Removes custom sections from an input WebAssembly file. /// @@ -13,10 +12,14 @@ pub struct Opts { #[clap(flatten)] io: wasm_tools::InputOutput, - /// Strip all custom sections, including the `name` section + /// Remove all custom sections, regardless of name. #[clap(long, short)] all: bool, + /// Remove custom sections matching the specified regex. + #[clap(long, short, value_name = "REGEX")] + delete: Vec, + /// Output the text format of WebAssembly instead of the binary format. #[clap(short = 't', long)] wat: bool, @@ -25,74 +28,41 @@ pub struct Opts { impl Opts { pub fn run(&self) -> Result<()> { let input = self.io.parse_input_wasm()?; + let to_delete = regex::RegexSet::new(self.delete.iter())?; - let mut module = wasm_encoder::Module::new(); + let strip_custom_section = |name: &str| { + // If explicitly specified, strip everything. + if self.all { + return true; + } - for payload in Parser::new(0).parse_all(&input) { - let payload = payload?; - let mut section = |id: SectionId, range: Range| { - module.section(&RawSection { - id: id as u8, - data: &input[range], - }); - }; - match payload { - Version { - encoding: Encoding::Module, - .. - } => {} - Version { - encoding: Encoding::Component, - .. - } => { - bail!("components are not supported yet with the `strip` command"); - } + // If any section was called out by name only delete those sections. + if !to_delete.is_empty() { + return to_delete.is_match(name); + } - TypeSection(s) => section(SectionId::Type, s.range()), - ImportSection(s) => section(SectionId::Import, s.range()), - FunctionSection(s) => section(SectionId::Function, s.range()), - TableSection(s) => section(SectionId::Table, s.range()), - MemorySection(s) => section(SectionId::Memory, s.range()), - TagSection(s) => section(SectionId::Tag, s.range()), - GlobalSection(s) => section(SectionId::Global, s.range()), - ExportSection(s) => section(SectionId::Export, s.range()), - ElementSection(s) => section(SectionId::Element, s.range()), - DataSection(s) => section(SectionId::Data, s.range()), - StartSection { range, .. } => section(SectionId::Start, range), - DataCountSection { range, .. } => section(SectionId::DataCount, range), - CodeSectionStart { range, .. } => section(SectionId::Code, range), - CodeSectionEntry(_) => {} + // Finally default strip everything but the `name` section. + name != "name" + }; - ModuleSection { .. } - | InstanceSection(_) - | CoreTypeSection(_) - | ComponentSection { .. } - | ComponentInstanceSection(_) - | ComponentAliasSection(_) - | ComponentTypeSection(_) - | ComponentCanonicalSection(_) - | ComponentStartSection(_) - | ComponentImportSection(_) - | ComponentExportSection(_) => unimplemented!("component model"), + let mut module = wasm_encoder::Module::new(); - CustomSection(c) if c.name() == "name" && !self.all => { - module.section(&RawSection { - id: SectionId::Custom as u8, - data: &input[c.range()], - }); + for payload in Parser::new(0).parse_all(&input) { + let payload = payload?; + match &payload { + CustomSection(c) => { + if strip_custom_section(c.name()) { + continue; + } } - CustomSection(_) => {} - - UnknownSection { + _ => {} + } + if let Some((id, range)) = payload.as_section() { + module.section(&RawSection { id, - contents, - range: _, - } => { - module.section(&RawSection { id, data: contents }); - } - - End(_) => {} + data: &input[range], + }); } } diff --git a/src/bin/wasm-tools/validate.rs b/src/bin/wasm-tools/validate.rs index 35ae8c4bc7..9ccae9e6c9 100644 --- a/src/bin/wasm-tools/validate.rs +++ b/src/bin/wasm-tools/validate.rs @@ -1,7 +1,8 @@ use anyhow::{anyhow, Context, Result}; use rayon::prelude::*; +use std::mem; use std::time::Instant; -use wasmparser::{Parser, ValidPayload, Validator, WasmFeatures}; +use wasmparser::{FuncValidatorAllocations, Parser, ValidPayload, Validator, WasmFeatures}; /// Validate a WebAssembly binary /// @@ -29,7 +30,7 @@ pub struct Opts { /// The placeholder "all" can be used to enable all wasm features. If a "-" /// character is present in front of a feature it will disable that feature. /// For example "all,-simd" would enable everything but simd. - #[clap(long, short = 'f', parse(try_from_str = parse_features))] + #[clap(long, short = 'f', value_parser = parse_features)] features: Option, #[clap(flatten)] @@ -67,13 +68,17 @@ impl Opts { // over all functions in parallel and perform parallel validation of the // input wasm module. let start = Instant::now(); - functions_to_validate - .into_par_iter() - .try_for_each(|(mut validator, body)| { + functions_to_validate.into_par_iter().try_for_each_init( + FuncValidatorAllocations::default, + |allocs, (to_validate, body)| -> Result<_> { + let mut validator = to_validate.into_validator(mem::take(allocs)); validator .validate(&body) - .with_context(|| format!("func {} failed to validate", validator.index())) - })?; + .with_context(|| format!("func {} failed to validate", validator.index()))?; + *allocs = validator.into_allocations(); + Ok(()) + }, + )?; log::info!("functions validated in {:?}", start.elapsed()); Ok(()) } diff --git a/src/lib.rs b/src/lib.rs index a1fd694903..d678f0451f 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -5,6 +5,29 @@ use std::fs::File; use std::io::{BufWriter, Read, Write}; use std::path::{Path, PathBuf}; +// Implements the verbosity flag for the CLI commands. +#[derive(clap::Parser)] +pub struct Verbosity { + /// Use verbose output (-vv very verbose output). + #[clap(long = "verbose", short = 'v', action = clap::ArgAction::Count)] + verbose: u8, +} + +impl Verbosity { + /// Initializes the logger based on the verbosity level. + pub fn init_logger(&self) { + let default = match self.verbose { + 0 => "warn", + 1 => "info", + _ => "debug", + }; + + env_logger::Builder::from_env(env_logger::Env::default().default_filter_or(default)) + .format_target(false) + .init(); + } +} + // This is intended to be included in a struct as: // // #[clap(flatten)] diff --git a/tests/dump/alias.wat b/tests/dump/alias.wat index 7a79f26ebb..d7048ac8a5 100644 --- a/tests/dump/alias.wat +++ b/tests/dump/alias.wat @@ -1,7 +1,7 @@ (component (import "i" (instance $i (export "f1" (func $f1)) - (export "f2" (func $f2 (param string))) + (export "f2" (func $f2 (param "p1" string))) )) (func (alias export $i "f1")) diff --git a/tests/dump/alias.wat.dump b/tests/dump/alias.wat.dump index 47855ce37d..229958e463 100644 --- a/tests/dump/alias.wat.dump +++ b/tests/dump/alias.wat.dump @@ -1,58 +1,58 @@ 0x0 | 00 61 73 6d | version 65546 (Component) | 0a 00 01 00 - 0x8 | 07 1b | component type section + 0x8 | 07 1d | component type section 0xa | 01 | 1 count - 0xb | 42 04 01 40 | [type 0] Instance([Type(Func(ComponentFuncType { params: Named([]), results: Named([]) })), Export { name: "f1", ty: Func(0) }, Type(Func(ComponentFuncType { params: Unnamed(Primitive(String)), results: Named([]) })), Export { name: "f2", ty: Func(1) }]) - | 01 00 01 00 - | 04 02 66 31 - | 01 00 01 40 - | 00 73 01 00 - | 04 02 66 32 - | 01 01 - 0x25 | 0a 05 | component import section - 0x27 | 01 | 1 count - 0x28 | 01 69 05 00 | [instance 0] ComponentImport { name: "i", ty: Instance(0) } - 0x2c | 06 13 | component alias section - 0x2e | 03 | 3 count - 0x2f | 01 00 00 02 | alias [func 0] InstanceExport { kind: Func, instance_index: 0, name: "f1" } + 0xb | 42 04 01 40 | [type 0] Instance([Type(Func(ComponentFuncType { params: [], results: Named([]) })), Export { name: "f1", ty: Func(0) }, Type(Func(ComponentFuncType { params: [("p1", Primitive(String))], results: Named([]) })), Export { name: "f2", ty: Func(1) }]) + | 00 01 00 04 + | 02 66 31 01 + | 00 01 40 01 + | 02 70 31 73 + | 01 00 04 02 + | 66 32 01 01 + 0x27 | 0a 05 | component import section + 0x29 | 01 | 1 count + 0x2a | 01 69 05 00 | [instance 0] ComponentImport { name: "i", ty: Instance(0) } + 0x2e | 06 13 | component alias section + 0x30 | 03 | 3 count + 0x31 | 01 00 00 02 | alias [func 0] InstanceExport { kind: Func, instance_index: 0, name: "f1" } | 66 31 - 0x35 | 01 00 00 02 | alias [func 1] InstanceExport { kind: Func, instance_index: 0, name: "f2" } + 0x37 | 01 00 00 02 | alias [func 1] InstanceExport { kind: Func, instance_index: 0, name: "f2" } | 66 32 - 0x3b | 01 00 00 02 | alias [func 2] InstanceExport { kind: Func, instance_index: 0, name: "f1" } + 0x3d | 01 00 00 02 | alias [func 2] InstanceExport { kind: Func, instance_index: 0, name: "f1" } | 66 31 - 0x41 | 08 05 | canonical function section - 0x43 | 01 | 1 count - 0x44 | 01 00 02 00 | [core func 0] Lower { func_index: 2, options: [] } - 0x48 | 01 2b | [core module 0] inline size - 0x4a | 00 61 73 6d | version 1 (Module) + 0x43 | 08 05 | canonical function section + 0x45 | 01 | 1 count + 0x46 | 01 00 02 00 | [core func 0] Lower { func_index: 2, options: [] } + 0x4a | 01 2b | [core module 0] inline size + 0x4c | 00 61 73 6d | version 1 (Module) | 01 00 00 00 - 0x52 | 01 04 | type section - 0x54 | 01 | 1 count - 0x55 | 60 00 00 | [type 0] Func(FuncType { params: [], returns: [] }) - 0x58 | 03 02 | func section - 0x5a | 01 | 1 count - 0x5b | 00 | [func 0] type 0 - 0x5c | 07 06 | export section - 0x5e | 01 | 1 count - 0x5f | 02 66 33 00 | export Export { name: "f3", kind: Func, index: 0 } + 0x54 | 01 04 | type section + 0x56 | 01 | 1 count + 0x57 | 60 00 00 | [type 0] Func(FuncType { params: [], returns: [] }) + 0x5a | 03 02 | func section + 0x5c | 01 | 1 count + 0x5d | 00 | [func 0] type 0 + 0x5e | 07 06 | export section + 0x60 | 01 | 1 count + 0x61 | 02 66 33 00 | export Export { name: "f3", kind: Func, index: 0 } | 00 - 0x64 | 0a 04 | code section - 0x66 | 01 | 1 count + 0x66 | 0a 04 | code section + 0x68 | 01 | 1 count ============== func 0 ==================== - 0x67 | 02 | size of function - 0x68 | 00 | 0 local blocks - 0x69 | 0b | end - 0x6a | 00 09 | custom section - 0x6c | 04 6e 61 6d | name: "name" + 0x69 | 02 | size of function + 0x6a | 00 | 0 local blocks + 0x6b | 0b | end + 0x6c | 00 09 | custom section + 0x6e | 04 6e 61 6d | name: "name" | 65 - 0x71 | 00 02 | module name - 0x73 | 01 6d | "m" - 0x75 | 02 04 | core instance section - 0x77 | 01 | 1 count - 0x78 | 00 00 00 | [core instance 0] Instantiate { module_index: 0, args: [] } - 0x7b | 06 0f | component alias section - 0x7d | 02 | 2 count - 0x7e | 00 00 01 00 | alias [core func 1] CoreInstanceExport { kind: Func, instance_index: 0, name: "f3" } + 0x73 | 00 02 | module name + 0x75 | 01 6d | "m" + 0x77 | 02 04 | core instance section + 0x79 | 01 | 1 count + 0x7a | 00 00 00 | [core instance 0] Instantiate { module_index: 0, args: [] } + 0x7d | 06 0f | component alias section + 0x7f | 02 | 2 count + 0x80 | 00 00 01 00 | alias [core func 1] CoreInstanceExport { kind: Func, instance_index: 0, name: "f3" } | 02 66 33 - 0x85 | 00 00 01 00 | alias [core func 2] CoreInstanceExport { kind: Func, instance_index: 0, name: "f3" } + 0x87 | 00 00 01 00 | alias [core func 2] CoreInstanceExport { kind: Func, instance_index: 0, name: "f3" } | 02 66 33 diff --git a/tests/dump/alias2.wat.dump b/tests/dump/alias2.wat.dump index 19a200d28d..bafdf87e07 100644 --- a/tests/dump/alias2.wat.dump +++ b/tests/dump/alias2.wat.dump @@ -1,104 +1,103 @@ 0x0 | 00 61 73 6d | version 65546 (Component) | 0a 00 01 00 - 0x8 | 07 2c | component type section + 0x8 | 07 2b | component type section 0xa | 01 | 1 count - 0xb | 42 09 00 50 | [type 0] Instance([CoreType(Module([])), Export { name: "1", ty: Module(0) }, Type(Func(ComponentFuncType { params: Named([]), results: Named([]) })), Export { name: "2", ty: Func(0) }, Export { name: "3", ty: Value(Primitive(String)) }, Type(Instance([])), Export { name: "4", ty: Instance(1) }, Type(Component([])), Export { name: "5", ty: Component(2) }]) + 0xb | 42 09 00 50 | [type 0] Instance([CoreType(Module([])), Export { name: "1", ty: Module(0) }, Type(Func(ComponentFuncType { params: [], results: Named([]) })), Export { name: "2", ty: Func(0) }, Export { name: "3", ty: Value(Primitive(String)) }, Type(Instance([])), Export { name: "4", ty: Instance(1) }, Type(Component([])), Export { name: "5", ty: Component(2) }]) | 00 04 01 31 | 00 11 00 01 - | 40 01 00 01 - | 00 04 01 32 - | 01 00 04 01 - | 33 02 73 01 - | 42 00 04 01 - | 34 05 01 01 - | 41 00 04 01 - | 35 04 02 - 0x36 | 0a 04 | component import section - 0x38 | 01 | 1 count - 0x39 | 00 05 00 | [instance 0] ComponentImport { name: "", ty: Instance(0) } - 0x3c | 04 40 | [component 0] inline size - 0x3e | 00 61 73 6d | version 65546 (Component) + | 40 00 01 00 + | 04 01 32 01 + | 00 04 01 33 + | 02 73 01 42 + | 00 04 01 34 + | 05 01 01 41 + | 00 04 01 35 + | 04 02 + 0x35 | 0a 04 | component import section + 0x37 | 01 | 1 count + 0x38 | 00 05 00 | [instance 0] ComponentImport { name: "", ty: Instance(0) } + 0x3b | 04 3f | [component 0] inline size + 0x3d | 00 61 73 6d | version 65546 (Component) | 0a 00 01 00 - 0x46 | 03 03 | core type section - 0x48 | 01 | 1 count - 0x49 | 50 00 | [core type 0] Module([]) - 0x4b | 0a 06 | component import section - 0x4d | 01 | 1 count - 0x4e | 01 31 00 11 | [module 0] ComponentImport { name: "1", ty: Module(0) } + 0x45 | 03 03 | core type section + 0x47 | 01 | 1 count + 0x48 | 50 00 | [core type 0] Module([]) + 0x4a | 0a 06 | component import section + 0x4c | 01 | 1 count + 0x4d | 01 31 00 11 | [module 0] ComponentImport { name: "1", ty: Module(0) } | 00 - 0x53 | 07 06 | component type section - 0x55 | 01 | 1 count - 0x56 | 40 01 00 01 | [type 0] Func(ComponentFuncType { params: Named([]), results: Named([]) }) - | 00 - 0x5b | 0a 09 | component import section - 0x5d | 02 | 2 count - 0x5e | 01 32 01 00 | [func 0] ComponentImport { name: "2", ty: Func(0) } - 0x62 | 01 33 02 73 | [value 0] ComponentImport { name: "3", ty: Value(Primitive(String)) } - 0x66 | 07 03 | component type section - 0x68 | 01 | 1 count - 0x69 | 42 00 | [type 1] Instance([]) - 0x6b | 0a 05 | component import section - 0x6d | 01 | 1 count - 0x6e | 01 34 05 01 | [instance 0] ComponentImport { name: "4", ty: Instance(1) } - 0x72 | 07 03 | component type section - 0x74 | 01 | 1 count - 0x75 | 41 00 | [type 2] Component([]) - 0x77 | 0a 05 | component import section - 0x79 | 01 | 1 count - 0x7a | 01 35 04 02 | [component 0] ComponentImport { name: "5", ty: Component(2) } - 0x7e | 06 1b | component alias section - 0x80 | 05 | 5 count - 0x81 | 00 11 00 00 | alias [module 0] InstanceExport { kind: Module, instance_index: 0, name: "1" } + 0x52 | 07 05 | component type section + 0x54 | 01 | 1 count + 0x55 | 40 00 01 00 | [type 0] Func(ComponentFuncType { params: [], results: Named([]) }) + 0x59 | 0a 09 | component import section + 0x5b | 02 | 2 count + 0x5c | 01 32 01 00 | [func 0] ComponentImport { name: "2", ty: Func(0) } + 0x60 | 01 33 02 73 | [value 0] ComponentImport { name: "3", ty: Value(Primitive(String)) } + 0x64 | 07 03 | component type section + 0x66 | 01 | 1 count + 0x67 | 42 00 | [type 1] Instance([]) + 0x69 | 0a 05 | component import section + 0x6b | 01 | 1 count + 0x6c | 01 34 05 01 | [instance 0] ComponentImport { name: "4", ty: Instance(1) } + 0x70 | 07 03 | component type section + 0x72 | 01 | 1 count + 0x73 | 41 00 | [type 2] Component([]) + 0x75 | 0a 05 | component import section + 0x77 | 01 | 1 count + 0x78 | 01 35 04 02 | [component 0] ComponentImport { name: "5", ty: Component(2) } + 0x7c | 06 1b | component alias section + 0x7e | 05 | 5 count + 0x7f | 00 11 00 00 | alias [module 0] InstanceExport { kind: Module, instance_index: 0, name: "1" } | 01 31 - 0x87 | 01 00 00 01 | alias [func 0] InstanceExport { kind: Func, instance_index: 0, name: "2" } + 0x85 | 01 00 00 01 | alias [func 0] InstanceExport { kind: Func, instance_index: 0, name: "2" } | 32 - 0x8c | 02 00 00 01 | alias [value 0] InstanceExport { kind: Value, instance_index: 0, name: "4" } + 0x8a | 02 00 00 01 | alias [value 0] InstanceExport { kind: Value, instance_index: 0, name: "4" } | 34 - 0x91 | 05 00 00 01 | alias [instance 1] InstanceExport { kind: Instance, instance_index: 0, name: "3" } + 0x8f | 05 00 00 01 | alias [instance 1] InstanceExport { kind: Instance, instance_index: 0, name: "3" } | 33 - 0x96 | 04 00 00 01 | alias [component 1] InstanceExport { kind: Component, instance_index: 0, name: "5" } + 0x94 | 04 00 00 01 | alias [component 1] InstanceExport { kind: Component, instance_index: 0, name: "5" } | 35 - 0x9b | 05 19 | component instance section - 0x9d | 01 | 1 count - 0x9e | 00 00 05 01 | [instance 2] Instantiate { component_index: 0, args: [ComponentInstantiationArg { name: "1", kind: Module, index: 0 }, ComponentInstantiationArg { name: "2", kind: Func, index: 0 }, ComponentInstantiationArg { name: "3", kind: Value, index: 0 }, ComponentInstantiationArg { name: "4", kind: Instance, index: 1 }, ComponentInstantiationArg { name: "5", kind: Component, index: 1 }] } + 0x99 | 05 19 | component instance section + 0x9b | 01 | 1 count + 0x9c | 00 00 05 01 | [instance 2] Instantiate { component_index: 0, args: [ComponentInstantiationArg { name: "1", kind: Module, index: 0 }, ComponentInstantiationArg { name: "2", kind: Func, index: 0 }, ComponentInstantiationArg { name: "3", kind: Value, index: 0 }, ComponentInstantiationArg { name: "4", kind: Instance, index: 1 }, ComponentInstantiationArg { name: "5", kind: Component, index: 1 }] } | 31 00 11 00 | 01 32 01 00 | 01 33 02 00 | 01 34 05 01 | 01 35 04 01 - 0xb6 | 04 15 | [component 2] inline size - 0xb8 | 00 61 73 6d | version 65546 (Component) + 0xb4 | 04 15 | [component 2] inline size + 0xb6 | 00 61 73 6d | version 65546 (Component) | 0a 00 01 00 - 0xc0 | 06 05 | component alias section - 0xc2 | 01 | 1 count - 0xc3 | 03 02 01 00 | alias [type 0] Outer { kind: Type, count: 1, index: 0 } - 0xc7 | 0a 04 | component import section - 0xc9 | 01 | 1 count - 0xca | 00 05 00 | [instance 0] ComponentImport { name: "", ty: Instance(0) } - 0xcd | 06 1b | component alias section - 0xcf | 05 | 5 count - 0xd0 | 00 11 00 00 | alias [module 1] InstanceExport { kind: Module, instance_index: 0, name: "1" } + 0xbe | 06 05 | component alias section + 0xc0 | 01 | 1 count + 0xc1 | 03 02 01 00 | alias [type 0] Outer { kind: Type, count: 1, index: 0 } + 0xc5 | 0a 04 | component import section + 0xc7 | 01 | 1 count + 0xc8 | 00 05 00 | [instance 0] ComponentImport { name: "", ty: Instance(0) } + 0xcb | 06 1b | component alias section + 0xcd | 05 | 5 count + 0xce | 00 11 00 00 | alias [module 1] InstanceExport { kind: Module, instance_index: 0, name: "1" } | 01 31 - 0xd6 | 01 00 00 01 | alias [func 1] InstanceExport { kind: Func, instance_index: 0, name: "2" } + 0xd4 | 01 00 00 01 | alias [func 1] InstanceExport { kind: Func, instance_index: 0, name: "2" } | 32 - 0xdb | 02 00 00 01 | alias [value 1] InstanceExport { kind: Value, instance_index: 0, name: "3" } + 0xd9 | 02 00 00 01 | alias [value 1] InstanceExport { kind: Value, instance_index: 0, name: "3" } | 33 - 0xe0 | 05 00 00 01 | alias [instance 3] InstanceExport { kind: Instance, instance_index: 0, name: "4" } + 0xde | 05 00 00 01 | alias [instance 3] InstanceExport { kind: Instance, instance_index: 0, name: "4" } | 34 - 0xe5 | 04 00 00 01 | alias [component 3] InstanceExport { kind: Component, instance_index: 0, name: "5" } + 0xe3 | 04 00 00 01 | alias [component 3] InstanceExport { kind: Component, instance_index: 0, name: "5" } | 35 - 0xea | 05 1e | component instance section - 0xec | 02 | 2 count - 0xed | 01 05 01 31 | [instance 4] FromExports([ComponentExport { name: "1", kind: Module, index: 1 }, ComponentExport { name: "2", kind: Func, index: 1 }, ComponentExport { name: "3", kind: Value, index: 1 }, ComponentExport { name: "4", kind: Instance, index: 3 }, ComponentExport { name: "5", kind: Component, index: 3 }]) + 0xe8 | 05 1e | component instance section + 0xea | 02 | 2 count + 0xeb | 01 05 01 31 | [instance 4] FromExports([ComponentExport { name: "1", kind: Module, index: 1 }, ComponentExport { name: "2", kind: Func, index: 1 }, ComponentExport { name: "3", kind: Value, index: 1 }, ComponentExport { name: "4", kind: Instance, index: 3 }, ComponentExport { name: "5", kind: Component, index: 3 }]) | 00 11 01 01 | 32 01 01 01 | 33 02 01 01 | 34 05 03 01 | 35 04 03 - 0x104 | 00 02 01 00 | [instance 5] Instantiate { component_index: 2, args: [ComponentInstantiationArg { name: "", kind: Instance, index: 4 }] } + 0x102 | 00 02 01 00 | [instance 5] Instantiate { component_index: 2, args: [ComponentInstantiationArg { name: "", kind: Instance, index: 4 }] } | 05 04 - 0x10a | 01 48 | [core module 2] inline size - 0x10c | 00 61 73 6d | version 1 (Module) + 0x108 | 01 48 | [core module 2] inline size + 0x10a | 00 61 73 6d | version 1 (Module) | 01 00 00 00 0x114 | 01 04 | type section 0x116 | 01 | 1 count @@ -125,56 +124,56 @@ 0x142 | 0a 04 | code section 0x144 | 01 | 1 count ============== func 0 ==================== - 0x145 | 02 | size of function - 0x146 | 00 | 0 local blocks - 0x147 | 0b | end - 0x148 | 00 0a | custom section - 0x14a | 04 6e 61 6d | name: "name" + 0x143 | 02 | size of function + 0x144 | 00 | 0 local blocks + 0x145 | 0b | end + 0x146 | 00 0a | custom section + 0x148 | 04 6e 61 6d | name: "name" | 65 - 0x14f | 00 03 | module name - 0x151 | 02 6d 31 | "m1" - 0x154 | 01 35 | [core module 3] inline size - 0x156 | 00 61 73 6d | version 1 (Module) + 0x14d | 00 03 | module name + 0x14f | 02 6d 31 | "m1" + 0x152 | 01 35 | [core module 3] inline size + 0x154 | 00 61 73 6d | version 1 (Module) | 01 00 00 00 - 0x15e | 01 04 | type section - 0x160 | 01 | 1 count - 0x161 | 60 00 00 | [type 0] Func(FuncType { params: [], returns: [] }) - 0x164 | 02 19 | import section - 0x166 | 04 | 4 count - 0x167 | 00 01 31 00 | import [func 0] Import { module: "", name: "1", ty: Func(0) } + 0x15c | 01 04 | type section + 0x15e | 01 | 1 count + 0x15f | 60 00 00 | [type 0] Func(FuncType { params: [], returns: [] }) + 0x162 | 02 19 | import section + 0x164 | 04 | 4 count + 0x165 | 00 01 31 00 | import [func 0] Import { module: "", name: "1", ty: Func(0) } | 00 - 0x16c | 00 01 32 02 | import [memory 0] Import { module: "", name: "2", ty: Memory(MemoryType { memory64: false, shared: false, initial: 1, maximum: None }) } + 0x16a | 00 01 32 02 | import [memory 0] Import { module: "", name: "2", ty: Memory(MemoryType { memory64: false, shared: false, initial: 1, maximum: None }) } | 00 01 - 0x172 | 00 01 33 03 | import [global 0] Import { module: "", name: "3", ty: Global(GlobalType { content_type: I32, mutable: false }) } + 0x170 | 00 01 33 03 | import [global 0] Import { module: "", name: "3", ty: Global(GlobalType { content_type: I32, mutable: false }) } | 7f 00 0x178 | 00 01 34 01 | import [table 0] Import { module: "", name: "4", ty: Table(TableType { element_type: RefType { nullable: true, heap_type: Func }, initial: 1, maximum: None }) } | 70 00 01 - 0x17f | 00 0a | custom section - 0x181 | 04 6e 61 6d | name: "name" + 0x17d | 00 0a | custom section + 0x17f | 04 6e 61 6d | name: "name" | 65 - 0x186 | 00 03 | module name - 0x188 | 02 6d 32 | "m2" - 0x18b | 02 0a | core instance section - 0x18d | 02 | 2 count - 0x18e | 00 02 00 | [core instance 0] Instantiate { module_index: 2, args: [] } - 0x191 | 00 03 01 00 | [core instance 1] Instantiate { module_index: 3, args: [InstantiationArg { name: "", kind: Instance, index: 0 }] } + 0x184 | 00 03 | module name + 0x186 | 02 6d 32 | "m2" + 0x189 | 02 0a | core instance section + 0x18b | 02 | 2 count + 0x18c | 00 02 00 | [core instance 0] Instantiate { module_index: 2, args: [] } + 0x18f | 00 03 01 00 | [core instance 1] Instantiate { module_index: 3, args: [InstantiationArg { name: "", kind: Instance, index: 0 }] } | 12 00 - 0x197 | 06 19 | component alias section - 0x199 | 04 | 4 count - 0x19a | 00 00 01 00 | alias [core func 0] CoreInstanceExport { kind: Func, instance_index: 0, name: "1" } + 0x195 | 06 19 | component alias section + 0x197 | 04 | 4 count + 0x198 | 00 00 01 00 | alias [core func 0] CoreInstanceExport { kind: Func, instance_index: 0, name: "1" } | 01 31 - 0x1a0 | 00 02 01 00 | alias [core memory 0] CoreInstanceExport { kind: Memory, instance_index: 0, name: "2" } + 0x19e | 00 02 01 00 | alias [core memory 0] CoreInstanceExport { kind: Memory, instance_index: 0, name: "2" } | 01 32 - 0x1a6 | 00 03 01 00 | alias [core global 0] CoreInstanceExport { kind: Global, instance_index: 0, name: "3" } + 0x1a4 | 00 03 01 00 | alias [core global 0] CoreInstanceExport { kind: Global, instance_index: 0, name: "3" } | 01 33 - 0x1ac | 00 01 01 00 | alias [core table 0] CoreInstanceExport { kind: Table, instance_index: 0, name: "4" } + 0x1aa | 00 01 01 00 | alias [core table 0] CoreInstanceExport { kind: Table, instance_index: 0, name: "4" } | 01 34 - 0x1b2 | 02 19 | core instance section - 0x1b4 | 02 | 2 count - 0x1b5 | 01 04 01 31 | [core instance 2] FromExports([Export { name: "1", kind: Func, index: 0 }, Export { name: "2", kind: Memory, index: 0 }, Export { name: "3", kind: Global, index: 0 }, Export { name: "4", kind: Table, index: 0 }]) + 0x1b0 | 02 19 | core instance section + 0x1b2 | 02 | 2 count + 0x1b3 | 01 04 01 31 | [core instance 2] FromExports([Export { name: "1", kind: Func, index: 0 }, Export { name: "2", kind: Memory, index: 0 }, Export { name: "3", kind: Global, index: 0 }, Export { name: "4", kind: Table, index: 0 }]) | 00 00 01 32 | 02 00 01 33 | 03 00 01 34 | 01 00 - 0x1c7 | 00 03 01 00 | [core instance 3] Instantiate { module_index: 3, args: [InstantiationArg { name: "", kind: Instance, index: 2 }] } + 0x1c5 | 00 03 01 00 | [core instance 3] Instantiate { module_index: 3, args: [InstantiationArg { name: "", kind: Instance, index: 2 }] } | 12 02 diff --git a/tests/dump/bundled.wat b/tests/dump/bundled.wat index 4e17eac4d7..68fc95dda5 100644 --- a/tests/dump/bundled.wat +++ b/tests/dump/bundled.wat @@ -1,7 +1,7 @@ (component (type $WasiFile (instance - (export "read" (func $read (param u32) (result (list u8)))) - (export "write" (func $write (param (list u8)) (result u32))) + (export "read" (func $read (param "len" u32) (result (list u8)))) + (export "write" (func $write (param "buf" (list u8)) (result u32))) )) (import "wasi_file" (instance $real-wasi (type $WasiFile))) diff --git a/tests/dump/bundled.wat.dump b/tests/dump/bundled.wat.dump index 84fbc810ae..1b1c4ade16 100644 --- a/tests/dump/bundled.wat.dump +++ b/tests/dump/bundled.wat.dump @@ -1,191 +1,192 @@ 0x0 | 00 61 73 6d | version 65546 (Component) | 0a 00 01 00 - 0x8 | 07 26 | component type section + 0x8 | 07 2e | component type section 0xa | 01 | 1 count - 0xb | 42 06 01 70 | [type 0] Instance([Type(Defined(List(Primitive(U8)))), Type(Func(ComponentFuncType { params: Unnamed(Primitive(U32)), results: Unnamed(Type(0)) })), Export { name: "read", ty: Func(1) }, Type(Defined(List(Primitive(U8)))), Type(Func(ComponentFuncType { params: Unnamed(Type(2)), results: Unnamed(Primitive(U32)) })), Export { name: "write", ty: Func(3) }]) - | 7d 01 40 00 + 0xb | 42 06 01 70 | [type 0] Instance([Type(Defined(List(Primitive(U8)))), Type(Func(ComponentFuncType { params: [("len", Primitive(U32))], results: Unnamed(Type(0)) })), Export { name: "read", ty: Func(1) }, Type(Defined(List(Primitive(U8)))), Type(Func(ComponentFuncType { params: [("buf", Type(2))], results: Unnamed(Primitive(U32)) })), Export { name: "write", ty: Func(3) }]) + | 7d 01 40 01 + | 03 6c 65 6e | 79 00 00 04 | 04 72 65 61 | 64 01 01 01 | 70 7d 01 40 - | 00 02 00 79 + | 01 03 62 75 + | 66 02 00 79 | 04 05 77 72 | 69 74 65 01 | 03 - 0x30 | 0a 0d | component import section - 0x32 | 01 | 1 count - 0x33 | 09 77 61 73 | [instance 0] ComponentImport { name: "wasi_file", ty: Instance(0) } + 0x38 | 0a 0d | component import section + 0x3a | 01 | 1 count + 0x3b | 09 77 61 73 | [instance 0] ComponentImport { name: "wasi_file", ty: Instance(0) } | 69 5f 66 69 | 6c 65 05 00 - 0x3f | 01 44 | [core module 0] inline size - 0x41 | 00 61 73 6d | version 1 (Module) + 0x47 | 01 44 | [core module 0] inline size + 0x49 | 00 61 73 6d | version 1 (Module) | 01 00 00 00 - 0x49 | 01 09 | type section - 0x4b | 01 | 1 count - 0x4c | 60 04 7f 7f | [type 0] Func(FuncType { params: [I32, I32, I32, I32], returns: [I32] }) + 0x51 | 01 09 | type section + 0x53 | 01 | 1 count + 0x54 | 60 04 7f 7f | [type 0] Func(FuncType { params: [I32, I32, I32, I32], returns: [I32] }) | 7f 7f 01 7f - 0x54 | 03 02 | func section - 0x56 | 01 | 1 count - 0x57 | 00 | [func 0] type 0 - 0x58 | 05 03 | memory section - 0x5a | 01 | 1 count - 0x5b | 00 00 | [memory 0] MemoryType { memory64: false, shared: false, initial: 0, maximum: None } - 0x5d | 07 11 | export section - 0x5f | 02 | 2 count - 0x60 | 03 6d 65 6d | export Export { name: "mem", kind: Memory, index: 0 } + 0x5c | 03 02 | func section + 0x5e | 01 | 1 count + 0x5f | 00 | [func 0] type 0 + 0x60 | 05 03 | memory section + 0x62 | 01 | 1 count + 0x63 | 00 00 | [memory 0] MemoryType { memory64: false, shared: false, initial: 0, maximum: None } + 0x65 | 07 11 | export section + 0x67 | 02 | 2 count + 0x68 | 03 6d 65 6d | export Export { name: "mem", kind: Memory, index: 0 } | 02 00 - 0x66 | 07 72 65 61 | export Export { name: "realloc", kind: Func, index: 0 } + 0x6e | 07 72 65 61 | export Export { name: "realloc", kind: Func, index: 0 } | 6c 6c 6f 63 | 00 00 - 0x70 | 0a 05 | code section - 0x72 | 01 | 1 count + 0x78 | 0a 05 | code section + 0x7a | 01 | 1 count ============== func 0 ==================== - 0x73 | 03 | size of function - 0x74 | 00 | 0 local blocks - 0x75 | 00 | unreachable - 0x76 | 0b | end - 0x77 | 00 0c | custom section - 0x79 | 04 6e 61 6d | name: "name" + 0x7b | 03 | size of function + 0x7c | 00 | 0 local blocks + 0x7d | 00 | unreachable + 0x7e | 0b | end + 0x7f | 00 0c | custom section + 0x81 | 04 6e 61 6d | name: "name" | 65 - 0x7e | 00 05 | module name - 0x80 | 04 6c 69 62 | "libc" + 0x86 | 00 05 | module name + 0x88 | 04 6c 69 62 | "libc" | 63 - 0x85 | 02 04 | core instance section - 0x87 | 01 | 1 count - 0x88 | 00 00 00 | [core instance 0] Instantiate { module_index: 0, args: [] } - 0x8b | 01 5f | [core module 1] inline size - 0x8d | 00 61 73 6d | version 1 (Module) + 0x8d | 02 04 | core instance section + 0x8f | 01 | 1 count + 0x90 | 00 00 00 | [core instance 0] Instantiate { module_index: 0, args: [] } + 0x93 | 01 5f | [core module 1] inline size + 0x95 | 00 61 73 6d | version 1 (Module) | 01 00 00 00 - 0x95 | 01 09 | type section - 0x97 | 02 | 2 count - 0x98 | 60 02 7f 7f | [type 0] Func(FuncType { params: [I32, I32], returns: [] }) + 0x9d | 01 09 | type section + 0x9f | 02 | 2 count + 0xa0 | 60 02 7f 7f | [type 0] Func(FuncType { params: [I32, I32], returns: [] }) | 00 - 0x9d | 60 00 00 | [type 1] Func(FuncType { params: [], returns: [] }) - 0xa0 | 02 12 | import section - 0xa2 | 01 | 1 count - 0xa3 | 09 77 61 73 | import [func 0] Import { module: "wasi_file", name: "read", ty: Func(0) } + 0xa5 | 60 00 00 | [type 1] Func(FuncType { params: [], returns: [] }) + 0xa8 | 02 12 | import section + 0xaa | 01 | 1 count + 0xab | 09 77 61 73 | import [func 0] Import { module: "wasi_file", name: "read", ty: Func(0) } | 69 5f 66 69 | 6c 65 04 72 | 65 61 64 00 | 00 - 0xb4 | 03 02 | func section - 0xb6 | 01 | 1 count - 0xb7 | 01 | [func 1] type 1 - 0xb8 | 07 08 | export section - 0xba | 01 | 1 count - 0xbb | 04 70 6c 61 | export Export { name: "play", kind: Func, index: 1 } + 0xbc | 03 02 | func section + 0xbe | 01 | 1 count + 0xbf | 01 | [func 1] type 1 + 0xc0 | 07 08 | export section + 0xc2 | 01 | 1 count + 0xc3 | 04 70 6c 61 | export Export { name: "play", kind: Func, index: 1 } | 79 00 01 - 0xc2 | 0a 05 | code section - 0xc4 | 01 | 1 count + 0xca | 0a 05 | code section + 0xcc | 01 | 1 count ============== func 1 ==================== - 0xc5 | 03 | size of function - 0xc6 | 00 | 0 local blocks - 0xc7 | 00 | unreachable - 0xc8 | 0b | end - 0xc9 | 00 21 | custom section - 0xcb | 04 6e 61 6d | name: "name" + 0xcd | 03 | size of function + 0xce | 00 | 0 local blocks + 0xcf | 00 | unreachable + 0xd0 | 0b | end + 0xd1 | 00 21 | custom section + 0xd3 | 04 6e 61 6d | name: "name" | 65 - 0xd0 | 00 06 | module name - 0xd2 | 05 43 48 49 | "CHILD" + 0xd8 | 00 06 | module name + 0xda | 05 43 48 49 | "CHILD" | 4c 44 - 0xd8 | 01 12 | function names - 0xda | 02 | 2 count - 0xdb | 00 09 77 61 | Naming { index: 0, name: "wasi-file" } + 0xe0 | 01 12 | function names + 0xe2 | 02 | 2 count + 0xe3 | 00 09 77 61 | Naming { index: 0, name: "wasi-file" } | 73 69 2d 66 | 69 6c 65 - 0xe6 | 01 04 70 6c | Naming { index: 1, name: "play" } + 0xee | 01 04 70 6c | Naming { index: 1, name: "play" } | 61 79 - 0xec | 01 60 | [core module 2] inline size - 0xee | 00 61 73 6d | version 1 (Module) + 0xf4 | 01 60 | [core module 2] inline size + 0xf6 | 00 61 73 6d | version 1 (Module) | 01 00 00 00 - 0xf6 | 01 0c | type section - 0xf8 | 02 | 2 count - 0xf9 | 60 02 7f 7f | [type 0] Func(FuncType { params: [I32, I32], returns: [] }) + 0xfe | 01 0c | type section + 0x100 | 02 | 2 count + 0x101 | 60 02 7f 7f | [type 0] Func(FuncType { params: [I32, I32], returns: [] }) | 00 - 0xfe | 60 03 7f 7f | [type 1] Func(FuncType { params: [I32, I32, I32], returns: [] }) + 0x106 | 60 03 7f 7f | [type 1] Func(FuncType { params: [I32, I32, I32], returns: [] }) | 7f 00 - 0x104 | 02 12 | import section - 0x106 | 01 | 1 count - 0x107 | 09 77 61 73 | import [func 0] Import { module: "wasi_file", name: "read", ty: Func(0) } + 0x10c | 02 12 | import section + 0x10e | 01 | 1 count + 0x10f | 09 77 61 73 | import [func 0] Import { module: "wasi_file", name: "read", ty: Func(0) } | 69 5f 66 69 | 6c 65 04 72 | 65 61 64 00 | 00 - 0x118 | 03 03 | func section - 0x11a | 02 | 2 count - 0x11b | 00 | [func 1] type 0 - 0x11c | 01 | [func 2] type 1 - 0x11d | 07 10 | export section - 0x11f | 02 | 2 count - 0x120 | 04 72 65 61 | export Export { name: "read", kind: Func, index: 1 } + 0x120 | 03 03 | func section + 0x122 | 02 | 2 count + 0x123 | 00 | [func 1] type 0 + 0x124 | 01 | [func 2] type 1 + 0x125 | 07 10 | export section + 0x127 | 02 | 2 count + 0x128 | 04 72 65 61 | export Export { name: "read", kind: Func, index: 1 } | 64 00 01 - 0x127 | 05 77 72 69 | export Export { name: "write", kind: Func, index: 2 } + 0x12f | 05 77 72 69 | export Export { name: "write", kind: Func, index: 2 } | 74 65 00 02 - 0x12f | 0a 09 | code section - 0x131 | 02 | 2 count + 0x137 | 0a 09 | code section + 0x139 | 02 | 2 count ============== func 1 ==================== - 0x132 | 03 | size of function - 0x133 | 00 | 0 local blocks - 0x134 | 00 | unreachable - 0x135 | 0b | end + 0x13a | 03 | size of function + 0x13b | 00 | 0 local blocks + 0x13c | 00 | unreachable + 0x13d | 0b | end ============== func 2 ==================== - 0x136 | 03 | size of function - 0x137 | 00 | 0 local blocks - 0x138 | 00 | unreachable - 0x139 | 0b | end - 0x13a | 00 12 | custom section - 0x13c | 04 6e 61 6d | name: "name" + 0x13e | 03 | size of function + 0x13f | 00 | 0 local blocks + 0x140 | 00 | unreachable + 0x141 | 0b | end + 0x142 | 00 12 | custom section + 0x144 | 04 6e 61 6d | name: "name" | 65 - 0x141 | 00 0b | module name - 0x143 | 0a 56 49 52 | "VIRTUALIZE" + 0x149 | 00 0b | module name + 0x14b | 0a 56 49 52 | "VIRTUALIZE" | 54 55 41 4c | 49 5a 45 - 0x14e | 06 1d | component alias section - 0x150 | 03 | 3 count - 0x151 | 01 00 00 04 | alias [func 0] InstanceExport { kind: Func, instance_index: 0, name: "read" } + 0x156 | 06 1d | component alias section + 0x158 | 03 | 3 count + 0x159 | 01 00 00 04 | alias [func 0] InstanceExport { kind: Func, instance_index: 0, name: "read" } | 72 65 61 64 - 0x159 | 00 02 01 00 | alias [core memory 0] CoreInstanceExport { kind: Memory, instance_index: 0, name: "mem" } + 0x161 | 00 02 01 00 | alias [core memory 0] CoreInstanceExport { kind: Memory, instance_index: 0, name: "mem" } | 03 6d 65 6d - 0x161 | 00 00 01 00 | alias [core func 0] CoreInstanceExport { kind: Func, instance_index: 0, name: "realloc" } + 0x169 | 00 00 01 00 | alias [core func 0] CoreInstanceExport { kind: Func, instance_index: 0, name: "realloc" } | 07 72 65 61 | 6c 6c 6f 63 - 0x16d | 08 09 | canonical function section - 0x16f | 01 | 1 count - 0x170 | 01 00 00 02 | [core func 1] Lower { func_index: 0, options: [Memory(0), Realloc(0)] } + 0x175 | 08 09 | canonical function section + 0x177 | 01 | 1 count + 0x178 | 01 00 00 02 | [core func 1] Lower { func_index: 0, options: [Memory(0), Realloc(0)] } | 03 00 04 00 - 0x178 | 02 28 | core instance section - 0x17a | 03 | 3 count - 0x17b | 01 01 04 72 | [core instance 1] FromExports([Export { name: "read", kind: Func, index: 1 }]) + 0x180 | 02 28 | core instance section + 0x182 | 03 | 3 count + 0x183 | 01 01 04 72 | [core instance 1] FromExports([Export { name: "read", kind: Func, index: 1 }]) | 65 61 64 00 | 01 - 0x184 | 00 02 01 09 | [core instance 2] Instantiate { module_index: 2, args: [InstantiationArg { name: "wasi_file", kind: Instance, index: 1 }] } + 0x18c | 00 02 01 09 | [core instance 2] Instantiate { module_index: 2, args: [InstantiationArg { name: "wasi_file", kind: Instance, index: 1 }] } | 77 61 73 69 | 5f 66 69 6c | 65 12 01 - 0x193 | 00 01 01 09 | [core instance 3] Instantiate { module_index: 1, args: [InstantiationArg { name: "wasi_file", kind: Instance, index: 2 }] } + 0x19b | 00 01 01 09 | [core instance 3] Instantiate { module_index: 1, args: [InstantiationArg { name: "wasi_file", kind: Instance, index: 2 }] } | 77 61 73 69 | 5f 66 69 6c | 65 12 02 - 0x1a2 | 07 06 | component type section - 0x1a4 | 01 | 1 count - 0x1a5 | 40 01 00 01 | [type 1] Func(ComponentFuncType { params: Named([]), results: Named([]) }) - | 00 - 0x1aa | 06 1e | component alias section - 0x1ac | 03 | 3 count - 0x1ad | 00 00 01 03 | alias [core func 2] CoreInstanceExport { kind: Func, instance_index: 3, name: "play" } + 0x1aa | 07 05 | component type section + 0x1ac | 01 | 1 count + 0x1ad | 40 00 01 00 | [type 1] Func(ComponentFuncType { params: [], results: Named([]) }) + 0x1b1 | 06 1e | component alias section + 0x1b3 | 03 | 3 count + 0x1b4 | 00 00 01 03 | alias [core func 2] CoreInstanceExport { kind: Func, instance_index: 3, name: "play" } | 04 70 6c 61 | 79 - 0x1b6 | 00 02 01 00 | alias [core memory 1] CoreInstanceExport { kind: Memory, instance_index: 0, name: "mem" } + 0x1bd | 00 02 01 00 | alias [core memory 1] CoreInstanceExport { kind: Memory, instance_index: 0, name: "mem" } | 03 6d 65 6d - 0x1be | 00 00 01 00 | alias [core func 3] CoreInstanceExport { kind: Func, instance_index: 0, name: "realloc" } + 0x1c5 | 00 00 01 00 | alias [core func 3] CoreInstanceExport { kind: Func, instance_index: 0, name: "realloc" } | 07 72 65 61 | 6c 6c 6f 63 - 0x1ca | 08 0a | canonical function section - 0x1cc | 01 | 1 count - 0x1cd | 00 00 02 02 | [func 1] Lift { core_func_index: 2, type_index: 1, options: [Memory(1), Realloc(3)] } + 0x1d1 | 08 0a | canonical function section + 0x1d3 | 01 | 1 count + 0x1d4 | 00 00 02 02 | [func 1] Lift { core_func_index: 2, type_index: 1, options: [Memory(1), Realloc(3)] } | 03 01 04 03 | 01 - 0x1d6 | 0b 08 | component export section - 0x1d8 | 01 | 1 count - 0x1d9 | 04 77 6f 72 | export ComponentExport { name: "work", kind: Func, index: 1 } + 0x1dd | 0b 08 | component export section + 0x1df | 01 | 1 count + 0x1e0 | 04 77 6f 72 | export ComponentExport { name: "work", kind: Func, index: 1 } | 6b 01 01 diff --git a/tests/dump/component-inline-type.wat.dump b/tests/dump/component-inline-type.wat.dump index 1cab3fbc71..ddde5a7344 100644 --- a/tests/dump/component-inline-type.wat.dump +++ b/tests/dump/component-inline-type.wat.dump @@ -18,10 +18,9 @@ 0x24 | 0a 04 | component import section 0x26 | 01 | 1 count 0x27 | 00 05 01 | [instance 0] ComponentImport { name: "", ty: Instance(1) } - 0x2a | 07 06 | component type section + 0x2a | 07 05 | component type section 0x2c | 01 | 1 count - 0x2d | 40 01 00 01 | [type 2] Func(ComponentFuncType { params: Named([]), results: Named([]) }) - | 00 - 0x32 | 0a 04 | component import section - 0x34 | 01 | 1 count - 0x35 | 00 01 02 | [func 0] ComponentImport { name: "", ty: Func(2) } + 0x2d | 40 00 01 00 | [type 2] Func(ComponentFuncType { params: [], results: Named([]) }) + 0x31 | 0a 04 | component import section + 0x33 | 01 | 1 count + 0x34 | 00 01 02 | [func 0] ComponentImport { name: "", ty: Func(2) } diff --git a/tests/dump/component-instance-type.wat.dump b/tests/dump/component-instance-type.wat.dump index f8e09afc41..1a89f8ea57 100644 --- a/tests/dump/component-instance-type.wat.dump +++ b/tests/dump/component-instance-type.wat.dump @@ -1,14 +1,13 @@ 0x0 | 00 61 73 6d | version 65546 (Component) | 0a 00 01 00 - 0x8 | 07 27 | component type section + 0x8 | 07 25 | component type section 0xa | 01 | 1 count - 0xb | 42 03 01 40 | [type 0] Instance([Type(Func(ComponentFuncType { params: Named([]), results: Named([]) })), Type(Component([Type(Func(ComponentFuncType { params: Named([]), results: Named([]) })), Alias(Outer { kind: Type, count: 1, index: 0 }), Import(ComponentImport { name: "1", ty: Func(0) }), Export { name: "1", ty: Func(1) }])), Export { name: "c5", ty: Component(1) }]) - | 01 00 01 00 - | 01 41 04 01 - | 40 01 00 01 - | 00 02 03 02 - | 01 00 03 01 - | 31 01 00 04 - | 01 31 01 01 - | 04 02 63 35 - | 04 01 + 0xb | 42 03 01 40 | [type 0] Instance([Type(Func(ComponentFuncType { params: [], results: Named([]) })), Type(Component([Type(Func(ComponentFuncType { params: [], results: Named([]) })), Alias(Outer { kind: Type, count: 1, index: 0 }), Import(ComponentImport { name: "1", ty: Func(0) }), Export { name: "1", ty: Func(1) }])), Export { name: "c5", ty: Component(1) }]) + | 00 01 00 01 + | 41 04 01 40 + | 00 01 00 02 + | 03 02 01 00 + | 03 01 31 01 + | 00 04 01 31 + | 01 01 04 02 + | 63 35 04 01 diff --git a/tests/dump/component-linking.wat.dump b/tests/dump/component-linking.wat.dump index d24e1629cf..456f8fc73d 100644 --- a/tests/dump/component-linking.wat.dump +++ b/tests/dump/component-linking.wat.dump @@ -1,66 +1,65 @@ 0x0 | 00 61 73 6d | version 65546 (Component) | 0a 00 01 00 - 0x8 | 07 2c | component type section + 0x8 | 07 2b | component type section 0xa | 01 | 1 count - 0xb | 42 09 00 50 | [type 0] Instance([CoreType(Module([])), Export { name: "1", ty: Module(0) }, Type(Func(ComponentFuncType { params: Named([]), results: Named([]) })), Export { name: "2", ty: Func(0) }, Export { name: "3", ty: Value(Primitive(String)) }, Type(Instance([])), Export { name: "4", ty: Instance(1) }, Type(Component([])), Export { name: "5", ty: Component(2) }]) + 0xb | 42 09 00 50 | [type 0] Instance([CoreType(Module([])), Export { name: "1", ty: Module(0) }, Type(Func(ComponentFuncType { params: [], results: Named([]) })), Export { name: "2", ty: Func(0) }, Export { name: "3", ty: Value(Primitive(String)) }, Type(Instance([])), Export { name: "4", ty: Instance(1) }, Type(Component([])), Export { name: "5", ty: Component(2) }]) | 00 04 01 31 | 00 11 00 01 - | 40 01 00 01 - | 00 04 01 32 - | 01 00 04 01 - | 33 02 73 01 - | 42 00 04 01 - | 34 05 01 01 - | 41 00 04 01 - | 35 04 02 - 0x36 | 0a 04 | component import section - 0x38 | 01 | 1 count - 0x39 | 00 05 00 | [instance 0] ComponentImport { name: "", ty: Instance(0) } - 0x3c | 04 40 | [component 0] inline size - 0x3e | 00 61 73 6d | version 65546 (Component) + | 40 00 01 00 + | 04 01 32 01 + | 00 04 01 33 + | 02 73 01 42 + | 00 04 01 34 + | 05 01 01 41 + | 00 04 01 35 + | 04 02 + 0x35 | 0a 04 | component import section + 0x37 | 01 | 1 count + 0x38 | 00 05 00 | [instance 0] ComponentImport { name: "", ty: Instance(0) } + 0x3b | 04 3f | [component 0] inline size + 0x3d | 00 61 73 6d | version 65546 (Component) | 0a 00 01 00 - 0x46 | 03 03 | core type section - 0x48 | 01 | 1 count - 0x49 | 50 00 | [core type 0] Module([]) - 0x4b | 0a 06 | component import section - 0x4d | 01 | 1 count - 0x4e | 01 31 00 11 | [module 0] ComponentImport { name: "1", ty: Module(0) } + 0x45 | 03 03 | core type section + 0x47 | 01 | 1 count + 0x48 | 50 00 | [core type 0] Module([]) + 0x4a | 0a 06 | component import section + 0x4c | 01 | 1 count + 0x4d | 01 31 00 11 | [module 0] ComponentImport { name: "1", ty: Module(0) } | 00 - 0x53 | 07 06 | component type section - 0x55 | 01 | 1 count - 0x56 | 40 01 00 01 | [type 0] Func(ComponentFuncType { params: Named([]), results: Named([]) }) - | 00 - 0x5b | 0a 09 | component import section - 0x5d | 02 | 2 count - 0x5e | 01 32 01 00 | [func 0] ComponentImport { name: "2", ty: Func(0) } - 0x62 | 01 33 02 73 | [value 0] ComponentImport { name: "3", ty: Value(Primitive(String)) } - 0x66 | 07 03 | component type section - 0x68 | 01 | 1 count - 0x69 | 42 00 | [type 1] Instance([]) - 0x6b | 0a 05 | component import section - 0x6d | 01 | 1 count - 0x6e | 01 34 05 01 | [instance 0] ComponentImport { name: "4", ty: Instance(1) } - 0x72 | 07 03 | component type section - 0x74 | 01 | 1 count - 0x75 | 41 00 | [type 2] Component([]) - 0x77 | 0a 05 | component import section - 0x79 | 01 | 1 count - 0x7a | 01 35 04 02 | [component 0] ComponentImport { name: "5", ty: Component(2) } - 0x7e | 06 1b | component alias section - 0x80 | 05 | 5 count - 0x81 | 00 11 00 00 | alias [module 0] InstanceExport { kind: Module, instance_index: 0, name: "1" } + 0x52 | 07 05 | component type section + 0x54 | 01 | 1 count + 0x55 | 40 00 01 00 | [type 0] Func(ComponentFuncType { params: [], results: Named([]) }) + 0x59 | 0a 09 | component import section + 0x5b | 02 | 2 count + 0x5c | 01 32 01 00 | [func 0] ComponentImport { name: "2", ty: Func(0) } + 0x60 | 01 33 02 73 | [value 0] ComponentImport { name: "3", ty: Value(Primitive(String)) } + 0x64 | 07 03 | component type section + 0x66 | 01 | 1 count + 0x67 | 42 00 | [type 1] Instance([]) + 0x69 | 0a 05 | component import section + 0x6b | 01 | 1 count + 0x6c | 01 34 05 01 | [instance 0] ComponentImport { name: "4", ty: Instance(1) } + 0x70 | 07 03 | component type section + 0x72 | 01 | 1 count + 0x73 | 41 00 | [type 2] Component([]) + 0x75 | 0a 05 | component import section + 0x77 | 01 | 1 count + 0x78 | 01 35 04 02 | [component 0] ComponentImport { name: "5", ty: Component(2) } + 0x7c | 06 1b | component alias section + 0x7e | 05 | 5 count + 0x7f | 00 11 00 00 | alias [module 0] InstanceExport { kind: Module, instance_index: 0, name: "1" } | 01 31 - 0x87 | 01 00 00 01 | alias [func 0] InstanceExport { kind: Func, instance_index: 0, name: "2" } + 0x85 | 01 00 00 01 | alias [func 0] InstanceExport { kind: Func, instance_index: 0, name: "2" } | 32 - 0x8c | 02 00 00 01 | alias [value 0] InstanceExport { kind: Value, instance_index: 0, name: "4" } + 0x8a | 02 00 00 01 | alias [value 0] InstanceExport { kind: Value, instance_index: 0, name: "4" } | 34 - 0x91 | 05 00 00 01 | alias [instance 1] InstanceExport { kind: Instance, instance_index: 0, name: "3" } + 0x8f | 05 00 00 01 | alias [instance 1] InstanceExport { kind: Instance, instance_index: 0, name: "3" } | 33 - 0x96 | 04 00 00 01 | alias [component 1] InstanceExport { kind: Component, instance_index: 0, name: "5" } + 0x94 | 04 00 00 01 | alias [component 1] InstanceExport { kind: Component, instance_index: 0, name: "5" } | 35 - 0x9b | 05 19 | component instance section - 0x9d | 01 | 1 count - 0x9e | 00 00 05 01 | [instance 2] Instantiate { component_index: 0, args: [ComponentInstantiationArg { name: "1", kind: Module, index: 0 }, ComponentInstantiationArg { name: "2", kind: Func, index: 0 }, ComponentInstantiationArg { name: "3", kind: Value, index: 0 }, ComponentInstantiationArg { name: "4", kind: Instance, index: 1 }, ComponentInstantiationArg { name: "5", kind: Component, index: 1 }] } + 0x99 | 05 19 | component instance section + 0x9b | 01 | 1 count + 0x9c | 00 00 05 01 | [instance 2] Instantiate { component_index: 0, args: [ComponentInstantiationArg { name: "1", kind: Module, index: 0 }, ComponentInstantiationArg { name: "2", kind: Func, index: 0 }, ComponentInstantiationArg { name: "3", kind: Value, index: 0 }, ComponentInstantiationArg { name: "4", kind: Instance, index: 1 }, ComponentInstantiationArg { name: "5", kind: Component, index: 1 }] } | 31 00 11 00 | 01 32 01 00 | 01 33 02 00 diff --git a/tests/dump/component-outer-alias.wat.dump b/tests/dump/component-outer-alias.wat.dump index 50909df8cd..a5e97dec81 100644 --- a/tests/dump/component-outer-alias.wat.dump +++ b/tests/dump/component-outer-alias.wat.dump @@ -1,46 +1,40 @@ 0x0 | 00 61 73 6d | version 65546 (Component) | 0a 00 01 00 - 0x8 | 07 0f | component type section + 0x8 | 07 0e | component type section 0xa | 02 | 2 count 0xb | 73 | [type 0] Defined(Primitive(String)) - 0xc | 41 02 02 03 | [type 1] Component([Alias(Outer { kind: Type, count: 1, index: 0 }), Type(Func(ComponentFuncType { params: Named([]), results: Unnamed(Type(0)) }))]) + 0xc | 41 02 02 03 | [type 1] Component([Alias(Outer { kind: Type, count: 1, index: 0 }), Type(Func(ComponentFuncType { params: [], results: Unnamed(Type(0)) }))]) | 02 01 00 01 - | 40 01 00 00 - | 00 - 0x19 | 04 17 | [component 0] inline size - 0x1b | 00 61 73 6d | version 65546 (Component) + | 40 00 00 00 + 0x18 | 04 16 | [component 0] inline size + 0x1a | 00 61 73 6d | version 65546 (Component) | 0a 00 01 00 - 0x23 | 06 05 | component alias section - 0x25 | 01 | 1 count - 0x26 | 03 02 01 00 | alias [type 0] Outer { kind: Type, count: 1, index: 0 } - 0x2a | 07 06 | component type section - 0x2c | 01 | 1 count - 0x2d | 40 01 00 00 | [type 1] Func(ComponentFuncType { params: Named([]), results: Unnamed(Type(0)) }) - | 00 - 0x32 | 04 1c | [component 1] inline size - 0x34 | 00 61 73 6d | version 65546 (Component) + 0x22 | 06 05 | component alias section + 0x24 | 01 | 1 count + 0x25 | 03 02 01 00 | alias [type 0] Outer { kind: Type, count: 1, index: 0 } + 0x29 | 07 05 | component type section + 0x2b | 01 | 1 count + 0x2c | 40 00 00 00 | [type 1] Func(ComponentFuncType { params: [], results: Unnamed(Type(0)) }) + 0x30 | 04 1a | [component 1] inline size + 0x32 | 00 61 73 6d | version 65546 (Component) | 0a 00 01 00 - 0x3c | 06 05 | component alias section - 0x3e | 01 | 1 count - 0x3f | 03 02 01 00 | alias [type 0] Outer { kind: Type, count: 1, index: 0 } - 0x43 | 07 0b | component type section - 0x45 | 02 | 2 count - 0x46 | 40 01 00 00 | [type 1] Func(ComponentFuncType { params: Named([]), results: Unnamed(Type(0)) }) - | 00 - 0x4b | 40 01 00 00 | [type 2] Func(ComponentFuncType { params: Named([]), results: Unnamed(Type(0)) }) - | 00 - 0x50 | 07 02 | component type section - 0x52 | 01 | 1 count - 0x53 | 7d | [type 2] Defined(Primitive(U8)) - 0x54 | 04 1c | [component 2] inline size - 0x56 | 00 61 73 6d | version 65546 (Component) + 0x3a | 06 05 | component alias section + 0x3c | 01 | 1 count + 0x3d | 03 02 01 00 | alias [type 0] Outer { kind: Type, count: 1, index: 0 } + 0x41 | 07 09 | component type section + 0x43 | 02 | 2 count + 0x44 | 40 00 00 00 | [type 1] Func(ComponentFuncType { params: [], results: Unnamed(Type(0)) }) + 0x48 | 40 00 00 00 | [type 2] Func(ComponentFuncType { params: [], results: Unnamed(Type(0)) }) + 0x4c | 07 02 | component type section + 0x4e | 01 | 1 count + 0x4f | 7d | [type 2] Defined(Primitive(U8)) + 0x50 | 04 1a | [component 2] inline size + 0x52 | 00 61 73 6d | version 65546 (Component) | 0a 00 01 00 - 0x5e | 06 05 | component alias section - 0x60 | 01 | 1 count - 0x61 | 03 02 01 02 | alias [type 0] Outer { kind: Type, count: 1, index: 2 } - 0x65 | 07 0b | component type section - 0x67 | 02 | 2 count - 0x68 | 40 01 00 00 | [type 1] Func(ComponentFuncType { params: Named([]), results: Unnamed(Type(0)) }) - | 00 - 0x6d | 40 01 00 00 | [type 2] Func(ComponentFuncType { params: Named([]), results: Unnamed(Type(0)) }) - | 00 + 0x5a | 06 05 | component alias section + 0x5c | 01 | 1 count + 0x5d | 03 02 01 02 | alias [type 0] Outer { kind: Type, count: 1, index: 2 } + 0x61 | 07 09 | component type section + 0x63 | 02 | 2 count + 0x64 | 40 00 00 00 | [type 1] Func(ComponentFuncType { params: [], results: Unnamed(Type(0)) }) + 0x68 | 40 00 00 00 | [type 2] Func(ComponentFuncType { params: [], results: Unnamed(Type(0)) }) diff --git a/tests/dump/instance-expand.wat.dump b/tests/dump/instance-expand.wat.dump index 8ae675bee4..38ea71ff30 100644 --- a/tests/dump/instance-expand.wat.dump +++ b/tests/dump/instance-expand.wat.dump @@ -1,10 +1,10 @@ 0x0 | 00 61 73 6d | version 65546 (Component) | 0a 00 01 00 - 0x8 | 07 0d | component type section + 0x8 | 07 0c | component type section 0xa | 01 | 1 count - 0xb | 42 02 01 40 | [type 0] Instance([Type(Func(ComponentFuncType { params: Named([]), results: Named([]) })), Export { name: "", ty: Func(0) }]) - | 01 00 01 00 - | 04 00 01 00 - 0x17 | 0a 04 | component import section - 0x19 | 01 | 1 count - 0x1a | 00 05 00 | [instance 0] ComponentImport { name: "", ty: Instance(0) } + 0xb | 42 02 01 40 | [type 0] Instance([Type(Func(ComponentFuncType { params: [], results: Named([]) })), Export { name: "", ty: Func(0) }]) + | 00 01 00 04 + | 00 01 00 + 0x16 | 0a 04 | component import section + 0x18 | 01 | 1 count + 0x19 | 00 05 00 | [instance 0] ComponentImport { name: "", ty: Instance(0) } diff --git a/tests/dump/instance-type.wat.dump b/tests/dump/instance-type.wat.dump index 245d86504d..d39ca2ef84 100644 --- a/tests/dump/instance-type.wat.dump +++ b/tests/dump/instance-type.wat.dump @@ -1,10 +1,10 @@ 0x0 | 00 61 73 6d | version 65546 (Component) | 0a 00 01 00 - 0x8 | 07 16 | component type section + 0x8 | 07 15 | component type section 0xa | 02 | 2 count - 0xb | 42 02 01 40 | [type 0] Instance([Type(Func(ComponentFuncType { params: Named([]), results: Named([]) })), Export { name: "", ty: Func(0) }]) - | 01 00 01 00 - | 04 00 01 00 - 0x17 | 42 02 01 42 | [type 1] Instance([Type(Instance([])), Export { name: "", ty: Instance(0) }]) + 0xb | 42 02 01 40 | [type 0] Instance([Type(Func(ComponentFuncType { params: [], results: Named([]) })), Export { name: "", ty: Func(0) }]) + | 00 01 00 04 + | 00 01 00 + 0x16 | 42 02 01 42 | [type 1] Instance([Type(Instance([])), Export { name: "", ty: Instance(0) }]) | 00 04 00 05 | 00 diff --git a/tests/dump/instantiate.wat.dump b/tests/dump/instantiate.wat.dump index 816e976439..e7ebf9573e 100644 --- a/tests/dump/instantiate.wat.dump +++ b/tests/dump/instantiate.wat.dump @@ -6,14 +6,13 @@ 0xd | 0a 05 | component import section 0xf | 01 | 1 count 0x10 | 01 61 04 00 | [component 0] ComponentImport { name: "a", ty: Component(0) } - 0x14 | 07 06 | component type section + 0x14 | 07 05 | component type section 0x16 | 01 | 1 count - 0x17 | 40 01 00 01 | [type 1] Func(ComponentFuncType { params: Named([]), results: Named([]) }) - | 00 - 0x1c | 0a 05 | component import section - 0x1e | 01 | 1 count - 0x1f | 01 66 01 01 | [func 0] ComponentImport { name: "f", ty: Func(1) } - 0x23 | 05 08 | component instance section - 0x25 | 01 | 1 count - 0x26 | 00 00 01 01 | [instance 0] Instantiate { component_index: 0, args: [ComponentInstantiationArg { name: "a", kind: Func, index: 0 }] } + 0x17 | 40 00 01 00 | [type 1] Func(ComponentFuncType { params: [], results: Named([]) }) + 0x1b | 0a 05 | component import section + 0x1d | 01 | 1 count + 0x1e | 01 66 01 01 | [func 0] ComponentImport { name: "f", ty: Func(1) } + 0x22 | 05 08 | component instance section + 0x24 | 01 | 1 count + 0x25 | 00 00 01 01 | [instance 0] Instantiate { component_index: 0, args: [ComponentInstantiationArg { name: "a", kind: Func, index: 0 }] } | 61 01 00 diff --git a/tests/dump/instantiate2.wat.dump b/tests/dump/instantiate2.wat.dump index 7cd6cb2c52..7a3cae3602 100644 --- a/tests/dump/instantiate2.wat.dump +++ b/tests/dump/instantiate2.wat.dump @@ -1,13 +1,13 @@ 0x0 | 00 61 73 6d | version 65546 (Component) | 0a 00 01 00 - 0x8 | 07 0d | component type section + 0x8 | 07 0c | component type section 0xa | 01 | 1 count - 0xb | 41 02 01 40 | [type 0] Component([Type(Func(ComponentFuncType { params: Named([]), results: Named([]) })), Import(ComponentImport { name: "", ty: Func(0) })]) - | 01 00 01 00 - | 03 00 01 00 - 0x17 | 0a 04 | component import section - 0x19 | 01 | 1 count - 0x1a | 00 04 00 | [component 0] ComponentImport { name: "", ty: Component(0) } - 0x1d | 05 04 | component instance section - 0x1f | 01 | 1 count - 0x20 | 00 00 00 | [instance 0] Instantiate { component_index: 0, args: [] } + 0xb | 41 02 01 40 | [type 0] Component([Type(Func(ComponentFuncType { params: [], results: Named([]) })), Import(ComponentImport { name: "", ty: Func(0) })]) + | 00 01 00 03 + | 00 01 00 + 0x16 | 0a 04 | component import section + 0x18 | 01 | 1 count + 0x19 | 00 04 00 | [component 0] ComponentImport { name: "", ty: Component(0) } + 0x1c | 05 04 | component instance section + 0x1e | 01 | 1 count + 0x1f | 00 00 00 | [instance 0] Instantiate { component_index: 0, args: [] } diff --git a/tests/dump/nested-component.wat b/tests/dump/nested-component.wat index 714e77328d..47990d513c 100644 --- a/tests/dump/nested-component.wat +++ b/tests/dump/nested-component.wat @@ -13,7 +13,7 @@ (component (core module $m) - (import "" (func (param string))) + (import "" (func (param "p" string))) (export "a" (core module $m)) (instance (export "b") (import "") diff --git a/tests/dump/nested-component.wat.dump b/tests/dump/nested-component.wat.dump index ecf043b61f..86ce8e06d6 100644 --- a/tests/dump/nested-component.wat.dump +++ b/tests/dump/nested-component.wat.dump @@ -21,7 +21,7 @@ 0x3b | 04 08 | [component 0] inline size 0x3d | 00 61 73 6d | version 65546 (Component) | 0a 00 01 00 - 0x45 | 04 50 | [component 5] inline size + 0x45 | 04 51 | [component 5] inline size 0x47 | 00 61 73 6d | version 65546 (Component) | 0a 00 01 00 0x4f | 01 13 | [core module 0] inline size @@ -32,29 +32,28 @@ | 65 0x60 | 00 02 | module name 0x62 | 01 6d | "m" - 0x64 | 07 06 | component type section + 0x64 | 07 08 | component type section 0x66 | 01 | 1 count - 0x67 | 40 00 73 01 | [type 0] Func(ComponentFuncType { params: Unnamed(Primitive(String)), results: Named([]) }) + 0x67 | 40 01 01 70 | [type 0] Func(ComponentFuncType { params: [("p", Primitive(String))], results: Named([]) }) + | 73 01 00 + 0x6e | 0a 04 | component import section + 0x70 | 01 | 1 count + 0x71 | 00 01 00 | [func 0] ComponentImport { name: "", ty: Func(0) } + 0x74 | 0b 06 | component export section + 0x76 | 01 | 1 count + 0x77 | 01 61 00 11 | export ComponentExport { name: "a", kind: Module, index: 0 } | 00 - 0x6c | 0a 04 | component import section - 0x6e | 01 | 1 count - 0x6f | 00 01 00 | [func 0] ComponentImport { name: "", ty: Func(0) } - 0x72 | 0b 06 | component export section - 0x74 | 01 | 1 count - 0x75 | 01 61 00 11 | export ComponentExport { name: "a", kind: Module, index: 0 } - | 00 - 0x7a | 07 0e | component type section - 0x7c | 01 | 1 count - 0x7d | 42 02 01 40 | [type 1] Instance([Type(Func(ComponentFuncType { params: Named([]), results: Named([]) })), Export { name: "b", ty: Func(0) }]) - | 01 00 01 00 - | 04 01 62 01 - | 00 - 0x8a | 0a 04 | component import section - 0x8c | 01 | 1 count - 0x8d | 00 05 01 | [instance 0] ComponentImport { name: "", ty: Instance(1) } - 0x90 | 0b 05 | component export section - 0x92 | 01 | 1 count - 0x93 | 01 62 05 00 | export ComponentExport { name: "b", kind: Instance, index: 0 } - 0x97 | 0b 05 | component export section - 0x99 | 01 | 1 count - 0x9a | 01 78 04 03 | export ComponentExport { name: "x", kind: Component, index: 3 } + 0x7c | 07 0d | component type section + 0x7e | 01 | 1 count + 0x7f | 42 02 01 40 | [type 1] Instance([Type(Func(ComponentFuncType { params: [], results: Named([]) })), Export { name: "b", ty: Func(0) }]) + | 00 01 00 04 + | 01 62 01 00 + 0x8b | 0a 04 | component import section + 0x8d | 01 | 1 count + 0x8e | 00 05 01 | [instance 0] ComponentImport { name: "", ty: Instance(1) } + 0x91 | 0b 05 | component export section + 0x93 | 01 | 1 count + 0x94 | 01 62 05 00 | export ComponentExport { name: "b", kind: Instance, index: 0 } + 0x98 | 0b 05 | component export section + 0x9a | 01 | 1 count + 0x9b | 01 78 04 03 | export ComponentExport { name: "x", kind: Component, index: 3 } diff --git a/tests/dump/try-delegate.wat.dump b/tests/dump/try-delegate.wat.dump index 039f6cea8c..6103104750 100644 --- a/tests/dump/try-delegate.wat.dump +++ b/tests/dump/try-delegate.wat.dump @@ -11,8 +11,8 @@ ============== func 0 ==================== 0x15 | 09 | size of function 0x16 | 00 | 0 local blocks - 0x17 | 06 40 | try ty:Empty - 0x19 | 06 40 | try ty:Empty + 0x17 | 06 40 | try blockty:Empty + 0x19 | 06 40 | try blockty:Empty 0x1b | 18 00 | delegate relative_depth:0 0x1d | 0b | end 0x1e | 0b | end diff --git a/tests/local/component-model/adapt.wast b/tests/local/component-model/adapt.wast index 51a0fc8a2d..562a2cd9ac 100644 --- a/tests/local/component-model/adapt.wast +++ b/tests/local/component-model/adapt.wast @@ -1,5 +1,5 @@ (component - (import "log" (func $log (param string))) + (import "log" (func $log (param "msg" string))) (core module $libc (memory (export "memory") 1) (func (export "canonical_abi_realloc") (param i32 i32 i32 i32) (result i32) @@ -45,7 +45,7 @@ )) )) - (func (export "log1") (param string) + (func (export "log1") (param "msg" string) (canon lift (core func $my_instance "log-utf8") string-encoding=utf8 @@ -53,7 +53,7 @@ (realloc $realloc) ) ) - (func (export "log2") (param string) + (func (export "log2") (param "msg" string) (canon lift (core func $my_instance "log-utf16") string-encoding=utf16 @@ -61,7 +61,7 @@ (realloc $realloc) ) ) - (func (export "log3") (param string) + (func (export "log3") (param "msg" string) (canon lift (core func $my_instance "log-compact-utf16") string-encoding=latin1+utf16 @@ -114,7 +114,7 @@ (func (export "f") (param i32 i32)) ) (core instance $i (instantiate $m)) - (func (param (list u8)) (canon lift (core func $i "f"))) + (func (param "p1" (list u8)) (canon lift (core func $i "f"))) ) "canonical option `memory` is required") @@ -125,7 +125,7 @@ (func (export "f") (param i32 i32)) ) (core instance $i (instantiate $m)) - (func (param (list u8)) + (func (param "p1" (list u8)) (canon lift (core func $i "f") (memory $i "m") ) @@ -141,7 +141,7 @@ (func (export "r") (param i32 i32 i32 i32) (result i32)) ) (core instance $i (instantiate $m)) - (func (param (list u8)) + (func (param "p1" (list u8)) (canon lift (core func $i "f") (memory $i "m") (realloc (func $i "r")) @@ -159,7 +159,7 @@ (func (export "r")) ) (core instance $i (instantiate $m)) - (func (param (list u8)) + (func (param "p1" (list u8)) (canon lift (core func $i "f") (memory $i "m") (realloc (func $i "r")) @@ -209,7 +209,7 @@ (assert_invalid (component - (import "" (func $f (param string))) + (import "" (func $f (param "p1" string))) (core module $m (memory (export "m") 1) (func (export "f") (result i32)) @@ -252,7 +252,7 @@ (core instance $i (instantiate $m)) (core func (canon lower (func $i ""))) ) - "failed to find instance named `$i`") + "unknown instance: failed to find name `$i`") (assert_invalid (component @@ -284,4 +284,4 @@ (import "" (func $f)) (func (export "foo") (canon lift (core func $f))) ) - "failed to find core func named `$f`") + "unknown core func: failed to find name `$f`") diff --git a/tests/local/component-model/alias.wast b/tests/local/component-model/alias.wast index 61541abddb..2f0a11340a 100644 --- a/tests/local/component-model/alias.wast +++ b/tests/local/component-model/alias.wast @@ -1,7 +1,7 @@ (component (import "i" (instance $i (export "f1" (func $f1)) - (export "f2" (func $f2 (param string))) + (export "f2" (func $f2 (param "p1" string))) )) (export "run" (func $i "f1")) ) @@ -9,7 +9,7 @@ (component (import "i" (component $c (export "f1" (func $f1)) - (export "f2" (func $f2 (param string))) + (export "f2" (func $f2 (param "p1" string))) )) (instance $i (instantiate $c)) (export "run" (func $i "f1")) diff --git a/tests/local/component-model/big.wast b/tests/local/component-model/big.wast index 846f468b3e..befaceaeb0 100644 --- a/tests/local/component-model/big.wast +++ b/tests/local/component-model/big.wast @@ -1,6 +1,6 @@ (component (import "wasi:logging" (instance $logging - (export "log" (func (param string))) + (export "log" (func (param "msg" string))) )) (import "libc" (core module $Libc (export "memory" (memory 1)) @@ -26,7 +26,7 @@ (with "libc" (instance $libc)) (with "wasi:logging" (instance (export "log" (func $log)))) )) - (func $run (param string) (result string) (canon lift + (func $run (param "in" string) (result string) (canon lift (core func $main "run") (memory $libc "memory") (realloc (func $libc "realloc")) )) diff --git a/tests/local/component-model/definedtypes.wast b/tests/local/component-model/definedtypes.wast index 0f6e1f3984..d79a15205a 100644 --- a/tests/local/component-model/definedtypes.wast +++ b/tests/local/component-model/definedtypes.wast @@ -57,7 +57,7 @@ (component (type $t (variant (case "x" (refines $y)) (case $y "y" string))) ) - "failed to find variant case named `$y`" + "unknown variant case" ) (assert_invalid @@ -65,9 +65,10 @@ (type $t string) (type $v (variant (case "x" $t (refines $z)))) ) - "failed to find variant case named `$z`" + "unknown variant case" ) + (assert_invalid (component (type $t string) @@ -95,7 +96,7 @@ (assert_invalid (component (type $t (func)) - (type (func (param $t))) + (type (func (param "t" $t))) ) "type index 0 is not a defined type") diff --git a/tests/local/component-model/func.wast b/tests/local/component-model/func.wast index c9c63c0e47..7fbe43ac32 100644 --- a/tests/local/component-model/func.wast +++ b/tests/local/component-model/func.wast @@ -7,16 +7,9 @@ (component (import "" (func)) - (import "a" (func (param string))) + (import "a" (func (param "p1" string))) (import "b" (func (result u32))) - (import "c" (func (param bool) (result string))) -) - -(assert_invalid - (component - (import "a" (func (param "foo" string) (param s32) (param "bar" u32))) - ) - "function parameter name cannot be empty" + (import "c" (func (param "p1" bool) (result string))) ) (assert_invalid @@ -56,7 +49,7 @@ ) (component - (import "" (func $log (param string))) + (import "" (func $log (param "msg" string))) (core module $libc (memory (export "memory") 1) ) @@ -135,7 +128,7 @@ ) (core instance $i (instantiate $m)) - (func (export "param-list") (param (list u8)) + (func (export "param-list") (param "bytes" (list u8)) (canon lift (core func $i "param-list") (memory $i "memory")) ) ) diff --git a/tests/local/component-model/instance-type.wast b/tests/local/component-model/instance-type.wast index dd597dacc2..c1acc813bd 100644 --- a/tests/local/component-model/instance-type.wast +++ b/tests/local/component-model/instance-type.wast @@ -43,8 +43,8 @@ (export "c" (func (@name "bar"))) (export "d" (func $foo (@name "bar"))) (export "e" (func (type $t))) - (export "f" (func (param string))) - (export "g" (func (param s32) (result u32))) + (export "f" (func (param "f" string))) + (export "g" (func (param "g" s32) (result u32))) (export "h" (func (type $t))) ;; components @@ -135,15 +135,15 @@ (type (component (import "a" (func)) (import "b" (func (type $empty))) - (import "c" (func (param s32))) - (import "d" (func (param s32) (result s32))) + (import "c" (func (param "c" s32))) + (import "d" (func (param "d" s32) (result s32))) (import "h" (instance)) (import "i" (instance (type $i))) (import "j" (instance (export "a" (func)) (export "b" (func (type $empty))) - (export "c" (func (param s32))) + (export "c" (func (param "c" s32))) )) (import "k" (core module)) @@ -157,12 +157,12 @@ (export "a" (func)) (export "e" (func (type $empty))) - (export "f" (func (param s32))) + (export "f" (func (param "f" s32))) (export "g" (instance (export "a" (func)) (export "b" (func (type $empty))) - (export "c" (func (param s32))) + (export "c" (func (param "c" s32))) )) (export "h" (core module @@ -204,7 +204,7 @@ (type (instance (export "" (core module (type $t))) ))) - "failed to find core type named `$t`") + "unknown core type") (assert_invalid (component diff --git a/tests/local/component-model/instantiate.wast b/tests/local/component-model/instantiate.wast index 66cd4cfcc7..6fe088f335 100644 --- a/tests/local/component-model/instantiate.wast +++ b/tests/local/component-model/instantiate.wast @@ -190,7 +190,7 @@ (import "" (component $m (import "" (func)) )) - (import "i" (func (param string))) + (import "i" (func (param "i" string))) (instance $i (instantiate $m (with "" (func 0)))) ) "function type mismatch") diff --git a/tests/local/component-model/invalid.wast b/tests/local/component-model/invalid.wast index 0c5a6f46ed..3b57e3579b 100644 --- a/tests/local/component-model/invalid.wast +++ b/tests/local/component-model/invalid.wast @@ -11,7 +11,7 @@ (component quote "(export \"\" (func $foo))" ) - "failed to find func named") + "unknown func") (assert_malformed (component quote diff --git a/tests/local/component-model/nested-modules.wast b/tests/local/component-model/nested-modules.wast index ca62ba658b..149107b08b 100644 --- a/tests/local/component-model/nested-modules.wast +++ b/tests/local/component-model/nested-modules.wast @@ -12,7 +12,7 @@ (component (core module $m) - (import "" (func (param string))) + (import "" (func (param "p" string))) (export "a" (core module $m)) ) ) diff --git a/tests/local/component-model/start.wast b/tests/local/component-model/start.wast index 03e13aea3b..d85a83b569 100644 --- a/tests/local/component-model/start.wast +++ b/tests/local/component-model/start.wast @@ -1,14 +1,14 @@ (assert_invalid (component - (import "" (func $f (param string))) + (import "" (func $f (param "1" string))) (start $f) ) "start function requires 1 arguments") (assert_invalid (component - (import "" (func $f (param string))) + (import "" (func $f (param "p" string))) (import "v" (value $v string)) (start $f (value $v) (value $v)) ) @@ -76,10 +76,10 @@ (component binary "\00asm" "\0a\00\01\00" ;; component header - "\07\06" ;; type section, 6 bytes large + "\07\05" ;; type section, 5 bytes large "\01" ;; 1 count "\40" ;; function - "\01\00" ;; parameters, named, 0 count + "\00" ;; parameters, 0 count "\01\00" ;; results, named, 0 count "\0a\04" ;; import section, 4 bytes large @@ -98,10 +98,10 @@ (component binary "\00asm" "\0a\00\01\00" ;; component header - "\07\06" ;; type section, 6 bytes large + "\07\05" ;; type section, 5 bytes large "\01" ;; 1 count "\40" ;; function - "\01\00" ;; parameters, named, 0 count + "\00" ;; parameters, 0 count "\01\00" ;; results, named, 0 count "\0a\04" ;; import section, 4 bytes large diff --git a/tests/local/component-model/string.wast b/tests/local/component-model/string.wast index 465cada200..e768184486 100644 --- a/tests/local/component-model/string.wast +++ b/tests/local/component-model/string.wast @@ -19,7 +19,7 @@ ) (core instance $main (instantiate $Main (with "libc" (instance $libc)))) (alias core export $main "start" (core func $main_func)) - (func $start (param string) (result string) + (func $start (param "p1" string) (result string) (canon lift (core func $main_func) (memory $libc "memory") (realloc (func $libc "canonical_abi_realloc")) diff --git a/tests/local/component-model/types.wast b/tests/local/component-model/types.wast index 855ec64cd6..74d5355ba2 100644 --- a/tests/local/component-model/types.wast +++ b/tests/local/component-model/types.wast @@ -124,7 +124,7 @@ (alias outer $c $t (type)) )) ) - "failed to find core type named `$t`") + "unknown core type") (assert_invalid (component $c @@ -149,7 +149,7 @@ (alias outer $c $t (type)) )) ) - "failed to find type named `$t`") + "unknown type") (assert_invalid (component $c @@ -203,7 +203,7 @@ (alias outer $c $t (type)) )) ) - "failed to find type named `$t`") + "unknown type") (assert_invalid (component $c @@ -288,4 +288,4 @@ (import "" (type (eq 0))) (export "" (type (eq 0))) )) -) \ No newline at end of file +) diff --git a/tests/local/component-model/virtualize.wast b/tests/local/component-model/virtualize.wast index 0e24e92d5c..51f7b2b413 100644 --- a/tests/local/component-model/virtualize.wast +++ b/tests/local/component-model/virtualize.wast @@ -9,8 +9,8 @@ (component $child (import "wasi-file" (instance $wasi-file - (export "read" (func $read (param u32) (result (list u8)))) - (export "write" (func $write (param (list u8)) (result u32))) + (export "read" (func $read (param "count" u32) (result (list u8)))) + (export "write" (func $write (param "bytes" (list u8)) (result u32))) )) (core instance $libc (instantiate $libc)) @@ -42,8 +42,8 @@ (component $virtualize (import "wasi-file" (instance $wasi-file - (export "read" (func $read (param u32) (result (list u8)))) - (export "write" (func $write (param (list u8)) (result u32))) + (export "read" (func $read (param "len" u32) (result (list u8)))) + (export "write" (func $write (param "buf" (list u8)) (result u32))) )) (export "read" (func $wasi-file "read")) (export "write" (func $wasi-file "write")) @@ -51,14 +51,14 @@ (component (type $WasiFile (instance - (export "read" (func $read (param u32) (result (list u8)))) - (export "write" (func $write (param (list u8)) (result u32))) + (export "read" (func $read (param "len" u32) (result (list u8)))) + (export "write" (func $write (param "buf" (list u8)) (result u32))) )) (import "wasi_file" (instance $real-wasi (type $WasiFile))) (import "./virtualize.wasm" (component $VIRTUALIZE (import "wasi_file" (instance (type $WasiFile))) - (export "read" (func $read (param u32) (result (list u8)))) - (export "write" (func $write (param (list u8)) (result u32))) + (export "read" (func $read (param "len" u32) (result (list u8)))) + (export "write" (func $write (param "buf" (list u8)) (result u32))) )) (import "./child.wasm" (component $CHILD (import "wasi_file" (instance (type $WasiFile))) @@ -74,8 +74,8 @@ (component (type $WasiFile (instance - (export "read" (func $read (param u32) (result (list u8)))) - (export "write" (func $write (param (list u8)) (result u32))) + (export "read" (func $read (param "len" u32) (result (list u8)))) + (export "write" (func $write (param "buf" (list u8)) (result u32))) )) (import "wasi_file" (instance $real-wasi (type $WasiFile))) diff --git a/tests/local/missing-features/reference-types/v128-without-simd-feature.wast b/tests/local/missing-features/reference-types/v128-without-simd-feature.wast new file mode 100644 index 0000000000..7808459ac0 --- /dev/null +++ b/tests/local/missing-features/reference-types/v128-without-simd-feature.wast @@ -0,0 +1,3 @@ +(assert_invalid + (module (func select (result v128))) + "SIMD support is not enabled") diff --git a/tests/local/missing-features/v128-without-simd-feature.wast b/tests/local/missing-features/v128-without-simd-feature.wast index ec8e94e420..63a4a226d8 100644 --- a/tests/local/missing-features/v128-without-simd-feature.wast +++ b/tests/local/missing-features/v128-without-simd-feature.wast @@ -16,9 +16,6 @@ (assert_invalid (module (global v128 v128.const i64x2 0 0)) "SIMD support is not enabled") -(assert_invalid - (module (func select (result v128))) - "SIMD support is not enabled") (assert_invalid (module (func block (result v128) end)) "SIMD support is not enabled") diff --git a/tests/local/multi-memory.wast b/tests/local/multi-memory.wast index dc4b4755ac..89bc1a92ca 100644 --- a/tests/local/multi-memory.wast +++ b/tests/local/multi-memory.wast @@ -216,7 +216,7 @@ (module quote "(func i32.load $a)" ) - "failed to find memory") + "unknown memory") (module (memory 1) diff --git a/tests/local/relaxed-simd.wast b/tests/local/relaxed-simd.wast index 35cfbfcfbe..55f1b9d072 100644 --- a/tests/local/relaxed-simd.wast +++ b/tests/local/relaxed-simd.wast @@ -25,49 +25,49 @@ local.get 0 local.get 1 local.get 2 - f32x4.fma) + f32x4.relaxed_fma) - (func $f32x4_fms (param v128 v128 v128) (result v128) + (func $f32x4_fnma (param v128 v128 v128) (result v128) local.get 0 local.get 1 local.get 2 - f32x4.fms) + f32x4.relaxed_fnma) (func $f64x2_fma (param v128 v128 v128) (result v128) local.get 0 local.get 1 local.get 2 - f64x2.fma) + f64x2.relaxed_fma) - (func $f64x2_fms (param v128 v128 v128) (result v128) + (func $f64x2_fnma (param v128 v128 v128) (result v128) local.get 0 local.get 1 local.get 2 - f64x2.fms) + f64x2.relaxed_fnma) (func $i8x16_laneselect (param v128 v128 v128) (result v128) local.get 0 local.get 1 local.get 2 - i8x16.laneselect) + i8x16.relaxed_laneselect) (func $i16x8_laneselect (param v128 v128 v128) (result v128) local.get 0 local.get 1 local.get 2 - i16x8.laneselect) + i16x8.relaxed_laneselect) (func $i32x4_laneselect (param v128 v128 v128) (result v128) local.get 0 local.get 1 local.get 2 - i32x4.laneselect) + i32x4.relaxed_laneselect) (func $i64x2_laneselect (param v128 v128 v128) (result v128) local.get 0 local.get 1 local.get 2 - i64x2.laneselect) + i64x2.relaxed_laneselect) (func $f32x4_min (param v128 v128) (result v128) local.get 0 @@ -88,4 +88,26 @@ local.get 0 local.get 1 f64x2.relaxed_max) + + (func $i16x8_q15mulr_s (param v128 v128) (result v128) + local.get 0 + local.get 1 + i16x8.relaxed_q15mulr_s) + + (func $i16x8_dot_i8x16_i7x16_s (param v128 v128) (result v128) + local.get 0 + local.get 1 + i16x8.dot_i8x16_i7x16_s) + + (func $i32x4_dot_i8x16_i7x16_add_s (param v128 v128 v128) (result v128) + local.get 0 + local.get 1 + local.get 2 + i32x4.dot_i8x16_i7x16_add_s) + + (func $f32x4_relaxed_dot_bf16x8_add_f32x4 (param v128 v128 v128) (result v128) + local.get 0 + local.get 1 + local.get 2 + f32x4.relaxed_dot_bf16x8_add_f32x4) ) diff --git a/tests/local/try.wast b/tests/local/try.wast index bc4a93d650..e4ffa23d48 100644 --- a/tests/local/try.wast +++ b/tests/local/try.wast @@ -52,4 +52,4 @@ (module quote "(func (try $l (do) (delegate $l)))" ) - "failed to find label") + "unknown label") diff --git a/tests/roundtrip.rs b/tests/roundtrip.rs index 1ac420fefc..68fe8ac25e 100644 --- a/tests/roundtrip.rs +++ b/tests/roundtrip.rs @@ -132,6 +132,12 @@ fn skip_test(test: &Path, contents: &[u8]) -> bool { "function-references/func_bind.wast", "function-references/ref_as_non_null.wast", "function-references/return_call_ref.wast", + // TODO: new syntax for table types has been added with an optional + // initializer which needs parsing in the text format. + "function-references/table.wast", + // TODO: This references an instruction which has since been removed + // from the proposal so the test needs an update. + "relaxed-simd/relaxed_fma_fms.wast", ]; if broken.iter().any(|x| test.ends_with(x)) { return true; @@ -479,6 +485,8 @@ impl TestState { // function-references has tests for return_call_ref which // depend on tail calls "return_call_ref.wast" => features.tail_call = true, + "relaxed-simd" => features.relaxed_simd = true, + "reference-types" => features.reference_types = true, _ => {} } } @@ -627,12 +635,16 @@ fn error_matches(error: &str, message: &str) -> bool { return error.contains("invalid u32 number: constant out of range"); } + // The test suite includes "bad opcodes" that later became valid opcodes // (0xd3, function references proposal). However, they are still not constant // expressions, so we can sidestep by checking for that error instead if message == "illegal opcode" { return error.contains("constant expression required"); } + if message == "unknown global" { + return error.contains("global.get of locally defined global"); + } return false; } diff --git a/tests/testsuite b/tests/testsuite index d42da0117f..4f77306bb6 160000 --- a/tests/testsuite +++ b/tests/testsuite @@ -1 +1 @@ -Subproject commit d42da0117f7a93c6a9127e2b9eec64749152c4c1 +Subproject commit 4f77306bb63151631d84f58dedf67958eb9911b9