From 6228a747713a37bb72e004c00e56da919366fa03 Mon Sep 17 00:00:00 2001 From: Sam Estep Date: Tue, 28 Jan 2025 12:26:33 -0500 Subject: [PATCH] Use typed indices via a new `wasm-types` crate --- Cargo.lock | 26 + Cargo.toml | 2 + crates/wasm-encoder/Cargo.toml | 2 + crates/wasm-encoder/src/component/aliases.rs | 18 +- crates/wasm-encoder/src/component/builder.rs | 73 ++- .../wasm-encoder/src/component/canonicals.rs | 61 ++- crates/wasm-encoder/src/component/imports.rs | 21 +- .../wasm-encoder/src/component/instances.rs | 13 +- crates/wasm-encoder/src/component/names.rs | 33 +- crates/wasm-encoder/src/component/start.rs | 14 +- crates/wasm-encoder/src/component/types.rs | 15 +- crates/wasm-encoder/src/core/branch_hints.rs | 8 +- crates/wasm-encoder/src/core/code.rs | 302 +++++------ crates/wasm-encoder/src/core/data.rs | 10 +- crates/wasm-encoder/src/core/dump.rs | 3 +- crates/wasm-encoder/src/core/elements.rs | 12 +- crates/wasm-encoder/src/core/functions.rs | 6 +- crates/wasm-encoder/src/core/imports.rs | 4 +- crates/wasm-encoder/src/core/names.rs | 71 +-- crates/wasm-encoder/src/core/start.rs | 8 +- crates/wasm-encoder/src/core/tags.rs | 7 +- crates/wasm-encoder/src/core/types.rs | 11 +- crates/wasm-encoder/src/lib.rs | 126 ++++- crates/wasm-encoder/src/reencode.rs | 79 +-- crates/wasm-encoder/src/reencode/component.rs | 67 ++- crates/wasm-metadata/Cargo.toml | 1 + crates/wasm-metadata/src/utils.rs | 17 +- crates/wasm-mutate/Cargo.toml | 2 + crates/wasm-mutate/src/info.rs | 12 +- .../wasm-mutate/src/mutators/remove_item.rs | 3 +- crates/wasm-smith/Cargo.toml | 2 + crates/wasm-smith/src/core.rs | 6 +- crates/wasm-types/Cargo.toml | 17 + crates/wasm-types/README.md | 12 + crates/wasm-types/src/lib.rs | 129 +++++ crates/wasmparser/Cargo.toml | 2 + crates/wasmparser/src/arity.rs | 19 +- crates/wasmparser/src/binary_reader.rs | 493 +++++++++++++----- crates/wasmparser/src/lib.rs | 194 +++---- crates/wasmparser/src/parser.rs | 3 +- crates/wasmparser/src/readers.rs | 119 +++++ .../src/readers/component/aliases.rs | 10 +- .../src/readers/component/canonicals.rs | 69 +-- .../src/readers/component/imports.rs | 11 +- .../src/readers/component/instances.rs | 10 +- .../wasmparser/src/readers/component/names.rs | 81 +-- .../wasmparser/src/readers/component/start.rs | 7 +- .../wasmparser/src/readers/component/types.rs | 13 +- .../src/readers/core/branch_hinting.rs | 5 +- .../wasmparser/src/readers/core/coredumps.rs | 13 +- crates/wasmparser/src/readers/core/data.rs | 7 +- .../wasmparser/src/readers/core/elements.rs | 7 +- .../wasmparser/src/readers/core/functions.rs | 4 +- crates/wasmparser/src/readers/core/imports.rs | 5 +- crates/wasmparser/src/readers/core/linking.rs | 25 +- crates/wasmparser/src/readers/core/names.rs | 49 +- .../wasmparser/src/readers/core/operators.rs | 37 +- crates/wasmparser/src/readers/core/tags.rs | 2 +- crates/wasmparser/src/readers/core/types.rs | 28 +- crates/wasmparser/src/resources.rs | 55 +- crates/wasmparser/src/validator.rs | 3 +- crates/wasmparser/src/validator/component.rs | 290 ++++++----- .../src/validator/component_types.rs | 5 +- crates/wasmparser/src/validator/core.rs | 161 +++--- .../src/validator/core/canonical.rs | 18 +- crates/wasmparser/src/validator/func.rs | 29 +- crates/wasmparser/src/validator/operators.rs | 419 +++++++++------ crates/wasmparser/src/validator/types.rs | 68 +-- crates/wasmprinter/Cargo.toml | 2 + crates/wasmprinter/src/component.rs | 196 ++++--- crates/wasmprinter/src/lib.rs | 241 +++++---- crates/wasmprinter/src/operator.rs | 114 ++-- crates/wast/Cargo.toml | 2 + crates/wast/src/component/alias.rs | 12 +- crates/wast/src/component/expand.rs | 4 +- crates/wast/src/component/export.rs | 18 +- crates/wast/src/component/func.rs | 68 +-- crates/wast/src/component/import.rs | 3 +- crates/wast/src/component/item_ref.rs | 38 +- crates/wast/src/component/resolve.rs | 96 ++-- crates/wast/src/component/types.rs | 3 +- crates/wast/src/core/binary.rs | 222 +++++--- crates/wast/src/core/binary/dwarf.rs | 20 +- crates/wast/src/core/binary/dwarf_disabled.rs | 5 +- crates/wast/src/core/export.rs | 2 +- crates/wast/src/core/expr.rs | 232 +++++---- crates/wast/src/core/memory.rs | 7 +- crates/wast/src/core/module.rs | 3 +- crates/wast/src/core/resolve/mod.rs | 17 +- crates/wast/src/core/resolve/names.rs | 263 ++++++---- crates/wast/src/core/resolve/types.rs | 15 +- crates/wast/src/core/table.rs | 5 +- crates/wast/src/core/types.rs | 15 +- crates/wast/src/core/wast.rs | 3 +- crates/wast/src/encode.rs | 120 +++++ crates/wast/src/names.rs | 19 +- crates/wast/src/token.rs | 74 ++- 97 files changed, 3345 insertions(+), 1928 deletions(-) create mode 100644 crates/wasm-types/Cargo.toml create mode 100644 crates/wasm-types/README.md create mode 100644 crates/wasm-types/src/lib.rs diff --git a/Cargo.lock b/Cargo.lock index 6974f6ed35..25165bf84d 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -969,6 +969,12 @@ dependencies = [ "version_check", ] +[[package]] +name = "index_vec" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "44faf5bb8861a9c72e20d3fb0fdbd59233e43056e2b80475ab0aacdc2e781355" + [[package]] name = "indexmap" version = "1.9.3" @@ -1904,8 +1910,10 @@ name = "wasm-encoder" version = "0.225.0" dependencies = [ "anyhow", + "index_vec", "leb128fmt", "tempfile", + "wasm-types", "wasmparser 0.225.0", "wasmprinter 0.225.0", ] @@ -1932,6 +1940,7 @@ version = "0.225.0" dependencies = [ "anyhow", "clap", + "index_vec", "indexmap 2.7.1", "serde", "serde_derive", @@ -1950,10 +1959,12 @@ dependencies = [ "clap", "egg", "env_logger", + "index_vec", "log", "rand", "thiserror", "wasm-encoder 0.225.0", + "wasm-types", "wasmparser 0.225.0", "wasmprinter 0.225.0", "wat", @@ -2002,11 +2013,13 @@ dependencies = [ "clap", "criterion", "flagset", + "index_vec", "libfuzzer-sys", "rand", "serde", "serde_derive", "wasm-encoder 0.225.0", + "wasm-types", "wasmparser 0.225.0", "wasmprinter 0.225.0", "wat", @@ -2094,6 +2107,13 @@ dependencies = [ "wit-smith", ] +[[package]] +name = "wasm-types" +version = "0.225.0" +dependencies = [ + "index_vec", +] + [[package]] name = "wasm-wave" version = "0.225.0" @@ -2140,6 +2160,7 @@ dependencies = [ "criterion", "env_logger", "hashbrown 0.15.2", + "index_vec", "indexmap 2.7.1", "log", "once_cell", @@ -2147,6 +2168,7 @@ dependencies = [ "semver", "serde", "wasm-encoder 0.225.0", + "wasm-types", "wast", "wat", ] @@ -2167,7 +2189,9 @@ name = "wasmprinter" version = "0.225.0" dependencies = [ "anyhow", + "index_vec", "termcolor", + "wasm-types", "wasmparser 0.225.0", "wat", ] @@ -2387,12 +2411,14 @@ dependencies = [ "anyhow", "bumpalo", "gimli", + "index_vec", "leb128fmt", "libtest-mimic", "memchr", "rand", "unicode-width", "wasm-encoder 0.225.0", + "wasm-types", "wasmparser 0.225.0", "wat", ] diff --git a/Cargo.toml b/Cargo.toml index af10c5398b..e43d89b4f2 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -82,6 +82,7 @@ env_logger = "0.11" gimli = "0.31.1" hashbrown = { version = "0.15.2", default-features = false, features = ['default-hasher'] } id-arena = "2" +index_vec = "0.1" indexmap = { version = "2.7.0", default-features = false } indoc = "2.0.5" leb128fmt = { version = "0.1.0", default-features = false } @@ -108,6 +109,7 @@ wasm-metadata = { version = "0.225.0", path = "crates/wasm-metadata" } wasm-mutate = { version = "0.225.0", path = "crates/wasm-mutate" } wasm-shrink = { version = "0.225.0", path = "crates/wasm-shrink" } wasm-smith = { version = "0.225.0", path = "crates/wasm-smith" } +wasm-types = { version = "0.225.0", path = "crates/wasm-types" } wasmparser = { version = "0.225.0", path = "crates/wasmparser", default-features = false, features = ['simd'] } wasmprinter = { version = "0.225.0", path = "crates/wasmprinter", default-features = false } wast = { version = "225.0.0", path = "crates/wast", default-features = false } diff --git a/crates/wasm-encoder/Cargo.toml b/crates/wasm-encoder/Cargo.toml index c94fa351b2..c9922c868b 100644 --- a/crates/wasm-encoder/Cargo.toml +++ b/crates/wasm-encoder/Cargo.toml @@ -20,7 +20,9 @@ all-features = true workspace = true [dependencies] +index_vec.workspace = true leb128fmt.workspace = true +wasm-types.workspace = true # Enable this dependency to get a bunch of `From for # wasm_encoder::Foo` impls. diff --git a/crates/wasm-encoder/src/component/aliases.rs b/crates/wasm-encoder/src/component/aliases.rs index 07a93d0737..fa283c51ed 100644 --- a/crates/wasm-encoder/src/component/aliases.rs +++ b/crates/wasm-encoder/src/component/aliases.rs @@ -3,6 +3,7 @@ use crate::{ encode_section, ComponentExportKind, ComponentSection, ComponentSectionId, Encode, ExportKind, }; use alloc::vec::Vec; +use wasm_types::{ComponentInstanceIdx, CoreInstanceIdx}; /// Represents the kinds of outer aliasable items in a component. #[derive(Clone, Copy, Debug, Eq, PartialEq)] @@ -40,10 +41,19 @@ impl Encode for ComponentOuterAliasKind { /// /// ```rust /// use wasm_encoder::{Component, Alias, ComponentAliasSection, ComponentExportKind, ComponentOuterAliasKind}; +/// use wasm_types::ComponentInstanceIdx; /// /// let mut aliases = ComponentAliasSection::new(); -/// aliases.alias(Alias::InstanceExport { instance: 0, kind: ComponentExportKind::Func, name: "f" }); -/// aliases.alias(Alias::Outer { count: 0, kind: ComponentOuterAliasKind::Type, index: 1 }); +/// aliases.alias(Alias::InstanceExport { +/// instance: ComponentInstanceIdx(0), +/// kind: ComponentExportKind::Func, +/// name: "f", +/// }); +/// aliases.alias(Alias::Outer { +/// count: 0, +/// kind: ComponentOuterAliasKind::Type, +/// index: 1, +/// }); /// /// let mut component = Component::new(); /// component.section(&aliases); @@ -63,7 +73,7 @@ pub enum Alias<'a> { /// An alias of a component instance export. InstanceExport { /// The index of the component instance that's being aliased from. - instance: u32, + instance: ComponentInstanceIdx, /// The kind of item that's being extracted from the component /// instance. kind: ComponentExportKind, @@ -73,7 +83,7 @@ pub enum Alias<'a> { /// Same as `InstanceExport`, but for core instances. #[allow(missing_docs)] CoreInstanceExport { - instance: u32, + instance: CoreInstanceIdx, kind: ExportKind, name: &'a str, }, diff --git a/crates/wasm-encoder/src/component/builder.rs b/crates/wasm-encoder/src/component/builder.rs index 13c0eec03f..f075d7cf1e 100644 --- a/crates/wasm-encoder/src/component/builder.rs +++ b/crates/wasm-encoder/src/component/builder.rs @@ -2,6 +2,10 @@ use crate::component::*; use crate::{ExportKind, Module, RawSection, ValType}; use alloc::vec::Vec; use core::mem; +use wasm_types::{ + ComponentFuncIdx, ComponentIdx, ComponentInstanceIdx, ComponentTypeIdx, CoreInstanceIdx, + CoreModuleIdx, FuncIdx, MemIdx, TypeIdx, +}; /// Convenience type to build a component incrementally and automatically keep /// track of index spaces. @@ -135,7 +139,7 @@ impl ComponentBuilder { /// provided. /// /// Returns the index of the core wasm instance crated. - pub fn core_instantiate<'a, A>(&mut self, module_index: u32, args: A) -> u32 + pub fn core_instantiate<'a, A>(&mut self, module_index: CoreModuleIdx, args: A) -> u32 where A: IntoIterator, A::IntoIter: ExactSizeIterator, @@ -160,7 +164,12 @@ impl ComponentBuilder { /// export `name` aliased out with the `kind` specified. /// /// Returns the index of the item crated. - pub fn core_alias_export(&mut self, instance: u32, name: &str, kind: ExportKind) -> u32 { + pub fn core_alias_export( + &mut self, + instance: CoreInstanceIdx, + name: &str, + kind: ExportKind, + ) -> u32 { self.alias(Alias::CoreInstanceExport { instance, kind, @@ -199,7 +208,12 @@ impl ComponentBuilder { /// item to access. /// /// Returns the index of the new item defined. - pub fn alias_export(&mut self, instance: u32, name: &str, kind: ComponentExportKind) -> u32 { + pub fn alias_export( + &mut self, + instance: ComponentInstanceIdx, + name: &str, + kind: ComponentExportKind, + ) -> u32 { self.alias(Alias::InstanceExport { instance, kind, @@ -232,7 +246,7 @@ impl ComponentBuilder { /// using the `options` provided. /// /// Returns the index of the core wasm function created. - pub fn lower_func(&mut self, func_index: u32, options: O) -> u32 + pub fn lower_func(&mut self, func_index: ComponentFuncIdx, options: O) -> u32 where O: IntoIterator, O::IntoIter: ExactSizeIterator, @@ -245,7 +259,12 @@ impl ComponentBuilder { /// function type `type_index` and `options`. /// /// Returns the index of the component function created. - pub fn lift_func(&mut self, core_func_index: u32, type_index: u32, options: O) -> u32 + pub fn lift_func( + &mut self, + core_func_index: FuncIdx, + type_index: ComponentTypeIdx, + options: O, + ) -> u32 where O: IntoIterator, O::IntoIter: ExactSizeIterator, @@ -318,7 +337,7 @@ impl ComponentBuilder { } /// Declares a new resource type within this component. - pub fn type_resource(&mut self, rep: ValType, dtor: Option) -> u32 { + pub fn type_resource(&mut self, rep: ValType, dtor: Option) -> u32 { self.types().resource(rep, dtor); inc(&mut self.types) } @@ -344,7 +363,7 @@ impl ComponentBuilder { } /// Instantiates the `component_index` specified with the `args` specified. - pub fn instantiate(&mut self, component_index: u32, args: A) -> u32 + pub fn instantiate(&mut self, component_index: ComponentIdx, args: A) -> u32 where A: IntoIterator, A::IntoIter: ExactSizeIterator, @@ -356,25 +375,25 @@ impl ComponentBuilder { } /// Declares a new `resource.drop` intrinsic. - pub fn resource_drop(&mut self, ty: u32) -> u32 { + pub fn resource_drop(&mut self, ty: ComponentTypeIdx) -> u32 { self.canonical_functions().resource_drop(ty); inc(&mut self.core_funcs) } /// Declares a new `resource.new` intrinsic. - pub fn resource_new(&mut self, ty: u32) -> u32 { + pub fn resource_new(&mut self, ty: ComponentTypeIdx) -> u32 { self.canonical_functions().resource_new(ty); inc(&mut self.core_funcs) } /// Declares a new `resource.rep` intrinsic. - pub fn resource_rep(&mut self, ty: u32) -> u32 { + pub fn resource_rep(&mut self, ty: ComponentTypeIdx) -> u32 { self.canonical_functions().resource_rep(ty); inc(&mut self.core_funcs) } /// Declares a new `thread.spawn` intrinsic. - pub fn thread_spawn(&mut self, ty: u32) -> u32 { + pub fn thread_spawn(&mut self, ty: TypeIdx) -> u32 { self.canonical_functions().thread_spawn(ty); inc(&mut self.core_funcs) } @@ -398,13 +417,13 @@ impl ComponentBuilder { } /// Declares a new `task.wait` intrinsic. - pub fn task_wait(&mut self, async_: bool, memory: u32) -> u32 { + pub fn task_wait(&mut self, async_: bool, memory: MemIdx) -> u32 { self.canonical_functions().task_wait(async_, memory); inc(&mut self.core_funcs) } /// Declares a new `task.poll` intrinsic. - pub fn task_poll(&mut self, async_: bool, memory: u32) -> u32 { + pub fn task_poll(&mut self, async_: bool, memory: MemIdx) -> u32 { self.canonical_functions().task_poll(async_, memory); inc(&mut self.core_funcs) } @@ -422,13 +441,13 @@ impl ComponentBuilder { } /// Declares a new `stream.new` intrinsic. - pub fn stream_new(&mut self, ty: u32) -> u32 { + pub fn stream_new(&mut self, ty: ComponentTypeIdx) -> u32 { self.canonical_functions().stream_new(ty); inc(&mut self.core_funcs) } /// Declares a new `stream.read` intrinsic. - pub fn stream_read(&mut self, ty: u32, options: O) -> u32 + pub fn stream_read(&mut self, ty: ComponentTypeIdx, options: O) -> u32 where O: IntoIterator, O::IntoIter: ExactSizeIterator, @@ -438,7 +457,7 @@ impl ComponentBuilder { } /// Declares a new `stream.write` intrinsic. - pub fn stream_write(&mut self, ty: u32, options: O) -> u32 + pub fn stream_write(&mut self, ty: ComponentTypeIdx, options: O) -> u32 where O: IntoIterator, O::IntoIter: ExactSizeIterator, @@ -448,37 +467,37 @@ impl ComponentBuilder { } /// Declares a new `stream.cancel-read` intrinsic. - pub fn stream_cancel_read(&mut self, ty: u32, async_: bool) -> u32 { + pub fn stream_cancel_read(&mut self, ty: ComponentTypeIdx, async_: bool) -> u32 { self.canonical_functions().stream_cancel_read(ty, async_); inc(&mut self.core_funcs) } /// Declares a new `stream.cancel-write` intrinsic. - pub fn stream_cancel_write(&mut self, ty: u32, async_: bool) -> u32 { + pub fn stream_cancel_write(&mut self, ty: ComponentTypeIdx, async_: bool) -> u32 { self.canonical_functions().stream_cancel_write(ty, async_); inc(&mut self.core_funcs) } /// Declares a new `stream.close-readable` intrinsic. - pub fn stream_close_readable(&mut self, ty: u32) -> u32 { + pub fn stream_close_readable(&mut self, ty: ComponentTypeIdx) -> u32 { self.canonical_functions().stream_close_readable(ty); inc(&mut self.core_funcs) } /// Declares a new `stream.close-writable` intrinsic. - pub fn stream_close_writable(&mut self, ty: u32) -> u32 { + pub fn stream_close_writable(&mut self, ty: ComponentTypeIdx) -> u32 { self.canonical_functions().stream_close_writable(ty); inc(&mut self.core_funcs) } /// Declares a new `future.new` intrinsic. - pub fn future_new(&mut self, ty: u32) -> u32 { + pub fn future_new(&mut self, ty: ComponentTypeIdx) -> u32 { self.canonical_functions().future_new(ty); inc(&mut self.core_funcs) } /// Declares a new `future.read` intrinsic. - pub fn future_read(&mut self, ty: u32, options: O) -> u32 + pub fn future_read(&mut self, ty: ComponentTypeIdx, options: O) -> u32 where O: IntoIterator, O::IntoIter: ExactSizeIterator, @@ -488,7 +507,7 @@ impl ComponentBuilder { } /// Declares a new `future.write` intrinsic. - pub fn future_write(&mut self, ty: u32, options: O) -> u32 + pub fn future_write(&mut self, ty: ComponentTypeIdx, options: O) -> u32 where O: IntoIterator, O::IntoIter: ExactSizeIterator, @@ -498,25 +517,25 @@ impl ComponentBuilder { } /// Declares a new `future.cancel-read` intrinsic. - pub fn future_cancel_read(&mut self, ty: u32, async_: bool) -> u32 { + pub fn future_cancel_read(&mut self, ty: ComponentTypeIdx, async_: bool) -> u32 { self.canonical_functions().future_cancel_read(ty, async_); inc(&mut self.core_funcs) } /// Declares a new `future.cancel-write` intrinsic. - pub fn future_cancel_write(&mut self, ty: u32, async_: bool) -> u32 { + pub fn future_cancel_write(&mut self, ty: ComponentTypeIdx, async_: bool) -> u32 { self.canonical_functions().future_cancel_write(ty, async_); inc(&mut self.core_funcs) } /// Declares a new `future.close-readable` intrinsic. - pub fn future_close_readable(&mut self, ty: u32) -> u32 { + pub fn future_close_readable(&mut self, ty: ComponentTypeIdx) -> u32 { self.canonical_functions().future_close_readable(ty); inc(&mut self.core_funcs) } /// Declares a new `future.close-writable` intrinsic. - pub fn future_close_writable(&mut self, ty: u32) -> u32 { + pub fn future_close_writable(&mut self, ty: ComponentTypeIdx) -> u32 { self.canonical_functions().future_close_writable(ty); inc(&mut self.core_funcs) } diff --git a/crates/wasm-encoder/src/component/canonicals.rs b/crates/wasm-encoder/src/component/canonicals.rs index 7c5a253ea8..09cdfda1a1 100644 --- a/crates/wasm-encoder/src/component/canonicals.rs +++ b/crates/wasm-encoder/src/component/canonicals.rs @@ -1,5 +1,6 @@ use crate::{encode_section, ComponentSection, ComponentSectionId, ComponentValType, Encode}; use alloc::vec::Vec; +use wasm_types::{ComponentFuncIdx, ComponentTypeIdx, FuncIdx, MemIdx, TypeIdx}; /// Represents options for canonical function definitions. #[derive(Debug, Clone, Copy, PartialEq, Eq)] @@ -13,20 +14,20 @@ pub enum CanonicalOption { /// The memory to use if the lifting or lowering of a function requires memory access. /// /// The value is an index to a core memory. - Memory(u32), + Memory(MemIdx), /// The realloc function to use if the lifting or lowering of a function requires memory /// allocation. /// /// The value is an index to a core function of type `(func (param i32 i32 i32 i32) (result i32))`. - Realloc(u32), + Realloc(FuncIdx), /// The post-return function to use if the lifting of a function requires /// cleanup after the function returns. - PostReturn(u32), + PostReturn(FuncIdx), /// Indicates that specified function should be lifted or lowered using the `async` ABI. Async, /// The function to use if the async lifting of a function should receive task/stream/future progress events /// using a callback. - Callback(u32), + Callback(FuncIdx), } impl Encode for CanonicalOption { @@ -64,9 +65,10 @@ impl Encode for CanonicalOption { /// /// ``` /// use wasm_encoder::{Component, CanonicalFunctionSection, CanonicalOption}; +/// use wasm_types::{ComponentTypeIdx, FuncIdx}; /// /// let mut functions = CanonicalFunctionSection::new(); -/// functions.lift(0, 0, [CanonicalOption::UTF8]); +/// functions.lift(FuncIdx(0), ComponentTypeIdx(0), [CanonicalOption::UTF8]); /// /// let mut component = Component::new(); /// component.section(&functions); @@ -96,7 +98,12 @@ impl CanonicalFunctionSection { } /// Define a function that will lift a core WebAssembly function to the canonical ABI. - pub fn lift(&mut self, core_func_index: u32, type_index: u32, options: O) -> &mut Self + pub fn lift( + &mut self, + core_func_index: FuncIdx, + type_index: ComponentTypeIdx, + options: O, + ) -> &mut Self where O: IntoIterator, O::IntoIter: ExactSizeIterator, @@ -115,7 +122,7 @@ impl CanonicalFunctionSection { } /// Define a function that will lower a canonical ABI function to a core WebAssembly function. - pub fn lower(&mut self, func_index: u32, options: O) -> &mut Self + pub fn lower(&mut self, func_index: ComponentFuncIdx, options: O) -> &mut Self where O: IntoIterator, O::IntoIter: ExactSizeIterator, @@ -134,7 +141,7 @@ impl CanonicalFunctionSection { /// Defines a function which will create an owned handle to the resource /// specified by `ty_index`. - pub fn resource_new(&mut self, ty_index: u32) -> &mut Self { + pub fn resource_new(&mut self, ty_index: ComponentTypeIdx) -> &mut Self { self.bytes.push(0x02); ty_index.encode(&mut self.bytes); self.num_added += 1; @@ -142,7 +149,7 @@ impl CanonicalFunctionSection { } /// Defines a function which will drop the specified type of handle. - pub fn resource_drop(&mut self, ty_index: u32) -> &mut Self { + pub fn resource_drop(&mut self, ty_index: ComponentTypeIdx) -> &mut Self { self.bytes.push(0x03); ty_index.encode(&mut self.bytes); self.num_added += 1; @@ -151,7 +158,7 @@ impl CanonicalFunctionSection { /// Defines a function which will return the representation of the specified /// resource type. - pub fn resource_rep(&mut self, ty_index: u32) -> &mut Self { + pub fn resource_rep(&mut self, ty_index: ComponentTypeIdx) -> &mut Self { self.bytes.push(0x04); ty_index.encode(&mut self.bytes); self.num_added += 1; @@ -160,7 +167,7 @@ impl CanonicalFunctionSection { /// Defines a function which will spawns a new thread by invoking a shared /// function of type `ty_index`. - pub fn thread_spawn(&mut self, ty_index: u32) -> &mut Self { + pub fn thread_spawn(&mut self, ty_index: TypeIdx) -> &mut Self { self.bytes.push(0x05); ty_index.encode(&mut self.bytes); self.num_added += 1; @@ -205,7 +212,7 @@ impl CanonicalFunctionSection { /// task/stream/future to make progress, returning the first such event. /// /// If `async_` is true, the caller instance may be reentered. - pub fn task_wait(&mut self, async_: bool, memory: u32) -> &mut Self { + pub fn task_wait(&mut self, async_: bool, memory: MemIdx) -> &mut Self { self.bytes.push(0x0a); self.bytes.push(if async_ { 1 } else { 0 }); memory.encode(&mut self.bytes); @@ -218,7 +225,7 @@ impl CanonicalFunctionSection { /// block and may return nothing if no such event has occurred. /// /// If `async_` is true, the caller instance may be reentered. - pub fn task_poll(&mut self, async_: bool, memory: u32) -> &mut Self { + pub fn task_poll(&mut self, async_: bool, memory: MemIdx) -> &mut Self { self.bytes.push(0x0b); self.bytes.push(if async_ { 1 } else { 0 }); memory.encode(&mut self.bytes); @@ -246,7 +253,7 @@ impl CanonicalFunctionSection { /// Defines a function to create a new `stream` handle of the specified /// type. - pub fn stream_new(&mut self, ty: u32) -> &mut Self { + pub fn stream_new(&mut self, ty: ComponentTypeIdx) -> &mut Self { self.bytes.push(0x0e); ty.encode(&mut self.bytes); self.num_added += 1; @@ -254,7 +261,7 @@ impl CanonicalFunctionSection { } /// Defines a function to read from a `stream` of the specified type. - pub fn stream_read(&mut self, ty: u32, options: O) -> &mut Self + pub fn stream_read(&mut self, ty: ComponentTypeIdx, options: O) -> &mut Self where O: IntoIterator, O::IntoIter: ExactSizeIterator, @@ -271,7 +278,7 @@ impl CanonicalFunctionSection { } /// Defines a function to write to a `stream` of the specified type. - pub fn stream_write(&mut self, ty: u32, options: O) -> &mut Self + pub fn stream_write(&mut self, ty: ComponentTypeIdx, options: O) -> &mut Self where O: IntoIterator, O::IntoIter: ExactSizeIterator, @@ -289,7 +296,7 @@ impl CanonicalFunctionSection { /// Defines a function to cancel an in-progress read from a `stream` of the /// specified type. - pub fn stream_cancel_read(&mut self, ty: u32, async_: bool) -> &mut Self { + pub fn stream_cancel_read(&mut self, ty: ComponentTypeIdx, async_: bool) -> &mut Self { self.bytes.push(0x11); ty.encode(&mut self.bytes); self.bytes.push(if async_ { 1 } else { 0 }); @@ -299,7 +306,7 @@ impl CanonicalFunctionSection { /// Defines a function to cancel an in-progress write to a `stream` of the /// specified type. - pub fn stream_cancel_write(&mut self, ty: u32, async_: bool) -> &mut Self { + pub fn stream_cancel_write(&mut self, ty: ComponentTypeIdx, async_: bool) -> &mut Self { self.bytes.push(0x12); ty.encode(&mut self.bytes); self.bytes.push(if async_ { 1 } else { 0 }); @@ -309,7 +316,7 @@ impl CanonicalFunctionSection { /// Defines a function to close the readable end of a `stream` of the /// specified type. - pub fn stream_close_readable(&mut self, ty: u32) -> &mut Self { + pub fn stream_close_readable(&mut self, ty: ComponentTypeIdx) -> &mut Self { self.bytes.push(0x13); ty.encode(&mut self.bytes); self.num_added += 1; @@ -318,7 +325,7 @@ impl CanonicalFunctionSection { /// Defines a function to close the writable end of a `stream` of the /// specified type. - pub fn stream_close_writable(&mut self, ty: u32) -> &mut Self { + pub fn stream_close_writable(&mut self, ty: ComponentTypeIdx) -> &mut Self { self.bytes.push(0x14); ty.encode(&mut self.bytes); self.num_added += 1; @@ -327,7 +334,7 @@ impl CanonicalFunctionSection { /// Defines a function to create a new `future` handle of the specified /// type. - pub fn future_new(&mut self, ty: u32) -> &mut Self { + pub fn future_new(&mut self, ty: ComponentTypeIdx) -> &mut Self { self.bytes.push(0x15); ty.encode(&mut self.bytes); self.num_added += 1; @@ -335,7 +342,7 @@ impl CanonicalFunctionSection { } /// Defines a function to read from a `future` of the specified type. - pub fn future_read(&mut self, ty: u32, options: O) -> &mut Self + pub fn future_read(&mut self, ty: ComponentTypeIdx, options: O) -> &mut Self where O: IntoIterator, O::IntoIter: ExactSizeIterator, @@ -352,7 +359,7 @@ impl CanonicalFunctionSection { } /// Defines a function to write to a `future` of the specified type. - pub fn future_write(&mut self, ty: u32, options: O) -> &mut Self + pub fn future_write(&mut self, ty: ComponentTypeIdx, options: O) -> &mut Self where O: IntoIterator, O::IntoIter: ExactSizeIterator, @@ -370,7 +377,7 @@ impl CanonicalFunctionSection { /// Defines a function to cancel an in-progress read from a `future` of the /// specified type. - pub fn future_cancel_read(&mut self, ty: u32, async_: bool) -> &mut Self { + pub fn future_cancel_read(&mut self, ty: ComponentTypeIdx, async_: bool) -> &mut Self { self.bytes.push(0x18); ty.encode(&mut self.bytes); self.bytes.push(if async_ { 1 } else { 0 }); @@ -380,7 +387,7 @@ impl CanonicalFunctionSection { /// Defines a function to cancel an in-progress write to a `future` of the /// specified type. - pub fn future_cancel_write(&mut self, ty: u32, async_: bool) -> &mut Self { + pub fn future_cancel_write(&mut self, ty: ComponentTypeIdx, async_: bool) -> &mut Self { self.bytes.push(0x19); ty.encode(&mut self.bytes); self.bytes.push(if async_ { 1 } else { 0 }); @@ -390,7 +397,7 @@ impl CanonicalFunctionSection { /// Defines a function to close the readable end of a `future` of the /// specified type. - pub fn future_close_readable(&mut self, ty: u32) -> &mut Self { + pub fn future_close_readable(&mut self, ty: ComponentTypeIdx) -> &mut Self { self.bytes.push(0x1a); ty.encode(&mut self.bytes); self.num_added += 1; @@ -399,7 +406,7 @@ impl CanonicalFunctionSection { /// Defines a function to close the writable end of a `future` of the /// specified type. - pub fn future_close_writable(&mut self, ty: u32) -> &mut Self { + pub fn future_close_writable(&mut self, ty: ComponentTypeIdx) -> &mut Self { self.bytes.push(0x1b); ty.encode(&mut self.bytes); self.num_added += 1; diff --git a/crates/wasm-encoder/src/component/imports.rs b/crates/wasm-encoder/src/component/imports.rs index 9bd6716895..a293219f3f 100644 --- a/crates/wasm-encoder/src/component/imports.rs +++ b/crates/wasm-encoder/src/component/imports.rs @@ -3,12 +3,13 @@ use crate::{ Encode, }; use alloc::vec::Vec; +use wasm_types::{ComponentTypeIdx, TypeIdx}; /// Represents the possible type bounds for type references. #[derive(Clone, Copy, Debug, Eq, PartialEq, Hash)] pub enum TypeBounds { /// The type is bounded by equality to the type index specified. - Eq(u32), + Eq(ComponentTypeIdx), /// This type is a fresh resource type, SubResource, } @@ -31,11 +32,11 @@ pub enum ComponentTypeRef { /// The reference is to a core module type. /// /// The index is expected to be core type index to a core module type. - Module(u32), + Module(TypeIdx), /// The reference is to a function type. /// /// The index is expected to be a type index to a function type. - Func(u32), + Func(ComponentTypeIdx), /// The reference is to a value type. Value(ComponentValType), /// The reference is to a bounded type. @@ -43,11 +44,11 @@ pub enum ComponentTypeRef { /// The reference is to an instance type. /// /// The index is expected to be a type index to an instance type. - Instance(u32), + Instance(ComponentTypeIdx), /// The reference is to a component type. /// /// The index is expected to be a type index to a component type. - Component(u32), + Component(ComponentTypeIdx), } impl ComponentTypeRef { @@ -69,9 +70,10 @@ impl Encode for ComponentTypeRef { self.kind().encode(sink); match self { - Self::Module(idx) | Self::Func(idx) | Self::Instance(idx) | Self::Component(idx) => { - idx.encode(sink); - } + Self::Module(idx) => idx.encode(sink), + Self::Func(idx) => idx.encode(sink), + Self::Instance(idx) => idx.encode(sink), + Self::Component(idx) => idx.encode(sink), Self::Value(ty) => ty.encode(sink), Self::Type(bounds) => bounds.encode(sink), } @@ -84,6 +86,7 @@ impl Encode for ComponentTypeRef { /// /// ```rust /// use wasm_encoder::{Component, ComponentTypeSection, PrimitiveValType, ComponentImportSection, ComponentTypeRef}; +/// use wasm_types::ComponentTypeIdx; /// /// let mut types = ComponentTypeSection::new(); /// @@ -100,7 +103,7 @@ impl Encode for ComponentTypeRef { /// /// // This imports a function named `f` with the type defined above /// let mut imports = ComponentImportSection::new(); -/// imports.import("f", ComponentTypeRef::Func(0)); +/// imports.import("f", ComponentTypeRef::Func(ComponentTypeIdx(0))); /// /// let mut component = Component::new(); /// component.section(&types); diff --git a/crates/wasm-encoder/src/component/instances.rs b/crates/wasm-encoder/src/component/instances.rs index c7f26987bf..7ae90a456d 100644 --- a/crates/wasm-encoder/src/component/instances.rs +++ b/crates/wasm-encoder/src/component/instances.rs @@ -3,12 +3,13 @@ use crate::{ encode_section, ComponentExportKind, ComponentSection, ComponentSectionId, Encode, ExportKind, }; use alloc::vec::Vec; +use wasm_types::{ComponentIdx, CoreInstanceIdx, CoreModuleIdx}; /// Represents an argument to a module instantiation. #[derive(Clone, Copy, Debug, Eq, PartialEq)] pub enum ModuleArg { /// The argument is an instance. - Instance(u32), + Instance(CoreInstanceIdx), } impl Encode for ModuleArg { @@ -27,10 +28,11 @@ impl Encode for ModuleArg { /// /// ```rust /// use wasm_encoder::{Component, InstanceSection, ExportKind, ModuleArg}; +/// use wasm_types::{CoreInstanceIdx, CoreModuleIdx}; /// /// let mut instances = InstanceSection::new(); /// instances.export_items([("foo", ExportKind::Func, 0)]); -/// instances.instantiate(1, [("foo", ModuleArg::Instance(0))]); +/// instances.instantiate(CoreModuleIdx(1), [("foo", ModuleArg::Instance(CoreInstanceIdx(0)))]); /// /// let mut component = Component::new(); /// component.section(&instances); @@ -60,7 +62,7 @@ impl InstanceSection { } /// Define an instance by instantiating a core module. - pub fn instantiate(&mut self, module_index: u32, args: A) -> &mut Self + pub fn instantiate(&mut self, module_index: CoreModuleIdx, args: A) -> &mut Self where A: IntoIterator, A::IntoIter: ExactSizeIterator, @@ -116,10 +118,11 @@ impl ComponentSection for InstanceSection { /// /// ```rust /// use wasm_encoder::{Component, ComponentInstanceSection, ComponentExportKind}; +/// use wasm_types::ComponentIdx; /// /// let mut instances = ComponentInstanceSection::new(); /// instances.export_items([("foo", ComponentExportKind::Func, 0)]); -/// instances.instantiate(1, [("foo", ComponentExportKind::Instance, 0)]); +/// instances.instantiate(ComponentIdx(1), [("foo", ComponentExportKind::Instance, 0)]); /// /// let mut component = Component::new(); /// component.section(&instances); @@ -149,7 +152,7 @@ impl ComponentInstanceSection { } /// Define an instance by instantiating a component. - pub fn instantiate(&mut self, component_index: u32, args: A) -> &mut Self + pub fn instantiate(&mut self, component_index: ComponentIdx, args: A) -> &mut Self where A: IntoIterator, A::IntoIter: ExactSizeIterator, diff --git a/crates/wasm-encoder/src/component/names.rs b/crates/wasm-encoder/src/component/names.rs index bd2df42c01..0a4c5ff6f8 100644 --- a/crates/wasm-encoder/src/component/names.rs +++ b/crates/wasm-encoder/src/component/names.rs @@ -1,5 +1,10 @@ use alloc::borrow::Cow; use alloc::vec::Vec; +use index_vec::Idx; +use wasm_types::{ + ComponentFuncIdx, ComponentIdx, ComponentInstanceIdx, ComponentTypeIdx, ComponentValueIdx, + CoreInstanceIdx, CoreModuleIdx, FuncIdx, GlobalIdx, MemIdx, TableIdx, TypeIdx, +}; use super::*; use crate::{encoding_size, ExportKind, NameMap, SectionId}; @@ -35,73 +40,73 @@ impl ComponentNameSection { /// Appends a decls name subsection to name core functions within the /// component. - pub fn core_funcs(&mut self, names: &NameMap) { + pub fn core_funcs(&mut self, names: &NameMap) { self.core_decls(ExportKind::Func as u8, names) } /// Appends a decls name subsection to name core tables within the /// component. - pub fn core_tables(&mut self, names: &NameMap) { + pub fn core_tables(&mut self, names: &NameMap) { self.core_decls(ExportKind::Table as u8, names) } /// Appends a decls name subsection to name core memories within the /// component. - pub fn core_memories(&mut self, names: &NameMap) { + pub fn core_memories(&mut self, names: &NameMap) { self.core_decls(ExportKind::Memory as u8, names) } /// Appends a decls name subsection to name core globals within the /// component. - pub fn core_globals(&mut self, names: &NameMap) { + pub fn core_globals(&mut self, names: &NameMap) { self.core_decls(ExportKind::Global as u8, names) } /// Appends a decls name subsection to name core types within the /// component. - pub fn core_types(&mut self, names: &NameMap) { + pub fn core_types(&mut self, names: &NameMap) { self.core_decls(CORE_TYPE_SORT, names) } /// Appends a decls name subsection to name core modules within the /// component. - pub fn core_modules(&mut self, names: &NameMap) { + pub fn core_modules(&mut self, names: &NameMap) { self.core_decls(CORE_MODULE_SORT, names) } /// Appends a decls name subsection to name core instances within the /// component. - pub fn core_instances(&mut self, names: &NameMap) { + pub fn core_instances(&mut self, names: &NameMap) { self.core_decls(CORE_INSTANCE_SORT, names) } /// Appends a decls name subsection to name component functions within the /// component. - pub fn funcs(&mut self, names: &NameMap) { + pub fn funcs(&mut self, names: &NameMap) { self.component_decls(FUNCTION_SORT, names) } /// Appends a decls name subsection to name component values within the /// component. - pub fn values(&mut self, names: &NameMap) { + pub fn values(&mut self, names: &NameMap) { self.component_decls(VALUE_SORT, names) } /// Appends a decls name subsection to name component type within the /// component. - pub fn types(&mut self, names: &NameMap) { + pub fn types(&mut self, names: &NameMap) { self.component_decls(TYPE_SORT, names) } /// Appends a decls name subsection to name components within the /// component. - pub fn components(&mut self, names: &NameMap) { + pub fn components(&mut self, names: &NameMap) { self.component_decls(COMPONENT_SORT, names) } /// Appends a decls name subsection to name component instances within the /// component. - pub fn instances(&mut self, names: &NameMap) { + pub fn instances(&mut self, names: &NameMap) { self.component_decls(INSTANCE_SORT, names) } @@ -111,13 +116,13 @@ impl ComponentNameSection { data.encode(&mut self.bytes); } - fn component_decls(&mut self, kind: u8, names: &NameMap) { + fn component_decls(&mut self, kind: u8, names: &NameMap) { self.subsection_header(Subsection::Decls, 1 + names.size()); self.bytes.push(kind); names.encode(&mut self.bytes); } - fn core_decls(&mut self, kind: u8, names: &NameMap) { + fn core_decls(&mut self, kind: u8, names: &NameMap) { self.subsection_header(Subsection::Decls, 2 + names.size()); self.bytes.push(CORE_SORT); self.bytes.push(kind); diff --git a/crates/wasm-encoder/src/component/start.rs b/crates/wasm-encoder/src/component/start.rs index 7a68de9ea0..8759d09072 100644 --- a/crates/wasm-encoder/src/component/start.rs +++ b/crates/wasm-encoder/src/component/start.rs @@ -1,5 +1,6 @@ use crate::{ComponentSection, ComponentSectionId, Encode}; use alloc::vec::Vec; +use wasm_types::{ComponentFuncIdx, ComponentValueIdx}; /// An encoder for the start section of WebAssembly components. /// @@ -7,8 +8,13 @@ use alloc::vec::Vec; /// /// ``` /// use wasm_encoder::{Component, ComponentStartSection}; +/// use wasm_types::{ComponentFuncIdx, ComponentValueIdx}; /// -/// let start = ComponentStartSection { function_index: 0, args: [0, 1], results: 1 }; +/// let start = ComponentStartSection { +/// function_index: ComponentFuncIdx(0), +/// args: [0, 1].map(ComponentValueIdx), +/// results: 1, +/// }; /// /// let mut component = Component::new(); /// component.section(&start); @@ -18,7 +24,7 @@ use alloc::vec::Vec; #[derive(Clone, Debug)] pub struct ComponentStartSection { /// The index to the start function. - pub function_index: u32, + pub function_index: ComponentFuncIdx, /// The arguments to pass to the start function. /// /// An argument is an index to a value. @@ -32,7 +38,7 @@ pub struct ComponentStartSection { impl Encode for ComponentStartSection where - A: AsRef<[u32]>, + A: AsRef<[ComponentValueIdx]>, { fn encode(&self, sink: &mut Vec) { let mut bytes = Vec::new(); @@ -45,7 +51,7 @@ where impl ComponentSection for ComponentStartSection where - A: AsRef<[u32]>, + A: AsRef<[ComponentValueIdx]>, { fn id(&self) -> u8 { ComponentSectionId::Start.into() diff --git a/crates/wasm-encoder/src/component/types.rs b/crates/wasm-encoder/src/component/types.rs index 543bddbb33..745e6418f8 100644 --- a/crates/wasm-encoder/src/component/types.rs +++ b/crates/wasm-encoder/src/component/types.rs @@ -4,6 +4,7 @@ use crate::{ ComponentSectionId, ComponentTypeRef, CoreTypeEncoder, Encode, EntityType, ValType, }; use alloc::vec::Vec; +use wasm_types::{ComponentTypeIdx, FuncIdx, TypeIdx}; /// Represents the type of a core module. #[derive(Debug, Clone, Default)] @@ -44,7 +45,7 @@ impl ModuleType { } /// Defines an outer core type alias in this module type. - pub fn alias_outer_core_type(&mut self, count: u32, index: u32) -> &mut Self { + pub fn alias_outer_core_type(&mut self, count: u32, index: TypeIdx) -> &mut Self { self.bytes.push(0x02); self.bytes.push(CORE_TYPE_SORT); self.bytes.push(0x01); // outer @@ -467,7 +468,7 @@ impl<'a> ComponentTypeEncoder<'a> { } /// Define a resource type. - pub fn resource(self, rep: ValType, dtor: Option) { + pub fn resource(self, rep: ValType, dtor: Option) { self.0.push(0x3f); rep.encode(self.0); match dtor { @@ -539,14 +540,14 @@ pub enum ComponentValType { /// The value is to a defined value type. /// /// The type index must be to a value type. - Type(u32), + Type(ComponentTypeIdx), } impl Encode for ComponentValType { fn encode(&self, sink: &mut Vec) { match self { Self::Primitive(ty) => ty.encode(sink), - Self::Type(index) => (*index as i64).encode(sink), + Self::Type(index) => (index.0 as i64).encode(sink), } } } @@ -662,13 +663,13 @@ impl ComponentDefinedTypeEncoder<'_> { } /// Define a `own` handle type - pub fn own(self, idx: u32) { + pub fn own(self, idx: ComponentTypeIdx) { self.0.push(0x69); idx.encode(self.0); } /// Define a `borrow` handle type - pub fn borrow(self, idx: u32) { + pub fn borrow(self, idx: ComponentTypeIdx) { self.0.push(0x68); idx.encode(self.0); } @@ -773,7 +774,7 @@ impl ComponentTypeSection { } /// Defines a new resource type. - pub fn resource(&mut self, rep: ValType, dtor: Option) -> &mut Self { + pub fn resource(&mut self, rep: ValType, dtor: Option) -> &mut Self { self.ty().resource(rep, dtor); self } diff --git a/crates/wasm-encoder/src/core/branch_hints.rs b/crates/wasm-encoder/src/core/branch_hints.rs index 96231b11e9..bcea4f08db 100644 --- a/crates/wasm-encoder/src/core/branch_hints.rs +++ b/crates/wasm-encoder/src/core/branch_hints.rs @@ -1,6 +1,7 @@ use crate::{CustomSection, Encode, Section, SectionId}; use alloc::borrow::Cow; use alloc::vec::Vec; +use wasm_types::FuncIdx; /// Helper structure to encode the `metadata.code.branch_hint` custom section. /// @@ -11,6 +12,7 @@ use alloc::vec::Vec; /// /// ``` /// use wasm_encoder::*; +/// use wasm_types::*; /// /// let mut module = Module::new(); /// @@ -19,7 +21,7 @@ use alloc::vec::Vec; /// module.section(&types); /// /// let mut funcs = FunctionSection::new(); -/// funcs.function(0); +/// funcs.function(TypeIdx(0)); /// module.section(&funcs); /// /// let mut code = CodeSection::new(); @@ -33,7 +35,7 @@ use alloc::vec::Vec; /// code.function(&body); /// /// let mut hints = BranchHints::new(); -/// hints.function_hints(0, [BranchHint { +/// hints.function_hints(FuncIdx(0), [BranchHint { /// branch_func_offset: if_offset as u32, /// branch_hint_value: 1, // taken /// }]); @@ -77,7 +79,7 @@ impl BranchHints { } /// Adds a new set of function hints for the `func` specified. - pub fn function_hints(&mut self, func: u32, hints: I) + pub fn function_hints(&mut self, func: FuncIdx, hints: I) where I: IntoIterator, I::IntoIter: ExactSizeIterator, diff --git a/crates/wasm-encoder/src/core/code.rs b/crates/wasm-encoder/src/core/code.rs index 547c574181..eb4ba56014 100644 --- a/crates/wasm-encoder/src/core/code.rs +++ b/crates/wasm-encoder/src/core/code.rs @@ -2,6 +2,10 @@ use crate::{encode_section, Encode, HeapType, RefType, Section, SectionId, ValTy use alloc::borrow::Cow; use alloc::vec; use alloc::vec::Vec; +use wasm_types::{ + DataIdx, ElemIdx, FieldIdx, FuncIdx, GlobalIdx, LabelIdx, LocalIdx, MemIdx, TableIdx, TagIdx, + TypeIdx, +}; /// An encoder for the code section. /// @@ -14,12 +18,13 @@ use alloc::vec::Vec; /// CodeSection, Function, FunctionSection, Instruction, Module, /// TypeSection, ValType /// }; +/// use wasm_types::TypeIdx; /// /// let mut types = TypeSection::new(); /// types.ty().function(vec![], vec![ValType::I32]); /// /// let mut functions = FunctionSection::new(); -/// let type_index = 0; +/// let type_index = TypeIdx(0); /// functions.function(type_index); /// /// let locals = vec![]; @@ -125,6 +130,7 @@ impl Section for CodeSection { /// /// ``` /// use wasm_encoder::{CodeSection, Function, Instruction}; +/// use wasm_types::LocalIdx; /// /// // Define the function body for: /// // @@ -134,8 +140,8 @@ impl Section for CodeSection { /// // i32.add) /// let locals = vec![]; /// let mut func = Function::new(locals); -/// func.instruction(&Instruction::LocalGet(0)); -/// func.instruction(&Instruction::LocalGet(1)); +/// func.instruction(&Instruction::LocalGet(LocalIdx(0))); +/// func.instruction(&Instruction::LocalGet(LocalIdx(1))); /// func.instruction(&Instruction::I32Add); /// /// // Add our function to the code section. @@ -301,12 +307,12 @@ pub struct MemArg { /// (expressed the exponent of a power of two). pub align: u32, /// The index of the memory this instruction is operating upon. - pub memory_index: u32, + pub memory_index: MemIdx, } impl Encode for MemArg { fn encode(&self, sink: &mut Vec) { - if self.memory_index == 0 { + if self.memory_index == MemIdx(0) { self.align.encode(sink); self.offset.encode(sink); } else { @@ -356,7 +362,7 @@ pub enum BlockType { /// `[] -> [t]` Result(ValType), /// The `n`th function type. - FunctionType(u32), + FunctionType(TypeIdx), } impl Encode for BlockType { @@ -364,7 +370,7 @@ impl Encode for BlockType { match *self { Self::Empty => sink.push(0x40), Self::Result(ty) => ty.encode(sink), - Self::FunctionType(f) => (f as i64).encode(sink), + Self::FunctionType(f) => (f.0 as i64).encode(sink), } } } @@ -382,45 +388,45 @@ pub enum Instruction<'a> { If(BlockType), Else, End, - Br(u32), - BrIf(u32), - BrTable(Cow<'a, [u32]>, u32), - BrOnNull(u32), - BrOnNonNull(u32), + Br(LabelIdx), + BrIf(LabelIdx), + BrTable(Cow<'a, [LabelIdx]>, LabelIdx), + BrOnNull(LabelIdx), + BrOnNonNull(LabelIdx), Return, - Call(u32), - CallRef(u32), + Call(FuncIdx), + CallRef(TypeIdx), CallIndirect { - type_index: u32, - table_index: u32, + type_index: TypeIdx, + table_index: TableIdx, }, - ReturnCallRef(u32), - ReturnCall(u32), + ReturnCallRef(TypeIdx), + ReturnCall(FuncIdx), ReturnCallIndirect { - type_index: u32, - table_index: u32, + type_index: TypeIdx, + table_index: TableIdx, }, TryTable(BlockType, Cow<'a, [Catch]>), - Throw(u32), + Throw(TagIdx), ThrowRef, // Deprecated exception-handling instructions Try(BlockType), - Delegate(u32), - Catch(u32), + Delegate(LabelIdx), + Catch(TagIdx), CatchAll, - Rethrow(u32), + Rethrow(LabelIdx), // Parametric instructions. Drop, Select, // Variable instructions. - LocalGet(u32), - LocalSet(u32), - LocalTee(u32), - GlobalGet(u32), - GlobalSet(u32), + LocalGet(LocalIdx), + LocalSet(LocalIdx), + LocalTee(LocalIdx), + GlobalGet(GlobalIdx), + GlobalSet(GlobalIdx), // Memory instructions. I32Load(MemArg), @@ -446,19 +452,19 @@ pub enum Instruction<'a> { I64Store8(MemArg), I64Store16(MemArg), I64Store32(MemArg), - MemorySize(u32), - MemoryGrow(u32), + MemorySize(MemIdx), + MemoryGrow(MemIdx), MemoryInit { - mem: u32, - data_index: u32, + mem: MemIdx, + data_index: DataIdx, }, - DataDrop(u32), + DataDrop(DataIdx), MemoryCopy { - src_mem: u32, - dst_mem: u32, + src_mem: MemIdx, + dst_mem: MemIdx, }, - MemoryFill(u32), - MemoryDiscard(u32), + MemoryFill(MemIdx), + MemoryDiscard(MemIdx), // Numeric instructions. I32Const(i32), @@ -606,73 +612,73 @@ pub enum Instruction<'a> { TypedSelect(ValType), RefNull(HeapType), RefIsNull, - RefFunc(u32), + RefFunc(FuncIdx), RefEq, RefAsNonNull, // GC types instructions. - StructNew(u32), - StructNewDefault(u32), + StructNew(TypeIdx), + StructNewDefault(TypeIdx), StructGet { - struct_type_index: u32, - field_index: u32, + struct_type_index: TypeIdx, + field_index: FieldIdx, }, StructGetS { - struct_type_index: u32, - field_index: u32, + struct_type_index: TypeIdx, + field_index: FieldIdx, }, StructGetU { - struct_type_index: u32, - field_index: u32, + struct_type_index: TypeIdx, + field_index: FieldIdx, }, StructSet { - struct_type_index: u32, - field_index: u32, + struct_type_index: TypeIdx, + field_index: FieldIdx, }, - ArrayNew(u32), - ArrayNewDefault(u32), + ArrayNew(TypeIdx), + ArrayNewDefault(TypeIdx), ArrayNewFixed { - array_type_index: u32, + array_type_index: TypeIdx, array_size: u32, }, ArrayNewData { - array_type_index: u32, - array_data_index: u32, + array_type_index: TypeIdx, + array_data_index: DataIdx, }, ArrayNewElem { - array_type_index: u32, - array_elem_index: u32, + array_type_index: TypeIdx, + array_elem_index: ElemIdx, }, - ArrayGet(u32), - ArrayGetS(u32), - ArrayGetU(u32), - ArraySet(u32), + ArrayGet(TypeIdx), + ArrayGetS(TypeIdx), + ArrayGetU(TypeIdx), + ArraySet(TypeIdx), ArrayLen, - ArrayFill(u32), + ArrayFill(TypeIdx), ArrayCopy { - array_type_index_dst: u32, - array_type_index_src: u32, + array_type_index_dst: TypeIdx, + array_type_index_src: TypeIdx, }, ArrayInitData { - array_type_index: u32, - array_data_index: u32, + array_type_index: TypeIdx, + array_data_index: DataIdx, }, ArrayInitElem { - array_type_index: u32, - array_elem_index: u32, + array_type_index: TypeIdx, + array_elem_index: ElemIdx, }, RefTestNonNull(HeapType), RefTestNullable(HeapType), RefCastNonNull(HeapType), RefCastNullable(HeapType), BrOnCast { - relative_depth: u32, + relative_depth: LabelIdx, from_ref_type: RefType, to_ref_type: RefType, }, BrOnCastFail { - relative_depth: u32, + relative_depth: LabelIdx, from_ref_type: RefType, to_ref_type: RefType, }, @@ -685,18 +691,18 @@ pub enum Instruction<'a> { // Bulk memory instructions. TableInit { - elem_index: u32, - table: u32, - }, - ElemDrop(u32), - TableFill(u32), - TableSet(u32), - TableGet(u32), - TableGrow(u32), - TableSize(u32), + elem_index: ElemIdx, + table: TableIdx, + }, + ElemDrop(ElemIdx), + TableFill(TableIdx), + TableSet(TableIdx), + TableGet(TableIdx), + TableGrow(TableIdx), + TableSize(TableIdx), TableCopy { - src_table: u32, - dst_table: u32, + src_table: TableIdx, + dst_table: TableIdx, }, // SIMD instructions. @@ -1055,175 +1061,175 @@ pub enum Instruction<'a> { // More atomic instructions (the shared-everything-threads proposal) GlobalAtomicGet { ordering: Ordering, - global_index: u32, + global_index: GlobalIdx, }, GlobalAtomicSet { ordering: Ordering, - global_index: u32, + global_index: GlobalIdx, }, GlobalAtomicRmwAdd { ordering: Ordering, - global_index: u32, + global_index: GlobalIdx, }, GlobalAtomicRmwSub { ordering: Ordering, - global_index: u32, + global_index: GlobalIdx, }, GlobalAtomicRmwAnd { ordering: Ordering, - global_index: u32, + global_index: GlobalIdx, }, GlobalAtomicRmwOr { ordering: Ordering, - global_index: u32, + global_index: GlobalIdx, }, GlobalAtomicRmwXor { ordering: Ordering, - global_index: u32, + global_index: GlobalIdx, }, GlobalAtomicRmwXchg { ordering: Ordering, - global_index: u32, + global_index: GlobalIdx, }, GlobalAtomicRmwCmpxchg { ordering: Ordering, - global_index: u32, + global_index: GlobalIdx, }, TableAtomicGet { ordering: Ordering, - table_index: u32, + table_index: TableIdx, }, TableAtomicSet { ordering: Ordering, - table_index: u32, + table_index: TableIdx, }, TableAtomicRmwXchg { ordering: Ordering, - table_index: u32, + table_index: TableIdx, }, TableAtomicRmwCmpxchg { ordering: Ordering, - table_index: u32, + table_index: TableIdx, }, StructAtomicGet { ordering: Ordering, - struct_type_index: u32, - field_index: u32, + struct_type_index: TypeIdx, + field_index: FieldIdx, }, StructAtomicGetS { ordering: Ordering, - struct_type_index: u32, - field_index: u32, + struct_type_index: TypeIdx, + field_index: FieldIdx, }, StructAtomicGetU { ordering: Ordering, - struct_type_index: u32, - field_index: u32, + struct_type_index: TypeIdx, + field_index: FieldIdx, }, StructAtomicSet { ordering: Ordering, - struct_type_index: u32, - field_index: u32, + struct_type_index: TypeIdx, + field_index: FieldIdx, }, StructAtomicRmwAdd { ordering: Ordering, - struct_type_index: u32, - field_index: u32, + struct_type_index: TypeIdx, + field_index: FieldIdx, }, StructAtomicRmwSub { ordering: Ordering, - struct_type_index: u32, - field_index: u32, + struct_type_index: TypeIdx, + field_index: FieldIdx, }, StructAtomicRmwAnd { ordering: Ordering, - struct_type_index: u32, - field_index: u32, + struct_type_index: TypeIdx, + field_index: FieldIdx, }, StructAtomicRmwOr { ordering: Ordering, - struct_type_index: u32, - field_index: u32, + struct_type_index: TypeIdx, + field_index: FieldIdx, }, StructAtomicRmwXor { ordering: Ordering, - struct_type_index: u32, - field_index: u32, + struct_type_index: TypeIdx, + field_index: FieldIdx, }, StructAtomicRmwXchg { ordering: Ordering, - struct_type_index: u32, - field_index: u32, + struct_type_index: TypeIdx, + field_index: FieldIdx, }, StructAtomicRmwCmpxchg { ordering: Ordering, - struct_type_index: u32, - field_index: u32, + struct_type_index: TypeIdx, + field_index: FieldIdx, }, ArrayAtomicGet { ordering: Ordering, - array_type_index: u32, + array_type_index: TypeIdx, }, ArrayAtomicGetS { ordering: Ordering, - array_type_index: u32, + array_type_index: TypeIdx, }, ArrayAtomicGetU { ordering: Ordering, - array_type_index: u32, + array_type_index: TypeIdx, }, ArrayAtomicSet { ordering: Ordering, - array_type_index: u32, + array_type_index: TypeIdx, }, ArrayAtomicRmwAdd { ordering: Ordering, - array_type_index: u32, + array_type_index: TypeIdx, }, ArrayAtomicRmwSub { ordering: Ordering, - array_type_index: u32, + array_type_index: TypeIdx, }, ArrayAtomicRmwAnd { ordering: Ordering, - array_type_index: u32, + array_type_index: TypeIdx, }, ArrayAtomicRmwOr { ordering: Ordering, - array_type_index: u32, + array_type_index: TypeIdx, }, ArrayAtomicRmwXor { ordering: Ordering, - array_type_index: u32, + array_type_index: TypeIdx, }, ArrayAtomicRmwXchg { ordering: Ordering, - array_type_index: u32, + array_type_index: TypeIdx, }, ArrayAtomicRmwCmpxchg { ordering: Ordering, - array_type_index: u32, + array_type_index: TypeIdx, }, RefI31Shared, // Stack switching - ContNew(u32), + ContNew(TypeIdx), ContBind { - argument_index: u32, - result_index: u32, + argument_index: TypeIdx, + result_index: TypeIdx, }, - Suspend(u32), + Suspend(TagIdx), Resume { - cont_type_index: u32, + cont_type_index: TypeIdx, resume_table: Cow<'a, [Handle]>, }, ResumeThrow { - cont_type_index: u32, - tag_index: u32, + cont_type_index: TypeIdx, + tag_index: TagIdx, resume_table: Cow<'a, [Handle]>, }, Switch { - cont_type_index: u32, - tag_index: u32, + cont_type_index: TypeIdx, + tag_index: TagIdx, }, // Wide Arithmetic @@ -3788,10 +3794,10 @@ impl Encode for Instruction<'_> { #[derive(Clone, Debug)] #[allow(missing_docs)] pub enum Catch { - One { tag: u32, label: u32 }, - OneRef { tag: u32, label: u32 }, - All { label: u32 }, - AllRef { label: u32 }, + One { tag: TagIdx, label: LabelIdx }, + OneRef { tag: TagIdx, label: LabelIdx }, + All { label: LabelIdx }, + AllRef { label: LabelIdx }, } impl Encode for Catch { @@ -3822,8 +3828,8 @@ impl Encode for Catch { #[derive(Clone, Debug)] #[allow(missing_docs)] pub enum Handle { - OnLabel { tag: u32, label: u32 }, - OnSwitch { tag: u32 }, + OnLabel { tag: TagIdx, label: LabelIdx }, + OnSwitch { tag: TagIdx }, } impl Encode for Handle { @@ -3884,7 +3890,7 @@ impl ConstExpr { } /// Create a constant expression containing a single `global.get` instruction. - pub fn global_get(index: u32) -> Self { + pub fn global_get(index: GlobalIdx) -> Self { Self::new_insn(Instruction::GlobalGet(index)) } @@ -3894,7 +3900,7 @@ impl ConstExpr { } /// Create a constant expression containing a single `ref.func` instruction. - pub fn ref_func(func: u32) -> Self { + pub fn ref_func(func: FuncIdx) -> Self { Self::new_insn(Instruction::RefFunc(func)) } @@ -3924,7 +3930,7 @@ impl ConstExpr { } /// Add a `global.get` instruction to this constant expression. - pub fn with_global_get(self, index: u32) -> Self { + pub fn with_global_get(self, index: GlobalIdx) -> Self { self.with_insn(Instruction::GlobalGet(index)) } @@ -3934,7 +3940,7 @@ impl ConstExpr { } /// Add a `ref.func` instruction to this constant expression. - pub fn with_ref_func(self, func: u32) -> Self { + pub fn with_ref_func(self, func: FuncIdx) -> Self { self.with_insn(Instruction::RefFunc(func)) } @@ -3994,14 +4000,16 @@ impl ConstExpr { } /// Returns the function, if any, referenced by this global. - pub fn get_ref_func(&self) -> Option { + pub fn get_ref_func(&self) -> Option { let prefix = *self.bytes.get(0)?; // 0xd2 == `ref.func` opcode, and if that's found then load the leb // corresponding to the function index. if prefix != 0xd2 { return None; } - leb128fmt::decode_uint_slice::(&self.bytes[1..], &mut 0).ok() + leb128fmt::decode_uint_slice::(&self.bytes[1..], &mut 0) + .ok() + .map(FuncIdx) } } diff --git a/crates/wasm-encoder/src/core/data.rs b/crates/wasm-encoder/src/core/data.rs index 9d7ac752a3..579325e3ca 100644 --- a/crates/wasm-encoder/src/core/data.rs +++ b/crates/wasm-encoder/src/core/data.rs @@ -1,5 +1,6 @@ use crate::{encode_section, encoding_size, ConstExpr, Encode, Section, SectionId}; use alloc::vec::Vec; +use wasm_types::MemIdx; /// An encoder for the data section. /// @@ -12,6 +13,7 @@ use alloc::vec::Vec; /// ConstExpr, DataSection, Instruction, MemorySection, MemoryType, /// Module, /// }; +/// use wasm_types::MemIdx; /// /// let mut memory = MemorySection::new(); /// memory.memory(MemoryType { @@ -23,7 +25,7 @@ use alloc::vec::Vec; /// }); /// /// let mut data = DataSection::new(); -/// let memory_index = 0; +/// let memory_index = MemIdx(0); /// let offset = ConstExpr::i32_const(42); /// let segment_data = b"hello"; /// data.active(memory_index, &offset, segment_data.iter().copied()); @@ -56,7 +58,7 @@ pub enum DataSegmentMode<'a> { /// An active data segment. Active { /// The memory this segment applies to. - memory_index: u32, + memory_index: MemIdx, /// The offset where this segment's data is initialized at. offset: &'a ConstExpr, }, @@ -93,7 +95,7 @@ impl DataSection { self.bytes.push(0x01); } DataSegmentMode::Active { - memory_index: 0, + memory_index: MemIdx(0), offset, } => { self.bytes.push(0x00); @@ -118,7 +120,7 @@ impl DataSection { } /// Define an active data segment. - pub fn active(&mut self, memory_index: u32, offset: &ConstExpr, data: D) -> &mut Self + pub fn active(&mut self, memory_index: MemIdx, offset: &ConstExpr, data: D) -> &mut Self where D: IntoIterator, D::IntoIter: ExactSizeIterator, diff --git a/crates/wasm-encoder/src/core/dump.rs b/crates/wasm-encoder/src/core/dump.rs index 5eec139f39..efe9682f17 100644 --- a/crates/wasm-encoder/src/core/dump.rs +++ b/crates/wasm-encoder/src/core/dump.rs @@ -338,6 +338,7 @@ impl Encode for CoreDumpValue { mod tests { use super::*; use crate::Module; + use wasm_types::FuncIdx; use wasmparser::{KnownCustom, Parser, Payload}; // Create new core dump section and test whether it is properly encoded and @@ -488,7 +489,7 @@ mod tests { .first() .expect("frame is encoded in corestack"); assert_eq!(frame.instanceidx, 0); - assert_eq!(frame.funcidx, 12); + assert_eq!(frame.funcidx, FuncIdx(12)); assert_eq!(frame.codeoffset, 0); assert_eq!(frame.locals.len(), 1); match frame.locals.first().expect("frame contains a local") { diff --git a/crates/wasm-encoder/src/core/elements.rs b/crates/wasm-encoder/src/core/elements.rs index b3a3b5139d..f18ba6ae11 100644 --- a/crates/wasm-encoder/src/core/elements.rs +++ b/crates/wasm-encoder/src/core/elements.rs @@ -1,6 +1,7 @@ use crate::{encode_section, ConstExpr, Encode, RefType, Section, SectionId}; use alloc::borrow::Cow; use alloc::vec::Vec; +use wasm_types::{FuncIdx, TableIdx}; /// An encoder for the element section. /// @@ -14,6 +15,7 @@ use alloc::vec::Vec; /// Elements, ElementSection, Module, TableSection, TableType, /// RefType, ConstExpr /// }; +/// use wasm_types::TableIdx; /// /// let mut tables = TableSection::new(); /// tables.table(TableType { @@ -25,7 +27,7 @@ use alloc::vec::Vec; /// }); /// /// let mut elements = ElementSection::new(); -/// let table_index = 0; +/// let table_index = TableIdx(0); /// let offset = ConstExpr::i32_const(42); /// let functions = Elements::Functions(Cow::Borrowed(&[ /// // Function indices... @@ -49,7 +51,7 @@ pub struct ElementSection { #[derive(Clone, Debug)] pub enum Elements<'a> { /// A sequences of references to functions by their indices. - Functions(Cow<'a, [u32]>), + Functions(Cow<'a, [FuncIdx]>), /// A sequence of reference expressions. Expressions(RefType, Cow<'a, [ConstExpr]>), } @@ -72,7 +74,7 @@ pub enum ElementMode<'a> { /// `Active` element specifying a `None` table forces the MVP encoding and refers to the /// 0th table holding `funcref`s. Non-`None` tables use the encoding introduced with the /// bulk memory proposal and can refer to tables with any valid reference type. - table: Option, + table: Option, /// The offset within the table to place this segment. offset: &'a ConstExpr, }, @@ -129,7 +131,7 @@ impl ElementSection { // encoding. (None, Elements::Expressions(..)) | (Some(_), _) => { (0x02 | expr_bit).encode(&mut self.bytes); - table.unwrap_or(0).encode(&mut self.bytes); + table.unwrap_or(TableIdx(0)).encode(&mut self.bytes); encode_type = true; } } @@ -171,7 +173,7 @@ impl ElementSection { /// memory proposal and can refer to tables with any valid reference type. pub fn active( &mut self, - table_index: Option, + table_index: Option, offset: &ConstExpr, elements: Elements<'_>, ) -> &mut Self { diff --git a/crates/wasm-encoder/src/core/functions.rs b/crates/wasm-encoder/src/core/functions.rs index 063b48953e..b8faf0c78d 100644 --- a/crates/wasm-encoder/src/core/functions.rs +++ b/crates/wasm-encoder/src/core/functions.rs @@ -1,5 +1,6 @@ use crate::{encode_section, Encode, Section, SectionId}; use alloc::vec::Vec; +use wasm_types::TypeIdx; /// An encoder for the function section of WebAssembly modules. /// @@ -7,9 +8,10 @@ use alloc::vec::Vec; /// /// ``` /// use wasm_encoder::{Module, FunctionSection, ValType}; +/// use wasm_types::TypeIdx; /// /// let mut functions = FunctionSection::new(); -/// let type_index = 0; +/// let type_index = TypeIdx(0); /// functions.function(type_index); /// /// let mut module = Module::new(); @@ -44,7 +46,7 @@ impl FunctionSection { } /// Define a function in a module's function section. - pub fn function(&mut self, type_index: u32) -> &mut Self { + pub fn function(&mut self, type_index: TypeIdx) -> &mut Self { type_index.encode(&mut self.bytes); self.num_added += 1; self diff --git a/crates/wasm-encoder/src/core/imports.rs b/crates/wasm-encoder/src/core/imports.rs index 7db71ba4d0..095f1af6b3 100644 --- a/crates/wasm-encoder/src/core/imports.rs +++ b/crates/wasm-encoder/src/core/imports.rs @@ -3,14 +3,14 @@ use crate::{ CORE_FUNCTION_SORT, CORE_GLOBAL_SORT, CORE_MEMORY_SORT, CORE_TABLE_SORT, CORE_TAG_SORT, }; use alloc::vec::Vec; - +use wasm_types::TypeIdx; /// The type of an entity. #[derive(Debug, Clone, Copy, PartialEq, Eq)] pub enum EntityType { /// A function type. /// /// The value is an index into the types section. - Function(u32), + Function(TypeIdx), /// A table type. Table(TableType), /// A memory type. diff --git a/crates/wasm-encoder/src/core/names.rs b/crates/wasm-encoder/src/core/names.rs index b3b96c8189..d95f3e300a 100644 --- a/crates/wasm-encoder/src/core/names.rs +++ b/crates/wasm-encoder/src/core/names.rs @@ -2,6 +2,8 @@ use crate::{encoding_size, CustomSection, Encode, Section, SectionId}; use alloc::borrow::Cow; use alloc::vec; use alloc::vec::Vec; +use index_vec::Idx; +use wasm_types::{DataIdx, ElemIdx, FuncIdx, GlobalIdx, MemIdx, TableIdx, TagIdx, TypeIdx}; /// An encoder for the custom `name` section. /// @@ -9,14 +11,15 @@ use alloc::vec::Vec; /// /// ``` /// use wasm_encoder::{Module, NameSection, NameMap}; +/// use wasm_types::FuncIdx; /// /// let mut names = NameSection::new(); /// names.module("the module name"); /// /// let mut function_names = NameMap::new(); -/// function_names.append(0, "name of function 0"); -/// function_names.append(1, "a better function"); -/// function_names.append(3, "the best function"); +/// function_names.append(FuncIdx(0), "name of function 0"); +/// function_names.append(FuncIdx(1), "a better function"); +/// function_names.append(FuncIdx(3), "the best function"); /// names.functions(&function_names); /// /// let mut module = Module::new(); @@ -76,7 +79,7 @@ impl NameSection { /// in the map corresponds to the wasm index of the function. This section /// should come after the module name subsection (if present) and before the /// locals subsection (if present). - pub fn functions(&mut self, names: &NameMap) { + pub fn functions(&mut self, names: &NameMap) { self.subsection_header(Subsection::Function, names.size()); names.encode(&mut self.bytes); } @@ -86,7 +89,7 @@ impl NameSection { /// /// This section should come after the function name subsection (if present) /// and before the labels subsection (if present). - pub fn locals(&mut self, names: &IndirectNameMap) { + pub fn locals(&mut self, names: &IndirectNameMap) { self.subsection_header(Subsection::Local, names.size()); names.encode(&mut self.bytes); } @@ -96,7 +99,7 @@ impl NameSection { /// /// This section should come after the local name subsection (if present) /// and before the type subsection (if present). - pub fn labels(&mut self, names: &IndirectNameMap) { + pub fn labels(&mut self, names: &IndirectNameMap) { self.subsection_header(Subsection::Label, names.size()); names.encode(&mut self.bytes); } @@ -105,7 +108,7 @@ impl NameSection { /// /// This section should come after the label name subsection (if present) /// and before the table subsection (if present). - pub fn types(&mut self, names: &NameMap) { + pub fn types(&mut self, names: &NameMap) { self.subsection_header(Subsection::Type, names.size()); names.encode(&mut self.bytes); } @@ -114,7 +117,7 @@ impl NameSection { /// /// This section should come after the type name subsection (if present) /// and before the memory subsection (if present). - pub fn tables(&mut self, names: &NameMap) { + pub fn tables(&mut self, names: &NameMap) { self.subsection_header(Subsection::Table, names.size()); names.encode(&mut self.bytes); } @@ -123,7 +126,7 @@ impl NameSection { /// /// This section should come after the table name subsection (if present) /// and before the global subsection (if present). - pub fn memories(&mut self, names: &NameMap) { + pub fn memories(&mut self, names: &NameMap) { self.subsection_header(Subsection::Memory, names.size()); names.encode(&mut self.bytes); } @@ -132,7 +135,7 @@ impl NameSection { /// /// This section should come after the memory name subsection (if present) /// and before the element subsection (if present). - pub fn globals(&mut self, names: &NameMap) { + pub fn globals(&mut self, names: &NameMap) { self.subsection_header(Subsection::Global, names.size()); names.encode(&mut self.bytes); } @@ -141,7 +144,7 @@ impl NameSection { /// /// This section should come after the global name subsection (if present) /// and before the data subsection (if present). - pub fn elements(&mut self, names: &NameMap) { + pub fn elements(&mut self, names: &NameMap) { self.subsection_header(Subsection::Element, names.size()); names.encode(&mut self.bytes); } @@ -150,7 +153,7 @@ impl NameSection { /// /// This section should come after the element name subsection (if present) /// and before the field subsection (if present). - pub fn data(&mut self, names: &NameMap) { + pub fn data(&mut self, names: &NameMap) { self.subsection_header(Subsection::Data, names.size()); names.encode(&mut self.bytes); } @@ -158,7 +161,7 @@ impl NameSection { /// Appends a subsection for the names of all tags in this wasm module. /// /// This section should come after the data name subsection (if present). - pub fn tag(&mut self, names: &NameMap) { + pub fn tag(&mut self, names: &NameMap) { self.subsection_header(Subsection::Tag, names.size()); names.encode(&mut self.bytes); } @@ -168,7 +171,7 @@ impl NameSection { /// /// This section should come after the data name subsection (if present) /// and before the tag subsection (if present). - pub fn fields(&mut self, names: &IndirectNameMap) { + pub fn fields(&mut self, names: &IndirectNameMap) { self.subsection_header(Subsection::Field, names.size()); names.encode(&mut self.bytes); } @@ -176,7 +179,7 @@ impl NameSection { /// Appends a subsection for the names of all tags in this wasm module. /// /// This section should come after the field name subsection (if present). - pub fn tags(&mut self, names: &NameMap) { + pub fn tags(&mut self, names: &NameMap) { self.subsection_header(Subsection::Tag, names.size()); names.encode(&mut self.bytes); } @@ -219,17 +222,17 @@ impl Section for NameSection { /// This is used in conjunction with [`NameSection::functions`] and simlar /// methods. #[derive(Clone, Debug, Default)] -pub struct NameMap { +pub struct NameMap { bytes: Vec, - count: u32, + count: I, } -impl NameMap { +impl NameMap { /// Creates a new empty `NameMap`. - pub fn new() -> NameMap { + pub fn new() -> NameMap { NameMap { bytes: vec![], - count: 0, + count: I::from_usize(0), } } @@ -239,23 +242,23 @@ impl NameMap { /// value. Each index may only be named once, but not all indices must be /// named (e.g. `0 foo; 1 bar; 7 qux` is valid but `0 foo; 0 bar` is not). /// Names do not have to be unique (e.g. `0 foo; 1 foo; 2 foo` is valid). - pub fn append(&mut self, idx: u32, name: &str) { + pub fn append(&mut self, idx: I, name: &str) { idx.encode(&mut self.bytes); name.encode(&mut self.bytes); - self.count += 1; + self.count = I::from_usize(self.count.index() + 1); } pub(crate) fn size(&self) -> usize { - encoding_size(self.count) + self.bytes.len() + encoding_size(self.count.index() as u32) + self.bytes.len() } /// Returns whether no names have been added to this map. pub fn is_empty(&self) -> bool { - self.count == 0 + self.count.index() == 0 } } -impl Encode for NameMap { +impl Encode for NameMap { fn encode(&self, sink: &mut Vec) { self.count.encode(sink); sink.extend(&self.bytes); @@ -267,17 +270,17 @@ impl Encode for NameMap { /// /// This naming map is used with [`NameSection::locals`], for example. #[derive(Clone, Debug, Default)] -pub struct IndirectNameMap { +pub struct IndirectNameMap { bytes: Vec, - count: u32, + count: I, } -impl IndirectNameMap { +impl IndirectNameMap { /// Creates a new empty name map. - pub fn new() -> IndirectNameMap { + pub fn new() -> IndirectNameMap { IndirectNameMap { bytes: vec![], - count: 0, + count: I::from_usize(0), } } @@ -286,18 +289,18 @@ impl IndirectNameMap { /// /// For example if this is describing local names then `idx` is a function /// index where the indexes within `names` are local indices. - pub fn append(&mut self, idx: u32, names: &NameMap) { + pub fn append(&mut self, idx: I, names: &NameMap) { idx.encode(&mut self.bytes); names.encode(&mut self.bytes); - self.count += 1; + self.count = I::from_usize(self.count.index() + 1); } fn size(&self) -> usize { - encoding_size(self.count) + self.bytes.len() + encoding_size(self.count.index() as u32) + self.bytes.len() } } -impl Encode for IndirectNameMap { +impl Encode for IndirectNameMap { fn encode(&self, sink: &mut Vec) { self.count.encode(sink); sink.extend(&self.bytes); diff --git a/crates/wasm-encoder/src/core/start.rs b/crates/wasm-encoder/src/core/start.rs index 22294a1952..791e93f815 100644 --- a/crates/wasm-encoder/src/core/start.rs +++ b/crates/wasm-encoder/src/core/start.rs @@ -1,5 +1,6 @@ use crate::{encoding_size, Encode, Section, SectionId}; use alloc::vec::Vec; +use wasm_types::FuncIdx; /// An encoder for the start section of WebAssembly modules. /// @@ -12,8 +13,9 @@ use alloc::vec::Vec; /// /// ``` /// use wasm_encoder::{Module, StartSection}; +/// use wasm_types::FuncIdx; /// -/// let start = StartSection { function_index: 0 }; +/// let start = StartSection { function_index: FuncIdx(0) }; /// /// let mut module = Module::new(); /// module.section(&start); @@ -23,12 +25,12 @@ use alloc::vec::Vec; #[derive(Clone, Copy, Debug)] pub struct StartSection { /// The index of the start function. - pub function_index: u32, + pub function_index: FuncIdx, } impl Encode for StartSection { fn encode(&self, sink: &mut Vec) { - encoding_size(self.function_index).encode(sink); + encoding_size(self.function_index.0).encode(sink); self.function_index.encode(sink); } } diff --git a/crates/wasm-encoder/src/core/tags.rs b/crates/wasm-encoder/src/core/tags.rs index 008d40ebc2..156cb3c2b2 100644 --- a/crates/wasm-encoder/src/core/tags.rs +++ b/crates/wasm-encoder/src/core/tags.rs @@ -1,17 +1,18 @@ use crate::{encode_section, Encode, Section, SectionId}; use alloc::vec::Vec; - +use wasm_types::TypeIdx; /// An encoder for the tag section. /// /// # Example /// /// ``` /// use wasm_encoder::{Module, TagSection, TagType, TagKind}; +/// use wasm_types::TypeIdx; /// /// let mut tags = TagSection::new(); /// tags.tag(TagType { /// kind: TagKind::Exception, -/// func_type_idx: 0, +/// func_type_idx: TypeIdx(0), /// }); /// /// let mut module = Module::new(); @@ -75,7 +76,7 @@ pub struct TagType { /// The kind of tag pub kind: TagKind, /// The function type this tag uses - pub func_type_idx: u32, + pub func_type_idx: TypeIdx, } impl Encode for TagType { diff --git a/crates/wasm-encoder/src/core/types.rs b/crates/wasm-encoder/src/core/types.rs index e9611849d5..f91bc3bcb0 100644 --- a/crates/wasm-encoder/src/core/types.rs +++ b/crates/wasm-encoder/src/core/types.rs @@ -1,6 +1,7 @@ use crate::{encode_section, Encode, Section, SectionId}; use alloc::boxed::Box; use alloc::vec::Vec; +use wasm_types::TypeIdx; /// Represents a subtype of possible other types in a WebAssembly module. #[derive(Debug, Clone)] @@ -9,7 +10,7 @@ pub struct SubType { pub is_final: bool, /// The list of supertype indexes. As of GC MVP, there can be at most one /// supertype. - pub supertype_idx: Option, + pub supertype_idx: Option, /// The composite type of the subtype. pub composite_type: CompositeType, } @@ -94,7 +95,7 @@ impl StorageType { /// Represents a type of a continuation in a WebAssembly module. #[derive(Debug, Clone, Copy, Eq, PartialEq, Hash)] -pub struct ContType(pub u32); +pub struct ContType(pub TypeIdx); /// The type of a core WebAssembly value. #[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, Ord, PartialOrd)] @@ -361,7 +362,7 @@ pub enum HeapType { }, /// A concrete Wasm-defined type at the given index. - Concrete(u32), + Concrete(TypeIdx), } impl HeapType { @@ -401,7 +402,7 @@ impl Encode for HeapType { } // Note that this is encoded as a signed type rather than unsigned // as it's decoded as an s33 - HeapType::Concrete(i) => i64::from(*i).encode(sink), + HeapType::Concrete(i) => i64::from(i.0).encode(sink), } } } @@ -637,7 +638,7 @@ impl<'a> CoreTypeEncoder<'a> { fn encode_cont(&mut self, ty: &ContType) { self.bytes.push(0x5d); - i64::from(ty.0).encode(self.bytes); + i64::from(ty.0 .0).encode(self.bytes); } /// Define an explicit subtype in this type section. diff --git a/crates/wasm-encoder/src/lib.rs b/crates/wasm-encoder/src/lib.rs index 2d17c3fb29..c5f10c649b 100644 --- a/crates/wasm-encoder/src/lib.rs +++ b/crates/wasm-encoder/src/lib.rs @@ -29,6 +29,7 @@ //! CodeSection, ExportKind, ExportSection, Function, FunctionSection, Instruction, //! Module, TypeSection, ValType, //! }; +//! use wasm_types::{LocalIdx, TypeIdx}; //! //! let mut module = Module::new(); //! @@ -41,7 +42,7 @@ //! //! // Encode the function section. //! let mut functions = FunctionSection::new(); -//! let type_index = 0; +//! let type_index = TypeIdx(0); //! functions.function(type_index); //! module.section(&functions); //! @@ -54,8 +55,8 @@ //! 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::LocalGet(LocalIdx(0))); +//! f.instruction(&Instruction::LocalGet(LocalIdx(1))); //! f.instruction(&Instruction::I32Add); //! f.instruction(&Instruction::End); //! codes.function(&f); @@ -90,6 +91,11 @@ pub use self::core::*; pub use self::raw::*; use alloc::vec::Vec; +use wasm_types::{ + AbsoluteLabelIdx, ComponentFuncIdx, ComponentIdx, ComponentInstanceIdx, ComponentTypeIdx, + ComponentValueIdx, CoreInstanceIdx, CoreModuleIdx, DataIdx, ElemIdx, FieldIdx, FuncIdx, + GlobalIdx, LabelIdx, LocalIdx, MemIdx, TableIdx, TagIdx, TypeIdx, +}; /// Implemented by types that can be encoded into a byte sink. pub trait Encode { @@ -140,6 +146,120 @@ impl Encode for u32 { } } +impl Encode for TypeIdx { + fn encode(&self, sink: &mut Vec) { + self.0.encode(sink); + } +} + +impl Encode for FuncIdx { + fn encode(&self, sink: &mut Vec) { + self.0.encode(sink); + } +} + +impl Encode for TableIdx { + fn encode(&self, sink: &mut Vec) { + self.0.encode(sink); + } +} + +impl Encode for MemIdx { + fn encode(&self, sink: &mut Vec) { + self.0.encode(sink); + } +} + +impl Encode for TagIdx { + fn encode(&self, sink: &mut Vec) { + self.0.encode(sink); + } +} + +impl Encode for GlobalIdx { + fn encode(&self, sink: &mut Vec) { + self.0.encode(sink); + } +} + +impl Encode for ElemIdx { + fn encode(&self, sink: &mut Vec) { + self.0.encode(sink); + } +} + +impl Encode for DataIdx { + fn encode(&self, sink: &mut Vec) { + self.0.encode(sink); + } +} + +impl Encode for LocalIdx { + fn encode(&self, sink: &mut Vec) { + self.0.encode(sink); + } +} + +impl Encode for LabelIdx { + fn encode(&self, sink: &mut Vec) { + self.0.encode(sink); + } +} + +impl Encode for FieldIdx { + fn encode(&self, sink: &mut Vec) { + self.0.encode(sink); + } +} + +impl Encode for AbsoluteLabelIdx { + fn encode(&self, sink: &mut Vec) { + self.0.encode(sink); + } +} + +impl Encode for CoreModuleIdx { + fn encode(&self, sink: &mut Vec) { + self.0.encode(sink); + } +} + +impl Encode for CoreInstanceIdx { + fn encode(&self, sink: &mut Vec) { + self.0.encode(sink); + } +} + +impl Encode for ComponentTypeIdx { + fn encode(&self, sink: &mut Vec) { + self.0.encode(sink); + } +} + +impl Encode for ComponentFuncIdx { + fn encode(&self, sink: &mut Vec) { + self.0.encode(sink); + } +} + +impl Encode for ComponentIdx { + fn encode(&self, sink: &mut Vec) { + self.0.encode(sink); + } +} + +impl Encode for ComponentInstanceIdx { + fn encode(&self, sink: &mut Vec) { + self.0.encode(sink); + } +} + +impl Encode for ComponentValueIdx { + fn encode(&self, sink: &mut Vec) { + self.0.encode(sink); + } +} + impl Encode for i32 { fn encode(&self, sink: &mut Vec) { let (value, pos) = leb128fmt::encode_s32(*self).unwrap(); diff --git a/crates/wasm-encoder/src/reencode.rs b/crates/wasm-encoder/src/reencode.rs index 1d64d8f7be..52cbe3f72a 100644 --- a/crates/wasm-encoder/src/reencode.rs +++ b/crates/wasm-encoder/src/reencode.rs @@ -10,6 +10,7 @@ use std::error::Error as StdError; use crate::CoreTypeEncoder; use core::convert::Infallible; +use wasm_types::{DataIdx, ElemIdx, FuncIdx, GlobalIdx, MemIdx, TableIdx, TagIdx, TypeIdx}; #[cfg(feature = "component-model")] mod component; @@ -21,52 +22,52 @@ pub use self::component::*; pub trait Reencode { type Error; - fn data_index(&mut self, data: u32) -> u32 { + fn data_index(&mut self, data: DataIdx) -> DataIdx { utils::data_index(self, data) } - fn element_index(&mut self, element: u32) -> u32 { + fn element_index(&mut self, element: ElemIdx) -> ElemIdx { utils::element_index(self, element) } - fn function_index(&mut self, func: u32) -> u32 { + fn function_index(&mut self, func: FuncIdx) -> FuncIdx { utils::function_index(self, func) } - fn global_index(&mut self, global: u32) -> u32 { + fn global_index(&mut self, global: GlobalIdx) -> GlobalIdx { utils::global_index(self, global) } - fn memory_index(&mut self, memory: u32) -> u32 { + fn memory_index(&mut self, memory: MemIdx) -> MemIdx { utils::memory_index(self, memory) } - fn table_index(&mut self, table: u32) -> u32 { + fn table_index(&mut self, table: TableIdx) -> TableIdx { utils::table_index(self, table) } - fn tag_index(&mut self, tag: u32) -> u32 { + fn tag_index(&mut self, tag: TagIdx) -> TagIdx { utils::tag_index(self, tag) } - fn type_index(&mut self, ty: u32) -> u32 { + fn type_index(&mut self, ty: TypeIdx) -> TypeIdx { utils::type_index(self, ty) } fn type_index_unpacked( &mut self, ty: wasmparser::UnpackedIndex, - ) -> Result> { + ) -> Result> { utils::type_index_unpacked(self, ty) } fn external_index(&mut self, kind: wasmparser::ExternalKind, index: u32) -> u32 { match kind { - wasmparser::ExternalKind::Func => self.function_index(index), - wasmparser::ExternalKind::Table => self.table_index(index), - wasmparser::ExternalKind::Memory => self.memory_index(index), - wasmparser::ExternalKind::Global => self.global_index(index), - wasmparser::ExternalKind::Tag => self.tag_index(index), + wasmparser::ExternalKind::Func => self.function_index(FuncIdx(index)).0, + wasmparser::ExternalKind::Table => self.table_index(TableIdx(index)).0, + wasmparser::ExternalKind::Memory => self.memory_index(MemIdx(index)).0, + wasmparser::ExternalKind::Global => self.global_index(GlobalIdx(index)).0, + wasmparser::ExternalKind::Tag => self.tag_index(TagIdx(index)).0, } } @@ -516,7 +517,7 @@ pub trait Reencode { count } - fn start_section(&mut self, start: u32) -> u32 { + fn start_section(&mut self, start: FuncIdx) -> FuncIdx { self.function_index(start) } } @@ -610,6 +611,9 @@ pub mod utils { use crate::{CoreTypeEncoder, Encode}; use alloc::vec::Vec; use core::ops::Range; + use index_vec::Idx; + use wasm_types::{DataIdx, ElemIdx, FuncIdx, GlobalIdx, MemIdx, TableIdx, TagIdx, TypeIdx}; + use wasmparser::FromReader; pub fn parse_core_module( reencoder: &mut T, @@ -868,7 +872,7 @@ pub mod utils { Ok(()) } - pub fn memory_index(_reencoder: &mut T, memory: u32) -> u32 { + pub fn memory_index(_reencoder: &mut T, memory: MemIdx) -> MemIdx { memory } @@ -893,11 +897,11 @@ pub mod utils { } } - pub fn function_index(_reencoder: &mut T, func: u32) -> u32 { + pub fn function_index(_reencoder: &mut T, func: FuncIdx) -> FuncIdx { func } - pub fn tag_index(_reencoder: &mut T, tag: u32) -> u32 { + pub fn tag_index(_reencoder: &mut T, tag: TagIdx) -> TagIdx { tag } @@ -996,14 +1000,14 @@ pub mod utils { } } - pub fn type_index(_reencoder: &mut T, ty: u32) -> u32 { + pub fn type_index(_reencoder: &mut T, ty: TypeIdx) -> TypeIdx { ty } pub fn type_index_unpacked( reencoder: &mut T, ty: wasmparser::UnpackedIndex, - ) -> Result> { + ) -> Result> { ty.as_module_index() .map(|ty| reencoder.type_index(ty)) .ok_or(Error::CanonicalizedHeapTypeReference) @@ -1474,8 +1478,11 @@ pub mod utils { // preserve this encoding and keep it at `None`. Otherwise if // the result is nonzero or it was previously nonzero then keep // that encoding too. - match (table_index, reencoder.table_index(table_index.unwrap_or(0))) { - (None, 0) => None, + match ( + table_index, + reencoder.table_index(table_index.unwrap_or(TableIdx(0))), + ) { + (None, TableIdx(0)) => None, (_, n) => Some(n), }, &reencoder.const_expr(offset_expr)?, @@ -1509,19 +1516,19 @@ pub mod utils { }) } - pub fn table_index(_reencoder: &mut T, table: u32) -> u32 { + pub fn table_index(_reencoder: &mut T, table: TableIdx) -> TableIdx { table } - pub fn global_index(_reencoder: &mut T, global: u32) -> u32 { + pub fn global_index(_reencoder: &mut T, global: GlobalIdx) -> GlobalIdx { global } - pub fn data_index(_reencoder: &mut T, data: u32) -> u32 { + pub fn data_index(_reencoder: &mut T, data: DataIdx) -> DataIdx { data } - pub fn element_index(_reencoder: &mut T, element: u32) -> u32 { + pub fn element_index(_reencoder: &mut T, element: ElemIdx) -> ElemIdx { element } @@ -1767,10 +1774,10 @@ pub mod utils { Ok(()) } - pub fn name_map( - map: wasmparser::NameMap<'_>, - mut map_index: impl FnMut(u32) -> u32, - ) -> wasmparser::Result { + pub fn name_map<'a, I: Idx + FromReader<'a> + Encode>( + map: wasmparser::NameMap<'a, I>, + mut map_index: impl FnMut(I) -> I, + ) -> wasmparser::Result> { let mut ret = crate::NameMap::new(); for naming in map { let naming = naming?; @@ -1779,10 +1786,14 @@ pub mod utils { Ok(ret) } - pub fn indirect_name_map( - map: wasmparser::IndirectNameMap<'_>, - mut map_index: impl FnMut(u32) -> u32, - ) -> wasmparser::Result { + pub fn indirect_name_map< + 'a, + I: Idx + FromReader<'a> + Encode, + J: Idx + FromReader<'a> + Encode, + >( + map: wasmparser::IndirectNameMap<'a, I, J>, + mut map_index: impl FnMut(I) -> I, + ) -> wasmparser::Result> { let mut ret = crate::IndirectNameMap::new(); for naming in map { let naming = naming?; diff --git a/crates/wasm-encoder/src/reencode/component.rs b/crates/wasm-encoder/src/reencode/component.rs index 12b08130f6..89156dd03d 100644 --- a/crates/wasm-encoder/src/reencode/component.rs +++ b/crates/wasm-encoder/src/reencode/component.rs @@ -1,52 +1,56 @@ use crate::reencode::{Error, Reencode, RoundtripReencoder}; use alloc::boxed::Box; +use wasm_types::{ + ComponentFuncIdx, ComponentIdx, ComponentInstanceIdx, ComponentTypeIdx, ComponentValueIdx, + CoreInstanceIdx, CoreModuleIdx, TypeIdx, +}; #[allow(missing_docs)] // FIXME pub trait ReencodeComponent: Reencode { - fn component_type_index(&mut self, ty: u32) -> u32 { + fn component_type_index(&mut self, ty: ComponentTypeIdx) -> ComponentTypeIdx { ty } - fn component_instance_index(&mut self, ty: u32) -> u32 { + fn component_instance_index(&mut self, ty: ComponentInstanceIdx) -> ComponentInstanceIdx { ty } - fn component_func_index(&mut self, ty: u32) -> u32 { + fn component_func_index(&mut self, ty: ComponentFuncIdx) -> ComponentFuncIdx { ty } - fn component_index(&mut self, ty: u32) -> u32 { + fn component_index(&mut self, ty: ComponentIdx) -> ComponentIdx { ty } - fn module_index(&mut self, ty: u32) -> u32 { + fn module_index(&mut self, ty: CoreModuleIdx) -> CoreModuleIdx { ty } - fn instance_index(&mut self, ty: u32) -> u32 { + fn instance_index(&mut self, ty: CoreInstanceIdx) -> CoreInstanceIdx { ty } - fn component_value_index(&mut self, ty: u32) -> u32 { + fn component_value_index(&mut self, ty: ComponentValueIdx) -> ComponentValueIdx { ty } - fn outer_type_index(&mut self, count: u32, ty: u32) -> u32 { + fn outer_type_index(&mut self, count: u32, ty: TypeIdx) -> TypeIdx { let _ = count; self.type_index(ty) } - fn outer_component_type_index(&mut self, count: u32, ty: u32) -> u32 { + fn outer_component_type_index(&mut self, count: u32, ty: ComponentTypeIdx) -> ComponentTypeIdx { let _ = count; self.component_type_index(ty) } - fn outer_component_index(&mut self, count: u32, component: u32) -> u32 { + fn outer_component_index(&mut self, count: u32, component: ComponentIdx) -> ComponentIdx { let _ = count; self.component_index(component) } - fn outer_module_index(&mut self, count: u32, module: u32) -> u32 { + fn outer_module_index(&mut self, count: u32, module: CoreModuleIdx) -> CoreModuleIdx { let _ = count; self.module_index(module) } @@ -61,12 +65,22 @@ pub trait ReencodeComponent: Reencode { index: u32, ) -> u32 { match kind { - wasmparser::ComponentExternalKind::Func => self.component_func_index(index), - wasmparser::ComponentExternalKind::Module => self.module_index(index), - wasmparser::ComponentExternalKind::Component => self.component_index(index), - wasmparser::ComponentExternalKind::Type => self.component_type_index(index), - wasmparser::ComponentExternalKind::Instance => self.component_instance_index(index), - wasmparser::ComponentExternalKind::Value => self.component_value_index(index), + wasmparser::ComponentExternalKind::Func => { + self.component_func_index(ComponentFuncIdx(index)).0 + } + wasmparser::ComponentExternalKind::Module => self.module_index(CoreModuleIdx(index)).0, + wasmparser::ComponentExternalKind::Component => { + self.component_index(ComponentIdx(index)).0 + } + wasmparser::ComponentExternalKind::Type => { + self.component_type_index(ComponentTypeIdx(index)).0 + } + wasmparser::ComponentExternalKind::Instance => { + self.component_instance_index(ComponentInstanceIdx(index)).0 + } + wasmparser::ComponentExternalKind::Value => { + self.component_value_index(ComponentValueIdx(index)).0 + } } } @@ -389,6 +403,7 @@ pub mod component_utils { use crate::reencode::Error; use alloc::boxed::Box; use alloc::vec::Vec; + use wasm_types::{ComponentIdx, ComponentTypeIdx, CoreInstanceIdx, CoreModuleIdx, TypeIdx}; pub fn parse_component( reencoder: &mut T, @@ -841,7 +856,7 @@ pub mod component_utils { count, index, } => { - let index = reencoder.outer_type_index(count, index); + let index = reencoder.outer_type_index(count, TypeIdx(index)); module.alias_outer_core_type(count, index); } wasmparser::ModuleTypeDeclaration::Import(import) => { @@ -883,16 +898,20 @@ pub mod component_utils { count, index: match kind { wasmparser::ComponentOuterAliasKind::CoreModule => { - reencoder.outer_module_index(count, index) + reencoder.outer_module_index(count, CoreModuleIdx(index)).0 } wasmparser::ComponentOuterAliasKind::CoreType => { - reencoder.outer_type_index(count, index) + reencoder.outer_type_index(count, TypeIdx(index)).0 } wasmparser::ComponentOuterAliasKind::Type => { - reencoder.outer_component_type_index(count, index) + reencoder + .outer_component_type_index(count, ComponentTypeIdx(index)) + .0 } wasmparser::ComponentOuterAliasKind::Component => { - reencoder.outer_component_index(count, index) + reencoder + .outer_component_index(count, ComponentIdx(index)) + .0 } }, }), @@ -1133,7 +1152,9 @@ pub mod component_utils { args.iter().map(|arg| match arg.kind { wasmparser::InstantiationArgKind::Instance => ( arg.name, - crate::ModuleArg::Instance(reencoder.instance_index(arg.index)), + crate::ModuleArg::Instance( + reencoder.instance_index(CoreInstanceIdx(arg.index)), + ), ), }), ); diff --git a/crates/wasm-metadata/Cargo.toml b/crates/wasm-metadata/Cargo.toml index 11eb0b0752..f46ac82781 100644 --- a/crates/wasm-metadata/Cargo.toml +++ b/crates/wasm-metadata/Cargo.toml @@ -13,6 +13,7 @@ workspace = true [dependencies] anyhow = { workspace = true } clap = { workspace = true, optional = true } +index_vec = { workspace = true } indexmap = { workspace = true, features = ["serde"] } serde = { workspace = true } serde_derive = { workspace = true } diff --git a/crates/wasm-metadata/src/utils.rs b/crates/wasm-metadata/src/utils.rs index b002571b5c..e745b47a76 100644 --- a/crates/wasm-metadata/src/utils.rs +++ b/crates/wasm-metadata/src/utils.rs @@ -1,6 +1,11 @@ use anyhow::Result; +use index_vec::Idx; +use wasm_encoder::Encode; +use wasmparser::FromReader; -pub(crate) fn name_map(map: &wasmparser::NameMap<'_>) -> Result { +pub(crate) fn name_map<'a, I: Idx + FromReader<'a> + Encode>( + map: &wasmparser::NameMap<'a, I>, +) -> Result> { let mut out = wasm_encoder::NameMap::new(); for m in map.clone().into_iter() { let m = m?; @@ -9,9 +14,13 @@ pub(crate) fn name_map(map: &wasmparser::NameMap<'_>) -> Result, -) -> Result { +pub(crate) fn indirect_name_map< + 'a, + I: Idx + FromReader<'a> + Encode, + J: Idx + FromReader<'a> + Encode, +>( + map: &wasmparser::IndirectNameMap<'a, I, J>, +) -> Result> { let mut out = wasm_encoder::IndirectNameMap::new(); for m in map.clone().into_iter() { let m = m?; diff --git a/crates/wasm-mutate/Cargo.toml b/crates/wasm-mutate/Cargo.toml index 74ab4739cd..96a5bf896c 100644 --- a/crates/wasm-mutate/Cargo.toml +++ b/crates/wasm-mutate/Cargo.toml @@ -13,10 +13,12 @@ workspace = true [dependencies] clap = { workspace = true, optional = true } egg = "0.6.0" +index_vec = { workspace = true } log = { workspace = true } rand = { workspace = true } thiserror = "1.0.28" wasm-encoder = { workspace = true, features = ['std', 'wasmparser'] } +wasm-types = { workspace = true } wasmparser = { workspace = true, features = ['std', 'simd'] } [dev-dependencies] diff --git a/crates/wasm-mutate/src/info.rs b/crates/wasm-mutate/src/info.rs index 5126db058c..100a97661a 100644 --- a/crates/wasm-mutate/src/info.rs +++ b/crates/wasm-mutate/src/info.rs @@ -2,9 +2,11 @@ use crate::{ module::{PrimitiveTypeInfo, TypeInfo}, Error, Result, }; +use index_vec::IndexVec; use std::collections::HashSet; use std::ops::Range; use wasm_encoder::{RawSection, SectionId}; +use wasm_types::{FuncIdx, TypeIdx}; use wasmparser::{BinaryReader, Chunk, Parser, Payload}; /// Provides module information for future usage during mutation @@ -32,7 +34,7 @@ pub struct ModuleInfo<'a> { pub exports_count: u32, elements_count: u32, data_segments_count: u32, - start_function: Option, + start_function: Option, memory_count: u32, table_count: u32, tag_count: u32, @@ -44,10 +46,10 @@ pub struct ModuleInfo<'a> { imported_tags_count: u32, // types for inner functions - pub types_map: Vec, + pub types_map: IndexVec, // function idx to type idx - pub function_map: Vec, + pub function_map: IndexVec, pub global_types: Vec, pub table_types: Vec, pub memory_types: Vec, @@ -262,8 +264,8 @@ impl<'a> ModuleInfo<'a> { /// Returns the function type based on the index of the function type /// `types[functions[idx]]` - pub fn get_functype_idx(&self, idx: u32) -> &TypeInfo { - let functpeindex = self.function_map[idx as usize] as usize; + pub fn get_functype_idx(&self, idx: FuncIdx) -> &TypeInfo { + let functpeindex = self.function_map[idx]; &self.types_map[functpeindex] } diff --git a/crates/wasm-mutate/src/mutators/remove_item.rs b/crates/wasm-mutate/src/mutators/remove_item.rs index 9a2246c143..ec776b8e6b 100644 --- a/crates/wasm-mutate/src/mutators/remove_item.rs +++ b/crates/wasm-mutate/src/mutators/remove_item.rs @@ -14,6 +14,7 @@ use rand::Rng; use std::collections::HashSet; use wasm_encoder::reencode::Reencode; use wasm_encoder::*; +use wasm_types::FuncIdx; /// Mutator that removes a random item in a wasm module (function, global, /// table, etc). @@ -100,7 +101,7 @@ struct RemoveItem<'a> { item: Item, idx: u32, function_reference_action: Funcref, - referenced_functions: HashSet, + referenced_functions: HashSet, used_index_that_was_removed: bool, } diff --git a/crates/wasm-smith/Cargo.toml b/crates/wasm-smith/Cargo.toml index d94573cda6..69bd9534b4 100644 --- a/crates/wasm-smith/Cargo.toml +++ b/crates/wasm-smith/Cargo.toml @@ -27,9 +27,11 @@ anyhow = { workspace = true } arbitrary = { workspace = true, features = ["derive"] } clap = { workspace = true, optional = true } flagset = "0.4" +index_vec = { workspace = true } serde = { workspace = true, optional = true } serde_derive = { workspace = true, optional = true } wasm-encoder = { workspace = true, features = ['std'] } +wasm-types = { workspace = true } wasmparser = { workspace = true, optional = true, features = ['std', 'validate', 'features', 'simd'] } wat = { workspace = true, optional = true } diff --git a/crates/wasm-smith/src/core.rs b/crates/wasm-smith/src/core.rs index 1e01785e8b..9319788135 100644 --- a/crates/wasm-smith/src/core.rs +++ b/crates/wasm-smith/src/core.rs @@ -8,6 +8,7 @@ use crate::{arbitrary_loop, limited_string, unique_string, Config}; use arbitrary::{Arbitrary, Result, Unstructured}; use code_builder::CodeBuilderAllocations; use flagset::{flags, FlagSet}; +use index_vec::IndexVec; use std::collections::{HashMap, HashSet}; use std::fmt; use std::mem; @@ -19,6 +20,7 @@ use wasm_encoder::{ StorageType, StructType, ValType, }; pub(crate) use wasm_encoder::{GlobalType, MemoryType, TableType}; +use wasm_types::TypeIdx; // NB: these constants are used to control the rate at which various events // occur. For more information see where these constants are used. Their values @@ -50,7 +52,7 @@ pub struct Module { /// All types locally defined in this module (available in the type index /// space). - types: Vec, + types: IndexVec, /// Non-overlapping ranges within `types` that belong to the same rec /// group. All of `types` is covered by these ranges. When GC is not @@ -2637,7 +2639,7 @@ impl Module { fn is_shared_ref_type(&self, ty: RefType) -> bool { match ty.heap_type { HeapType::Abstract { shared, .. } => shared, - HeapType::Concrete(i) => self.types[i as usize].composite_type.shared, + HeapType::Concrete(i) => self.types[i].composite_type.shared, } } diff --git a/crates/wasm-types/Cargo.toml b/crates/wasm-types/Cargo.toml new file mode 100644 index 0000000000..fb89495a6c --- /dev/null +++ b/crates/wasm-types/Cargo.toml @@ -0,0 +1,17 @@ +[package] +name = "wasm-types" +version.workspace = true +edition.workspace = true +rust-version.workspace = true +description = """ +Basic WebAssembly types. +""" +homepage = "https://github.com/bytecodealliance/wasm-tools/tree/main/crates/wasm-types" +repository = "https://github.com/bytecodealliance/wasm-tools/tree/main/crates/wasm-types" +license.workspace = true + +[lints] +workspace = true + +[dependencies] +index_vec.workspace = true diff --git a/crates/wasm-types/README.md b/crates/wasm-types/README.md new file mode 100644 index 0000000000..09df806617 --- /dev/null +++ b/crates/wasm-types/README.md @@ -0,0 +1,12 @@ +# `wasm-types` + +**A [Bytecode Alliance](https://bytecodealliance.org/) project** + +[![crates.io link](https://img.shields.io/crates/v/wasm-types.svg)](https://crates.io/crates/wasm-types) +[![docs.rs docs](https://img.shields.io/static/v1?label=docs&message=wasm-types&color=blue&style=flat-square)](https://docs.rs/wasm-types/) + +Basic WebAssembly types. + +## Documentation + +Documentation and examples can be found at https://docs.rs/wasm-types/ diff --git a/crates/wasm-types/src/lib.rs b/crates/wasm-types/src/lib.rs new file mode 100644 index 0000000000..a3dc2dae13 --- /dev/null +++ b/crates/wasm-types/src/lib.rs @@ -0,0 +1,129 @@ +//! Basic WebAssembly types. +//! +//! These are simple types, mostly from the WebAssembly spec, that can be shared across different +//! crates like `wasmparser`, `wasmprinter`, and `wasm-encoder`. + +use core::fmt; +use index_vec::Idx; + +/// A Wasm _typeidx_. +#[derive(Clone, Copy, Debug, Default, Eq, Hash, Ord, PartialEq, PartialOrd)] +pub struct TypeIdx(pub u32); + +/// A Wasm _funcidx_. +#[derive(Clone, Copy, Debug, Default, Eq, Hash, Ord, PartialEq, PartialOrd)] +pub struct FuncIdx(pub u32); + +/// A Wasm _tableidx_. +#[derive(Clone, Copy, Debug, Default, Eq, Hash, Ord, PartialEq, PartialOrd)] +pub struct TableIdx(pub u32); + +/// A Wasm _memidx_. +#[derive(Clone, Copy, Debug, Default, Eq, Hash, Ord, PartialEq, PartialOrd)] +pub struct MemIdx(pub u32); + +/// A Wasm _tagidx_. +#[derive(Clone, Copy, Debug, Default, Eq, Hash, Ord, PartialEq, PartialOrd)] +pub struct TagIdx(pub u32); + +/// A Wasm _globalidx_. +#[derive(Clone, Copy, Debug, Default, Eq, Hash, Ord, PartialEq, PartialOrd)] +pub struct GlobalIdx(pub u32); + +/// A Wasm _elemidx_. +#[derive(Clone, Copy, Debug, Default, Eq, Hash, Ord, PartialEq, PartialOrd)] +pub struct ElemIdx(pub u32); + +/// A Wasm _dataidx_. +#[derive(Clone, Copy, Debug, Default, Eq, Hash, Ord, PartialEq, PartialOrd)] +pub struct DataIdx(pub u32); + +/// A Wasm _localidx_. +#[derive(Clone, Copy, Debug, Default, Eq, Hash, Ord, PartialEq, PartialOrd)] +pub struct LocalIdx(pub u32); + +/// A Wasm _labelidx_. +#[derive(Clone, Copy, Debug, Default, Eq, Hash, Ord, PartialEq, PartialOrd)] +pub struct LabelIdx(pub u32); + +/// A Wasm _fieldidx_. +#[derive(Clone, Copy, Debug, Default, Eq, Hash, Ord, PartialEq, PartialOrd)] +pub struct FieldIdx(pub u32); + +/// An absolute label index within a Wasm function. +#[derive(Clone, Copy, Debug, Default, Eq, Hash, Ord, PartialEq, PartialOrd)] +pub struct AbsoluteLabelIdx(pub u32); + +/// A Wasm core module index. +#[derive(Clone, Copy, Debug, Default, Eq, Hash, Ord, PartialEq, PartialOrd)] +pub struct CoreModuleIdx(pub u32); + +/// A Wasm core instance index. +#[derive(Clone, Copy, Debug, Default, Eq, Hash, Ord, PartialEq, PartialOrd)] +pub struct CoreInstanceIdx(pub u32); + +/// A Wasm component type index. +#[derive(Clone, Copy, Debug, Default, Eq, Hash, Ord, PartialEq, PartialOrd)] +pub struct ComponentTypeIdx(pub u32); + +/// A Wasm component function index. +#[derive(Clone, Copy, Debug, Default, Eq, Hash, Ord, PartialEq, PartialOrd)] +pub struct ComponentFuncIdx(pub u32); + +/// A Wasm component index. +#[derive(Clone, Copy, Debug, Default, Eq, Hash, Ord, PartialEq, PartialOrd)] +pub struct ComponentIdx(pub u32); + +/// A Wasm component instance index. +#[derive(Clone, Copy, Debug, Default, Eq, Hash, Ord, PartialEq, PartialOrd)] +pub struct ComponentInstanceIdx(pub u32); + +/// A Wasm component value index. +#[derive(Clone, Copy, Debug, Default, Eq, Hash, Ord, PartialEq, PartialOrd)] +pub struct ComponentValueIdx(pub u32); + +macro_rules! idx_impls { + ($name:ident) => { + impl AsMut for $name { + fn as_mut(&mut self) -> &mut u32 { + &mut self.0 + } + } + + impl fmt::Display for $name { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + write!(f, "{}", self.0) + } + } + + impl Idx for $name { + fn from_usize(idx: usize) -> Self { + Self(idx.try_into().unwrap()) + } + + fn index(self) -> usize { + self.0 as usize + } + } + }; +} + +idx_impls!(TypeIdx); +idx_impls!(FuncIdx); +idx_impls!(TableIdx); +idx_impls!(MemIdx); +idx_impls!(TagIdx); +idx_impls!(GlobalIdx); +idx_impls!(ElemIdx); +idx_impls!(DataIdx); +idx_impls!(LocalIdx); +idx_impls!(LabelIdx); +idx_impls!(FieldIdx); +idx_impls!(AbsoluteLabelIdx); +idx_impls!(CoreModuleIdx); +idx_impls!(CoreInstanceIdx); +idx_impls!(ComponentTypeIdx); +idx_impls!(ComponentFuncIdx); +idx_impls!(ComponentIdx); +idx_impls!(ComponentInstanceIdx); +idx_impls!(ComponentValueIdx); diff --git a/crates/wasmparser/Cargo.toml b/crates/wasmparser/Cargo.toml index 275b6e2878..09babb7567 100644 --- a/crates/wasmparser/Cargo.toml +++ b/crates/wasmparser/Cargo.toml @@ -22,9 +22,11 @@ all-features = true [dependencies] bitflags = "2.4.1" hashbrown = { workspace = true, optional = true } +index_vec = { workspace = true } indexmap = { workspace = true, optional = true } semver = { workspace = true, optional = true } serde = { workspace = true, optional = true } +wasm-types = { workspace = true } [dev-dependencies] anyhow = { workspace = true } diff --git a/crates/wasmparser/src/arity.rs b/crates/wasmparser/src/arity.rs index 9f60d86ced..308081834e 100644 --- a/crates/wasmparser/src/arity.rs +++ b/crates/wasmparser/src/arity.rs @@ -17,6 +17,7 @@ use crate::{ BinaryReader, BinaryReaderError, BlockType, CompositeInnerType, ContType, FrameKind, FuncType, Operator, RefType, Result, SubType, }; +use wasm_types::{FuncIdx, LabelIdx, TagIdx, TypeIdx}; /// To compute the arity (param and result counts) of "variable-arity" /// operators, the operator_arity macro needs information about the @@ -24,13 +25,13 @@ use crate::{ /// trait exposes this information. pub trait ModuleArity { /// Type with given index - fn sub_type_at(&self, type_idx: u32) -> Option<&SubType>; + fn sub_type_at(&self, type_idx: TypeIdx) -> Option<&SubType>; /// Arity (param and result counts) of tag with given index - fn tag_type_arity(&self, at: u32) -> Option<(u32, u32)>; + fn tag_type_arity(&self, at: TagIdx) -> Option<(u32, u32)>; /// Type index of function with given index - fn type_index_of_function(&self, function_idx: u32) -> Option; + fn type_index_of_function(&self, function_idx: FuncIdx) -> Option; /// Function type for a given continuation type fn func_type_of_cont_type(&self, c: &ContType) -> Option<&FuncType>; @@ -42,7 +43,7 @@ pub trait ModuleArity { fn control_stack_height(&self) -> u32; /// BlockType and FrameKind of label with given index - fn label_block(&self, depth: u32) -> Option<(BlockType, FrameKind)>; + fn label_block(&self, depth: LabelIdx) -> Option<(BlockType, FrameKind)>; /// Computes arity of given SubType fn sub_type_arity(&self, t: &SubType) -> Option<(u32, u32)> { @@ -169,7 +170,7 @@ macro_rules! operator_arity { (count $self:ident { $($_:ident: $__:ty),* } ret) => {{ let (ty, _) = $self.control_stack_height().checked_sub(1) - .and_then(|x| $self.label_block(x))?; + .and_then(|x| $self.label_block(LabelIdx(x)))?; $self.block_type_arity(ty) }}; @@ -179,7 +180,7 @@ macro_rules! operator_arity { }}; (count $self:ident {} implicit_else) => {{ - let (ty, kind) = $self.label_block(0)?; + let (ty, kind) = $self.label_block(LabelIdx(0))?; let (params, results) = $self.block_type_arity(ty)?; Some(match kind { FrameKind::If => (results, params), @@ -188,7 +189,7 @@ macro_rules! operator_arity { }}; (count $self:ident { $($_: ident: $__:ty),* } end) => {{ - let (ty, _) = $self.label_block(0)?; + let (ty, _) = $self.label_block(LabelIdx(0))?; $self.block_type_arity(ty) }}; @@ -199,8 +200,8 @@ macro_rules! operator_arity { (count $self:ident { $br_table:ident: $($_:tt)* } br_table) => {{ operator_arity!(br_table $br_table); - let relative_depth: u32 = $br_table.default(); - operator_arity!(count $self { relative_depth: u32 } br) + let relative_depth: LabelIdx = $br_table.default(); + operator_arity!(count $self { relative_depth: LabelIdx } br) }}; (tag_index tag_index $($_:tt)*) => {}; diff --git a/crates/wasmparser/src/binary_reader.rs b/crates/wasmparser/src/binary_reader.rs index 050a967f14..5f8fa4161c 100644 --- a/crates/wasmparser/src/binary_reader.rs +++ b/crates/wasmparser/src/binary_reader.rs @@ -22,6 +22,11 @@ use core::fmt; use core::marker; use core::ops::Range; use core::str; +use wasm_types::{ + AbsoluteLabelIdx, ComponentFuncIdx, ComponentIdx, ComponentInstanceIdx, ComponentTypeIdx, + ComponentValueIdx, CoreInstanceIdx, CoreModuleIdx, DataIdx, ElemIdx, FieldIdx, FuncIdx, + GlobalIdx, LabelIdx, LocalIdx, MemIdx, TableIdx, TagIdx, TypeIdx, +}; pub(crate) const WASM_MAGIC_NUMBER: &[u8; 4] = b"\0asm"; @@ -352,12 +357,12 @@ impl<'a> BinaryReader<'a> { let flags_pos = self.original_position(); let mut flags = self.read_var_u32()?; - let memory = if self.multi_memory() && flags & (1 << 6) != 0 { + let memory = MemIdx(if self.multi_memory() && flags & (1 << 6) != 0 { flags ^= 1 << 6; self.read_var_u32()? } else { 0 - }; + }); let align = if flags >= (1 << 6) { return Err(BinaryReaderError::new( "malformed memop alignment: alignment too large", @@ -399,7 +404,7 @@ impl<'a> BinaryReader<'a> { } Ok(()) })?; - let default = self.read_var_u32()?; + let default = self.read_labelidx()?; Ok(BrTable { reader, cnt: cnt as u32, @@ -513,6 +518,229 @@ impl<'a> BinaryReader<'a> { } } + /// Advances the `BinaryReader` up to four bytes to parse a variable + /// length integer as a _typeidx_. + /// + /// # Errors + /// + /// If `BinaryReader` has less than one or up to four bytes remaining, or + /// the integer is larger than 32 bits. + #[inline] + pub fn read_typeidx(&mut self) -> Result { + Ok(TypeIdx(self.read_var_u32()?)) + } + + /// Advances the `BinaryReader` up to four bytes to parse a variable + /// length integer as a _funcidx_. + /// + /// # Errors + /// + /// If `BinaryReader` has less than one or up to four bytes remaining, or + /// the integer is larger than 32 bits. + #[inline] + pub fn read_funcidx(&mut self) -> Result { + Ok(FuncIdx(self.read_var_u32()?)) + } + + /// Advances the `BinaryReader` up to four bytes to parse a variable + /// length integer as a _tableidx_. + /// + /// # Errors + /// + /// If `BinaryReader` has less than one or up to four bytes remaining, or + /// the integer is larger than 32 bits. + #[inline] + pub fn read_tableidx(&mut self) -> Result { + Ok(TableIdx(self.read_var_u32()?)) + } + + /// Advances the `BinaryReader` up to four bytes to parse a variable + /// length integer as a _memidx_. + /// + /// # Errors + /// + /// If `BinaryReader` has less than one or up to four bytes remaining, or + /// the integer is larger than 32 bits. + #[inline] + pub fn read_memidx(&mut self) -> Result { + Ok(MemIdx(self.read_var_u32()?)) + } + + /// Advances the `BinaryReader` up to four bytes to parse a variable + /// length integer as a _tagidx_. + /// + /// # Errors + /// + /// If `BinaryReader` has less than one or up to four bytes remaining, or + /// the integer is larger than 32 bits. + #[inline] + pub fn read_tagidx(&mut self) -> Result { + Ok(TagIdx(self.read_var_u32()?)) + } + + /// Advances the `BinaryReader` up to four bytes to parse a variable + /// length integer as a _globalidx_. + /// + /// # Errors + /// + /// If `BinaryReader` has less than one or up to four bytes remaining, or + /// the integer is larger than 32 bits. + #[inline] + pub fn read_globalidx(&mut self) -> Result { + Ok(GlobalIdx(self.read_var_u32()?)) + } + + /// Advances the `BinaryReader` up to four bytes to parse a variable + /// length integer as a _elemidx_. + /// + /// # Errors + /// + /// If `BinaryReader` has less than one or up to four bytes remaining, or + /// the integer is larger than 32 bits. + #[inline] + pub fn read_elemidx(&mut self) -> Result { + Ok(ElemIdx(self.read_var_u32()?)) + } + + /// Advances the `BinaryReader` up to four bytes to parse a variable + /// length integer as a _dataidx_. + /// + /// # Errors + /// + /// If `BinaryReader` has less than one or up to four bytes remaining, or + /// the integer is larger than 32 bits. + #[inline] + pub fn read_dataidx(&mut self) -> Result { + Ok(DataIdx(self.read_var_u32()?)) + } + + /// Advances the `BinaryReader` up to four bytes to parse a variable + /// length integer as a _localidx_. + /// + /// # Errors + /// + /// If `BinaryReader` has less than one or up to four bytes remaining, or + /// the integer is larger than 32 bits. + #[inline] + pub fn read_localidx(&mut self) -> Result { + Ok(LocalIdx(self.read_var_u32()?)) + } + + /// Advances the `BinaryReader` up to four bytes to parse a variable + /// length integer as a _labelidx_. + /// + /// # Errors + /// + /// If `BinaryReader` has less than one or up to four bytes remaining, or + /// the integer is larger than 32 bits. + #[inline] + pub fn read_labelidx(&mut self) -> Result { + Ok(LabelIdx(self.read_var_u32()?)) + } + + /// Advances the `BinaryReader` up to four bytes to parse a variable + /// length integer as a _fieldidx_. + /// + /// # Errors + /// + /// If `BinaryReader` has less than one or up to four bytes remaining, or + /// the integer is larger than 32 bits. + #[inline] + pub fn read_fieldidx(&mut self) -> Result { + Ok(FieldIdx(self.read_var_u32()?)) + } + + /// Advances the `BinaryReader` up to four bytes to parse a variable + /// length integer as an absolute label index. + /// + /// # Errors + /// + /// If `BinaryReader` has less than one or up to four bytes remaining, or + /// the integer is larger than 32 bits. + #[inline] + pub fn read_absolute_label_idx(&mut self) -> Result { + Ok(AbsoluteLabelIdx(self.read_var_u32()?)) + } + + /// Advances the `BinaryReader` up to four bytes to parse a variable + /// length integer as a core module index. + /// + /// # Errors + /// + /// If `BinaryReader` has less than one or up to four bytes remaining, or + /// the integer is larger than 32 bits. + #[inline] + pub fn read_core_module_idx(&mut self) -> Result { + Ok(CoreModuleIdx(self.read_var_u32()?)) + } + + /// Advances the `BinaryReader` up to four bytes to parse a variable + /// length integer as a core instance index. + /// + /// # Errors + /// + /// If `BinaryReader` has less than one or up to four bytes remaining, or + /// the integer is larger than 32 bits. + #[inline] + pub fn read_core_instance_idx(&mut self) -> Result { + Ok(CoreInstanceIdx(self.read_var_u32()?)) + } + + /// Advances the `BinaryReader` up to four bytes to parse a variable + /// length integer as a component type index. + /// + /// # Errors + /// + /// If `BinaryReader` has less than one or up to four bytes remaining, or + #[inline] + pub fn read_component_type_idx(&mut self) -> Result { + Ok(ComponentTypeIdx(self.read_var_u32()?)) + } + + /// Advances the `BinaryReader` up to four bytes to parse a variable + /// length integer as a component function index. + /// + /// # Errors + /// + /// If `BinaryReader` has less than one or up to four bytes remaining, or + #[inline] + pub fn read_component_func_idx(&mut self) -> Result { + Ok(ComponentFuncIdx(self.read_var_u32()?)) + } + + /// Advances the `BinaryReader` up to four bytes to parse a variable + /// length integer as a component index. + /// + /// # Errors + /// + /// If `BinaryReader` has less than one or up to four bytes remaining, or + #[inline] + pub fn read_component_idx(&mut self) -> Result { + Ok(ComponentIdx(self.read_var_u32()?)) + } + + /// Advances the `BinaryReader` up to four bytes to parse a variable + /// length integer as a component instance index. + /// + /// # Errors + /// + /// If `BinaryReader` has less than one or up to four bytes remaining, or + #[inline] + pub fn read_component_instance_idx(&mut self) -> Result { + Ok(ComponentInstanceIdx(self.read_var_u32()?)) + } + + /// Advances the `BinaryReader` up to four bytes to parse a variable + /// length integer as a component value index. + /// + /// # Errors + /// + /// If `BinaryReader` has less than one or up to four bytes remaining, or + #[inline] + pub fn read_component_value_idx(&mut self) -> Result { + Ok(ComponentValueIdx(self.read_var_u32()?)) + } + fn read_var_u32_big(&mut self, byte: u8) -> Result { let mut result = (byte & 0x7F) as u32; let mut shift = 7; @@ -828,7 +1056,7 @@ impl<'a> BinaryReader<'a> { // Not empty or a singular type, so read the function type index let idx = self.read_var_s33()?; match u32::try_from(idx) { - Ok(idx) => Ok(BlockType::FuncType(idx)), + Ok(idx) => Ok(BlockType::FuncType(TypeIdx(idx))), Err(_) => { return Err(BinaryReaderError::new( "invalid function type", @@ -897,26 +1125,26 @@ impl<'a> BinaryReader<'a> { 0x04 => visitor.visit_if(self.read_block_type()?), 0x05 => visitor.visit_else(), 0x06 => visitor.visit_try(self.read_block_type()?), - 0x07 => visitor.visit_catch(self.read_var_u32()?), - 0x08 => visitor.visit_throw(self.read_var_u32()?), - 0x09 => visitor.visit_rethrow(self.read_var_u32()?), + 0x07 => visitor.visit_catch(self.read_tagidx()?), + 0x08 => visitor.visit_throw(self.read_tagidx()?), + 0x09 => visitor.visit_rethrow(self.read_labelidx()?), 0x0a => visitor.visit_throw_ref(), 0x0b => visitor.visit_end(), - 0x0c => visitor.visit_br(self.read_var_u32()?), - 0x0d => visitor.visit_br_if(self.read_var_u32()?), + 0x0c => visitor.visit_br(self.read_labelidx()?), + 0x0d => visitor.visit_br_if(self.read_labelidx()?), 0x0e => visitor.visit_br_table(self.read_br_table()?), 0x0f => visitor.visit_return(), - 0x10 => visitor.visit_call(self.read_var_u32()?), + 0x10 => visitor.visit_call(self.read_funcidx()?), 0x11 => { - let index = self.read_var_u32()?; + let index = self.read_typeidx()?; let table = self.read_table_index_or_zero_if_not_reference_types()?; visitor.visit_call_indirect(index, table) } - 0x12 => visitor.visit_return_call(self.read_var_u32()?), - 0x13 => visitor.visit_return_call_indirect(self.read_var_u32()?, self.read_var_u32()?), + 0x12 => visitor.visit_return_call(self.read_funcidx()?), + 0x13 => visitor.visit_return_call_indirect(self.read_typeidx()?, self.read_tableidx()?), 0x14 => visitor.visit_call_ref(self.read()?), 0x15 => visitor.visit_return_call_ref(self.read()?), - 0x18 => visitor.visit_delegate(self.read_var_u32()?), + 0x18 => visitor.visit_delegate(self.read_labelidx()?), 0x19 => visitor.visit_catch_all(), 0x1a => visitor.visit_drop(), 0x1b => visitor.visit_select(), @@ -932,13 +1160,13 @@ impl<'a> BinaryReader<'a> { } 0x1f => visitor.visit_try_table(self.read()?), - 0x20 => visitor.visit_local_get(self.read_var_u32()?), - 0x21 => visitor.visit_local_set(self.read_var_u32()?), - 0x22 => visitor.visit_local_tee(self.read_var_u32()?), - 0x23 => visitor.visit_global_get(self.read_var_u32()?), - 0x24 => visitor.visit_global_set(self.read_var_u32()?), - 0x25 => visitor.visit_table_get(self.read_var_u32()?), - 0x26 => visitor.visit_table_set(self.read_var_u32()?), + 0x20 => visitor.visit_local_get(self.read_localidx()?), + 0x21 => visitor.visit_local_set(self.read_localidx()?), + 0x22 => visitor.visit_local_tee(self.read_localidx()?), + 0x23 => visitor.visit_global_get(self.read_globalidx()?), + 0x24 => visitor.visit_global_set(self.read_globalidx()?), + 0x25 => visitor.visit_table_get(self.read_tableidx()?), + 0x26 => visitor.visit_table_set(self.read_tableidx()?), 0x28 => visitor.visit_i32_load(self.read_memarg(2)?), 0x29 => visitor.visit_i64_load(self.read_memarg(3)?), @@ -1109,20 +1337,20 @@ impl<'a> BinaryReader<'a> { 0xd0 => visitor.visit_ref_null(self.read()?), 0xd1 => visitor.visit_ref_is_null(), - 0xd2 => visitor.visit_ref_func(self.read_var_u32()?), + 0xd2 => visitor.visit_ref_func(self.read_funcidx()?), 0xd3 => visitor.visit_ref_eq(), 0xd4 => visitor.visit_ref_as_non_null(), - 0xd5 => visitor.visit_br_on_null(self.read_var_u32()?), - 0xd6 => visitor.visit_br_on_non_null(self.read_var_u32()?), + 0xd5 => visitor.visit_br_on_null(self.read_labelidx()?), + 0xd6 => visitor.visit_br_on_non_null(self.read_labelidx()?), - 0xe0 => visitor.visit_cont_new(self.read_var_u32()?), - 0xe1 => visitor.visit_cont_bind(self.read_var_u32()?, self.read_var_u32()?), - 0xe2 => visitor.visit_suspend(self.read_var_u32()?), - 0xe3 => visitor.visit_resume(self.read_var_u32()?, self.read()?), + 0xe0 => visitor.visit_cont_new(self.read_typeidx()?), + 0xe1 => visitor.visit_cont_bind(self.read_typeidx()?, self.read_typeidx()?), + 0xe2 => visitor.visit_suspend(self.read_tagidx()?), + 0xe3 => visitor.visit_resume(self.read_typeidx()?, self.read()?), 0xe4 => { - visitor.visit_resume_throw(self.read_var_u32()?, self.read_var_u32()?, self.read()?) + visitor.visit_resume_throw(self.read_typeidx()?, self.read_tagidx()?, self.read()?) } - 0xe5 => visitor.visit_switch(self.read_var_u32()?, self.read_var_u32()?), + 0xe5 => visitor.visit_switch(self.read_typeidx()?, self.read_tagidx()?), 0xfb => self.visit_0xfb_operator(pos, visitor)?, 0xfc => self.visit_0xfc_operator(pos, visitor)?, @@ -1150,90 +1378,90 @@ impl<'a> BinaryReader<'a> { let code = self.read_var_u32()?; Ok(match code { 0x0 => { - let type_index = self.read_var_u32()?; + let type_index = self.read_typeidx()?; visitor.visit_struct_new(type_index) } 0x01 => { - let type_index = self.read_var_u32()?; + let type_index = self.read_typeidx()?; visitor.visit_struct_new_default(type_index) } 0x02 => { - let type_index = self.read_var_u32()?; - let field_index = self.read_var_u32()?; + let type_index = self.read_typeidx()?; + let field_index = self.read_fieldidx()?; visitor.visit_struct_get(type_index, field_index) } 0x03 => { - let type_index = self.read_var_u32()?; - let field_index = self.read_var_u32()?; + let type_index = self.read_typeidx()?; + let field_index = self.read_fieldidx()?; visitor.visit_struct_get_s(type_index, field_index) } 0x04 => { - let type_index = self.read_var_u32()?; - let field_index = self.read_var_u32()?; + let type_index = self.read_typeidx()?; + let field_index = self.read_fieldidx()?; visitor.visit_struct_get_u(type_index, field_index) } 0x05 => { - let type_index = self.read_var_u32()?; - let field_index = self.read_var_u32()?; + let type_index = self.read_typeidx()?; + let field_index = self.read_fieldidx()?; visitor.visit_struct_set(type_index, field_index) } 0x06 => { - let type_index = self.read_var_u32()?; + let type_index = self.read_typeidx()?; visitor.visit_array_new(type_index) } 0x07 => { - let type_index = self.read_var_u32()?; + let type_index = self.read_typeidx()?; visitor.visit_array_new_default(type_index) } 0x08 => { - let type_index = self.read_var_u32()?; + let type_index = self.read_typeidx()?; let n = self.read_var_u32()?; visitor.visit_array_new_fixed(type_index, n) } 0x09 => { - let type_index = self.read_var_u32()?; - let data_index = self.read_var_u32()?; + let type_index = self.read_typeidx()?; + let data_index = self.read_dataidx()?; visitor.visit_array_new_data(type_index, data_index) } 0x0a => { - let type_index = self.read_var_u32()?; - let elem_index = self.read_var_u32()?; + let type_index = self.read_typeidx()?; + let elem_index = self.read_elemidx()?; visitor.visit_array_new_elem(type_index, elem_index) } 0x0b => { - let type_index = self.read_var_u32()?; + let type_index = self.read_typeidx()?; visitor.visit_array_get(type_index) } 0x0c => { - let type_index = self.read_var_u32()?; + let type_index = self.read_typeidx()?; visitor.visit_array_get_s(type_index) } 0x0d => { - let type_index = self.read_var_u32()?; + let type_index = self.read_typeidx()?; visitor.visit_array_get_u(type_index) } 0x0e => { - let type_index = self.read_var_u32()?; + let type_index = self.read_typeidx()?; visitor.visit_array_set(type_index) } 0x0f => visitor.visit_array_len(), 0x10 => { - let type_index = self.read_var_u32()?; + let type_index = self.read_typeidx()?; visitor.visit_array_fill(type_index) } 0x11 => { - let type_index_dst = self.read_var_u32()?; - let type_index_src = self.read_var_u32()?; + let type_index_dst = self.read_typeidx()?; + let type_index_src = self.read_typeidx()?; visitor.visit_array_copy(type_index_dst, type_index_src) } 0x12 => { - let type_index = self.read_var_u32()?; - let data_index = self.read_var_u32()?; + let type_index = self.read_typeidx()?; + let data_index = self.read_dataidx()?; visitor.visit_array_init_data(type_index, data_index) } 0x13 => { - let type_index = self.read_var_u32()?; - let elem_index = self.read_var_u32()?; + let type_index = self.read_typeidx()?; + let elem_index = self.read_elemidx()?; visitor.visit_array_init_elem(type_index, elem_index) } 0x14 => visitor.visit_ref_test_non_null(self.read()?), @@ -1243,7 +1471,7 @@ impl<'a> BinaryReader<'a> { 0x18 => { let pos = self.original_position(); let cast_flags = self.read_u8()?; - let relative_depth = self.read_var_u32()?; + let relative_depth = self.read_labelidx()?; let (from_type_nullable, to_type_nullable) = match cast_flags { 0b00 => (false, false), 0b01 => (true, false), @@ -1266,7 +1494,7 @@ impl<'a> BinaryReader<'a> { 0x19 => { let pos = self.original_position(); let cast_flags = self.read_u8()?; - let relative_depth = self.read_var_u32()?; + let relative_depth = self.read_labelidx()?; let (from_type_nullable, to_type_nullable) = match cast_flags { 0 => (false, false), 1 => (true, false), @@ -1318,54 +1546,54 @@ impl<'a> BinaryReader<'a> { 0x07 => visitor.visit_i64_trunc_sat_f64_u(), 0x08 => { - let segment = self.read_var_u32()?; - let mem = self.read_var_u32()?; + let segment = self.read_dataidx()?; + let mem = self.read_memidx()?; visitor.visit_memory_init(segment, mem) } 0x09 => { - let segment = self.read_var_u32()?; + let segment = self.read_dataidx()?; visitor.visit_data_drop(segment) } 0x0a => { - let dst = self.read_var_u32()?; - let src = self.read_var_u32()?; + let dst = self.read_memidx()?; + let src = self.read_memidx()?; visitor.visit_memory_copy(dst, src) } 0x0b => { - let mem = self.read_var_u32()?; + let mem = self.read_memidx()?; visitor.visit_memory_fill(mem) } 0x0c => { - let segment = self.read_var_u32()?; - let table = self.read_var_u32()?; + let segment = self.read_elemidx()?; + let table = self.read_tableidx()?; visitor.visit_table_init(segment, table) } 0x0d => { - let segment = self.read_var_u32()?; + let segment = self.read_elemidx()?; visitor.visit_elem_drop(segment) } 0x0e => { - let dst_table = self.read_var_u32()?; - let src_table = self.read_var_u32()?; + let dst_table = self.read_tableidx()?; + let src_table = self.read_tableidx()?; visitor.visit_table_copy(dst_table, src_table) } 0x0f => { - let table = self.read_var_u32()?; + let table = self.read_tableidx()?; visitor.visit_table_grow(table) } 0x10 => { - let table = self.read_var_u32()?; + let table = self.read_tableidx()?; visitor.visit_table_size(table) } 0x11 => { - let table = self.read_var_u32()?; + let table = self.read_tableidx()?; visitor.visit_table_fill(table) } 0x12 => { - let mem = self.read_var_u32()?; + let mem = self.read_memidx()?; visitor.visit_memory_discard(mem) } @@ -1462,104 +1690,105 @@ impl<'a> BinaryReader<'a> { 0x4e => visitor.visit_i64_atomic_rmw32_cmpxchg_u(self.read_memarg(2)?), // Decode shared-everything-threads proposal. - 0x4f => visitor.visit_global_atomic_get(self.read_ordering()?, self.read_var_u32()?), - 0x50 => visitor.visit_global_atomic_set(self.read_ordering()?, self.read_var_u32()?), + 0x4f => visitor.visit_global_atomic_get(self.read_ordering()?, self.read_globalidx()?), + 0x50 => visitor.visit_global_atomic_set(self.read_ordering()?, self.read_globalidx()?), 0x51 => { - visitor.visit_global_atomic_rmw_add(self.read_ordering()?, self.read_var_u32()?) + visitor.visit_global_atomic_rmw_add(self.read_ordering()?, self.read_globalidx()?) } 0x52 => { - visitor.visit_global_atomic_rmw_sub(self.read_ordering()?, self.read_var_u32()?) + visitor.visit_global_atomic_rmw_sub(self.read_ordering()?, self.read_globalidx()?) } 0x53 => { - visitor.visit_global_atomic_rmw_and(self.read_ordering()?, self.read_var_u32()?) + visitor.visit_global_atomic_rmw_and(self.read_ordering()?, self.read_globalidx()?) + } + 0x54 => { + visitor.visit_global_atomic_rmw_or(self.read_ordering()?, self.read_globalidx()?) } - 0x54 => visitor.visit_global_atomic_rmw_or(self.read_ordering()?, self.read_var_u32()?), 0x55 => { - visitor.visit_global_atomic_rmw_xor(self.read_ordering()?, self.read_var_u32()?) + visitor.visit_global_atomic_rmw_xor(self.read_ordering()?, self.read_globalidx()?) } 0x56 => { - visitor.visit_global_atomic_rmw_xchg(self.read_ordering()?, self.read_var_u32()?) - } - 0x57 => { - visitor.visit_global_atomic_rmw_cmpxchg(self.read_ordering()?, self.read_var_u32()?) + visitor.visit_global_atomic_rmw_xchg(self.read_ordering()?, self.read_globalidx()?) } - 0x58 => visitor.visit_table_atomic_get(self.read_ordering()?, self.read_var_u32()?), - 0x59 => visitor.visit_table_atomic_set(self.read_ordering()?, self.read_var_u32()?), + 0x57 => visitor + .visit_global_atomic_rmw_cmpxchg(self.read_ordering()?, self.read_globalidx()?), + 0x58 => visitor.visit_table_atomic_get(self.read_ordering()?, self.read_tableidx()?), + 0x59 => visitor.visit_table_atomic_set(self.read_ordering()?, self.read_tableidx()?), 0x5a => { - visitor.visit_table_atomic_rmw_xchg(self.read_ordering()?, self.read_var_u32()?) + visitor.visit_table_atomic_rmw_xchg(self.read_ordering()?, self.read_tableidx()?) } 0x5b => { - visitor.visit_table_atomic_rmw_cmpxchg(self.read_ordering()?, self.read_var_u32()?) + visitor.visit_table_atomic_rmw_cmpxchg(self.read_ordering()?, self.read_tableidx()?) } 0x5c => visitor.visit_struct_atomic_get( self.read_ordering()?, - self.read_var_u32()?, - self.read_var_u32()?, + self.read_typeidx()?, + self.read_fieldidx()?, ), 0x5d => visitor.visit_struct_atomic_get_s( self.read_ordering()?, - self.read_var_u32()?, - self.read_var_u32()?, + self.read_typeidx()?, + self.read_fieldidx()?, ), 0x5e => visitor.visit_struct_atomic_get_u( self.read_ordering()?, - self.read_var_u32()?, - self.read_var_u32()?, + self.read_typeidx()?, + self.read_fieldidx()?, ), 0x5f => visitor.visit_struct_atomic_set( self.read_ordering()?, - self.read_var_u32()?, - self.read_var_u32()?, + self.read_typeidx()?, + self.read_fieldidx()?, ), 0x60 => visitor.visit_struct_atomic_rmw_add( self.read_ordering()?, - self.read_var_u32()?, - self.read_var_u32()?, + self.read_typeidx()?, + self.read_fieldidx()?, ), 0x61 => visitor.visit_struct_atomic_rmw_sub( self.read_ordering()?, - self.read_var_u32()?, - self.read_var_u32()?, + self.read_typeidx()?, + self.read_fieldidx()?, ), 0x62 => visitor.visit_struct_atomic_rmw_and( self.read_ordering()?, - self.read_var_u32()?, - self.read_var_u32()?, + self.read_typeidx()?, + self.read_fieldidx()?, ), 0x63 => visitor.visit_struct_atomic_rmw_or( self.read_ordering()?, - self.read_var_u32()?, - self.read_var_u32()?, + self.read_typeidx()?, + self.read_fieldidx()?, ), 0x64 => visitor.visit_struct_atomic_rmw_xor( self.read_ordering()?, - self.read_var_u32()?, - self.read_var_u32()?, + self.read_typeidx()?, + self.read_fieldidx()?, ), 0x65 => visitor.visit_struct_atomic_rmw_xchg( self.read_ordering()?, - self.read_var_u32()?, - self.read_var_u32()?, + self.read_typeidx()?, + self.read_fieldidx()?, ), 0x66 => visitor.visit_struct_atomic_rmw_cmpxchg( self.read_ordering()?, - self.read_var_u32()?, - self.read_var_u32()?, + self.read_typeidx()?, + self.read_fieldidx()?, ), - 0x67 => visitor.visit_array_atomic_get(self.read_ordering()?, self.read_var_u32()?), - 0x68 => visitor.visit_array_atomic_get_s(self.read_ordering()?, self.read_var_u32()?), - 0x69 => visitor.visit_array_atomic_get_u(self.read_ordering()?, self.read_var_u32()?), - 0x6a => visitor.visit_array_atomic_set(self.read_ordering()?, self.read_var_u32()?), - 0x6b => visitor.visit_array_atomic_rmw_add(self.read_ordering()?, self.read_var_u32()?), - 0x6c => visitor.visit_array_atomic_rmw_sub(self.read_ordering()?, self.read_var_u32()?), - 0x6d => visitor.visit_array_atomic_rmw_and(self.read_ordering()?, self.read_var_u32()?), - 0x6e => visitor.visit_array_atomic_rmw_or(self.read_ordering()?, self.read_var_u32()?), - 0x6f => visitor.visit_array_atomic_rmw_xor(self.read_ordering()?, self.read_var_u32()?), + 0x67 => visitor.visit_array_atomic_get(self.read_ordering()?, self.read_typeidx()?), + 0x68 => visitor.visit_array_atomic_get_s(self.read_ordering()?, self.read_typeidx()?), + 0x69 => visitor.visit_array_atomic_get_u(self.read_ordering()?, self.read_typeidx()?), + 0x6a => visitor.visit_array_atomic_set(self.read_ordering()?, self.read_typeidx()?), + 0x6b => visitor.visit_array_atomic_rmw_add(self.read_ordering()?, self.read_typeidx()?), + 0x6c => visitor.visit_array_atomic_rmw_sub(self.read_ordering()?, self.read_typeidx()?), + 0x6d => visitor.visit_array_atomic_rmw_and(self.read_ordering()?, self.read_typeidx()?), + 0x6e => visitor.visit_array_atomic_rmw_or(self.read_ordering()?, self.read_typeidx()?), + 0x6f => visitor.visit_array_atomic_rmw_xor(self.read_ordering()?, self.read_typeidx()?), 0x70 => { - visitor.visit_array_atomic_rmw_xchg(self.read_ordering()?, self.read_var_u32()?) + visitor.visit_array_atomic_rmw_xchg(self.read_ordering()?, self.read_typeidx()?) } 0x71 => { - visitor.visit_array_atomic_rmw_cmpxchg(self.read_ordering()?, self.read_var_u32()?) + visitor.visit_array_atomic_rmw_cmpxchg(self.read_ordering()?, self.read_typeidx()?) } 0x72 => visitor.visit_ref_i31_shared(), @@ -1622,27 +1851,27 @@ impl<'a> BinaryReader<'a> { } } - fn read_memory_index_or_zero_if_not_multi_memory(&mut self) -> Result { + fn read_memory_index_or_zero_if_not_multi_memory(&mut self) -> Result { if self.multi_memory() { - self.read_var_u32() + self.read_memidx() } else { // Before bulk memory this byte was required to be a single zero // byte, not a LEB-encoded zero, so require a precise zero byte. match self.read_u8()? { - 0 => Ok(0), + 0 => Ok(MemIdx(0)), _ => bail!(self.original_position() - 1, "zero byte expected"), } } } - fn read_table_index_or_zero_if_not_reference_types(&mut self) -> Result { + fn read_table_index_or_zero_if_not_reference_types(&mut self) -> Result { if self.reference_types() { - self.read_var_u32() + self.read_tableidx() } else { // Before reference types this byte was required to be a single zero // byte, not a LEB-encoded zero, so require a precise zero byte. match self.read_u8()? { - 0 => Ok(0), + 0 => Ok(TableIdx(0)), _ => bail!(self.original_position() - 1, "zero byte expected"), } } @@ -1685,7 +1914,7 @@ impl<'a> BrTable<'a> { } /// Returns the default target of this `br_table` instruction. - pub fn default(&self) -> u32 { + pub fn default(&self) -> LabelIdx { self.default } @@ -1730,7 +1959,7 @@ pub struct BrTableTargets<'a> { } impl<'a> Iterator for BrTableTargets<'a> { - type Item = Result; + type Item = Result; fn size_hint(&self) -> (usize, Option) { let remaining = usize::try_from(self.remaining).unwrap_or_else(|error| { @@ -1750,7 +1979,7 @@ impl<'a> Iterator for BrTableTargets<'a> { return None; } self.remaining -= 1; - Some(self.reader.read_var_u32()) + Some(self.reader.read_labelidx()) } } diff --git a/crates/wasmparser/src/lib.rs b/crates/wasmparser/src/lib.rs index 21c377536c..9ce7caed25 100644 --- a/crates/wasmparser/src/lib.rs +++ b/crates/wasmparser/src/lib.rs @@ -78,19 +78,19 @@ macro_rules! _for_each_operator_group { If { blockty: $crate::BlockType } => visit_if (arity 1 block -> ~block) Else => visit_else (arity ~end -> ~end) End => visit_end (arity implicit_else ~end -> implicit_else end) - Br { relative_depth: u32 } => visit_br (arity br -> 0) - BrIf { relative_depth: u32 } => visit_br_if (arity 1 br -> br) + Br { relative_depth: ::wasm_types::LabelIdx } => visit_br (arity br -> 0) + BrIf { relative_depth: ::wasm_types::LabelIdx } => visit_br_if (arity 1 br -> br) BrTable { targets: $crate::BrTable<'a> } => visit_br_table (arity 1 br_table -> 0) Return => visit_return (arity ~ret -> 0) - Call { function_index: u32 } => visit_call (arity func -> func) - CallIndirect { type_index: u32, table_index: u32 } => visit_call_indirect (arity 1 type -> type) + Call { function_index: ::wasm_types::FuncIdx } => visit_call (arity func -> func) + CallIndirect { type_index: ::wasm_types::TypeIdx, table_index: ::wasm_types::TableIdx } => visit_call_indirect (arity 1 type -> type) Drop => visit_drop (arity 1 -> 0) Select => visit_select (arity 3 -> 1) - LocalGet { local_index: u32 } => visit_local_get (arity 0 -> 1) - LocalSet { local_index: u32 } => visit_local_set (arity 1 -> 0) - LocalTee { local_index: u32 } => visit_local_tee (arity 1 -> 1) - GlobalGet { global_index: u32 } => visit_global_get (arity 0 -> 1) - GlobalSet { global_index: u32 } => visit_global_set (arity 1 -> 0) + LocalGet { local_index: ::wasm_types::LocalIdx } => visit_local_get (arity 0 -> 1) + LocalSet { local_index: ::wasm_types::LocalIdx } => visit_local_set (arity 1 -> 0) + LocalTee { local_index: ::wasm_types::LocalIdx } => visit_local_tee (arity 1 -> 1) + GlobalGet { global_index: ::wasm_types::GlobalIdx } => visit_global_get (arity 0 -> 1) + GlobalSet { global_index: ::wasm_types::GlobalIdx } => visit_global_set (arity 1 -> 0) I32Load { memarg: $crate::MemArg } => visit_i32_load (load i32) I64Load { memarg: $crate::MemArg } => visit_i64_load (load i64) F32Load { memarg: $crate::MemArg } => visit_f32_load (load f32) @@ -114,8 +114,8 @@ macro_rules! _for_each_operator_group { I64Store8 { memarg: $crate::MemArg } => visit_i64_store8 (store i64) I64Store16 { memarg: $crate::MemArg } => visit_i64_store16 (store i64) I64Store32 { memarg: $crate::MemArg } => visit_i64_store32 (store i64) - MemorySize { mem: u32 } => visit_memory_size (arity 0 -> 1) - MemoryGrow { mem: u32 } => visit_memory_grow (arity 1 -> 1) + MemorySize { mem: ::wasm_types::MemIdx } => visit_memory_size (arity 0 -> 1) + MemoryGrow { mem: ::wasm_types::MemIdx } => visit_memory_grow (arity 1 -> 1) I32Const { value: i32 } => visit_i32_const (push i32) I64Const { value: i64 } => visit_i64_const (push i64) F32Const { value: $crate::Ieee32 } => visit_f32_const (push f32) @@ -258,37 +258,37 @@ macro_rules! _for_each_operator_group { // http://github.com/WebAssembly/gc @gc { RefEq => visit_ref_eq (arity 2 -> 1) - StructNew { struct_type_index: u32 } => visit_struct_new (arity type -> 1) - StructNewDefault { struct_type_index: u32 } => visit_struct_new_default (arity 0 -> 1) - StructGet { struct_type_index: u32, field_index: u32 } => visit_struct_get (arity 1 -> 1) - StructGetS { struct_type_index: u32, field_index: u32 } => visit_struct_get_s (arity 1 -> 1) - StructGetU { struct_type_index: u32, field_index: u32 } => visit_struct_get_u (arity 1 -> 1) - StructSet { struct_type_index: u32, field_index: u32 } => visit_struct_set (arity 2 -> 0) - ArrayNew { array_type_index: u32 } => visit_array_new (arity 2 -> 1) - ArrayNewDefault { array_type_index: u32 } => visit_array_new_default (arity 1 -> 1) - ArrayNewFixed { array_type_index: u32, array_size: u32 } => visit_array_new_fixed (arity size -> 1) - ArrayNewData { array_type_index: u32, array_data_index: u32 } => visit_array_new_data (arity 2 -> 1) - ArrayNewElem { array_type_index: u32, array_elem_index: u32 } => visit_array_new_elem (arity 2 -> 1) - ArrayGet { array_type_index: u32 } => visit_array_get (arity 2 -> 1) - ArrayGetS { array_type_index: u32 } => visit_array_get_s (arity 2 -> 1) - ArrayGetU { array_type_index: u32 } => visit_array_get_u (arity 2 -> 1) - ArraySet { array_type_index: u32 } => visit_array_set (arity 3 -> 0) + StructNew { struct_type_index: ::wasm_types::TypeIdx } => visit_struct_new (arity type -> 1) + StructNewDefault { struct_type_index: ::wasm_types::TypeIdx } => visit_struct_new_default (arity 0 -> 1) + StructGet { struct_type_index: ::wasm_types::TypeIdx, field_index: ::wasm_types::FieldIdx } => visit_struct_get (arity 1 -> 1) + StructGetS { struct_type_index: ::wasm_types::TypeIdx, field_index: ::wasm_types::FieldIdx } => visit_struct_get_s (arity 1 -> 1) + StructGetU { struct_type_index: ::wasm_types::TypeIdx, field_index: ::wasm_types::FieldIdx } => visit_struct_get_u (arity 1 -> 1) + StructSet { struct_type_index: ::wasm_types::TypeIdx, field_index: ::wasm_types::FieldIdx } => visit_struct_set (arity 2 -> 0) + ArrayNew { array_type_index: ::wasm_types::TypeIdx } => visit_array_new (arity 2 -> 1) + ArrayNewDefault { array_type_index: ::wasm_types::TypeIdx } => visit_array_new_default (arity 1 -> 1) + ArrayNewFixed { array_type_index: ::wasm_types::TypeIdx, array_size: u32 } => visit_array_new_fixed (arity size -> 1) + ArrayNewData { array_type_index: ::wasm_types::TypeIdx, array_data_index: ::wasm_types::DataIdx } => visit_array_new_data (arity 2 -> 1) + ArrayNewElem { array_type_index: ::wasm_types::TypeIdx, array_elem_index: ::wasm_types::ElemIdx } => visit_array_new_elem (arity 2 -> 1) + ArrayGet { array_type_index: ::wasm_types::TypeIdx } => visit_array_get (arity 2 -> 1) + ArrayGetS { array_type_index: ::wasm_types::TypeIdx } => visit_array_get_s (arity 2 -> 1) + ArrayGetU { array_type_index: ::wasm_types::TypeIdx } => visit_array_get_u (arity 2 -> 1) + ArraySet { array_type_index: ::wasm_types::TypeIdx } => visit_array_set (arity 3 -> 0) ArrayLen => visit_array_len (arity 1 -> 1) - ArrayFill { array_type_index: u32 } => visit_array_fill (arity 4 -> 0) - ArrayCopy { array_type_index_dst: u32, array_type_index_src: u32 } => visit_array_copy (arity 5 -> 0) - ArrayInitData { array_type_index: u32, array_data_index: u32 } => visit_array_init_data (arity 4 -> 0) - ArrayInitElem { array_type_index: u32, array_elem_index: u32 } => visit_array_init_elem (arity 4 -> 0) + ArrayFill { array_type_index: ::wasm_types::TypeIdx } => visit_array_fill (arity 4 -> 0) + ArrayCopy { array_type_index_dst: ::wasm_types::TypeIdx, array_type_index_src: ::wasm_types::TypeIdx } => visit_array_copy (arity 5 -> 0) + ArrayInitData { array_type_index: ::wasm_types::TypeIdx, array_data_index: ::wasm_types::DataIdx } => visit_array_init_data (arity 4 -> 0) + ArrayInitElem { array_type_index: ::wasm_types::TypeIdx, array_elem_index: ::wasm_types::ElemIdx } => visit_array_init_elem (arity 4 -> 0) RefTestNonNull { hty: $crate::HeapType } => visit_ref_test_non_null (arity 1 -> 1) RefTestNullable { hty: $crate::HeapType } => visit_ref_test_nullable (arity 1 -> 1) RefCastNonNull { hty: $crate::HeapType } => visit_ref_cast_non_null (arity 1 -> 1) RefCastNullable { hty: $crate::HeapType } => visit_ref_cast_nullable (arity 1 -> 1) BrOnCast { - relative_depth: u32, + relative_depth: ::wasm_types::LabelIdx, from_ref_type: $crate::RefType, to_ref_type: $crate::RefType } => visit_br_on_cast (arity br -> br) BrOnCastFail { - relative_depth: u32, + relative_depth: ::wasm_types::LabelIdx, from_ref_type: $crate::RefType, to_ref_type: $crate::RefType } => visit_br_on_cast_fail (arity br -> br) @@ -317,13 +317,13 @@ macro_rules! _for_each_operator_group { // bulk memory operations // https://github.com/WebAssembly/bulk-memory-operations @bulk_memory { - MemoryInit { data_index: u32, mem: u32 } => visit_memory_init (arity 3 -> 0) - DataDrop { data_index: u32 } => visit_data_drop (arity 0 -> 0) - MemoryCopy { dst_mem: u32, src_mem: u32 } => visit_memory_copy (arity 3 -> 0) - MemoryFill { mem: u32 } => visit_memory_fill (arity 3 -> 0) - TableInit { elem_index: u32, table: u32 } => visit_table_init (arity 3 -> 0) - ElemDrop { elem_index: u32 } => visit_elem_drop (arity 0 -> 0) - TableCopy { dst_table: u32, src_table: u32 } => visit_table_copy (arity 3 -> 0) + MemoryInit { data_index: ::wasm_types::DataIdx, mem: ::wasm_types::MemIdx } => visit_memory_init (arity 3 -> 0) + DataDrop { data_index: ::wasm_types::DataIdx } => visit_data_drop (arity 0 -> 0) + MemoryCopy { dst_mem: ::wasm_types::MemIdx, src_mem: ::wasm_types::MemIdx } => visit_memory_copy (arity 3 -> 0) + MemoryFill { mem: ::wasm_types::MemIdx } => visit_memory_fill (arity 3 -> 0) + TableInit { elem_index: ::wasm_types::ElemIdx, table: ::wasm_types::TableIdx } => visit_table_init (arity 3 -> 0) + ElemDrop { elem_index: ::wasm_types::ElemIdx } => visit_elem_drop (arity 0 -> 0) + TableCopy { dst_table: ::wasm_types::TableIdx, src_table: ::wasm_types::TableIdx } => visit_table_copy (arity 3 -> 0) } // 0xFC prefixed operators @@ -333,26 +333,26 @@ macro_rules! _for_each_operator_group { TypedSelect { ty: $crate::ValType } => visit_typed_select (arity 3 -> 1) RefNull { hty: $crate::HeapType } => visit_ref_null (arity 0 -> 1) RefIsNull => visit_ref_is_null (arity 1 -> 1) - RefFunc { function_index: u32 } => visit_ref_func (arity 0 -> 1) - TableFill { table: u32 } => visit_table_fill (arity 3 -> 0) - TableGet { table: u32 } => visit_table_get (arity 1 -> 1) - TableSet { table: u32 } => visit_table_set (arity 2 -> 0) - TableGrow { table: u32 } => visit_table_grow (arity 2 -> 1) - TableSize { table: u32 } => visit_table_size (arity 0 -> 1) + RefFunc { function_index: ::wasm_types::FuncIdx } => visit_ref_func (arity 0 -> 1) + TableFill { table: ::wasm_types::TableIdx } => visit_table_fill (arity 3 -> 0) + TableGet { table: ::wasm_types::TableIdx } => visit_table_get (arity 1 -> 1) + TableSet { table: ::wasm_types::TableIdx } => visit_table_set (arity 2 -> 0) + TableGrow { table: ::wasm_types::TableIdx } => visit_table_grow (arity 2 -> 1) + TableSize { table: ::wasm_types::TableIdx } => visit_table_size (arity 0 -> 1) } // Wasm tail-call proposal // https://github.com/WebAssembly/tail-call @tail_call { - ReturnCall { function_index: u32 } => visit_return_call (arity func -> 0) - ReturnCallIndirect { type_index: u32, table_index: u32 } => visit_return_call_indirect (arity 1 type -> 0) + ReturnCall { function_index: ::wasm_types::FuncIdx } => visit_return_call (arity func -> 0) + ReturnCallIndirect { type_index: ::wasm_types::TypeIdx, table_index: ::wasm_types::TableIdx } => visit_return_call_indirect (arity 1 type -> 0) } // OxFC prefixed operators // memory control (experimental) // https://github.com/WebAssembly/design/issues/1439 @memory_control { - MemoryDiscard { mem: u32 } => visit_memory_discard (arity 2 -> 0) + MemoryDiscard { mem: ::wasm_types::MemIdx } => visit_memory_discard (arity 2 -> 0) } // 0xFE prefixed operators @@ -698,15 +698,15 @@ macro_rules! _for_each_operator_group { @exceptions { TryTable { try_table: $crate::TryTable } => visit_try_table (arity try_table -> ~try_table) - Throw { tag_index: u32 } => visit_throw (arity tag -> 0) + Throw { tag_index: ::wasm_types::TagIdx } => visit_throw (arity tag -> 0) ThrowRef => visit_throw_ref (arity 1 -> 0) } // Deprecated old instructions from the exceptions proposal @legacy_exceptions { Try { blockty: $crate::BlockType } => visit_try (arity block -> ~block) - Catch { tag_index: u32 } => visit_catch (arity ~end -> ~tag) - Rethrow { relative_depth: u32 } => visit_rethrow (arity 0 -> 0) - Delegate { relative_depth: u32 } => visit_delegate (arity ~end -> end) + Catch { tag_index: ::wasm_types::TagIdx } => visit_catch (arity ~end -> ~tag) + Rethrow { relative_depth: ::wasm_types::LabelIdx } => visit_rethrow (arity 0 -> 0) + Delegate { relative_depth: ::wasm_types::LabelIdx } => visit_delegate (arity ~end -> end) CatchAll => visit_catch_all (arity ~end -> 0) } @@ -714,61 +714,61 @@ macro_rules! _for_each_operator_group { // shared-everything threads // https://github.com/WebAssembly/shared-everything-threads @shared_everything_threads { - GlobalAtomicGet { ordering: $crate::Ordering, global_index: u32 } => visit_global_atomic_get (arity 0 -> 1) - GlobalAtomicSet { ordering: $crate::Ordering, global_index: u32 } => visit_global_atomic_set (arity 1 -> 0) - GlobalAtomicRmwAdd { ordering: $crate::Ordering, global_index: u32 } => visit_global_atomic_rmw_add (unary atomic global) - GlobalAtomicRmwSub { ordering: $crate::Ordering, global_index: u32 } => visit_global_atomic_rmw_sub (unary atomic global) - GlobalAtomicRmwAnd { ordering: $crate::Ordering, global_index: u32 } => visit_global_atomic_rmw_and (unary atomic global) - GlobalAtomicRmwOr { ordering: $crate::Ordering, global_index: u32 } => visit_global_atomic_rmw_or (unary atomic global) - GlobalAtomicRmwXor { ordering: $crate::Ordering, global_index: u32 } => visit_global_atomic_rmw_xor (unary atomic global) - GlobalAtomicRmwXchg { ordering: $crate::Ordering, global_index: u32 } => visit_global_atomic_rmw_xchg (arity 1 -> 1) - GlobalAtomicRmwCmpxchg { ordering: $crate::Ordering, global_index: u32 } => visit_global_atomic_rmw_cmpxchg (arity 2 -> 1) - TableAtomicGet { ordering: $crate::Ordering, table_index: u32 } => visit_table_atomic_get (arity 1 -> 1) - TableAtomicSet { ordering: $crate::Ordering, table_index: u32 } => visit_table_atomic_set (arity 2 -> 0) - TableAtomicRmwXchg { ordering: $crate::Ordering, table_index: u32 } => visit_table_atomic_rmw_xchg (arity 2 -> 1) - TableAtomicRmwCmpxchg { ordering: $crate::Ordering, table_index: u32 } => visit_table_atomic_rmw_cmpxchg (arity 3 -> 1) - StructAtomicGet { ordering: $crate::Ordering, struct_type_index: u32, field_index: u32 } => visit_struct_atomic_get (arity 1 -> 1) - StructAtomicGetS { ordering: $crate::Ordering, struct_type_index: u32, field_index: u32 } => visit_struct_atomic_get_s (arity 1 -> 1) - StructAtomicGetU { ordering: $crate::Ordering, struct_type_index: u32, field_index: u32 } => visit_struct_atomic_get_u (arity 1 -> 1) - StructAtomicSet { ordering: $crate::Ordering, struct_type_index: u32, field_index: u32 } => visit_struct_atomic_set (arity 2 -> 0) - StructAtomicRmwAdd { ordering: $crate::Ordering, struct_type_index: u32, field_index: u32 } => visit_struct_atomic_rmw_add (atomic rmw struct add) - StructAtomicRmwSub { ordering: $crate::Ordering, struct_type_index: u32, field_index: u32 } => visit_struct_atomic_rmw_sub (atomic rmw struct sub) - StructAtomicRmwAnd { ordering: $crate::Ordering, struct_type_index: u32, field_index: u32 } => visit_struct_atomic_rmw_and (atomic rmw struct and) - StructAtomicRmwOr { ordering: $crate::Ordering, struct_type_index: u32, field_index: u32 } => visit_struct_atomic_rmw_or (atomic rmw struct or) - StructAtomicRmwXor { ordering: $crate::Ordering, struct_type_index: u32, field_index: u32 } => visit_struct_atomic_rmw_xor (atomic rmw struct xor) - StructAtomicRmwXchg { ordering: $crate::Ordering, struct_type_index: u32, field_index: u32 } => visit_struct_atomic_rmw_xchg (arity 2 -> 1) - StructAtomicRmwCmpxchg { ordering: $crate::Ordering, struct_type_index: u32, field_index: u32 } => visit_struct_atomic_rmw_cmpxchg (arity 3 -> 1) - ArrayAtomicGet { ordering: $crate::Ordering, array_type_index: u32 } => visit_array_atomic_get (arity 2 -> 1) - ArrayAtomicGetS { ordering: $crate::Ordering, array_type_index: u32 } => visit_array_atomic_get_s (arity 2 -> 1) - ArrayAtomicGetU { ordering: $crate::Ordering, array_type_index: u32 } => visit_array_atomic_get_u (arity 2 -> 1) - ArrayAtomicSet { ordering: $crate::Ordering, array_type_index: u32 } => visit_array_atomic_set (arity 3 -> 0) - ArrayAtomicRmwAdd { ordering: $crate::Ordering, array_type_index: u32 } => visit_array_atomic_rmw_add (atomic rmw array add) - ArrayAtomicRmwSub { ordering: $crate::Ordering, array_type_index: u32 } => visit_array_atomic_rmw_sub (atomic rmw array sub) - ArrayAtomicRmwAnd { ordering: $crate::Ordering, array_type_index: u32 } => visit_array_atomic_rmw_and (atomic rmw array and) - ArrayAtomicRmwOr { ordering: $crate::Ordering, array_type_index: u32 } => visit_array_atomic_rmw_or (atomic rmw array or) - ArrayAtomicRmwXor { ordering: $crate::Ordering, array_type_index: u32 } => visit_array_atomic_rmw_xor (atomic rmw array xor) - ArrayAtomicRmwXchg { ordering: $crate::Ordering, array_type_index: u32 } => visit_array_atomic_rmw_xchg (arity 3 -> 1) - ArrayAtomicRmwCmpxchg { ordering: $crate::Ordering, array_type_index: u32 } => visit_array_atomic_rmw_cmpxchg (arity 4 -> 1) + GlobalAtomicGet { ordering: $crate::Ordering, global_index: ::wasm_types::GlobalIdx } => visit_global_atomic_get (arity 0 -> 1) + GlobalAtomicSet { ordering: $crate::Ordering, global_index: ::wasm_types::GlobalIdx } => visit_global_atomic_set (arity 1 -> 0) + GlobalAtomicRmwAdd { ordering: $crate::Ordering, global_index: ::wasm_types::GlobalIdx } => visit_global_atomic_rmw_add (unary atomic global) + GlobalAtomicRmwSub { ordering: $crate::Ordering, global_index: ::wasm_types::GlobalIdx } => visit_global_atomic_rmw_sub (unary atomic global) + GlobalAtomicRmwAnd { ordering: $crate::Ordering, global_index: ::wasm_types::GlobalIdx } => visit_global_atomic_rmw_and (unary atomic global) + GlobalAtomicRmwOr { ordering: $crate::Ordering, global_index: ::wasm_types::GlobalIdx } => visit_global_atomic_rmw_or (unary atomic global) + GlobalAtomicRmwXor { ordering: $crate::Ordering, global_index: ::wasm_types::GlobalIdx } => visit_global_atomic_rmw_xor (unary atomic global) + GlobalAtomicRmwXchg { ordering: $crate::Ordering, global_index: ::wasm_types::GlobalIdx } => visit_global_atomic_rmw_xchg (arity 1 -> 1) + GlobalAtomicRmwCmpxchg { ordering: $crate::Ordering, global_index: ::wasm_types::GlobalIdx } => visit_global_atomic_rmw_cmpxchg (arity 2 -> 1) + TableAtomicGet { ordering: $crate::Ordering, table_index: ::wasm_types::TableIdx } => visit_table_atomic_get (arity 1 -> 1) + TableAtomicSet { ordering: $crate::Ordering, table_index: ::wasm_types::TableIdx } => visit_table_atomic_set (arity 2 -> 0) + TableAtomicRmwXchg { ordering: $crate::Ordering, table_index: ::wasm_types::TableIdx } => visit_table_atomic_rmw_xchg (arity 2 -> 1) + TableAtomicRmwCmpxchg { ordering: $crate::Ordering, table_index: ::wasm_types::TableIdx } => visit_table_atomic_rmw_cmpxchg (arity 3 -> 1) + StructAtomicGet { ordering: $crate::Ordering, struct_type_index: ::wasm_types::TypeIdx, field_index: ::wasm_types::FieldIdx } => visit_struct_atomic_get (arity 1 -> 1) + StructAtomicGetS { ordering: $crate::Ordering, struct_type_index: ::wasm_types::TypeIdx, field_index: ::wasm_types::FieldIdx } => visit_struct_atomic_get_s (arity 1 -> 1) + StructAtomicGetU { ordering: $crate::Ordering, struct_type_index: ::wasm_types::TypeIdx, field_index: ::wasm_types::FieldIdx } => visit_struct_atomic_get_u (arity 1 -> 1) + StructAtomicSet { ordering: $crate::Ordering, struct_type_index: ::wasm_types::TypeIdx, field_index: ::wasm_types::FieldIdx } => visit_struct_atomic_set (arity 2 -> 0) + StructAtomicRmwAdd { ordering: $crate::Ordering, struct_type_index: ::wasm_types::TypeIdx, field_index: ::wasm_types::FieldIdx } => visit_struct_atomic_rmw_add (atomic rmw struct add) + StructAtomicRmwSub { ordering: $crate::Ordering, struct_type_index: ::wasm_types::TypeIdx, field_index: ::wasm_types::FieldIdx } => visit_struct_atomic_rmw_sub (atomic rmw struct sub) + StructAtomicRmwAnd { ordering: $crate::Ordering, struct_type_index: ::wasm_types::TypeIdx, field_index: ::wasm_types::FieldIdx } => visit_struct_atomic_rmw_and (atomic rmw struct and) + StructAtomicRmwOr { ordering: $crate::Ordering, struct_type_index: ::wasm_types::TypeIdx, field_index: ::wasm_types::FieldIdx } => visit_struct_atomic_rmw_or (atomic rmw struct or) + StructAtomicRmwXor { ordering: $crate::Ordering, struct_type_index: ::wasm_types::TypeIdx, field_index: ::wasm_types::FieldIdx } => visit_struct_atomic_rmw_xor (atomic rmw struct xor) + StructAtomicRmwXchg { ordering: $crate::Ordering, struct_type_index: ::wasm_types::TypeIdx, field_index: ::wasm_types::FieldIdx } => visit_struct_atomic_rmw_xchg (arity 2 -> 1) + StructAtomicRmwCmpxchg { ordering: $crate::Ordering, struct_type_index: ::wasm_types::TypeIdx, field_index: ::wasm_types::FieldIdx } => visit_struct_atomic_rmw_cmpxchg (arity 3 -> 1) + ArrayAtomicGet { ordering: $crate::Ordering, array_type_index: ::wasm_types::TypeIdx } => visit_array_atomic_get (arity 2 -> 1) + ArrayAtomicGetS { ordering: $crate::Ordering, array_type_index: ::wasm_types::TypeIdx } => visit_array_atomic_get_s (arity 2 -> 1) + ArrayAtomicGetU { ordering: $crate::Ordering, array_type_index: ::wasm_types::TypeIdx } => visit_array_atomic_get_u (arity 2 -> 1) + ArrayAtomicSet { ordering: $crate::Ordering, array_type_index: ::wasm_types::TypeIdx } => visit_array_atomic_set (arity 3 -> 0) + ArrayAtomicRmwAdd { ordering: $crate::Ordering, array_type_index: ::wasm_types::TypeIdx } => visit_array_atomic_rmw_add (atomic rmw array add) + ArrayAtomicRmwSub { ordering: $crate::Ordering, array_type_index: ::wasm_types::TypeIdx } => visit_array_atomic_rmw_sub (atomic rmw array sub) + ArrayAtomicRmwAnd { ordering: $crate::Ordering, array_type_index: ::wasm_types::TypeIdx } => visit_array_atomic_rmw_and (atomic rmw array and) + ArrayAtomicRmwOr { ordering: $crate::Ordering, array_type_index: ::wasm_types::TypeIdx } => visit_array_atomic_rmw_or (atomic rmw array or) + ArrayAtomicRmwXor { ordering: $crate::Ordering, array_type_index: ::wasm_types::TypeIdx } => visit_array_atomic_rmw_xor (atomic rmw array xor) + ArrayAtomicRmwXchg { ordering: $crate::Ordering, array_type_index: ::wasm_types::TypeIdx } => visit_array_atomic_rmw_xchg (arity 3 -> 1) + ArrayAtomicRmwCmpxchg { ordering: $crate::Ordering, array_type_index: ::wasm_types::TypeIdx } => visit_array_atomic_rmw_cmpxchg (arity 4 -> 1) RefI31Shared => visit_ref_i31_shared (arity 1 -> 1) } // Typed Function references @function_references { - CallRef { type_index: u32 } => visit_call_ref (arity 1 type -> type) - ReturnCallRef { type_index: u32 } => visit_return_call_ref (arity 1 type -> 0) + CallRef { type_index: ::wasm_types::TypeIdx } => visit_call_ref (arity 1 type -> type) + ReturnCallRef { type_index: ::wasm_types::TypeIdx } => visit_return_call_ref (arity 1 type -> 0) RefAsNonNull => visit_ref_as_non_null (arity 1 -> 1) - BrOnNull { relative_depth: u32 } => visit_br_on_null (arity 1 br -> 1 br) - BrOnNonNull { relative_depth: u32 } => visit_br_on_non_null (arity br -> br -1) + BrOnNull { relative_depth: ::wasm_types::LabelIdx } => visit_br_on_null (arity 1 br -> 1 br) + BrOnNonNull { relative_depth: ::wasm_types::LabelIdx } => visit_br_on_non_null (arity br -> br -1) } // Stack switching @stack_switching { - ContNew { cont_type_index: u32 } => visit_cont_new (arity 1 -> 1) - ContBind { argument_index: u32, result_index: u32 } => visit_cont_bind (arity type_diff 1 -> 1) - Suspend { tag_index: u32 } => visit_suspend (arity tag -> tag) - Resume { cont_type_index: u32, resume_table: $crate::ResumeTable } => visit_resume (arity 1 type -> type) - ResumeThrow { cont_type_index: u32, tag_index: u32, resume_table: $crate::ResumeTable } => visit_resume_throw (arity 1 tag -> type) - Switch { cont_type_index: u32, tag_index: u32 } => visit_switch (arity type -> ~switch) + ContNew { cont_type_index: ::wasm_types::TypeIdx } => visit_cont_new (arity 1 -> 1) + ContBind { argument_index: ::wasm_types::TypeIdx, result_index: ::wasm_types::TypeIdx } => visit_cont_bind (arity type_diff 1 -> 1) + Suspend { tag_index: ::wasm_types::TagIdx } => visit_suspend (arity tag -> tag) + Resume { cont_type_index: ::wasm_types::TypeIdx, resume_table: $crate::ResumeTable } => visit_resume (arity 1 type -> type) + ResumeThrow { cont_type_index: ::wasm_types::TypeIdx, tag_index: ::wasm_types::TagIdx, resume_table: $crate::ResumeTable } => visit_resume_throw (arity 1 tag -> type) + Switch { cont_type_index: ::wasm_types::TypeIdx, tag_index: ::wasm_types::TagIdx } => visit_switch (arity type -> ~switch) } @wide_arithmetic { diff --git a/crates/wasmparser/src/parser.rs b/crates/wasmparser/src/parser.rs index a8aa331bbb..82827d5ff1 100644 --- a/crates/wasmparser/src/parser.rs +++ b/crates/wasmparser/src/parser.rs @@ -17,6 +17,7 @@ use crate::{ use core::fmt; use core::iter; use core::ops::Range; +use wasm_types::FuncIdx; pub(crate) const WASM_MODULE_VERSION: u16 = 0x1; @@ -151,7 +152,7 @@ pub enum Payload<'a> { /// A module start section was received. StartSection { /// The start function index - func: u32, + func: FuncIdx, /// The range of bytes that specify the `func` field, specified in /// offsets relative to the start of the byte stream. range: Range, diff --git a/crates/wasmparser/src/readers.rs b/crates/wasmparser/src/readers.rs index 47a54deece..61dc227568 100644 --- a/crates/wasmparser/src/readers.rs +++ b/crates/wasmparser/src/readers.rs @@ -17,6 +17,11 @@ use crate::{BinaryReader, BinaryReaderError, Result}; use ::core::fmt; use ::core::marker; use ::core::ops::Range; +use wasm_types::{ + AbsoluteLabelIdx, ComponentFuncIdx, ComponentIdx, ComponentInstanceIdx, ComponentTypeIdx, + ComponentValueIdx, CoreInstanceIdx, CoreModuleIdx, DataIdx, ElemIdx, FieldIdx, FuncIdx, + GlobalIdx, LabelIdx, LocalIdx, MemIdx, TableIdx, TagIdx, TypeIdx, +}; #[cfg(feature = "component-model")] mod component; @@ -56,6 +61,120 @@ impl<'a> FromReader<'a> for u32 { } } +impl<'a> FromReader<'a> for TypeIdx { + fn from_reader(reader: &mut BinaryReader<'a>) -> Result { + reader.read_typeidx() + } +} + +impl<'a> FromReader<'a> for FuncIdx { + fn from_reader(reader: &mut BinaryReader<'a>) -> Result { + reader.read_funcidx() + } +} + +impl<'a> FromReader<'a> for TableIdx { + fn from_reader(reader: &mut BinaryReader<'a>) -> Result { + reader.read_tableidx() + } +} + +impl<'a> FromReader<'a> for MemIdx { + fn from_reader(reader: &mut BinaryReader<'a>) -> Result { + reader.read_memidx() + } +} + +impl<'a> FromReader<'a> for TagIdx { + fn from_reader(reader: &mut BinaryReader<'a>) -> Result { + reader.read_tagidx() + } +} + +impl<'a> FromReader<'a> for GlobalIdx { + fn from_reader(reader: &mut BinaryReader<'a>) -> Result { + reader.read_globalidx() + } +} + +impl<'a> FromReader<'a> for ElemIdx { + fn from_reader(reader: &mut BinaryReader<'a>) -> Result { + reader.read_elemidx() + } +} + +impl<'a> FromReader<'a> for DataIdx { + fn from_reader(reader: &mut BinaryReader<'a>) -> Result { + reader.read_dataidx() + } +} + +impl<'a> FromReader<'a> for LocalIdx { + fn from_reader(reader: &mut BinaryReader<'a>) -> Result { + reader.read_localidx() + } +} + +impl<'a> FromReader<'a> for LabelIdx { + fn from_reader(reader: &mut BinaryReader<'a>) -> Result { + reader.read_labelidx() + } +} + +impl<'a> FromReader<'a> for FieldIdx { + fn from_reader(reader: &mut BinaryReader<'a>) -> Result { + reader.read_fieldidx() + } +} + +impl<'a> FromReader<'a> for AbsoluteLabelIdx { + fn from_reader(reader: &mut BinaryReader<'a>) -> Result { + reader.read_absolute_label_idx() + } +} + +impl<'a> FromReader<'a> for CoreModuleIdx { + fn from_reader(reader: &mut BinaryReader<'a>) -> Result { + reader.read_core_module_idx() + } +} + +impl<'a> FromReader<'a> for CoreInstanceIdx { + fn from_reader(reader: &mut BinaryReader<'a>) -> Result { + reader.read_core_instance_idx() + } +} + +impl<'a> FromReader<'a> for ComponentTypeIdx { + fn from_reader(reader: &mut BinaryReader<'a>) -> Result { + reader.read_component_type_idx() + } +} + +impl<'a> FromReader<'a> for ComponentFuncIdx { + fn from_reader(reader: &mut BinaryReader<'a>) -> Result { + reader.read_component_func_idx() + } +} + +impl<'a> FromReader<'a> for ComponentIdx { + fn from_reader(reader: &mut BinaryReader<'a>) -> Result { + reader.read_component_idx() + } +} + +impl<'a> FromReader<'a> for ComponentInstanceIdx { + fn from_reader(reader: &mut BinaryReader<'a>) -> Result { + reader.read_component_instance_idx() + } +} + +impl<'a> FromReader<'a> for ComponentValueIdx { + fn from_reader(reader: &mut BinaryReader<'a>) -> Result { + reader.read_component_value_idx() + } +} + impl<'a> FromReader<'a> for &'a str { fn from_reader(reader: &mut BinaryReader<'a>) -> Result { reader.read_string() diff --git a/crates/wasmparser/src/readers/component/aliases.rs b/crates/wasmparser/src/readers/component/aliases.rs index bb0661a00a..12cca07cf1 100644 --- a/crates/wasmparser/src/readers/component/aliases.rs +++ b/crates/wasmparser/src/readers/component/aliases.rs @@ -1,3 +1,5 @@ +use wasm_types::{ComponentInstanceIdx, CoreInstanceIdx}; + use crate::{BinaryReader, ComponentExternalKind, ExternalKind, FromReader, Result}; /// Represents the kind of an outer alias in a WebAssembly component. @@ -21,7 +23,7 @@ pub enum ComponentAlias<'a> { /// The alias kind. kind: ComponentExternalKind, /// The instance index. - instance_index: u32, + instance_index: ComponentInstanceIdx, /// The export name. name: &'a str, }, @@ -30,7 +32,7 @@ pub enum ComponentAlias<'a> { /// The alias kind. kind: ExternalKind, /// The instance index. - instance_index: u32, + instance_index: CoreInstanceIdx, /// The export name. name: &'a str, }, @@ -62,7 +64,7 @@ impl<'a> FromReader<'a> for ComponentAlias<'a> { Ok(match reader.read_u8()? { 0x00 => ComponentAlias::InstanceExport { kind: ComponentExternalKind::from_bytes(byte1, byte2, offset)?, - instance_index: reader.read_var_u32()?, + instance_index: reader.read_component_instance_idx()?, name: reader.read_string()?, }, 0x01 => ComponentAlias::CoreInstanceExport { @@ -76,7 +78,7 @@ impl<'a> FromReader<'a> for ComponentAlias<'a> { })?, offset, )?, - instance_index: reader.read_var_u32()?, + instance_index: reader.read_core_instance_idx()?, name: reader.read_string()?, }, 0x02 => ComponentAlias::Outer { diff --git a/crates/wasmparser/src/readers/component/canonicals.rs b/crates/wasmparser/src/readers/component/canonicals.rs index bd3c06b4c7..1c7a92dbe9 100644 --- a/crates/wasmparser/src/readers/component/canonicals.rs +++ b/crates/wasmparser/src/readers/component/canonicals.rs @@ -3,6 +3,7 @@ use crate::prelude::*; use crate::{ BinaryReader, BinaryReaderError, ComponentValType, FromReader, Result, SectionLimited, }; +use wasm_types::{ComponentFuncIdx, ComponentTypeIdx, FuncIdx, MemIdx, TypeIdx}; /// Represents options for component functions. #[derive(Debug, Clone, Copy, PartialEq, Eq)] @@ -16,20 +17,20 @@ pub enum CanonicalOption { /// The memory to use if the lifting or lowering of a function requires memory access. /// /// The value is an index to a core memory. - Memory(u32), + Memory(MemIdx), /// The realloc function to use if the lifting or lowering of a function requires memory /// allocation. /// /// The value is an index to a core function of type `(func (param i32 i32 i32 i32) (result i32))`. - Realloc(u32), + Realloc(FuncIdx), /// The post-return function to use if the lifting of a function requires /// cleanup after the function returns. - PostReturn(u32), + PostReturn(FuncIdx), /// Indicates that specified function should be lifted or lowered using the `async` ABI. Async, /// The function to use if the async lifting of a function should receive task/stream/future progress events /// using a callback. - Callback(u32), + Callback(FuncIdx), } /// Represents a canonical function in a WebAssembly component. @@ -38,39 +39,39 @@ pub enum CanonicalFunction { /// The function lifts a core WebAssembly function to the canonical ABI. Lift { /// The index of the core WebAssembly function to lift. - core_func_index: u32, + core_func_index: FuncIdx, /// The index of the lifted function's type. - type_index: u32, + type_index: ComponentTypeIdx, /// The canonical options for the function. options: Box<[CanonicalOption]>, }, /// The function lowers a canonical ABI function to a core WebAssembly function. Lower { /// The index of the function to lower. - func_index: u32, + func_index: ComponentFuncIdx, /// The canonical options for the function. options: Box<[CanonicalOption]>, }, /// A function which creates a new owned handle to a resource. ResourceNew { /// The type index of the resource that's being created. - resource: u32, + resource: ComponentTypeIdx, }, /// A function which is used to drop resource handles of the specified type. ResourceDrop { /// The type index of the resource that's being dropped. - resource: u32, + resource: ComponentTypeIdx, }, /// A function which returns the underlying i32-based representation of the /// specified resource. ResourceRep { /// The type index of the resource that's being accessed. - resource: u32, + resource: ComponentTypeIdx, }, /// A function which spawns a new thread by invoking the shared function. ThreadSpawn { /// The index of the function to spawn. - func_ty_index: u32, + func_ty_index: TypeIdx, }, /// A function which returns the number of threads that can be expected to /// execute concurrently @@ -91,7 +92,7 @@ pub enum CanonicalFunction { /// If `true`, indicates the caller instance maybe reentered. async_: bool, /// Memory to use when storing the event. - memory: u32, + memory: MemIdx, }, /// A function which checks whether any outstanding async task/stream/future /// has made progress. Unlike `task.wait`, this does not block and may @@ -100,7 +101,7 @@ pub enum CanonicalFunction { /// If `true`, indicates the caller instance maybe reentered. async_: bool, /// Memory to use when storing the event, if any. - memory: u32, + memory: MemIdx, }, /// A function which yields control to the host so that other tasks are able /// to make progress, if any. @@ -113,12 +114,12 @@ pub enum CanonicalFunction { /// A function to create a new `stream` handle of the specified type. StreamNew { /// The `stream` type to instantiate. - ty: u32, + ty: ComponentTypeIdx, }, /// A function to read from a `stream` of the specified type. StreamRead { /// The `stream` type to expect. - ty: u32, + ty: ComponentTypeIdx, /// Any options (e.g. string encoding) to use when storing values to /// memory. options: Box<[CanonicalOption]>, @@ -126,7 +127,7 @@ pub enum CanonicalFunction { /// A function to write to a `stream` of the specified type. StreamWrite { /// The `stream` type to expect. - ty: u32, + ty: ComponentTypeIdx, /// Any options (e.g. string encoding) to use when loading values from /// memory. options: Box<[CanonicalOption]>, @@ -135,7 +136,7 @@ pub enum CanonicalFunction { /// specified type. StreamCancelRead { /// The `stream` type to expect. - ty: u32, + ty: ComponentTypeIdx, /// If `false`, block until cancellation completes rather than return /// `BLOCKED`. async_: bool, @@ -144,7 +145,7 @@ pub enum CanonicalFunction { /// type. StreamCancelWrite { /// The `stream` type to expect. - ty: u32, + ty: ComponentTypeIdx, /// If `false`, block until cancellation completes rather than return /// `BLOCKED`. async_: bool, @@ -153,23 +154,23 @@ pub enum CanonicalFunction { /// type. StreamCloseReadable { /// The `stream` type to expect. - ty: u32, + ty: ComponentTypeIdx, }, /// A function to close the writable end of a `stream` of the specified /// type. StreamCloseWritable { /// The `stream` type to expect. - ty: u32, + ty: ComponentTypeIdx, }, /// A function to create a new `future` handle of the specified type. FutureNew { /// The `future` type to instantiate. - ty: u32, + ty: ComponentTypeIdx, }, /// A function to read from a `future` of the specified type. FutureRead { /// The `future` type to expect. - ty: u32, + ty: ComponentTypeIdx, /// Any options (e.g. string encoding) to use when storing values to /// memory. options: Box<[CanonicalOption]>, @@ -177,7 +178,7 @@ pub enum CanonicalFunction { /// A function to write to a `future` of the specified type. FutureWrite { /// The `future` type to expect. - ty: u32, + ty: ComponentTypeIdx, /// Any options (e.g. string encoding) to use when loading values from /// memory. options: Box<[CanonicalOption]>, @@ -186,7 +187,7 @@ pub enum CanonicalFunction { /// specified type. FutureCancelRead { /// The `future` type to expect. - ty: u32, + ty: ComponentTypeIdx, /// If `false`, block until cancellation completes rather than return /// `BLOCKED`. async_: bool, @@ -195,7 +196,7 @@ pub enum CanonicalFunction { /// type. FutureCancelWrite { /// The `future` type to expect. - ty: u32, + ty: ComponentTypeIdx, /// If `false`, block until cancellation completes rather than return /// `BLOCKED`. async_: bool, @@ -204,13 +205,13 @@ pub enum CanonicalFunction { /// type. FutureCloseReadable { /// The `future` type to expect. - ty: u32, + ty: ComponentTypeIdx, }, /// A function to close the writable end of a `future` of the specified /// type. FutureCloseWritable { /// The `future` type to expect. - ty: u32, + ty: ComponentTypeIdx, }, /// A function to create a new `error-context` with a specified debug /// message. @@ -238,11 +239,11 @@ impl<'a> FromReader<'a> for CanonicalFunction { Ok(match reader.read_u8()? { 0x00 => match reader.read_u8()? { 0x00 => { - let core_func_index = reader.read_var_u32()?; + let core_func_index = reader.read_funcidx()?; let options = reader .read_iter(MAX_WASM_CANONICAL_OPTIONS, "canonical options")? .collect::>()?; - let type_index = reader.read_var_u32()?; + let type_index = reader.read_component_type_idx()?; CanonicalFunction::Lift { core_func_index, options, @@ -253,7 +254,7 @@ impl<'a> FromReader<'a> for CanonicalFunction { }, 0x01 => match reader.read_u8()? { 0x00 => CanonicalFunction::Lower { - func_index: reader.read_var_u32()?, + func_index: reader.read_component_func_idx()?, options: reader .read_iter(MAX_WASM_CANONICAL_OPTIONS, "canonical options")? .collect::>()?, @@ -370,11 +371,11 @@ impl<'a> FromReader<'a> for CanonicalOption { 0x00 => CanonicalOption::UTF8, 0x01 => CanonicalOption::UTF16, 0x02 => CanonicalOption::CompactUTF16, - 0x03 => CanonicalOption::Memory(reader.read_var_u32()?), - 0x04 => CanonicalOption::Realloc(reader.read_var_u32()?), - 0x05 => CanonicalOption::PostReturn(reader.read_var_u32()?), + 0x03 => CanonicalOption::Memory(reader.read_memidx()?), + 0x04 => CanonicalOption::Realloc(reader.read_funcidx()?), + 0x05 => CanonicalOption::PostReturn(reader.read_funcidx()?), 0x06 => CanonicalOption::Async, - 0x07 => CanonicalOption::Callback(reader.read_var_u32()?), + 0x07 => CanonicalOption::Callback(reader.read_funcidx()?), x => return reader.invalid_leading_byte(x, "canonical option"), }) } diff --git a/crates/wasmparser/src/readers/component/imports.rs b/crates/wasmparser/src/readers/component/imports.rs index bd14428d85..9ae895c50a 100644 --- a/crates/wasmparser/src/readers/component/imports.rs +++ b/crates/wasmparser/src/readers/component/imports.rs @@ -1,12 +1,13 @@ use crate::{ BinaryReader, ComponentExternalKind, ComponentValType, FromReader, Result, SectionLimited, }; +use wasm_types::{ComponentTypeIdx, TypeIdx}; /// Represents the type bounds for imports and exports. #[derive(Clone, Copy, Debug, Eq, PartialEq)] pub enum TypeBounds { /// The type is bounded by equality. - Eq(u32), + Eq(ComponentTypeIdx), /// A fresh resource type, SubResource, } @@ -27,11 +28,11 @@ pub enum ComponentTypeRef { /// The reference is to a core module type. /// /// The index is expected to be core type index to a core module type. - Module(u32), + Module(TypeIdx), /// The reference is to a function type. /// /// The index is expected to be a type index to a function type. - Func(u32), + Func(ComponentTypeIdx), /// The reference is to a value type. Value(ComponentValType), /// The reference is to a bounded type. @@ -41,11 +42,11 @@ pub enum ComponentTypeRef { /// The reference is to an instance type. /// /// The index is a type index to an instance type. - Instance(u32), + Instance(ComponentTypeIdx), /// The reference is to a component type. /// /// The index is a type index to a component type. - Component(u32), + Component(ComponentTypeIdx), } impl ComponentTypeRef { diff --git a/crates/wasmparser/src/readers/component/instances.rs b/crates/wasmparser/src/readers/component/instances.rs index 135fa01317..931d8c0e8b 100644 --- a/crates/wasmparser/src/readers/component/instances.rs +++ b/crates/wasmparser/src/readers/component/instances.rs @@ -1,3 +1,5 @@ +use wasm_types::{ComponentIdx, CoreModuleIdx}; + use crate::limits::{MAX_WASM_INSTANTIATION_ARGS, MAX_WASM_INSTANTIATION_EXPORTS}; use crate::prelude::*; use crate::{ @@ -29,7 +31,7 @@ pub enum Instance<'a> { /// The instance is from instantiating a WebAssembly module. Instantiate { /// The module index. - module_index: u32, + module_index: CoreModuleIdx, /// The module's instantiation arguments. args: Box<[InstantiationArg<'a>]>, }, @@ -56,7 +58,7 @@ impl<'a> FromReader<'a> for Instance<'a> { fn from_reader(reader: &mut BinaryReader<'a>) -> Result { Ok(match reader.read_u8()? { 0x00 => Instance::Instantiate { - module_index: reader.read_var_u32()?, + module_index: reader.read_core_module_idx()?, args: reader .read_iter(MAX_WASM_INSTANTIATION_ARGS, "core instantiation arguments")? .collect::>()?, @@ -107,7 +109,7 @@ pub enum ComponentInstance<'a> { /// The instance is from instantiating a WebAssembly component. Instantiate { /// The component index. - component_index: u32, + component_index: ComponentIdx, /// The component's instantiation arguments. args: Box<[ComponentInstantiationArg<'a>]>, }, @@ -134,7 +136,7 @@ impl<'a> FromReader<'a> for ComponentInstance<'a> { fn from_reader(reader: &mut BinaryReader<'a>) -> Result { Ok(match reader.read_u8()? { 0x00 => ComponentInstance::Instantiate { - component_index: reader.read_var_u32()?, + component_index: reader.read_component_idx()?, args: reader .read_iter(MAX_WASM_INSTANTIATION_ARGS, "instantiation arguments")? .collect::>()?, diff --git a/crates/wasmparser/src/readers/component/names.rs b/crates/wasmparser/src/readers/component/names.rs index 39661cbd0a..827c03705d 100644 --- a/crates/wasmparser/src/readers/component/names.rs +++ b/crates/wasmparser/src/readers/component/names.rs @@ -1,5 +1,9 @@ use crate::{BinaryReader, BinaryReaderError, NameMap, Result, Subsection, Subsections}; use core::ops::Range; +use wasm_types::{ + ComponentFuncIdx, ComponentIdx, ComponentInstanceIdx, ComponentTypeIdx, ComponentValueIdx, + CoreInstanceIdx, CoreModuleIdx, FuncIdx, GlobalIdx, MemIdx, TableIdx, TypeIdx, +}; /// Type used to iterate and parse the contents of the `component-name` custom /// section in compnents, similar to the `name` section of core modules. @@ -13,18 +17,18 @@ pub enum ComponentName<'a> { name: &'a str, name_range: Range, }, - CoreFuncs(NameMap<'a>), - CoreGlobals(NameMap<'a>), - CoreMemories(NameMap<'a>), - CoreTables(NameMap<'a>), - CoreModules(NameMap<'a>), - CoreInstances(NameMap<'a>), - CoreTypes(NameMap<'a>), - Types(NameMap<'a>), - Instances(NameMap<'a>), - Components(NameMap<'a>), - Funcs(NameMap<'a>), - Values(NameMap<'a>), + CoreFuncs(NameMap<'a, FuncIdx>), + CoreGlobals(NameMap<'a, GlobalIdx>), + CoreMemories(NameMap<'a, MemIdx>), + CoreTables(NameMap<'a, TableIdx>), + CoreModules(NameMap<'a, CoreModuleIdx>), + CoreInstances(NameMap<'a, CoreInstanceIdx>), + CoreTypes(NameMap<'a, TypeIdx>), + Types(NameMap<'a, ComponentTypeIdx>), + Instances(NameMap<'a, ComponentInstanceIdx>), + Components(NameMap<'a, ComponentIdx>), + Funcs(NameMap<'a, ComponentFuncIdx>), + Values(NameMap<'a, ComponentValueIdx>), /// An unknown [name subsection](https://webassembly.github.io/spec/core/appendix/custom.html#subsections). Unknown { @@ -38,6 +42,10 @@ pub enum ComponentName<'a> { }, } +fn name_map<'a, I>(reader: &BinaryReader<'a>) -> Result> { + NameMap::new(reader.shrink()) +} + impl<'a> Subsection<'a> for ComponentName<'a> { fn from_reader(id: u8, mut reader: BinaryReader<'a>) -> Result { let data = reader.remaining_buffer(); @@ -56,29 +64,15 @@ impl<'a> Subsection<'a> for ComponentName<'a> { name_range: offset..reader.original_position(), } } - 1 => { - let ctor: fn(NameMap<'a>) -> ComponentName<'a> = match reader.read_u8()? { - 0x00 => match reader.read_u8()? { - 0x00 => ComponentName::CoreFuncs, - 0x01 => ComponentName::CoreTables, - 0x02 => ComponentName::CoreMemories, - 0x03 => ComponentName::CoreGlobals, - 0x10 => ComponentName::CoreTypes, - 0x11 => ComponentName::CoreModules, - 0x12 => ComponentName::CoreInstances, - _ => { - return Ok(ComponentName::Unknown { - ty: 1, - data, - range: offset..offset + data.len(), - }); - } - }, - 0x01 => ComponentName::Funcs, - 0x02 => ComponentName::Values, - 0x03 => ComponentName::Types, - 0x04 => ComponentName::Components, - 0x05 => ComponentName::Instances, + 1 => match reader.read_u8()? { + 0x00 => match reader.read_u8()? { + 0x00 => ComponentName::CoreFuncs(name_map(&reader)?), + 0x01 => ComponentName::CoreTables(name_map(&reader)?), + 0x02 => ComponentName::CoreMemories(name_map(&reader)?), + 0x03 => ComponentName::CoreGlobals(name_map(&reader)?), + 0x10 => ComponentName::CoreTypes(name_map(&reader)?), + 0x11 => ComponentName::CoreModules(name_map(&reader)?), + 0x12 => ComponentName::CoreInstances(name_map(&reader)?), _ => { return Ok(ComponentName::Unknown { ty: 1, @@ -86,9 +80,20 @@ impl<'a> Subsection<'a> for ComponentName<'a> { range: offset..offset + data.len(), }); } - }; - ctor(NameMap::new(reader.shrink())?) - } + }, + 0x01 => ComponentName::Funcs(name_map(&reader)?), + 0x02 => ComponentName::Values(name_map(&reader)?), + 0x03 => ComponentName::Types(name_map(&reader)?), + 0x04 => ComponentName::Components(name_map(&reader)?), + 0x05 => ComponentName::Instances(name_map(&reader)?), + _ => { + return Ok(ComponentName::Unknown { + ty: 1, + data, + range: offset..offset + data.len(), + }); + } + }, ty => ComponentName::Unknown { ty, data, diff --git a/crates/wasmparser/src/readers/component/start.rs b/crates/wasmparser/src/readers/component/start.rs index f2cb9225d4..835b906fa2 100644 --- a/crates/wasmparser/src/readers/component/start.rs +++ b/crates/wasmparser/src/readers/component/start.rs @@ -1,23 +1,24 @@ use crate::limits::{MAX_WASM_FUNCTION_RETURNS, MAX_WASM_START_ARGS}; use crate::prelude::*; use crate::{BinaryReader, FromReader, Result}; +use wasm_types::{ComponentFuncIdx, ComponentValueIdx}; /// Represents the start function in a WebAssembly component. #[derive(Debug, Clone)] pub struct ComponentStartFunction { /// The index to the start function. - pub func_index: u32, + pub func_index: ComponentFuncIdx, /// The start function arguments. /// /// The arguments are specified by value index. - pub arguments: Box<[u32]>, + pub arguments: Box<[ComponentValueIdx]>, /// The number of expected results for the start function. pub results: u32, } impl<'a> FromReader<'a> for ComponentStartFunction { fn from_reader(reader: &mut BinaryReader<'a>) -> Result { - let func_index = reader.read_var_u32()?; + let func_index = reader.read_component_func_idx()?; let arguments = reader .read_iter(MAX_WASM_START_ARGS, "start function arguments")? .collect::>()?; diff --git a/crates/wasmparser/src/readers/component/types.rs b/crates/wasmparser/src/readers/component/types.rs index a56835fd82..f53387de3b 100644 --- a/crates/wasmparser/src/readers/component/types.rs +++ b/crates/wasmparser/src/readers/component/types.rs @@ -6,6 +6,7 @@ use crate::{ FromReader, Import, Result, SectionLimited, TypeRef, ValType, }; use core::fmt; +use wasm_types::{ComponentTypeIdx, FuncIdx}; /// Represents the kind of an outer core alias in a WebAssembly component. #[derive(Clone, Copy, Debug, Eq, PartialEq)] @@ -132,7 +133,7 @@ pub enum ComponentValType { /// The value type is a primitive type. Primitive(PrimitiveValType), /// The value type is a reference to a defined type. - Type(u32), + Type(ComponentTypeIdx), } impl<'a> FromReader<'a> for ComponentValType { @@ -142,7 +143,9 @@ impl<'a> FromReader<'a> for ComponentValType { return Ok(ComponentValType::Primitive(ty)); } - Ok(ComponentValType::Type(reader.read_var_s33()? as u32)) + Ok(ComponentValType::Type(ComponentTypeIdx( + reader.read_var_s33()? as u32, + ))) } } @@ -263,7 +266,7 @@ pub enum ComponentType<'a> { rep: ValType, /// An optionally-specified destructor to use for when this resource is /// no longer needed. - dtor: Option, + dtor: Option, }, } @@ -502,9 +505,9 @@ pub enum ComponentDefinedType<'a> { err: Option, }, /// An owned handle to a resource. - Own(u32), + Own(ComponentTypeIdx), /// A borrowed handle to a resource. - Borrow(u32), + Borrow(ComponentTypeIdx), /// A future type with the specified payload type. Future(Option), /// A stream type with the specified payload type. diff --git a/crates/wasmparser/src/readers/core/branch_hinting.rs b/crates/wasmparser/src/readers/core/branch_hinting.rs index a343e4990c..46b34ed206 100644 --- a/crates/wasmparser/src/readers/core/branch_hinting.rs +++ b/crates/wasmparser/src/readers/core/branch_hinting.rs @@ -1,4 +1,5 @@ use crate::{BinaryReader, FromReader, Result, SectionLimited}; +use wasm_types::FuncIdx; /// A reader for the `metadata.code.branch_hint` custom section. pub type BranchHintSectionReader<'a> = SectionLimited<'a, BranchHintFunction<'a>>; @@ -9,14 +10,14 @@ pub type BranchHintSectionReader<'a> = SectionLimited<'a, BranchHintFunction<'a> #[derive(Debug, Clone)] pub struct BranchHintFunction<'a> { /// The function that these branch hints apply to. - pub func: u32, + pub func: FuncIdx, /// The branch hints available for this function. pub hints: SectionLimited<'a, BranchHint>, } impl<'a> FromReader<'a> for BranchHintFunction<'a> { fn from_reader(reader: &mut BinaryReader<'a>) -> Result { - let func = reader.read_var_u32()?; + let func = reader.read_funcidx()?; // FIXME(#188) ideally wouldn't have to do skips here let hints = reader.skip(|reader| { let items_count = reader.read_var_u32()?; diff --git a/crates/wasmparser/src/readers/core/coredumps.rs b/crates/wasmparser/src/readers/core/coredumps.rs index cec9fe3450..2f2baf139d 100644 --- a/crates/wasmparser/src/readers/core/coredumps.rs +++ b/crates/wasmparser/src/readers/core/coredumps.rs @@ -1,5 +1,6 @@ use crate::prelude::*; use crate::{BinaryReader, FromReader, Result}; +use wasm_types::{FuncIdx, GlobalIdx, MemIdx}; /// The data portion of a custom section representing a core dump. Per the /// tool-conventions repo, this section just specifies the executable name that @@ -113,11 +114,11 @@ pub struct CoreDumpInstance { /// Which of the coredump's memories are this instance's memories, via /// indexing into the memory index space. - pub memories: Vec, + pub memories: Vec, /// Which of the coredump's globals are this instance's globals, via /// indexing into the global index space. - pub globals: Vec, + pub globals: Vec, } impl<'a> FromReader<'a> for CoreDumpInstance { @@ -129,12 +130,12 @@ impl<'a> FromReader<'a> for CoreDumpInstance { let module_index = reader.read_var_u32()?; let mut memories = vec![]; for _ in 0..reader.read_var_u32()? { - memories.push(reader.read_var_u32()?); + memories.push(reader.read_memidx()?); } let mut globals = vec![]; for _ in 0..reader.read_var_u32()? { - globals.push(reader.read_var_u32()?); + globals.push(reader.read_globalidx()?); } Ok(CoreDumpInstance { @@ -205,7 +206,7 @@ pub struct CoreDumpStackFrame { /// The instance that this stack frame belongs to. pub instanceidx: u32, /// The function index in the module - pub funcidx: u32, + pub funcidx: FuncIdx, /// The instruction's offset relative to the function's start pub codeoffset: u32, /// The locals for this stack frame (including function parameters) @@ -221,7 +222,7 @@ impl<'a> FromReader<'a> for CoreDumpStackFrame { bail!(pos, "invalid start byte for core dump stack frame"); } let instanceidx = reader.read_var_u32()?; - let funcidx = reader.read_var_u32()?; + let funcidx = reader.read_funcidx()?; let codeoffset = reader.read_var_u32()?; let mut locals = vec![]; for _ in 0..reader.read_var_u32()? { diff --git a/crates/wasmparser/src/readers/core/data.rs b/crates/wasmparser/src/readers/core/data.rs index 12e5d67bbd..69ba3ba8d7 100644 --- a/crates/wasmparser/src/readers/core/data.rs +++ b/crates/wasmparser/src/readers/core/data.rs @@ -15,6 +15,7 @@ use crate::{BinaryReader, BinaryReaderError, ConstExpr, FromReader, Result, SectionLimited}; use core::ops::Range; +use wasm_types::MemIdx; /// Represents a data segment in a core WebAssembly module. #[derive(Debug, Clone)] @@ -35,7 +36,7 @@ pub enum DataKind<'a> { /// The data segment is active. Active { /// The memory index for the data segment. - memory_index: u32, + memory_index: MemIdx, /// The initialization expression for the data segment. offset_expr: ConstExpr<'a>, }, @@ -65,11 +66,11 @@ impl<'a> FromReader<'a> for Data<'a> { let kind = match flags { 1 => DataKind::Passive, 0 | 2 => { - let memory_index = if flags == 0 { + let memory_index = MemIdx(if flags == 0 { 0 } else { reader.read_var_u32()? - }; + }); let offset_expr = reader.read()?; DataKind::Active { memory_index, diff --git a/crates/wasmparser/src/readers/core/elements.rs b/crates/wasmparser/src/readers/core/elements.rs index 85e2040ffc..fc8b17db29 100644 --- a/crates/wasmparser/src/readers/core/elements.rs +++ b/crates/wasmparser/src/readers/core/elements.rs @@ -18,6 +18,7 @@ use crate::{ SectionLimited, }; use core::ops::Range; +use wasm_types::{FuncIdx, TableIdx}; /// Represents a core WebAssembly element segment. #[derive(Clone)] @@ -38,7 +39,7 @@ pub enum ElementKind<'a> { /// The element segment is active. Active { /// The index of the table being initialized. - table_index: Option, + table_index: Option, /// The initial expression of the element segment. offset_expr: ConstExpr<'a>, }, @@ -50,7 +51,7 @@ pub enum ElementKind<'a> { #[derive(Clone)] pub enum ElementItems<'a> { /// This element contains function indices. - Functions(SectionLimited<'a, u32>), + Functions(SectionLimited<'a, FuncIdx>), /// This element contains constant expressions used to initialize the table. Expressions(RefType, SectionLimited<'a, ConstExpr<'a>>), } @@ -91,7 +92,7 @@ impl<'a> FromReader<'a> for Element<'a> { let table_index = if flags & 0b010 == 0 { None } else { - Some(reader.read_var_u32()?) + Some(reader.read_tableidx()?) }; let offset_expr = reader.read()?; ElementKind::Active { diff --git a/crates/wasmparser/src/readers/core/functions.rs b/crates/wasmparser/src/readers/core/functions.rs index ebddce05a3..438967d293 100644 --- a/crates/wasmparser/src/readers/core/functions.rs +++ b/crates/wasmparser/src/readers/core/functions.rs @@ -13,5 +13,7 @@ * limitations under the License. */ +use wasm_types::TypeIdx; + /// A reader for the function section of a WebAssembly module. -pub type FunctionSectionReader<'a> = crate::SectionLimited<'a, u32>; +pub type FunctionSectionReader<'a> = crate::SectionLimited<'a, TypeIdx>; diff --git a/crates/wasmparser/src/readers/core/imports.rs b/crates/wasmparser/src/readers/core/imports.rs index 44808d9039..510194ea6d 100644 --- a/crates/wasmparser/src/readers/core/imports.rs +++ b/crates/wasmparser/src/readers/core/imports.rs @@ -17,6 +17,7 @@ use crate::{ BinaryReader, ExternalKind, FromReader, GlobalType, MemoryType, Result, SectionLimited, TableType, TagType, }; +use wasm_types::TypeIdx; /// Represents a reference to a type definition in a WebAssembly module. #[derive(Debug, Clone, Copy, Eq, PartialEq)] @@ -24,7 +25,7 @@ pub enum TypeRef { /// The type is a function. /// /// The value is an index into the type section. - Func(u32), + Func(TypeIdx), /// The type is a table. Table(TableType), /// The type is a memory. @@ -66,7 +67,7 @@ impl<'a> FromReader<'a> for Import<'a> { impl<'a> FromReader<'a> for TypeRef { fn from_reader(reader: &mut BinaryReader<'a>) -> Result { Ok(match reader.read()? { - ExternalKind::Func => TypeRef::Func(reader.read_var_u32()?), + ExternalKind::Func => TypeRef::Func(reader.read_typeidx()?), ExternalKind::Table => TypeRef::Table(reader.read()?), ExternalKind::Memory => TypeRef::Memory(reader.read()?), ExternalKind::Global => TypeRef::Global(reader.read()?), diff --git a/crates/wasmparser/src/readers/core/linking.rs b/crates/wasmparser/src/readers/core/linking.rs index 2de9b7a10c..ee1d071948 100644 --- a/crates/wasmparser/src/readers/core/linking.rs +++ b/crates/wasmparser/src/readers/core/linking.rs @@ -3,6 +3,7 @@ use crate::{ BinaryReader, BinaryReaderError, FromReader, Result, SectionLimited, Subsection, Subsections, }; use core::ops::Range; +use wasm_types::{FuncIdx, GlobalIdx, TableIdx}; bitflags::bitflags! { /// Flags for WebAssembly symbols. @@ -229,7 +230,7 @@ pub enum SymbolInfo<'a> { /// The flags for the symbol. flags: SymbolFlags, /// The index of the function corresponding to this symbol. - index: u32, + index: FuncIdx, /// The name for the function, if it is defined or uses an explicit name. name: Option<&'a str>, }, @@ -247,7 +248,7 @@ pub enum SymbolInfo<'a> { /// The flags for the symbol. flags: SymbolFlags, /// The index of the global corresponding to this symbol. - index: u32, + index: GlobalIdx, /// The name for the global, if it is defined or uses an explicit name. name: Option<&'a str>, }, @@ -272,7 +273,7 @@ pub enum SymbolInfo<'a> { /// The flags for the symbol. flags: SymbolFlags, /// The index of the table corresponding to this symbol. - index: u32, + index: TableIdx, /// The name for the table, if it is defined or uses an explicit name. name: Option<&'a str>, }, @@ -303,10 +304,22 @@ impl<'a> FromReader<'a> for SymbolInfo<'a> { false => None, }; Ok(match kind { - SYMTAB_FUNCTION => Self::Func { flags, index, name }, - SYMTAB_GLOBAL => Self::Global { flags, index, name }, + SYMTAB_FUNCTION => Self::Func { + flags, + index: FuncIdx(index), + name, + }, + SYMTAB_GLOBAL => Self::Global { + flags, + index: GlobalIdx(index), + name, + }, SYMTAB_EVENT => Self::Event { flags, index, name }, - SYMTAB_TABLE => Self::Table { flags, index, name }, + SYMTAB_TABLE => Self::Table { + flags, + index: TableIdx(index), + name, + }, _ => unreachable!(), }) } diff --git a/crates/wasmparser/src/readers/core/names.rs b/crates/wasmparser/src/readers/core/names.rs index d53211ad8a..1da7cdf4de 100644 --- a/crates/wasmparser/src/readers/core/names.rs +++ b/crates/wasmparser/src/readers/core/names.rs @@ -13,26 +13,31 @@ * limitations under the License. */ +use wasm_types::{ + AbsoluteLabelIdx, DataIdx, ElemIdx, FieldIdx, FuncIdx, GlobalIdx, LocalIdx, MemIdx, TableIdx, + TagIdx, TypeIdx, +}; + use crate::{ BinaryReader, BinaryReaderError, FromReader, Result, SectionLimited, Subsection, Subsections, }; use core::ops::Range; /// Represents a name map from the names custom section. -pub type NameMap<'a> = SectionLimited<'a, Naming<'a>>; +pub type NameMap<'a, I> = SectionLimited<'a, Naming<'a, I>>; /// Represents a name for an index from the names section. #[derive(Debug, Copy, Clone)] -pub struct Naming<'a> { +pub struct Naming<'a, I> { /// The index being named. - pub index: u32, + pub index: I, /// The name for the index. pub name: &'a str, } -impl<'a> FromReader<'a> for Naming<'a> { +impl<'a, I: FromReader<'a>> FromReader<'a> for Naming<'a, I> { fn from_reader(reader: &mut BinaryReader<'a>) -> Result { - let index = reader.read_var_u32()?; + let index = reader.read()?; // This seems to match what browsers do where they don't limit the // length of names in the `name` section while they do limit the names // in the import and export section for example. @@ -42,20 +47,20 @@ impl<'a> FromReader<'a> for Naming<'a> { } /// Represents a reader for indirect names from the names custom section. -pub type IndirectNameMap<'a> = SectionLimited<'a, IndirectNaming<'a>>; +pub type IndirectNameMap<'a, I, J> = SectionLimited<'a, IndirectNaming<'a, I, J>>; /// Represents an indirect name in the names custom section. #[derive(Debug, Clone)] -pub struct IndirectNaming<'a> { +pub struct IndirectNaming<'a, I, J> { /// The indirect index of the name. - pub index: u32, + pub index: I, /// The map of names within the `index` prior. - pub names: NameMap<'a>, + pub names: NameMap<'a, J>, } -impl<'a> FromReader<'a> for IndirectNaming<'a> { +impl<'a, I: FromReader<'a>, J: FromReader<'a>> FromReader<'a> for IndirectNaming<'a, I, J> { fn from_reader(reader: &mut BinaryReader<'a>) -> Result { - let index = reader.read_var_u32()?; + let index = reader.read()?; // Skip the `NameMap` manually here. // @@ -87,27 +92,27 @@ pub enum Name<'a> { name_range: Range, }, /// The name is for the functions. - Function(NameMap<'a>), + Function(NameMap<'a, FuncIdx>), /// The name is for the function locals. - Local(IndirectNameMap<'a>), + Local(IndirectNameMap<'a, FuncIdx, LocalIdx>), /// The name is for the function labels. - Label(IndirectNameMap<'a>), + Label(IndirectNameMap<'a, FuncIdx, AbsoluteLabelIdx>), /// The name is for the types. - Type(NameMap<'a>), + Type(NameMap<'a, TypeIdx>), /// The name is for the tables. - Table(NameMap<'a>), + Table(NameMap<'a, TableIdx>), /// The name is for the memories. - Memory(NameMap<'a>), + Memory(NameMap<'a, MemIdx>), /// The name is for the globals. - Global(NameMap<'a>), + Global(NameMap<'a, GlobalIdx>), /// The name is for the element segments. - Element(NameMap<'a>), + Element(NameMap<'a, ElemIdx>), /// The name is for the data segments. - Data(NameMap<'a>), + Data(NameMap<'a, DataIdx>), /// The name is for fields. - Field(IndirectNameMap<'a>), + Field(IndirectNameMap<'a, TypeIdx, FieldIdx>), /// The name is for tags. - Tag(NameMap<'a>), + Tag(NameMap<'a, TagIdx>), /// An unknown [name subsection](https://webassembly.github.io/spec/core/appendix/custom.html#subsections). Unknown { /// The identifier for this subsection. diff --git a/crates/wasmparser/src/readers/core/operators.rs b/crates/wasmparser/src/readers/core/operators.rs index 84c8ff840c..e9112bf78a 100644 --- a/crates/wasmparser/src/readers/core/operators.rs +++ b/crates/wasmparser/src/readers/core/operators.rs @@ -16,6 +16,7 @@ use crate::limits::{MAX_WASM_CATCHES, MAX_WASM_HANDLERS}; use crate::prelude::*; use crate::{BinaryReader, BinaryReaderError, FromReader, Result, ValType}; +use wasm_types::{LabelIdx, MemIdx, TagIdx, TypeIdx}; /// Represents a block type. #[derive(Debug, Copy, Clone, PartialEq, Eq)] @@ -27,7 +28,7 @@ pub enum BlockType { /// The block is described by a function type. /// /// The index is to a function type in the types section. - FuncType(u32), + FuncType(TypeIdx), } /// The kind of a control flow `Frame`. @@ -90,7 +91,7 @@ pub struct MemArg { /// Note that this points within the module's own memory index space, and /// is always zero unless the multi-memory proposal of WebAssembly is /// enabled. - pub memory: u32, + pub memory: MemIdx, } /// A br_table entries representation. @@ -98,7 +99,7 @@ pub struct MemArg { pub struct BrTable<'a> { pub(crate) reader: crate::BinaryReader<'a>, pub(crate) cnt: u32, - pub(crate) default: u32, + pub(crate) default: LabelIdx, } impl PartialEq for BrTable<'_> { @@ -558,13 +559,13 @@ pub struct TryTable { #[allow(missing_docs)] pub enum Catch { /// Equivalent of `catch` - One { tag: u32, label: u32 }, + One { tag: TagIdx, label: LabelIdx }, /// Equivalent of `catch_ref` - OneRef { tag: u32, label: u32 }, + OneRef { tag: TagIdx, label: LabelIdx }, /// Equivalent of `catch_all` - All { label: u32 }, + All { label: LabelIdx }, /// Equivalent of `catch_all_ref` - AllRef { label: u32 }, + AllRef { label: LabelIdx }, } impl<'a> FromReader<'a> for TryTable { @@ -581,18 +582,18 @@ impl<'a> FromReader<'a> for Catch { fn from_reader(reader: &mut BinaryReader<'a>) -> Result { Ok(match reader.read_u8()? { 0x00 => Catch::One { - tag: reader.read_var_u32()?, - label: reader.read_var_u32()?, + tag: reader.read_tagidx()?, + label: reader.read_labelidx()?, }, 0x01 => Catch::OneRef { - tag: reader.read_var_u32()?, - label: reader.read_var_u32()?, + tag: reader.read_tagidx()?, + label: reader.read_labelidx()?, }, 0x02 => Catch::All { - label: reader.read_var_u32()?, + label: reader.read_labelidx()?, }, 0x03 => Catch::AllRef { - label: reader.read_var_u32()?, + label: reader.read_labelidx()?, }, x => return reader.invalid_leading_byte(x, "catch"), @@ -614,9 +615,9 @@ pub struct ResumeTable { #[allow(missing_docs)] pub enum Handle { /// Equivalent of `(on $tag $lbl)`. - OnLabel { tag: u32, label: u32 }, + OnLabel { tag: TagIdx, label: LabelIdx }, /// Equivalent of `(on $tag switch)`. - OnSwitch { tag: u32 }, + OnSwitch { tag: TagIdx }, } impl ResumeTable { @@ -640,11 +641,11 @@ impl<'a> FromReader<'a> for Handle { fn from_reader(reader: &mut BinaryReader<'a>) -> Result { Ok(match reader.read_u8()? { 0x00 => Handle::OnLabel { - tag: reader.read_var_u32()?, - label: reader.read_var_u32()?, + tag: reader.read_tagidx()?, + label: reader.read_labelidx()?, }, 0x01 => Handle::OnSwitch { - tag: reader.read_var_u32()?, + tag: reader.read_tagidx()?, }, x => return reader.invalid_leading_byte(x, "on clause"), }) diff --git a/crates/wasmparser/src/readers/core/tags.rs b/crates/wasmparser/src/readers/core/tags.rs index 746b3ea7ac..9e6e4306ca 100644 --- a/crates/wasmparser/src/readers/core/tags.rs +++ b/crates/wasmparser/src/readers/core/tags.rs @@ -26,7 +26,7 @@ impl<'a> FromReader<'a> for TagType { } Ok(TagType { kind: TagKind::Exception, - func_type_idx: reader.read_var_u32()?, + func_type_idx: reader.read_typeidx()?, }) } } diff --git a/crates/wasmparser/src/readers/core/types.rs b/crates/wasmparser/src/readers/core/types.rs index 5147d26a95..aa31cf309a 100644 --- a/crates/wasmparser/src/readers/core/types.rs +++ b/crates/wasmparser/src/readers/core/types.rs @@ -25,6 +25,8 @@ use crate::{BinaryReader, BinaryReaderError, FromReader, Result, SectionLimited} use core::cmp::Ordering; use core::fmt::{self, Debug}; use core::hash::{Hash, Hasher}; +use index_vec::IndexBox; +use wasm_types::{FieldIdx, TypeIdx}; #[cfg(feature = "validate")] mod matches; @@ -121,9 +123,9 @@ impl PackedIndex { /// Construct a `PackedIndex` from an index into a module's types space. #[inline] - pub fn from_module_index(index: u32) -> Option { - if PackedIndex::can_represent_index(index) { - Some(PackedIndex(PackedIndex::MODULE_KIND | index)) + pub fn from_module_index(index: TypeIdx) -> Option { + if PackedIndex::can_represent_index(index.0) { + Some(PackedIndex(PackedIndex::MODULE_KIND | index.0)) } else { None } @@ -168,7 +170,7 @@ impl PackedIndex { #[inline] pub fn unpack(&self) -> UnpackedIndex { match self.kind() { - Self::MODULE_KIND => UnpackedIndex::Module(self.index()), + Self::MODULE_KIND => UnpackedIndex::Module(TypeIdx(self.index())), Self::REC_GROUP_KIND => UnpackedIndex::RecGroup(self.index()), #[cfg(feature = "validate")] Self::ID_KIND => UnpackedIndex::Id( @@ -180,9 +182,9 @@ impl PackedIndex { /// Get the underlying index into a module's types space, if any. #[inline] - pub fn as_module_index(&self) -> Option { + pub fn as_module_index(&self) -> Option { if self.kind() == Self::MODULE_KIND { - Some(self.index()) + Some(TypeIdx(self.index())) } else { None } @@ -242,7 +244,7 @@ impl fmt::Display for PackedIndex { #[derive(Clone, Copy, Debug, PartialEq, Eq, Ord, PartialOrd, Hash)] pub enum UnpackedIndex { /// An index into a Wasm module's types space. - Module(u32), + Module(TypeIdx), /// An index into the containing recursion group's elements. RecGroup(u32), @@ -274,7 +276,7 @@ impl UnpackedIndex { /// Get the underlying index into a module's types space, if any. #[inline] - pub fn as_module_index(&self) -> Option { + pub fn as_module_index(&self) -> Option { if let Self::Module(i) = *self { Some(i) } else { @@ -795,7 +797,7 @@ impl StorageType { #[derive(Debug, Clone, Eq, PartialEq, Ord, PartialOrd, Hash)] pub struct StructType { /// Struct fields. - pub fields: Box<[FieldType]>, + pub fields: IndexBox, } /// Represents a type of a continuation in a WebAssembly module. @@ -1769,7 +1771,7 @@ impl<'a> FromReader<'a> for HeapType { // Be sure to update `reader` with the state after the s33 was // read. *reader = clone; - let idx = PackedIndex::from_module_index(idx).ok_or_else(|| { + let idx = PackedIndex::from_module_index(TypeIdx(idx)).ok_or_else(|| { BinaryReaderError::new( "type index greater than implementation limits", reader.original_position(), @@ -1939,7 +1941,7 @@ pub struct TagType { /// The kind of tag pub kind: TagKind, /// The function type this tag uses. - pub func_type_idx: u32, + pub func_type_idx: TypeIdx, } /// A reader for the type section of a WebAssembly module. @@ -2032,7 +2034,7 @@ impl<'a> FromReader<'a> for SubType { Ok(match reader.read_u8()? { opcode @ (0x4f | 0x50) => { let idx_iter = reader.read_iter(MAX_WASM_SUPERTYPES, "supertype idxs")?; - let idxs = idx_iter.collect::>>()?; + let idxs = idx_iter.collect::>>()?; if idxs.len() > 1 { return Err(BinaryReaderError::new( "multiple supertypes not supported", @@ -2117,7 +2119,7 @@ impl<'a> FromReader<'a> for StructType { impl<'a> FromReader<'a> for ContType { fn from_reader(reader: &mut BinaryReader<'a>) -> Result { let idx = match u32::try_from(reader.read_var_s33()?) { - Ok(idx) => idx, + Ok(idx) => TypeIdx(idx), Err(_) => { bail!(reader.original_position(), "invalid continuation type"); } diff --git a/crates/wasmparser/src/resources.rs b/crates/wasmparser/src/resources.rs index d5873fcaef..ac68cf7c09 100644 --- a/crates/wasmparser/src/resources.rs +++ b/crates/wasmparser/src/resources.rs @@ -17,6 +17,7 @@ use crate::{ types::CoreTypeId, BinaryReaderError, FuncType, GlobalType, HeapType, MemoryType, RefType, SubType, TableType, ValType, WasmFeatures, }; +use wasm_types::{ElemIdx, FuncIdx, GlobalIdx, MemIdx, TableIdx, TagIdx, TypeIdx}; /// Types that qualify as Wasm validation database. /// @@ -30,39 +31,39 @@ pub trait WasmModuleResources { /// Returns the table at given index if any. /// /// The table element type must be canonicalized. - fn table_at(&self, at: u32) -> Option; + fn table_at(&self, at: TableIdx) -> Option; /// Returns the linear memory at given index. - fn memory_at(&self, at: u32) -> Option; + fn memory_at(&self, at: MemIdx) -> Option; /// Returns the tag at given index. /// /// The tag's function type must be canonicalized. - fn tag_at(&self, at: u32) -> Option<&FuncType>; + fn tag_at(&self, at: TagIdx) -> Option<&FuncType>; /// Returns the global variable at given index. /// /// The global's value type must be canonicalized. - fn global_at(&self, at: u32) -> Option; + fn global_at(&self, at: GlobalIdx) -> Option; /// Returns the `SubType` associated with the given type index. /// /// The sub type must be canonicalized. - fn sub_type_at(&self, type_index: u32) -> Option<&SubType>; + fn sub_type_at(&self, type_index: TypeIdx) -> Option<&SubType>; /// Returns the `SubType` associated with the given core type id. fn sub_type_at_id(&self, id: CoreTypeId) -> &SubType; /// Returns the type ID associated with the given function index. - fn type_id_of_function(&self, func_idx: u32) -> Option; + fn type_id_of_function(&self, func_idx: FuncIdx) -> Option; /// Returns the type index associated with the given function index. - fn type_index_of_function(&self, func_index: u32) -> Option; + fn type_index_of_function(&self, func_index: FuncIdx) -> Option; /// Returns the element type at the given index. /// /// The `RefType` must be canonicalized. - fn element_type_at(&self, at: u32) -> Option; + fn element_type_at(&self, at: ElemIdx) -> Option; /// Is `a` a subtype of `b`? fn is_subtype(&self, a: ValType, b: ValType) -> bool; @@ -128,35 +129,35 @@ pub trait WasmModuleResources { /// Returns whether the function index is referenced in the module anywhere /// outside of the start/function sections. - fn is_function_referenced(&self, idx: u32) -> bool; + fn is_function_referenced(&self, idx: FuncIdx) -> bool; } impl WasmModuleResources for &'_ T where T: ?Sized + WasmModuleResources, { - fn table_at(&self, at: u32) -> Option { + fn table_at(&self, at: TableIdx) -> Option { T::table_at(self, at) } - fn memory_at(&self, at: u32) -> Option { + fn memory_at(&self, at: MemIdx) -> Option { T::memory_at(self, at) } - fn tag_at(&self, at: u32) -> Option<&FuncType> { + fn tag_at(&self, at: TagIdx) -> Option<&FuncType> { T::tag_at(self, at) } - fn global_at(&self, at: u32) -> Option { + fn global_at(&self, at: GlobalIdx) -> Option { T::global_at(self, at) } - fn sub_type_at(&self, at: u32) -> Option<&SubType> { + fn sub_type_at(&self, at: TypeIdx) -> Option<&SubType> { T::sub_type_at(self, at) } fn sub_type_at_id(&self, at: CoreTypeId) -> &SubType { T::sub_type_at_id(self, at) } - fn type_id_of_function(&self, func_idx: u32) -> Option { + fn type_id_of_function(&self, func_idx: FuncIdx) -> Option { T::type_id_of_function(self, func_idx) } - fn type_index_of_function(&self, func_idx: u32) -> Option { + fn type_index_of_function(&self, func_idx: FuncIdx) -> Option { T::type_index_of_function(self, func_idx) } fn check_heap_type(&self, t: &mut HeapType, offset: usize) -> Result<(), BinaryReaderError> { @@ -165,7 +166,7 @@ where fn top_type(&self, heap_type: &HeapType) -> HeapType { T::top_type(self, heap_type) } - fn element_type_at(&self, at: u32) -> Option { + fn element_type_at(&self, at: ElemIdx) -> Option { T::element_type_at(self, at) } fn is_subtype(&self, a: ValType, b: ValType) -> bool { @@ -180,7 +181,7 @@ where fn data_count(&self) -> Option { T::data_count(self) } - fn is_function_referenced(&self, idx: u32) -> bool { + fn is_function_referenced(&self, idx: FuncIdx) -> bool { T::is_function_referenced(self, idx) } } @@ -189,23 +190,23 @@ impl WasmModuleResources for alloc::sync::Arc where T: WasmModuleResources, { - fn table_at(&self, at: u32) -> Option { + fn table_at(&self, at: TableIdx) -> Option { T::table_at(self, at) } - fn memory_at(&self, at: u32) -> Option { + fn memory_at(&self, at: MemIdx) -> Option { T::memory_at(self, at) } - fn tag_at(&self, at: u32) -> Option<&FuncType> { + fn tag_at(&self, at: TagIdx) -> Option<&FuncType> { T::tag_at(self, at) } - fn global_at(&self, at: u32) -> Option { + fn global_at(&self, at: GlobalIdx) -> Option { T::global_at(self, at) } - fn sub_type_at(&self, type_idx: u32) -> Option<&SubType> { + fn sub_type_at(&self, type_idx: TypeIdx) -> Option<&SubType> { T::sub_type_at(self, type_idx) } @@ -213,11 +214,11 @@ where T::sub_type_at_id(self, id) } - fn type_id_of_function(&self, func_idx: u32) -> Option { + fn type_id_of_function(&self, func_idx: FuncIdx) -> Option { T::type_id_of_function(self, func_idx) } - fn type_index_of_function(&self, func_idx: u32) -> Option { + fn type_index_of_function(&self, func_idx: FuncIdx) -> Option { T::type_index_of_function(self, func_idx) } @@ -229,7 +230,7 @@ where T::top_type(self, heap_type) } - fn element_type_at(&self, at: u32) -> Option { + fn element_type_at(&self, at: ElemIdx) -> Option { T::element_type_at(self, at) } @@ -249,7 +250,7 @@ where T::data_count(self) } - fn is_function_referenced(&self, idx: u32) -> bool { + fn is_function_referenced(&self, idx: FuncIdx) -> bool { T::is_function_referenced(self, idx) } } diff --git a/crates/wasmparser/src/validator.rs b/crates/wasmparser/src/validator.rs index 11b30088ca..239822f9db 100644 --- a/crates/wasmparser/src/validator.rs +++ b/crates/wasmparser/src/validator.rs @@ -22,6 +22,7 @@ use ::core::mem; use ::core::ops::Range; use ::core::sync::atomic::{AtomicUsize, Ordering}; use alloc::sync::Arc; +use wasm_types::FuncIdx; /// Test whether the given buffer contains a valid WebAssembly module or component, /// analogous to [`WebAssembly.validate`][js] in the JS API. @@ -924,7 +925,7 @@ impl Validator { /// Validates [`Payload::StartSection`](crate::Payload). /// /// This method should only be called when parsing a module. - pub fn start_section(&mut self, func: u32, range: &Range) -> Result<()> { + pub fn start_section(&mut self, func: FuncIdx, range: &Range) -> Result<()> { let offset = range.start; self.state.ensure_module("start", offset)?; let state = self.module.as_mut().unwrap(); diff --git a/crates/wasmparser/src/validator/component.rs b/crates/wasmparser/src/validator/component.rs index 06aadcbeda..442edef8e1 100644 --- a/crates/wasmparser/src/validator/component.rs +++ b/crates/wasmparser/src/validator/component.rs @@ -24,6 +24,11 @@ use crate::{ TypeBounds, ValType, WasmFeatures, }; use core::mem; +use index_vec::IndexVec; +use wasm_types::{ + ComponentFuncIdx, ComponentIdx, ComponentInstanceIdx, ComponentTypeIdx, CoreInstanceIdx, + CoreModuleIdx, FuncIdx, GlobalIdx, MemIdx, TableIdx, TagIdx, TypeIdx, ComponentValueIdx, +}; fn to_kebab_str<'a>(s: &'a str, desc: &str, offset: usize) -> Result<&'a KebabStr> { match KebabStr::new(s) { @@ -44,21 +49,21 @@ pub(crate) struct ComponentState { kind: ComponentKind, // Core index spaces - pub core_types: Vec, - pub core_funcs: Vec, - pub core_tags: Vec, - pub core_modules: Vec, - pub core_instances: Vec, - pub core_memories: Vec, - pub core_tables: Vec, - pub core_globals: Vec, + pub core_types: IndexVec, + pub core_funcs: IndexVec, + pub core_tags: IndexVec, + pub core_modules: IndexVec, + pub core_instances: IndexVec, + pub core_memories: IndexVec, + pub core_tables: IndexVec, + pub core_globals: IndexVec, // Component index spaces - pub types: Vec, - pub funcs: Vec, - pub values: Vec<(ComponentValType, bool)>, - pub instances: Vec, - pub components: Vec, + pub types: IndexVec, + pub funcs: IndexVec, + pub values: IndexVec, + pub instances: IndexVec, + pub components: IndexVec, pub imports: IndexMap, pub import_names: IndexSet, @@ -954,8 +959,8 @@ impl ComponentState { pub fn lift_function( &mut self, - core_func_index: u32, - type_index: u32, + core_func_index: FuncIdx, + type_index: ComponentTypeIdx, options: Vec, types: &TypeList, offset: usize, @@ -1011,15 +1016,14 @@ impl ComponentState { ); } - self.funcs - .push(self.types[type_index as usize].unwrap_func()); + self.funcs.push(self.types[type_index].unwrap_func()); Ok(()) } pub fn lower_function( &mut self, - func_index: u32, + func_index: ComponentFuncIdx, options: Vec, types: &mut TypeAlloc, offset: usize, @@ -1048,7 +1052,7 @@ impl ComponentState { pub fn resource_new( &mut self, - resource: u32, + resource: ComponentTypeIdx, types: &mut TypeAlloc, offset: usize, ) -> Result<()> { @@ -1060,7 +1064,7 @@ impl ComponentState { pub fn resource_drop( &mut self, - resource: u32, + resource: ComponentTypeIdx, types: &mut TypeAlloc, offset: usize, ) -> Result<()> { @@ -1072,7 +1076,7 @@ impl ComponentState { pub fn resource_rep( &mut self, - resource: u32, + resource: ComponentTypeIdx, types: &mut TypeAlloc, offset: usize, ) -> Result<()> { @@ -1146,7 +1150,7 @@ impl ComponentState { pub fn task_wait( &mut self, _async_: bool, - memory: u32, + memory: MemIdx, types: &mut TypeAlloc, offset: usize, features: &WasmFeatures, @@ -1168,7 +1172,7 @@ impl ComponentState { pub fn task_poll( &mut self, _async_: bool, - memory: u32, + memory: MemIdx, types: &mut TypeAlloc, offset: usize, features: &WasmFeatures, @@ -1226,7 +1230,7 @@ impl ComponentState { pub fn stream_new( &mut self, - ty: u32, + ty: ComponentTypeIdx, types: &mut TypeAlloc, offset: usize, features: &WasmFeatures, @@ -1250,7 +1254,7 @@ impl ComponentState { pub fn stream_read( &mut self, - ty: u32, + ty: ComponentTypeIdx, options: Vec, types: &mut TypeAlloc, offset: usize, @@ -1282,7 +1286,7 @@ impl ComponentState { pub fn stream_write( &mut self, - ty: u32, + ty: ComponentTypeIdx, options: Vec, types: &mut TypeAlloc, offset: usize, @@ -1312,7 +1316,7 @@ impl ComponentState { pub fn stream_cancel_read( &mut self, - ty: u32, + ty: ComponentTypeIdx, _async_: bool, types: &mut TypeAlloc, offset: usize, @@ -1337,7 +1341,7 @@ impl ComponentState { pub fn stream_cancel_write( &mut self, - ty: u32, + ty: ComponentTypeIdx, _async_: bool, types: &mut TypeAlloc, offset: usize, @@ -1362,7 +1366,7 @@ impl ComponentState { pub fn stream_close_readable( &mut self, - ty: u32, + ty: ComponentTypeIdx, types: &mut TypeAlloc, offset: usize, features: &WasmFeatures, @@ -1386,7 +1390,7 @@ impl ComponentState { pub fn stream_close_writable( &mut self, - ty: u32, + ty: ComponentTypeIdx, types: &mut TypeAlloc, offset: usize, features: &WasmFeatures, @@ -1410,7 +1414,7 @@ impl ComponentState { pub fn future_new( &mut self, - ty: u32, + ty: ComponentTypeIdx, types: &mut TypeAlloc, offset: usize, features: &WasmFeatures, @@ -1434,7 +1438,7 @@ impl ComponentState { pub fn future_read( &mut self, - ty: u32, + ty: ComponentTypeIdx, options: Vec, types: &mut TypeAlloc, offset: usize, @@ -1466,7 +1470,7 @@ impl ComponentState { pub fn future_write( &mut self, - ty: u32, + ty: ComponentTypeIdx, options: Vec, types: &mut TypeAlloc, offset: usize, @@ -1496,7 +1500,7 @@ impl ComponentState { pub fn future_cancel_read( &mut self, - ty: u32, + ty: ComponentTypeIdx, _async_: bool, types: &mut TypeAlloc, offset: usize, @@ -1521,7 +1525,7 @@ impl ComponentState { pub fn future_cancel_write( &mut self, - ty: u32, + ty: ComponentTypeIdx, _async_: bool, types: &mut TypeAlloc, offset: usize, @@ -1546,7 +1550,7 @@ impl ComponentState { pub fn future_close_readable( &mut self, - ty: u32, + ty: ComponentTypeIdx, types: &mut TypeAlloc, offset: usize, features: &WasmFeatures, @@ -1570,7 +1574,7 @@ impl ComponentState { pub fn future_close_writable( &mut self, - ty: u32, + ty: ComponentTypeIdx, types: &mut TypeAlloc, offset: usize, features: &WasmFeatures, @@ -1658,7 +1662,12 @@ impl ComponentState { Ok(()) } - fn check_local_resource(&self, idx: u32, types: &TypeList, offset: usize) -> Result { + fn check_local_resource( + &self, + idx: ComponentTypeIdx, + types: &TypeList, + offset: usize, + ) -> Result { let resource = self.resource_at(idx, types, offset)?; match self .defined_resources @@ -1672,7 +1681,7 @@ impl ComponentState { fn resource_at<'a>( &self, - idx: u32, + idx: ComponentTypeIdx, _types: &'a TypeList, offset: usize, ) -> Result { @@ -1684,7 +1693,7 @@ impl ComponentState { pub fn thread_spawn( &mut self, - func_ty_index: u32, + func_ty_index: TypeIdx, types: &mut TypeAlloc, offset: usize, features: &WasmFeatures, @@ -1821,16 +1830,16 @@ impl ComponentState { ), crate::ComponentAlias::Outer { kind, count, index } => match kind { ComponentOuterAliasKind::CoreModule => { - Self::alias_module(components, count, index, offset) + Self::alias_module(components, count, CoreModuleIdx(index), offset) } ComponentOuterAliasKind::CoreType => { - Self::alias_core_type(components, count, index, offset) + Self::alias_core_type(components, count, TypeIdx(index), offset) } ComponentOuterAliasKind::Type => { - Self::alias_type(components, count, index, types, offset) + Self::alias_type(components, count, ComponentTypeIdx(index), types, offset) } ComponentOuterAliasKind::Component => { - Self::alias_component(components, count, index, offset) + Self::alias_component(components, count, ComponentIdx(index), offset) } }, } @@ -1838,8 +1847,8 @@ impl ComponentState { pub fn add_start( &mut self, - func_index: u32, - args: &[u32], + func_index: ComponentFuncIdx, + args: &[ComponentValueIdx], results: u32, features: &WasmFeatures, types: &mut TypeList, @@ -2161,29 +2170,29 @@ impl ComponentState { ) -> Result { let actual = match export.kind { ComponentExternalKind::Module => { - ComponentEntityType::Module(self.module_at(export.index, offset)?) + ComponentEntityType::Module(self.module_at(CoreModuleIdx(export.index), offset)?) } ComponentExternalKind::Func => { - ComponentEntityType::Func(self.function_at(export.index, offset)?) + ComponentEntityType::Func(self.function_at(ComponentFuncIdx(export.index), offset)?) } ComponentExternalKind::Value => { self.check_value_support(features, offset)?; - ComponentEntityType::Value(*self.value_at(export.index, offset)?) + ComponentEntityType::Value(*self.value_at(ComponentValueIdx(export.index), offset)?) } ComponentExternalKind::Type => { - let referenced = self.component_type_at(export.index, offset)?; + let referenced = self.component_type_at(ComponentTypeIdx(export.index), offset)?; let created = types.with_unique(referenced); ComponentEntityType::Type { referenced, created, } } - ComponentExternalKind::Instance => { - ComponentEntityType::Instance(self.instance_at(export.index, offset)?) - } - ComponentExternalKind::Component => { - ComponentEntityType::Component(self.component_at(export.index, offset)?) - } + ComponentExternalKind::Instance => ComponentEntityType::Instance( + self.instance_at(ComponentInstanceIdx(export.index), offset)?, + ), + ComponentExternalKind::Component => ComponentEntityType::Component( + self.component_at(ComponentIdx(export.index), offset)?, + ), }; let ascribed = match &export.ty { @@ -2221,18 +2230,20 @@ impl ComponentState { crate::OuterAliasKind::Type => { let ty = if count == 0 { // Local alias, check the local module state - ComponentCoreTypeId::Sub(state.type_id_at(index, offset)?) + ComponentCoreTypeId::Sub(state.type_id_at(TypeIdx(index), offset)?) } else { // Otherwise, check the enclosing component state let component = Self::check_alias_count(components, count - 1, offset)?; - component.core_type_at(index, offset)? + component.core_type_at(TypeIdx(index), offset)? }; check_max(state.types.len(), 1, MAX_WASM_TYPES, "types", offset)?; match ty { - ComponentCoreTypeId::Sub(ty) => state.types.push(ty), + ComponentCoreTypeId::Sub(ty) => { + state.types.push(ty); + } // TODO https://github.com/WebAssembly/component-model/issues/265 ComponentCoreTypeId::Module(_) => bail!( offset, @@ -2434,7 +2445,7 @@ impl ComponentState { fn instantiate_core_module( &self, - module_index: u32, + module_index: CoreModuleIdx, module_args: Vec, types: &mut TypeAlloc, offset: usize, @@ -2462,7 +2473,8 @@ impl ComponentState { for module_arg in module_args { match module_arg.kind { InstantiationArgKind::Instance => { - let instance_type = &types[self.core_instance_at(module_arg.index, offset)?]; + let instance_type = + &types[self.core_instance_at(CoreInstanceIdx(module_arg.index), offset)?]; insert_arg(module_arg.name, instance_type, &mut args, offset)?; } } @@ -2511,7 +2523,7 @@ impl ComponentState { fn instantiate_component( &mut self, - component_index: u32, + component_index: ComponentIdx, component_args: Vec, features: &WasmFeatures, types: &mut TypeAlloc, @@ -2523,24 +2535,27 @@ impl ComponentState { // Populate the arguments for component_arg in component_args { let ty = match component_arg.kind { - ComponentExternalKind::Module => { - ComponentEntityType::Module(self.module_at(component_arg.index, offset)?) - } - ComponentExternalKind::Component => { - ComponentEntityType::Component(self.component_at(component_arg.index, offset)?) - } - ComponentExternalKind::Instance => { - ComponentEntityType::Instance(self.instance_at(component_arg.index, offset)?) - } - ComponentExternalKind::Func => { - ComponentEntityType::Func(self.function_at(component_arg.index, offset)?) - } + ComponentExternalKind::Module => ComponentEntityType::Module( + self.module_at(CoreModuleIdx(component_arg.index), offset)?, + ), + ComponentExternalKind::Component => ComponentEntityType::Component( + self.component_at(ComponentIdx(component_arg.index), offset)?, + ), + ComponentExternalKind::Instance => ComponentEntityType::Instance( + self.instance_at(ComponentInstanceIdx(component_arg.index), offset)?, + ), + ComponentExternalKind::Func => ComponentEntityType::Func( + self.function_at(ComponentFuncIdx(component_arg.index), offset)?, + ), ComponentExternalKind::Value => { self.check_value_support(features, offset)?; - ComponentEntityType::Value(*self.value_at(component_arg.index, offset)?) + ComponentEntityType::Value( + *self.value_at(ComponentValueIdx(component_arg.index), offset)?, + ) } ComponentExternalKind::Type => { - let ty = self.component_type_at(component_arg.index, offset)?; + let ty = + self.component_type_at(ComponentTypeIdx(component_arg.index), offset)?; ComponentEntityType::Type { referenced: ty, created: ty, @@ -2798,14 +2813,14 @@ impl ComponentState { for export in exports { assert!(export.ty.is_none()); let ty = match export.kind { - ComponentExternalKind::Module => { - ComponentEntityType::Module(self.module_at(export.index, offset)?) - } - ComponentExternalKind::Component => { - ComponentEntityType::Component(self.component_at(export.index, offset)?) - } + ComponentExternalKind::Module => ComponentEntityType::Module( + self.module_at(CoreModuleIdx(export.index), offset)?, + ), + ComponentExternalKind::Component => ComponentEntityType::Component( + self.component_at(ComponentIdx(export.index), offset)?, + ), ComponentExternalKind::Instance => { - let ty = self.instance_at(export.index, offset)?; + let ty = self.instance_at(ComponentInstanceIdx(export.index), offset)?; // When an instance is exported from an instance then // all explicitly exported resources on the sub-instance are @@ -2820,15 +2835,15 @@ impl ComponentState { )); ComponentEntityType::Instance(ty) } - ComponentExternalKind::Func => { - ComponentEntityType::Func(self.function_at(export.index, offset)?) - } + ComponentExternalKind::Func => ComponentEntityType::Func( + self.function_at(ComponentFuncIdx(export.index), offset)?, + ), ComponentExternalKind::Value => { self.check_value_support(features, offset)?; - ComponentEntityType::Value(*self.value_at(export.index, offset)?) + ComponentEntityType::Value(*self.value_at(ComponentValueIdx(export.index), offset)?) } ComponentExternalKind::Type => { - let ty = self.component_type_at(export.index, offset)?; + let ty = self.component_type_at(ComponentTypeIdx(export.index), offset)?; // If this is an export of a resource type be sure to // record that in the explicit list with the appropriate // path because if this instance ends up getting used @@ -2932,7 +2947,7 @@ impl ComponentState { insert_export( types, export.name, - EntityType::Func(self.core_function_at(export.index, offset)?), + EntityType::Func(self.core_function_at(FuncIdx(export.index), offset)?), &mut inst_exports, &mut info, offset, @@ -2941,7 +2956,7 @@ impl ComponentState { ExternalKind::Table => insert_export( types, export.name, - EntityType::Table(*self.table_at(export.index, offset)?), + EntityType::Table(*self.table_at(TableIdx(export.index), offset)?), &mut inst_exports, &mut info, offset, @@ -2949,7 +2964,7 @@ impl ComponentState { ExternalKind::Memory => insert_export( types, export.name, - EntityType::Memory(*self.memory_at(export.index, offset)?), + EntityType::Memory(*self.memory_at(MemIdx(export.index), offset)?), &mut inst_exports, &mut info, offset, @@ -2958,7 +2973,7 @@ impl ComponentState { insert_export( types, export.name, - EntityType::Global(*self.global_at(export.index, offset)?), + EntityType::Global(*self.global_at(GlobalIdx(export.index), offset)?), &mut inst_exports, &mut info, offset, @@ -2967,7 +2982,7 @@ impl ComponentState { ExternalKind::Tag => insert_export( types, export.name, - EntityType::Tag(self.core_function_at(export.index, offset)?), + EntityType::Tag(self.core_function_at(FuncIdx(export.index), offset)?), &mut inst_exports, &mut info, offset, @@ -2983,7 +2998,7 @@ impl ComponentState { fn alias_core_instance_export( &mut self, - instance_index: u32, + instance_index: CoreInstanceIdx, kind: ExternalKind, name: &str, types: &TypeList, @@ -3092,7 +3107,7 @@ impl ComponentState { fn alias_instance_export( &mut self, - instance_index: u32, + instance_index: ComponentInstanceIdx, kind: ComponentExternalKind, name: &str, features: &WasmFeatures, @@ -3139,7 +3154,12 @@ impl ComponentState { Ok(()) } - fn alias_module(components: &mut [Self], count: u32, index: u32, offset: usize) -> Result<()> { + fn alias_module( + components: &mut [Self], + count: u32, + index: CoreModuleIdx, + offset: usize, + ) -> Result<()> { let component = Self::check_alias_count(components, count, offset)?; let ty = component.module_at(index, offset)?; @@ -3159,7 +3179,7 @@ impl ComponentState { fn alias_component( components: &mut [Self], count: u32, - index: u32, + index: ComponentIdx, offset: usize, ) -> Result<()> { let component = Self::check_alias_count(components, count, offset)?; @@ -3181,7 +3201,7 @@ impl ComponentState { fn alias_core_type( components: &mut [Self], count: u32, - index: u32, + index: TypeIdx, offset: usize, ) -> Result<()> { let component = Self::check_alias_count(components, count, offset)?; @@ -3198,7 +3218,7 @@ impl ComponentState { fn alias_type( components: &mut [Self], count: u32, - index: u32, + index: ComponentTypeIdx, types: &mut TypeAlloc, offset: usize, ) -> Result<()> { @@ -3521,23 +3541,27 @@ impl ComponentState { }) } - pub fn core_type_at(&self, idx: u32, offset: usize) -> Result { + pub fn core_type_at(&self, idx: TypeIdx, offset: usize) -> Result { self.core_types - .get(idx as usize) + .get(idx) .copied() .ok_or_else(|| format_err!(offset, "unknown type {idx}: type index out of bounds")) } - pub fn component_type_at(&self, idx: u32, offset: usize) -> Result { + pub fn component_type_at( + &self, + idx: ComponentTypeIdx, + offset: usize, + ) -> Result { self.types - .get(idx as usize) + .get(idx) .copied() .ok_or_else(|| format_err!(offset, "unknown type {idx}: type index out of bounds")) } fn function_type_at<'a>( &self, - idx: u32, + idx: ComponentTypeIdx, types: &'a TypeList, offset: usize, ) -> Result<&'a ComponentFuncType> { @@ -3548,8 +3572,8 @@ impl ComponentState { } } - fn function_at(&self, idx: u32, offset: usize) -> Result { - self.funcs.get(idx as usize).copied().ok_or_else(|| { + fn function_at(&self, idx: ComponentFuncIdx, offset: usize) -> Result { + self.funcs.get(idx).copied().ok_or_else(|| { format_err!( offset, "unknown function {idx}: function index out of bounds" @@ -3557,8 +3581,8 @@ impl ComponentState { }) } - fn component_at(&self, idx: u32, offset: usize) -> Result { - self.components.get(idx as usize).copied().ok_or_else(|| { + fn component_at(&self, idx: ComponentIdx, offset: usize) -> Result { + self.components.get(idx).copied().ok_or_else(|| { format_err!( offset, "unknown component {idx}: component index out of bounds" @@ -3566,8 +3590,12 @@ impl ComponentState { }) } - fn instance_at(&self, idx: u32, offset: usize) -> Result { - self.instances.get(idx as usize).copied().ok_or_else(|| { + fn instance_at( + &self, + idx: ComponentInstanceIdx, + offset: usize, + ) -> Result { + self.instances.get(idx).copied().ok_or_else(|| { format_err!( offset, "unknown instance {idx}: instance index out of bounds" @@ -3575,8 +3603,8 @@ impl ComponentState { }) } - fn value_at(&mut self, idx: u32, offset: usize) -> Result<&ComponentValType> { - match self.values.get_mut(idx as usize) { + fn value_at(&mut self, idx: ComponentValueIdx, offset: usize) -> Result<&ComponentValType> { + match self.values.get_mut(idx) { Some((ty, used)) if !*used => { *used = true; Ok(ty) @@ -3586,15 +3614,19 @@ impl ComponentState { } } - fn defined_type_at(&self, idx: u32, offset: usize) -> Result { + fn defined_type_at( + &self, + idx: ComponentTypeIdx, + offset: usize, + ) -> Result { match self.component_type_at(idx, offset)? { ComponentAnyTypeId::Defined(id) => Ok(id), _ => bail!(offset, "type index {idx} is not a defined type"), } } - fn core_function_at(&self, idx: u32, offset: usize) -> Result { - match self.core_funcs.get(idx as usize) { + fn core_function_at(&self, idx: FuncIdx, offset: usize) -> Result { + match self.core_funcs.get(idx) { Some(id) => Ok(*id), None => bail!( offset, @@ -3603,15 +3635,19 @@ impl ComponentState { } } - fn module_at(&self, idx: u32, offset: usize) -> Result { - match self.core_modules.get(idx as usize) { + fn module_at(&self, idx: CoreModuleIdx, offset: usize) -> Result { + match self.core_modules.get(idx) { Some(id) => Ok(*id), None => bail!(offset, "unknown module {idx}: module index out of bounds"), } } - fn core_instance_at(&self, idx: u32, offset: usize) -> Result { - match self.core_instances.get(idx as usize) { + fn core_instance_at( + &self, + idx: CoreInstanceIdx, + offset: usize, + ) -> Result { + match self.core_instances.get(idx) { Some(id) => Ok(*id), None => bail!( offset, @@ -3622,7 +3658,7 @@ impl ComponentState { fn core_instance_export<'a>( &self, - instance_index: u32, + instance_index: CoreInstanceIdx, name: &str, types: &'a TypeList, offset: usize, @@ -3639,22 +3675,22 @@ impl ComponentState { } } - fn global_at(&self, idx: u32, offset: usize) -> Result<&GlobalType> { - match self.core_globals.get(idx as usize) { + fn global_at(&self, idx: GlobalIdx, offset: usize) -> Result<&GlobalType> { + match self.core_globals.get(idx) { Some(t) => Ok(t), None => bail!(offset, "unknown global {idx}: global index out of bounds"), } } - fn table_at(&self, idx: u32, offset: usize) -> Result<&TableType> { - match self.core_tables.get(idx as usize) { + fn table_at(&self, idx: TableIdx, offset: usize) -> Result<&TableType> { + match self.core_tables.get(idx) { Some(t) => Ok(t), None => bail!(offset, "unknown table {idx}: table index out of bounds"), } } - fn memory_at(&self, idx: u32, offset: usize) -> Result<&MemoryType> { - match self.core_memories.get(idx as usize) { + fn memory_at(&self, idx: MemIdx, offset: usize) -> Result<&MemoryType> { + match self.core_memories.get(idx) { Some(t) => Ok(t), None => bail!(offset, "unknown memory {idx}: memory index out of bounds"), } @@ -3776,7 +3812,7 @@ impl InternRecGroup for ComponentState { self.core_types.push(ComponentCoreTypeId::Sub(id)); } - fn type_id_at(&self, idx: u32, offset: usize) -> Result { + fn type_id_at(&self, idx: TypeIdx, offset: usize) -> Result { match self.core_type_at(idx, offset)? { ComponentCoreTypeId::Sub(id) => Ok(id), ComponentCoreTypeId::Module(_) => { diff --git a/crates/wasmparser/src/validator/component_types.rs b/crates/wasmparser/src/validator/component_types.rs index 76ab1ff57b..42aee273c9 100644 --- a/crates/wasmparser/src/validator/component_types.rs +++ b/crates/wasmparser/src/validator/component_types.rs @@ -15,6 +15,7 @@ use core::{ hash::{Hash, Hasher}, mem, }; +use wasm_types::TypeIdx; /// The maximum number of parameters in the canonical ABI that can be passed by value. /// @@ -1259,10 +1260,10 @@ impl<'a> TypesRef<'a> { /// # Panics /// /// This will panic if the `index` provided is out of bounds. - pub fn core_type_at_in_component(&self, index: u32) -> ComponentCoreTypeId { + pub fn core_type_at_in_component(&self, index: TypeIdx) -> ComponentCoreTypeId { match &self.kind { TypesRefKind::Module(_) => panic!("use `component_type_at_in_module` instead"), - TypesRefKind::Component(component) => component.core_types[index as usize], + TypesRefKind::Component(component) => component.core_types[index], } } diff --git a/crates/wasmparser/src/validator/core.rs b/crates/wasmparser/src/validator/core.rs index a6c76f5c13..41f41fa7fb 100644 --- a/crates/wasmparser/src/validator/core.rs +++ b/crates/wasmparser/src/validator/core.rs @@ -21,6 +21,8 @@ use crate::{ use crate::{prelude::*, CompositeInnerType}; use alloc::sync::Arc; use core::mem; +use index_vec::{Idx, IndexVec}; +use wasm_types::{ElemIdx, FuncIdx, GlobalIdx, MemIdx, TableIdx, TagIdx, TypeIdx}; // Section order for WebAssembly modules. // @@ -108,7 +110,7 @@ impl ModuleState { Ok(()) } - pub fn next_code_index_and_type(&mut self, offset: usize) -> Result<(u32, u32)> { + pub fn next_code_index_and_type(&mut self, offset: usize) -> Result<(FuncIdx, TypeIdx)> { let index = self .code_section_index .get_or_insert(self.module.num_imported_functions as usize); @@ -123,7 +125,7 @@ impl ModuleState { let ty = self.module.functions[*index]; *index += 1; - Ok(((*index - 1) as u32, ty)) + Ok((FuncIdx::from_usize(*index - 1), ty)) } pub fn add_global( @@ -212,7 +214,9 @@ impl ModuleState { table_index, offset_expr, } => { - let table = self.module.table_at(table_index.unwrap_or(0), offset)?; + let table = self + .module + .table_at(table_index.unwrap_or(TableIdx(0)), offset)?; if !types.reftype_is_subtype(element_ty, table.element_type) { return Err(BinaryReaderError::new( format!( @@ -360,11 +364,11 @@ impl ModuleState { } } - fn validate_global(&mut self, index: u32) -> Result<()> { + fn validate_global(&mut self, index: GlobalIdx) -> Result<()> { let module = &self.resources.module; let global = module.global_at(index, self.offset)?; - if index >= module.num_imported_globals && !self.features.gc() { + if index.0 >= module.num_imported_globals && !self.features.gc() { return Err(BinaryReaderError::new( "constant expression required: global.get of locally defined global", self.offset, @@ -396,7 +400,7 @@ impl ModuleState { // boolean here is used to track this and will cause a panic // (aka a fuzz bug) if we somehow forget to emit an error somewhere // else. - fn insert_ref_func(&mut self, index: u32) { + fn insert_ref_func(&mut self, index: FuncIdx) { if self.order == Order::Data { self.uninserted_funcref = true; } else { @@ -552,16 +556,16 @@ pub(crate) struct Module { // enable parallel validation of functions. pub snapshot: Option>, // Stores indexes into the validator's types list. - pub types: Vec, - pub tables: Vec, - pub memories: Vec, - pub globals: Vec, - pub element_types: Vec, + pub types: IndexVec, + pub tables: IndexVec, + pub memories: IndexVec, + pub globals: IndexVec, + pub element_types: IndexVec, pub data_count: Option, // Stores indexes into `types`. - pub functions: Vec, - pub tags: Vec, - pub function_references: Set, + pub functions: IndexVec, + pub tags: IndexVec, + pub function_references: Set, pub imports: IndexMap<(String, String), Vec>, pub exports: IndexMap, pub type_size: u32, @@ -614,7 +618,7 @@ impl Module { (self.memories.len(), self.max_memories(features), "memories") } TypeRef::Tag(ty) => { - self.tags.push(self.types[ty.func_type_idx as usize]); + self.tags.push(self.types[ty.func_type_idx]); (self.tags.len(), MAX_WASM_TAGS, "tags") } TypeRef::Global(ty) => { @@ -677,7 +681,12 @@ impl Module { } } - pub fn add_function(&mut self, type_index: u32, types: &TypeList, offset: usize) -> Result<()> { + pub fn add_function( + &mut self, + type_index: TypeIdx, + types: &TypeList, + offset: usize, + ) -> Result<()> { self.func_type_at(type_index, types, offset)?; self.functions.push(type_index); Ok(()) @@ -702,18 +711,23 @@ impl Module { offset: usize, ) -> Result<()> { self.check_tag_type(&ty, features, types, offset)?; - self.tags.push(self.types[ty.func_type_idx as usize]); + self.tags.push(self.types[ty.func_type_idx]); Ok(()) } - fn sub_type_at<'a>(&self, types: &'a TypeList, idx: u32, offset: usize) -> Result<&'a SubType> { + fn sub_type_at<'a>( + &self, + types: &'a TypeList, + idx: TypeIdx, + offset: usize, + ) -> Result<&'a SubType> { let id = self.type_id_at(idx, offset)?; Ok(&types[id]) } fn func_type_at<'a>( &self, - type_index: u32, + type_index: TypeIdx, types: &'a TypeList, offset: usize, ) -> Result<&'a FuncType> { @@ -737,7 +751,7 @@ impl Module { Ok(match type_ref { TypeRef::Func(type_index) => { self.func_type_at(*type_index, types, offset)?; - EntityType::Func(self.types[*type_index as usize]) + EntityType::Func(self.types[*type_index]) } TypeRef::Table(t) => { self.check_table_type(t, features, types, offset)?; @@ -749,7 +763,7 @@ impl Module { } TypeRef::Tag(t) => { self.check_tag_type(t, features, types, offset)?; - EntityType::Tag(self.types[t.func_type_idx as usize]) + EntityType::Tag(self.types[t.func_type_idx]) } TypeRef::Global(t) => { self.check_global_type(t, features, types, offset)?; @@ -1044,35 +1058,36 @@ impl Module { Ok(match export.kind { ExternalKind::Func => { check("function", export.index, self.functions.len())?; - self.function_references.insert(export.index); - EntityType::Func(self.types[self.functions[export.index as usize] as usize]) + let idx = FuncIdx(export.index); + self.function_references.insert(idx); + EntityType::Func(self.types[self.functions[idx]]) } ExternalKind::Table => { check("table", export.index, self.tables.len())?; - EntityType::Table(self.tables[export.index as usize]) + EntityType::Table(self.tables[TableIdx(export.index)]) } ExternalKind::Memory => { check("memory", export.index, self.memories.len())?; - EntityType::Memory(self.memories[export.index as usize]) + EntityType::Memory(self.memories[MemIdx(export.index)]) } ExternalKind::Global => { check("global", export.index, self.globals.len())?; - EntityType::Global(self.globals[export.index as usize]) + EntityType::Global(self.globals[GlobalIdx(export.index)]) } ExternalKind::Tag => { check("tag", export.index, self.tags.len())?; - EntityType::Tag(self.tags[export.index as usize]) + EntityType::Tag(self.tags[TagIdx(export.index)]) } }) } pub fn get_func_type<'a>( &self, - func_idx: u32, + func_idx: FuncIdx, types: &'a TypeList, offset: usize, ) -> Result<&'a FuncType> { - match self.functions.get(func_idx as usize) { + match self.functions.get(func_idx) { Some(idx) => self.func_type_at(*idx, types, offset), None => Err(format_err!( offset, @@ -1081,8 +1096,8 @@ impl Module { } } - fn global_at(&self, idx: u32, offset: usize) -> Result<&GlobalType> { - match self.globals.get(idx as usize) { + fn global_at(&self, idx: GlobalIdx, offset: usize) -> Result<&GlobalType> { + match self.globals.get(idx) { Some(t) => Ok(t), None => Err(format_err!( offset, @@ -1091,8 +1106,8 @@ impl Module { } } - fn table_at(&self, idx: u32, offset: usize) -> Result<&TableType> { - match self.tables.get(idx as usize) { + fn table_at(&self, idx: TableIdx, offset: usize) -> Result<&TableType> { + match self.tables.get(idx) { Some(t) => Ok(t), None => Err(format_err!( offset, @@ -1101,8 +1116,8 @@ impl Module { } } - fn memory_at(&self, idx: u32, offset: usize) -> Result<&MemoryType> { - match self.memories.get(idx as usize) { + fn memory_at(&self, idx: MemIdx, offset: usize) -> Result<&MemoryType> { + match self.memories.get(idx) { Some(t) => Ok(t), None => Err(format_err!( offset, @@ -1117,9 +1132,9 @@ impl InternRecGroup for Module { self.types.push(id); } - fn type_id_at(&self, idx: u32, offset: usize) -> Result { + fn type_id_at(&self, idx: TypeIdx, offset: usize) -> Result { self.types - .get(idx as usize) + .get(idx) .copied() .ok_or_else(|| format_err!(offset, "unknown type {idx}: type index out of bounds")) } @@ -1157,25 +1172,25 @@ struct OperatorValidatorResources<'a> { } impl WasmModuleResources for OperatorValidatorResources<'_> { - fn table_at(&self, at: u32) -> Option { - self.module.tables.get(at as usize).cloned() + fn table_at(&self, at: TableIdx) -> Option { + self.module.tables.get(at).cloned() } - fn memory_at(&self, at: u32) -> Option { - self.module.memories.get(at as usize).cloned() + fn memory_at(&self, at: MemIdx) -> Option { + self.module.memories.get(at).cloned() } - fn tag_at(&self, at: u32) -> Option<&FuncType> { - let type_id = *self.module.tags.get(at as usize)?; + fn tag_at(&self, at: TagIdx) -> Option<&FuncType> { + let type_id = *self.module.tags.get(at)?; Some(self.types[type_id].unwrap_func()) } - fn global_at(&self, at: u32) -> Option { - self.module.globals.get(at as usize).cloned() + fn global_at(&self, at: GlobalIdx) -> Option { + self.module.globals.get(at).cloned() } - fn sub_type_at(&self, at: u32) -> Option<&SubType> { - let id = *self.module.types.get(at as usize)?; + fn sub_type_at(&self, at: TypeIdx) -> Option<&SubType> { + let id = *self.module.types.get(at)?; Some(&self.types[id]) } @@ -1183,13 +1198,13 @@ impl WasmModuleResources for OperatorValidatorResources<'_> { &self.types[at] } - fn type_id_of_function(&self, at: u32) -> Option { - let type_index = self.module.functions.get(at as usize)?; - self.module.types.get(*type_index as usize).copied() + fn type_id_of_function(&self, at: FuncIdx) -> Option { + let type_index = self.module.functions.get(at)?; + self.module.types.get(*type_index).copied() } - fn type_index_of_function(&self, at: u32) -> Option { - self.module.functions.get(at as usize).copied() + fn type_index_of_function(&self, at: FuncIdx) -> Option { + self.module.functions.get(at).copied() } fn check_heap_type(&self, t: &mut HeapType, offset: usize) -> Result<()> { @@ -1200,8 +1215,8 @@ impl WasmModuleResources for OperatorValidatorResources<'_> { self.types.top_type(heap_type) } - fn element_type_at(&self, at: u32) -> Option { - self.module.element_types.get(at as usize).cloned() + fn element_type_at(&self, at: ElemIdx) -> Option { + self.module.element_types.get(at).cloned() } fn is_subtype(&self, a: ValType, b: ValType) -> bool { @@ -1220,7 +1235,7 @@ impl WasmModuleResources for OperatorValidatorResources<'_> { self.module.data_count } - fn is_function_referenced(&self, idx: u32) -> bool { + fn is_function_referenced(&self, idx: FuncIdx) -> bool { self.module.function_references.contains(&idx) } } @@ -1231,16 +1246,16 @@ impl WasmModuleResources for OperatorValidatorResources<'_> { pub struct ValidatorResources(pub(crate) Arc); impl WasmModuleResources for ValidatorResources { - fn table_at(&self, at: u32) -> Option { - self.0.tables.get(at as usize).cloned() + fn table_at(&self, at: TableIdx) -> Option { + self.0.tables.get(at).cloned() } - fn memory_at(&self, at: u32) -> Option { - self.0.memories.get(at as usize).cloned() + fn memory_at(&self, at: MemIdx) -> Option { + self.0.memories.get(at).cloned() } - fn tag_at(&self, at: u32) -> Option<&FuncType> { - let id = *self.0.tags.get(at as usize)?; + fn tag_at(&self, at: TagIdx) -> Option<&FuncType> { + let id = *self.0.tags.get(at)?; let types = self.0.snapshot.as_ref().unwrap(); match &types[id].composite_type.inner { CompositeInnerType::Func(f) => Some(f), @@ -1248,12 +1263,12 @@ impl WasmModuleResources for ValidatorResources { } } - fn global_at(&self, at: u32) -> Option { - self.0.globals.get(at as usize).cloned() + fn global_at(&self, at: GlobalIdx) -> Option { + self.0.globals.get(at).cloned() } - fn sub_type_at(&self, at: u32) -> Option<&SubType> { - let id = *self.0.types.get(at as usize)?; + fn sub_type_at(&self, at: TypeIdx) -> Option<&SubType> { + let id = *self.0.types.get(at)?; let types = self.0.snapshot.as_ref().unwrap(); Some(&types[id]) } @@ -1263,13 +1278,13 @@ impl WasmModuleResources for ValidatorResources { &types[at] } - fn type_id_of_function(&self, at: u32) -> Option { - let type_index = *self.0.functions.get(at as usize)?; - self.0.types.get(type_index as usize).copied() + fn type_id_of_function(&self, at: FuncIdx) -> Option { + let type_index = *self.0.functions.get(at)?; + self.0.types.get(type_index).copied() } - fn type_index_of_function(&self, at: u32) -> Option { - self.0.functions.get(at as usize).copied() + fn type_index_of_function(&self, at: FuncIdx) -> Option { + self.0.functions.get(at).copied() } fn check_heap_type(&self, t: &mut HeapType, offset: usize) -> Result<()> { @@ -1280,8 +1295,8 @@ impl WasmModuleResources for ValidatorResources { self.0.snapshot.as_ref().unwrap().top_type(heap_type) } - fn element_type_at(&self, at: u32) -> Option { - self.0.element_types.get(at as usize).cloned() + fn element_type_at(&self, at: ElemIdx) -> Option { + self.0.element_types.get(at).cloned() } fn is_subtype(&self, a: ValType, b: ValType) -> bool { @@ -1300,7 +1315,7 @@ impl WasmModuleResources for ValidatorResources { self.0.data_count } - fn is_function_referenced(&self, idx: u32) -> bool { + fn is_function_referenced(&self, idx: FuncIdx) -> bool { self.0.function_references.contains(&idx) } } diff --git a/crates/wasmparser/src/validator/core/canonical.rs b/crates/wasmparser/src/validator/core/canonical.rs index b109eb7520..02419e6d11 100644 --- a/crates/wasmparser/src/validator/core/canonical.rs +++ b/crates/wasmparser/src/validator/core/canonical.rs @@ -73,10 +73,12 @@ use crate::{ BinaryReaderError, CompositeInnerType, CompositeType, PackedIndex, RecGroup, Result, StorageType, UnpackedIndex, ValType, WasmFeatures, }; +use index_vec::Idx; +use wasm_types::TypeIdx; pub(crate) trait InternRecGroup { fn add_type_id(&mut self, id: CoreTypeId); - fn type_id_at(&self, idx: u32, offset: usize) -> Result; + fn type_id_at(&self, idx: TypeIdx, offset: usize) -> Result; fn types_len(&self) -> u32; /// Canonicalize the rec group and return its id and whether it is a new group @@ -306,7 +308,7 @@ enum CanonicalizationMode { pub(crate) struct TypeCanonicalizer<'a> { module: &'a dyn InternRecGroup, features: Option<&'a WasmFeatures>, - rec_group_start: u32, + rec_group_start: TypeIdx, rec_group_len: u32, offset: usize, mode: CanonicalizationMode, @@ -318,7 +320,7 @@ impl<'a> TypeCanonicalizer<'a> { // These defaults will work for when we are canonicalizing types from // outside of a rec group definition, forcing all `PackedIndex`es to be // canonicalized to `CoreTypeId`s. - let rec_group_start = u32::MAX; + let rec_group_start = TypeIdx(u32::MAX); let rec_group_len = 0; Self { @@ -346,12 +348,12 @@ impl<'a> TypeCanonicalizer<'a> { // Re-initialize these fields so that we properly canonicalize // intra-rec-group type references into indices into the rec group // rather than as `CoreTypeId`s. - self.rec_group_start = self.module.types_len(); + self.rec_group_start = TypeIdx(self.module.types_len()); self.rec_group_len = u32::try_from(rec_group.types().len()).unwrap(); for (rec_group_local_index, ty) in rec_group.types_mut().enumerate() { let rec_group_local_index = u32::try_from(rec_group_local_index).unwrap(); - let type_index = self.rec_group_start + rec_group_local_index; + let type_index = TypeIdx(self.rec_group_start.0 + rec_group_local_index); if let Some(sup) = ty.supertype_idx.as_mut() { if sup.as_module_index().map_or(false, |i| i >= type_index) { @@ -387,7 +389,7 @@ impl<'a> TypeCanonicalizer<'a> { // type recursion, including self references, is not allowed in the // typed function references proposal, only the GC proposal. debug_assert!(self.allow_gc() || self.rec_group_len == 1); - let local = index - self.rec_group_start; + let local = index.0 - self.rec_group_start.0; if self.allow_gc() && local < self.rec_group_len { if let Some(id) = PackedIndex::from_rec_group_index(local) { *ty = id; @@ -417,9 +419,9 @@ impl<'a> TypeCanonicalizer<'a> { let rec_group_len = u32::try_from(rec_group_len).unwrap(); assert!(local_index < rec_group_len); - let rec_group_start = u32::try_from(rec_group_elems.start.index()).unwrap(); + let rec_group_start = TypeIdx::from_usize(rec_group_elems.start.index()); - let id = CoreTypeId::from_index(rec_group_start + local_index); + let id = CoreTypeId::from_index(rec_group_start.0 + local_index); *ty = PackedIndex::from_id(id).expect( "should fit in impl limits since we already have the end of the rec group \ constructed successfully", diff --git a/crates/wasmparser/src/validator/func.rs b/crates/wasmparser/src/validator/func.rs index 90b5a50b07..26dfa31ae4 100644 --- a/crates/wasmparser/src/validator/func.rs +++ b/crates/wasmparser/src/validator/func.rs @@ -1,6 +1,7 @@ use super::operators::{Frame, OperatorValidator, OperatorValidatorAllocations}; use crate::{BinaryReader, Result, ValType, VisitOperator}; use crate::{FunctionBody, ModuleArity, Operator, WasmFeatures, WasmModuleResources}; +use wasm_types::{FuncIdx, LocalIdx, TypeIdx}; /// Resources necessary to perform validation of a function. /// @@ -14,10 +15,10 @@ pub struct FuncToValidate { /// Reusable, heap allocated resources to drive the Wasm validation. pub resources: T, /// The core Wasm function index being validated. - pub index: u32, + pub index: FuncIdx, /// The core Wasm type index of the function being validated, /// defining the results and parameters to the function. - pub ty: u32, + pub ty: TypeIdx, /// The Wasm features enabled to validate the function. pub features: WasmFeatures, } @@ -60,7 +61,7 @@ impl FuncToValidate { pub struct FuncValidator { validator: OperatorValidator, resources: T, - index: u32, + index: FuncIdx, } /// External handle to the internal allocations used during function validation. @@ -212,7 +213,7 @@ impl FuncValidator { /// The index of the function within the module's function index space that /// is being validated. - pub fn index(&self) -> u32 { + pub fn index(&self) -> FuncIdx { self.index } @@ -222,7 +223,7 @@ impl FuncValidator { } /// Returns the type of the local variable at the given `index` if any. - pub fn get_local_type(&self, index: u32) -> Option { + pub fn get_local_type(&self, index: LocalIdx) -> Option { self.validator.locals.get(index) } @@ -301,28 +302,28 @@ mod tests { } impl WasmModuleResources for EmptyResources { - fn table_at(&self, _at: u32) -> Option { + fn table_at(&self, _at: TableIdx) -> Option { todo!() } - fn memory_at(&self, _at: u32) -> Option { + fn memory_at(&self, _at: MemIdx) -> Option { todo!() } - fn tag_at(&self, _at: u32) -> Option<&crate::FuncType> { + fn tag_at(&self, _at: TagIdx) -> Option<&crate::FuncType> { todo!() } - fn global_at(&self, _at: u32) -> Option { + fn global_at(&self, _at: GlobalIdx) -> Option { todo!() } - fn sub_type_at(&self, _type_idx: u32) -> Option<&crate::SubType> { + fn sub_type_at(&self, _type_idx: CoreTypeId) -> Option<&crate::SubType> { Some(&self.0) } fn sub_type_at_id(&self, _id: CoreTypeId) -> &crate::SubType { todo!() } - fn type_id_of_function(&self, _at: u32) -> Option { + fn type_id_of_function(&self, _at: FuncIdx) -> Option { todo!() } - fn type_index_of_function(&self, _at: u32) -> Option { + fn type_index_of_function(&self, _at: FuncIdx) -> Option { todo!() } fn check_heap_type(&self, _t: &mut HeapType, _offset: usize) -> Result<()> { @@ -331,7 +332,7 @@ mod tests { fn top_type(&self, _heap_type: &HeapType) -> HeapType { todo!() } - fn element_type_at(&self, _at: u32) -> Option { + fn element_type_at(&self, _at: ElemIdx) -> Option { todo!() } fn is_subtype(&self, _t1: ValType, _t2: ValType) -> bool { @@ -346,7 +347,7 @@ mod tests { fn data_count(&self) -> Option { todo!() } - fn is_function_referenced(&self, _idx: u32) -> bool { + fn is_function_referenced(&self, _idx: FuncIdx) -> bool { todo!() } } diff --git a/crates/wasmparser/src/validator/operators.rs b/crates/wasmparser/src/validator/operators.rs index 249bc070d9..863b151228 100644 --- a/crates/wasmparser/src/validator/operators.rs +++ b/crates/wasmparser/src/validator/operators.rs @@ -32,6 +32,11 @@ use crate::{ }; use crate::{prelude::*, CompositeInnerType, Ordering}; use core::ops::{Deref, DerefMut}; +use index_vec::{Idx, IndexVec}; +use wasm_types::{ + DataIdx, ElemIdx, FieldIdx, FuncIdx, GlobalIdx, LabelIdx, LocalIdx, MemIdx, TableIdx, TagIdx, + TypeIdx, +}; #[cfg(feature = "simd")] mod simd; @@ -66,25 +71,25 @@ pub(crate) struct OperatorValidator { /// Captures the initialization of non-defaultable locals. struct LocalInits { /// Records if a local is already initialized. - local_inits: Vec, + local_inits: IndexVec, /// When `local_inits` is modified, the relevant `index` is recorded /// here to be undone when control pops. - inits: Vec, + inits: Vec, /// The index of the first non-defaultable local. /// /// # Note /// /// This is an optimization so that we only have to perform expensive /// look-ups for locals that have a local index equal to or higher than this. - first_non_default_local: u32, + first_non_default_local: LocalIdx, } impl Default for LocalInits { fn default() -> Self { Self { - local_inits: Vec::default(), + local_inits: IndexVec::default(), inits: Vec::default(), - first_non_default_local: u32::MAX, + first_non_default_local: LocalIdx(u32::MAX), } } } @@ -108,26 +113,26 @@ impl LocalInits { panic!("tried to define too many function locals: {count}"); }; let is_defaultable = ty.is_defaultable(); - if !is_defaultable && self.first_non_default_local == u32::MAX { - self.first_non_default_local = len as u32; + if !is_defaultable && self.first_non_default_local == LocalIdx(u32::MAX) { + self.first_non_default_local = LocalIdx::from_usize(len); } self.local_inits.resize(new_len, is_defaultable); } /// Returns `true` if the local at `local_index` has already been initialized. #[inline] - pub fn is_uninit(&self, local_index: u32) -> bool { + pub fn is_uninit(&self, local_index: LocalIdx) -> bool { if local_index < self.first_non_default_local { return false; } - !self.local_inits[local_index as usize] + !self.local_inits[local_index] } /// Marks the local at `local_index` as initialized. #[inline] - pub fn set_init(&mut self, local_index: u32) { + pub fn set_init(&mut self, local_index: LocalIdx) { if self.is_uninit(local_index) { - self.local_inits[local_index as usize] = true; + self.local_inits[local_index] = true; self.inits.push(local_index); } } @@ -142,7 +147,7 @@ impl LocalInits { /// This uninitializes all locals that have been initialized within it. pub fn pop_ctrl(&mut self, height: usize) { for local_index in self.inits.split_off(height) { - self.local_inits[local_index as usize] = false; + self.local_inits[local_index] = false; } } @@ -152,7 +157,7 @@ impl LocalInits { pub fn clear(&mut self) { self.local_inits.clear(); self.inits.clear(); - self.first_non_default_local = u32::MAX; + self.first_non_default_local = LocalIdx(u32::MAX); } /// Returns `true` if `self` is empty. @@ -173,7 +178,7 @@ pub(super) struct Locals { // optimize the theoretically common case where most functions don't have // many locals and don't need a full binary search in the entire local space // below. - first: Vec, + first: IndexVec, // This is a "compressed" list of locals for this function. The list of // locals are represented as a list of tuples. The second element is the @@ -185,7 +190,7 @@ pub(super) struct Locals { // `local.{get,set,tee}`. We do a binary search for the index desired, and // it either lies in a "hole" where the maximum index is specified later, // or it's at the end of the list meaning it's out of bounds. - all: Vec<(u32, ValType)>, + all: Vec<(LocalIdx, ValType)>, } /// A Wasm control flow block on the control flow stack during Wasm validation. @@ -221,8 +226,8 @@ pub struct OperatorValidatorAllocations { control: Vec, operands: Vec, local_inits: LocalInits, - locals_first: Vec, - locals_all: Vec<(u32, ValType)>, + locals_first: IndexVec, + locals_all: Vec<(LocalIdx, ValType)>, } /// Type storage within the validator. @@ -360,7 +365,7 @@ impl OperatorValidator { /// The `resources` are used to learn about the function type underlying /// `ty`. pub fn new_func( - ty: u32, + ty: TypeIdx, offset: usize, features: &WasmFeatures, resources: &T, @@ -547,7 +552,10 @@ impl OperatorValidator { self.local_inits.clear(); self.local_inits }, - locals_first: clear(self.locals.first), + locals_first: { + self.locals.first.clear(); + self.locals.first + }, locals_all: clear(self.locals.all), } } @@ -616,7 +624,7 @@ where Ok(()) } - fn push_concrete_ref(&mut self, nullable: bool, type_index: u32) -> Result<()> { + fn push_concrete_ref(&mut self, nullable: bool, type_index: TypeIdx) -> Result<()> { let mut heap_ty = HeapType::Concrete(UnpackedIndex::Module(type_index)); // Canonicalize the module index into an id. @@ -630,7 +638,7 @@ where self.push_operand(ref_ty) } - fn pop_concrete_ref(&mut self, nullable: bool, type_index: u32) -> Result { + fn pop_concrete_ref(&mut self, nullable: bool, type_index: TypeIdx) -> Result { let mut heap_ty = HeapType::Concrete(UnpackedIndex::Module(type_index)); // Canonicalize the module index into an id. @@ -900,7 +908,7 @@ where /// Fetches the type for the local at `idx`, returning an error if it's out /// of bounds. - fn local(&self, idx: u32) -> Result { + fn local(&self, idx: LocalIdx) -> Result { match self.locals.get(idx) { Some(ty) => Ok(ty), None => bail!( @@ -991,11 +999,11 @@ where /// /// Returns the type signature of the block that we're jumping to as well /// as the kind of block if the jump is valid. Otherwise returns an error. - fn jump(&self, depth: u32) -> Result<(BlockType, FrameKind)> { + fn jump(&self, depth: LabelIdx) -> Result<(BlockType, FrameKind)> { if self.control.is_empty() { return Err(self.err_beyond_end(self.offset)); } - match (self.control.len() - 1).checked_sub(depth as usize) { + match (self.control.len() - 1).checked_sub(depth.0 as usize) { Some(i) => { let frame = &self.control[i]; Ok((frame.block_type, frame.kind)) @@ -1006,7 +1014,7 @@ where /// 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, memory_index: u32) -> Result { + fn check_memory_index(&self, memory_index: MemIdx) -> Result { match self.resources.memory_at(memory_index) { Some(mem) => Ok(mem.index_type()), None => bail!(self.offset, "unknown memory {}", memory_index), @@ -1069,7 +1077,7 @@ where /// Returns the corresponding function type for the `func` item located at /// `function_index`. - fn type_of_function(&self, function_index: u32) -> Result<&'resources FuncType> { + fn type_of_function(&self, function_index: FuncIdx) -> Result<&'resources FuncType> { if let Some(type_index) = self.resources.type_index_of_function(function_index) { self.func_type_at(type_index) } else { @@ -1128,7 +1136,7 @@ where /// or a subtype. This will then return the corresponding function type used /// for this call (to be used with `check_call_ty` or /// `check_return_call_ty`). - fn check_call_ref_ty(&mut self, type_index: u32) -> Result<&'resources FuncType> { + fn check_call_ref_ty(&mut self, type_index: TypeIdx) -> Result<&'resources FuncType> { let unpacked_index = UnpackedIndex::Module(type_index); let mut hty = HeapType::Concrete(unpacked_index); self.resources.check_heap_type(&mut hty, self.offset)?; @@ -1148,8 +1156,8 @@ where /// `type_index` which must then be passed to `check_{call,return_call}_ty`. fn check_call_indirect_ty( &mut self, - type_index: u32, - table_index: u32, + type_index: TypeIdx, + table_index: TableIdx, ) -> Result<&'resources FuncType> { let tab = self.table_type_at(table_index)?; if !self @@ -1335,7 +1343,7 @@ where /// Common helper for checking the types of globals accessed with atomic RMW /// instructions, which only allow `i32` and `i64`. - fn check_atomic_global_rmw_ty(&self, global_index: u32) -> Result { + fn check_atomic_global_rmw_ty(&self, global_index: GlobalIdx) -> Result { let ty = self.global_type_at(global_index)?.content_type; if !(ty == ValType::I32 || ty == ValType::I64) { bail!( @@ -1351,8 +1359,8 @@ where fn check_struct_atomic_rmw( &mut self, op: &'static str, - struct_type_index: u32, - field_index: u32, + struct_type_index: TypeIdx, + field_index: FieldIdx, ) -> Result<()> { let field = self.mutable_struct_field_at(struct_type_index, field_index)?; let field_ty = match field.element_type { @@ -1372,7 +1380,7 @@ where /// Common helper for checking the types of arrays accessed with atomic RMW /// instructions, which only allow `i32` and `i64`. - fn check_array_atomic_rmw(&mut self, op: &'static str, type_index: u32) -> Result<()> { + fn check_array_atomic_rmw(&mut self, op: &'static str, type_index: TypeIdx) -> Result<()> { let field = self.mutable_array_type_at(type_index)?; let elem_ty = match field.element_type { StorageType::Val(ValType::I32) => ValType::I32, @@ -1390,7 +1398,7 @@ where Ok(()) } - fn element_type_at(&self, elem_index: u32) -> Result { + fn element_type_at(&self, elem_index: ElemIdx) -> Result { match self.resources.element_type_at(elem_index) { Some(ty) => Ok(ty), None => bail!( @@ -1401,13 +1409,13 @@ where } } - fn sub_type_at(&self, at: u32) -> Result<&'resources SubType> { + fn sub_type_at(&self, at: TypeIdx) -> Result<&'resources SubType> { self.resources .sub_type_at(at) .ok_or_else(|| format_err!(self.offset, "unknown type: type index out of bounds")) } - fn struct_type_at(&self, at: u32) -> Result<&'resources StructType> { + fn struct_type_at(&self, at: TypeIdx) -> Result<&'resources StructType> { let sub_ty = self.sub_type_at(at)?; if let CompositeInnerType::Struct(struct_ty) = &sub_ty.composite_type.inner { if self.inner.shared && !sub_ty.composite_type.shared { @@ -1425,10 +1433,11 @@ where } } - fn struct_field_at(&self, struct_type_index: u32, field_index: u32) -> Result { - let field_index = usize::try_from(field_index).map_err(|_| { - BinaryReaderError::new("unknown field: field index out of bounds", self.offset) - })?; + fn struct_field_at( + &self, + struct_type_index: TypeIdx, + field_index: FieldIdx, + ) -> Result { self.struct_type_at(struct_type_index)? .fields .get(field_index) @@ -1440,8 +1449,8 @@ where fn mutable_struct_field_at( &self, - struct_type_index: u32, - field_index: u32, + struct_type_index: TypeIdx, + field_index: FieldIdx, ) -> Result { let field = self.struct_field_at(struct_type_index, field_index)?; if !field.mutable { @@ -1453,7 +1462,7 @@ where Ok(field) } - fn array_type_at(&self, at: u32) -> Result { + fn array_type_at(&self, at: TypeIdx) -> Result { let sub_ty = self.sub_type_at(at)?; if let CompositeInnerType::Array(array_ty) = &sub_ty.composite_type.inner { if self.inner.shared && !sub_ty.composite_type.shared { @@ -1471,7 +1480,7 @@ where } } - fn mutable_array_type_at(&self, at: u32) -> Result { + fn mutable_array_type_at(&self, at: TypeIdx) -> Result { let field = self.array_type_at(at)?; if !field.mutable { bail!( @@ -1482,7 +1491,7 @@ where Ok(field) } - fn func_type_at(&self, at: u32) -> Result<&'resources FuncType> { + fn func_type_at(&self, at: TypeIdx) -> Result<&'resources FuncType> { let sub_ty = self.sub_type_at(at)?; if let CompositeInnerType::Func(func_ty) = &sub_ty.composite_type.inner { if self.inner.shared && !sub_ty.composite_type.shared { @@ -1500,7 +1509,7 @@ where } } - fn cont_type_at(&self, at: u32) -> Result<&ContType> { + fn cont_type_at(&self, at: TypeIdx) -> Result<&ContType> { let sub_ty = self.sub_type_at(at)?; if let CompositeInnerType::Cont(cont_ty) = &sub_ty.composite_type.inner { if self.inner.shared && !sub_ty.composite_type.shared { @@ -1520,7 +1529,7 @@ where self.resources.sub_type_at_id(func_id).unwrap_func() } - fn tag_at(&self, at: u32) -> Result<&'resources FuncType> { + fn tag_at(&self, at: TagIdx) -> Result<&'resources FuncType> { self.resources .tag_at(at) .ok_or_else(|| format_err!(self.offset, "unknown tag {}: tag index out of bounds", at)) @@ -1529,7 +1538,7 @@ where // Similar to `tag_at`, but checks that the result type is // empty. This is necessary when enabling the stack switching // feature as it allows non-empty result types on tags. - fn exception_tag_at(&self, at: u32) -> Result<&'resources FuncType> { + fn exception_tag_at(&self, at: TagIdx) -> Result<&'resources FuncType> { let func_ty = self.tag_at(at)?; if func_ty.results().len() != 0 { bail!( @@ -1540,7 +1549,7 @@ where Ok(func_ty) } - fn global_type_at(&self, at: u32) -> Result { + fn global_type_at(&self, at: GlobalIdx) -> Result { if let Some(ty) = self.resources.global_at(at) { if self.inner.shared && !ty.shared { bail!( @@ -1555,7 +1564,7 @@ where } /// Validates that the `table` is valid and returns the type it points to. - fn table_type_at(&self, table: u32) -> Result { + fn table_type_at(&self, table: TableIdx) -> Result { match self.resources.table_at(table) { Some(ty) => { if self.inner.shared && !ty.shared { @@ -1599,10 +1608,10 @@ where }) } - fn check_data_segment(&self, data_index: u32) -> Result<()> { + fn check_data_segment(&self, data_index: DataIdx) -> Result<()> { match self.resources.data_count() { None => bail!(self.offset, "data count section required"), - Some(count) if data_index < count => Ok(()), + Some(count) if data_index.0 < count => Ok(()), Some(_) => bail!(self.offset, "unknown data segment {data_index}"), } } @@ -1610,7 +1619,7 @@ where fn check_resume_table( &mut self, table: ResumeTable, - type_index: u32, // The type index annotation on the `resume` instruction, which `table` appears on. + type_index: TypeIdx, // The type index annotation on the `resume` instruction, which `table` appears on. ) -> Result<&'resources FuncType> { let cont_ty = self.cont_type_at(type_index)?; // ts1 -> ts2 @@ -1934,7 +1943,7 @@ where self.push_ctrl(FrameKind::TryTable, ty.ty)?; Ok(()) } - fn visit_throw(&mut self, index: u32) -> Self::Output { + fn visit_throw(&mut self, index: TagIdx) -> Self::Output { // Check values associated with the exception. let ty = self.exception_tag_at(index)?; for ty in ty.clone().params().iter().rev() { @@ -1971,7 +1980,7 @@ where } Ok(()) } - fn visit_br(&mut self, relative_depth: u32) -> Self::Output { + fn visit_br(&mut self, relative_depth: LabelIdx) -> Self::Output { let (ty, kind) = self.jump(relative_depth)?; for ty in self.label_types(ty, kind)?.rev() { self.pop_operand(Some(ty))?; @@ -1979,7 +1988,7 @@ where self.unreachable()?; Ok(()) } - fn visit_br_if(&mut self, relative_depth: u32) -> Self::Output { + fn visit_br_if(&mut self, relative_depth: LabelIdx) -> Self::Output { self.pop_operand(Some(ValType::I32))?; let (ty, kind) = self.jump(relative_depth)?; let label_types = self.label_types(ty, kind)?; @@ -2012,32 +2021,36 @@ where self.check_return()?; Ok(()) } - fn visit_call(&mut self, function_index: u32) -> Self::Output { + fn visit_call(&mut self, function_index: FuncIdx) -> Self::Output { let ty = self.type_of_function(function_index)?; self.check_call_ty(ty)?; Ok(()) } - fn visit_return_call(&mut self, function_index: u32) -> Self::Output { + fn visit_return_call(&mut self, function_index: FuncIdx) -> Self::Output { let ty = self.type_of_function(function_index)?; self.check_return_call_ty(ty)?; Ok(()) } - fn visit_call_ref(&mut self, type_index: u32) -> Self::Output { + fn visit_call_ref(&mut self, type_index: TypeIdx) -> Self::Output { let ty = self.check_call_ref_ty(type_index)?; self.check_call_ty(ty)?; Ok(()) } - fn visit_return_call_ref(&mut self, type_index: u32) -> Self::Output { + fn visit_return_call_ref(&mut self, type_index: TypeIdx) -> Self::Output { let ty = self.check_call_ref_ty(type_index)?; self.check_return_call_ty(ty)?; Ok(()) } - fn visit_call_indirect(&mut self, type_index: u32, table_index: u32) -> Self::Output { + fn visit_call_indirect(&mut self, type_index: TypeIdx, table_index: TableIdx) -> Self::Output { let ty = self.check_call_indirect_ty(type_index, table_index)?; self.check_call_ty(ty)?; Ok(()) } - fn visit_return_call_indirect(&mut self, type_index: u32, table_index: u32) -> Self::Output { + fn visit_return_call_indirect( + &mut self, + type_index: TypeIdx, + table_index: TableIdx, + ) -> Self::Output { let ty = self.check_call_indirect_ty(type_index, table_index)?; self.check_return_call_ty(ty)?; Ok(()) @@ -2092,7 +2105,7 @@ where self.push_operand(ty)?; Ok(()) } - fn visit_local_get(&mut self, local_index: u32) -> Self::Output { + fn visit_local_get(&mut self, local_index: LocalIdx) -> Self::Output { let ty = self.local(local_index)?; debug_assert_type_indices_are_ids(ty); if self.local_inits.is_uninit(local_index) { @@ -2101,26 +2114,30 @@ where self.push_operand(ty)?; Ok(()) } - fn visit_local_set(&mut self, local_index: u32) -> Self::Output { + fn visit_local_set(&mut self, local_index: LocalIdx) -> Self::Output { let ty = self.local(local_index)?; self.pop_operand(Some(ty))?; self.local_inits.set_init(local_index); Ok(()) } - fn visit_local_tee(&mut self, local_index: u32) -> Self::Output { + fn visit_local_tee(&mut self, local_index: LocalIdx) -> Self::Output { let expected_ty = self.local(local_index)?; self.pop_operand(Some(expected_ty))?; self.local_inits.set_init(local_index); self.push_operand(expected_ty)?; Ok(()) } - fn visit_global_get(&mut self, global_index: u32) -> Self::Output { + fn visit_global_get(&mut self, global_index: GlobalIdx) -> Self::Output { let ty = self.global_type_at(global_index)?.content_type; debug_assert_type_indices_are_ids(ty); self.push_operand(ty)?; Ok(()) } - fn visit_global_atomic_get(&mut self, _ordering: Ordering, global_index: u32) -> Self::Output { + fn visit_global_atomic_get( + &mut self, + _ordering: Ordering, + global_index: GlobalIdx, + ) -> Self::Output { self.visit_global_get(global_index)?; // No validation of `ordering` is needed because `global.atomic.get` can // be used on both shared and unshared globals. But we do need to limit @@ -2132,7 +2149,7 @@ where } Ok(()) } - fn visit_global_set(&mut self, global_index: u32) -> Self::Output { + fn visit_global_set(&mut self, global_index: GlobalIdx) -> Self::Output { let ty = self.global_type_at(global_index)?; if !ty.mutable { bail!( @@ -2143,7 +2160,11 @@ where self.pop_operand(Some(ty.content_type))?; Ok(()) } - fn visit_global_atomic_set(&mut self, _ordering: Ordering, global_index: u32) -> Self::Output { + fn visit_global_atomic_set( + &mut self, + _ordering: Ordering, + global_index: GlobalIdx, + ) -> Self::Output { self.visit_global_set(global_index)?; // No validation of `ordering` is needed because `global.atomic.get` can // be used on both shared and unshared globals. @@ -2157,7 +2178,7 @@ where fn visit_global_atomic_rmw_add( &mut self, _ordering: crate::Ordering, - global_index: u32, + global_index: GlobalIdx, ) -> Self::Output { let ty = self.check_atomic_global_rmw_ty(global_index)?; self.check_unary_op(ty) @@ -2165,7 +2186,7 @@ where fn visit_global_atomic_rmw_sub( &mut self, _ordering: crate::Ordering, - global_index: u32, + global_index: GlobalIdx, ) -> Self::Output { let ty = self.check_atomic_global_rmw_ty(global_index)?; self.check_unary_op(ty) @@ -2173,7 +2194,7 @@ where fn visit_global_atomic_rmw_and( &mut self, _ordering: crate::Ordering, - global_index: u32, + global_index: GlobalIdx, ) -> Self::Output { let ty = self.check_atomic_global_rmw_ty(global_index)?; self.check_unary_op(ty) @@ -2181,7 +2202,7 @@ where fn visit_global_atomic_rmw_or( &mut self, _ordering: crate::Ordering, - global_index: u32, + global_index: GlobalIdx, ) -> Self::Output { let ty = self.check_atomic_global_rmw_ty(global_index)?; self.check_unary_op(ty) @@ -2189,7 +2210,7 @@ where fn visit_global_atomic_rmw_xor( &mut self, _ordering: crate::Ordering, - global_index: u32, + global_index: GlobalIdx, ) -> Self::Output { let ty = self.check_atomic_global_rmw_ty(global_index)?; self.check_unary_op(ty) @@ -2197,7 +2218,7 @@ where fn visit_global_atomic_rmw_xchg( &mut self, _ordering: crate::Ordering, - global_index: u32, + global_index: GlobalIdx, ) -> Self::Output { let ty = self.global_type_at(global_index)?.content_type; if !(ty == ValType::I32 @@ -2211,7 +2232,7 @@ where fn visit_global_atomic_rmw_cmpxchg( &mut self, _ordering: crate::Ordering, - global_index: u32, + global_index: GlobalIdx, ) -> Self::Output { let ty = self.global_type_at(global_index)?.content_type; if !(ty == ValType::I32 @@ -2350,12 +2371,12 @@ where self.pop_operand(Some(ty))?; Ok(()) } - fn visit_memory_size(&mut self, mem: u32) -> Self::Output { + fn visit_memory_size(&mut self, mem: MemIdx) -> Self::Output { let index_ty = self.check_memory_index(mem)?; self.push_operand(index_ty)?; Ok(()) } - fn visit_memory_grow(&mut self, mem: u32) -> Self::Output { + fn visit_memory_grow(&mut self, mem: MemIdx) -> Self::Output { let index_ty = self.check_memory_index(mem)?; self.pop_operand(Some(index_ty))?; self.push_operand(index_ty)?; @@ -3022,7 +3043,7 @@ where self.push_operand(ty)?; Ok(()) } - fn visit_br_on_null(&mut self, relative_depth: u32) -> Self::Output { + fn visit_br_on_null(&mut self, relative_depth: LabelIdx) -> Self::Output { let ref_ty = self.pop_ref(None)?.as_non_null(); let (ft, kind) = self.jump(relative_depth)?; let label_types = self.label_types(ft, kind)?; @@ -3030,7 +3051,7 @@ where self.push_operand(ref_ty)?; Ok(()) } - fn visit_br_on_non_null(&mut self, relative_depth: u32) -> Self::Output { + fn visit_br_on_non_null(&mut self, relative_depth: LabelIdx) -> Self::Output { let (ft, kind) = self.jump(relative_depth)?; let mut label_types = self.label_types(ft, kind)?; @@ -3055,7 +3076,7 @@ where self.push_operand(ValType::I32)?; Ok(()) } - fn visit_ref_func(&mut self, function_index: u32) -> Self::Output { + fn visit_ref_func(&mut self, function_index: FuncIdx) -> Self::Output { let type_id = match self.resources.type_id_of_function(function_index) { Some(id) => id, None => bail!( @@ -3098,7 +3119,7 @@ where } self.push_operand(ValType::I32) } - fn visit_memory_init(&mut self, segment: u32, mem: u32) -> Self::Output { + fn visit_memory_init(&mut self, segment: DataIdx, mem: MemIdx) -> Self::Output { let ty = self.check_memory_index(mem)?; self.check_data_segment(segment)?; self.pop_operand(Some(ValType::I32))?; @@ -3106,11 +3127,11 @@ where self.pop_operand(Some(ty))?; Ok(()) } - fn visit_data_drop(&mut self, segment: u32) -> Self::Output { + fn visit_data_drop(&mut self, segment: DataIdx) -> Self::Output { self.check_data_segment(segment)?; Ok(()) } - fn visit_memory_copy(&mut self, dst: u32, src: u32) -> Self::Output { + fn visit_memory_copy(&mut self, dst: MemIdx, src: MemIdx) -> Self::Output { let dst_ty = self.check_memory_index(dst)?; let src_ty = self.check_memory_index(src)?; @@ -3127,20 +3148,20 @@ where self.pop_operand(Some(dst_ty))?; Ok(()) } - fn visit_memory_fill(&mut self, mem: u32) -> Self::Output { + fn visit_memory_fill(&mut self, mem: MemIdx) -> Self::Output { let ty = self.check_memory_index(mem)?; self.pop_operand(Some(ty))?; self.pop_operand(Some(ValType::I32))?; self.pop_operand(Some(ty))?; Ok(()) } - fn visit_memory_discard(&mut self, mem: u32) -> Self::Output { + fn visit_memory_discard(&mut self, mem: MemIdx) -> Self::Output { let ty = self.check_memory_index(mem)?; self.pop_operand(Some(ty))?; self.pop_operand(Some(ty))?; Ok(()) } - fn visit_table_init(&mut self, segment: u32, table: u32) -> Self::Output { + fn visit_table_init(&mut self, segment: ElemIdx, table: TableIdx) -> Self::Output { let table = self.table_type_at(table)?; let segment_ty = self.element_type_at(segment)?; if !self @@ -3154,11 +3175,11 @@ where self.pop_operand(Some(table.index_type()))?; Ok(()) } - fn visit_elem_drop(&mut self, segment: u32) -> Self::Output { + fn visit_elem_drop(&mut self, segment: ElemIdx) -> Self::Output { self.element_type_at(segment)?; Ok(()) } - fn visit_table_copy(&mut self, dst_table: u32, src_table: u32) -> Self::Output { + fn visit_table_copy(&mut self, dst_table: TableIdx, src_table: TableIdx) -> Self::Output { let src = self.table_type_at(src_table)?; let dst = self.table_type_at(dst_table)?; if !self.resources.is_subtype( @@ -3181,14 +3202,14 @@ where self.pop_operand(Some(dst.index_type()))?; Ok(()) } - fn visit_table_get(&mut self, table: u32) -> Self::Output { + fn visit_table_get(&mut self, table: TableIdx) -> Self::Output { let table = self.table_type_at(table)?; debug_assert_type_indices_are_ids(table.element_type.into()); self.pop_operand(Some(table.index_type()))?; self.push_operand(table.element_type)?; Ok(()) } - fn visit_table_atomic_get(&mut self, _ordering: Ordering, table: u32) -> Self::Output { + fn visit_table_atomic_get(&mut self, _ordering: Ordering, table: TableIdx) -> Self::Output { self.visit_table_get(table)?; // No validation of `ordering` is needed because `table.atomic.get` can // be used on both shared and unshared tables. But we do need to limit @@ -3203,14 +3224,14 @@ where } Ok(()) } - fn visit_table_set(&mut self, table: u32) -> Self::Output { + fn visit_table_set(&mut self, table: TableIdx) -> Self::Output { let table = self.table_type_at(table)?; debug_assert_type_indices_are_ids(table.element_type.into()); self.pop_operand(Some(table.element_type.into()))?; self.pop_operand(Some(table.index_type()))?; Ok(()) } - fn visit_table_atomic_set(&mut self, _ordering: Ordering, table: u32) -> Self::Output { + fn visit_table_atomic_set(&mut self, _ordering: Ordering, table: TableIdx) -> Self::Output { self.visit_table_set(table)?; // No validation of `ordering` is needed because `table.atomic.set` can // be used on both shared and unshared tables. But we do need to limit @@ -3225,7 +3246,7 @@ where } Ok(()) } - fn visit_table_grow(&mut self, table: u32) -> Self::Output { + fn visit_table_grow(&mut self, table: TableIdx) -> Self::Output { let table = self.table_type_at(table)?; debug_assert_type_indices_are_ids(table.element_type.into()); self.pop_operand(Some(table.index_type()))?; @@ -3233,12 +3254,12 @@ where self.push_operand(table.index_type())?; Ok(()) } - fn visit_table_size(&mut self, table: u32) -> Self::Output { + fn visit_table_size(&mut self, table: TableIdx) -> Self::Output { let table = self.table_type_at(table)?; self.push_operand(table.index_type())?; Ok(()) } - fn visit_table_fill(&mut self, table: u32) -> Self::Output { + fn visit_table_fill(&mut self, table: TableIdx) -> Self::Output { let table = self.table_type_at(table)?; debug_assert_type_indices_are_ids(table.element_type.into()); self.pop_operand(Some(table.index_type()))?; @@ -3246,7 +3267,11 @@ where self.pop_operand(Some(table.index_type()))?; Ok(()) } - fn visit_table_atomic_rmw_xchg(&mut self, _ordering: Ordering, table: u32) -> Self::Output { + fn visit_table_atomic_rmw_xchg( + &mut self, + _ordering: Ordering, + table: TableIdx, + ) -> Self::Output { let table = self.table_type_at(table)?; let elem_ty = table.element_type.into(); debug_assert_type_indices_are_ids(elem_ty); @@ -3262,7 +3287,11 @@ where self.push_operand(elem_ty)?; Ok(()) } - fn visit_table_atomic_rmw_cmpxchg(&mut self, _ordering: Ordering, table: u32) -> Self::Output { + fn visit_table_atomic_rmw_cmpxchg( + &mut self, + _ordering: Ordering, + table: TableIdx, + ) -> Self::Output { let table = self.table_type_at(table)?; let elem_ty = table.element_type.into(); debug_assert_type_indices_are_ids(elem_ty); @@ -3279,7 +3308,7 @@ where self.push_operand(elem_ty)?; Ok(()) } - fn visit_struct_new(&mut self, struct_type_index: u32) -> Self::Output { + fn visit_struct_new(&mut self, struct_type_index: TypeIdx) -> Self::Output { let struct_ty = self.struct_type_at(struct_type_index)?; for ty in struct_ty.fields.iter().rev() { self.pop_operand(Some(ty.element_type.unpack()))?; @@ -3287,7 +3316,7 @@ where self.push_concrete_ref(false, struct_type_index)?; Ok(()) } - fn visit_struct_new_default(&mut self, type_index: u32) -> Self::Output { + fn visit_struct_new_default(&mut self, type_index: TypeIdx) -> Self::Output { let ty = self.struct_type_at(type_index)?; for field in ty.fields.iter() { let val_ty = field.element_type.unpack(); @@ -3301,7 +3330,11 @@ where self.push_concrete_ref(false, type_index)?; Ok(()) } - fn visit_struct_get(&mut self, struct_type_index: u32, field_index: u32) -> Self::Output { + fn visit_struct_get( + &mut self, + struct_type_index: TypeIdx, + field_index: FieldIdx, + ) -> Self::Output { let field_ty = self.struct_field_at(struct_type_index, field_index)?; if field_ty.element_type.is_packed() { bail!( @@ -3315,8 +3348,8 @@ where fn visit_struct_atomic_get( &mut self, _ordering: Ordering, - struct_type_index: u32, - field_index: u32, + struct_type_index: TypeIdx, + field_index: FieldIdx, ) -> Self::Output { self.visit_struct_get(struct_type_index, field_index)?; // The `atomic` version has some additional type restrictions. @@ -3338,7 +3371,11 @@ where } Ok(()) } - fn visit_struct_get_s(&mut self, struct_type_index: u32, field_index: u32) -> Self::Output { + fn visit_struct_get_s( + &mut self, + struct_type_index: TypeIdx, + field_index: FieldIdx, + ) -> Self::Output { let field_ty = self.struct_field_at(struct_type_index, field_index)?; if !field_ty.element_type.is_packed() { bail!( @@ -3352,8 +3389,8 @@ where fn visit_struct_atomic_get_s( &mut self, _ordering: Ordering, - struct_type_index: u32, - field_index: u32, + struct_type_index: TypeIdx, + field_index: FieldIdx, ) -> Self::Output { self.visit_struct_get_s(struct_type_index, field_index)?; // This instruction has the same type restrictions as the non-`atomic` version. @@ -3364,7 +3401,11 @@ where )); Ok(()) } - fn visit_struct_get_u(&mut self, struct_type_index: u32, field_index: u32) -> Self::Output { + fn visit_struct_get_u( + &mut self, + struct_type_index: TypeIdx, + field_index: FieldIdx, + ) -> Self::Output { let field_ty = self.struct_field_at(struct_type_index, field_index)?; if !field_ty.element_type.is_packed() { bail!( @@ -3378,8 +3419,8 @@ where fn visit_struct_atomic_get_u( &mut self, _ordering: Ordering, - struct_type_index: u32, - field_index: u32, + struct_type_index: TypeIdx, + field_index: FieldIdx, ) -> Self::Output { self.visit_struct_get_s(struct_type_index, field_index)?; // This instruction has the same type restrictions as the non-`atomic` version. @@ -3390,7 +3431,11 @@ where )); Ok(()) } - fn visit_struct_set(&mut self, struct_type_index: u32, field_index: u32) -> Self::Output { + fn visit_struct_set( + &mut self, + struct_type_index: TypeIdx, + field_index: FieldIdx, + ) -> Self::Output { let field_ty = self.mutable_struct_field_at(struct_type_index, field_index)?; self.pop_operand(Some(field_ty.element_type.unpack()))?; self.pop_concrete_ref(true, struct_type_index)?; @@ -3399,8 +3444,8 @@ where fn visit_struct_atomic_set( &mut self, _ordering: Ordering, - struct_type_index: u32, - field_index: u32, + struct_type_index: TypeIdx, + field_index: FieldIdx, ) -> Self::Output { self.visit_struct_set(struct_type_index, field_index)?; // The `atomic` version has some additional type restrictions. @@ -3425,48 +3470,48 @@ where fn visit_struct_atomic_rmw_add( &mut self, _ordering: Ordering, - struct_type_index: u32, - field_index: u32, + struct_type_index: TypeIdx, + field_index: FieldIdx, ) -> Self::Output { self.check_struct_atomic_rmw("add", struct_type_index, field_index) } fn visit_struct_atomic_rmw_sub( &mut self, _ordering: Ordering, - struct_type_index: u32, - field_index: u32, + struct_type_index: TypeIdx, + field_index: FieldIdx, ) -> Self::Output { self.check_struct_atomic_rmw("sub", struct_type_index, field_index) } fn visit_struct_atomic_rmw_and( &mut self, _ordering: Ordering, - struct_type_index: u32, - field_index: u32, + struct_type_index: TypeIdx, + field_index: FieldIdx, ) -> Self::Output { self.check_struct_atomic_rmw("and", struct_type_index, field_index) } fn visit_struct_atomic_rmw_or( &mut self, _ordering: Ordering, - struct_type_index: u32, - field_index: u32, + struct_type_index: TypeIdx, + field_index: FieldIdx, ) -> Self::Output { self.check_struct_atomic_rmw("or", struct_type_index, field_index) } fn visit_struct_atomic_rmw_xor( &mut self, _ordering: Ordering, - struct_type_index: u32, - field_index: u32, + struct_type_index: TypeIdx, + field_index: FieldIdx, ) -> Self::Output { self.check_struct_atomic_rmw("xor", struct_type_index, field_index) } fn visit_struct_atomic_rmw_xchg( &mut self, _ordering: Ordering, - struct_type_index: u32, - field_index: u32, + struct_type_index: TypeIdx, + field_index: FieldIdx, ) -> Self::Output { let field = self.mutable_struct_field_at(struct_type_index, field_index)?; let is_valid_type = match field.element_type { @@ -3491,8 +3536,8 @@ where fn visit_struct_atomic_rmw_cmpxchg( &mut self, _ordering: Ordering, - struct_type_index: u32, - field_index: u32, + struct_type_index: TypeIdx, + field_index: FieldIdx, ) -> Self::Output { let field = self.mutable_struct_field_at(struct_type_index, field_index)?; let is_valid_type = match field.element_type { @@ -3515,13 +3560,13 @@ where self.push_operand(field_ty)?; Ok(()) } - fn visit_array_new(&mut self, type_index: u32) -> Self::Output { + fn visit_array_new(&mut self, type_index: TypeIdx) -> Self::Output { let array_ty = self.array_type_at(type_index)?; self.pop_operand(Some(ValType::I32))?; self.pop_operand(Some(array_ty.element_type.unpack()))?; self.push_concrete_ref(false, type_index) } - fn visit_array_new_default(&mut self, type_index: u32) -> Self::Output { + fn visit_array_new_default(&mut self, type_index: TypeIdx) -> Self::Output { let ty = self.array_type_at(type_index)?; let val_ty = ty.element_type.unpack(); if !val_ty.is_defaultable() { @@ -3533,7 +3578,7 @@ where self.pop_operand(Some(ValType::I32))?; self.push_concrete_ref(false, type_index) } - fn visit_array_new_fixed(&mut self, type_index: u32, n: u32) -> Self::Output { + fn visit_array_new_fixed(&mut self, type_index: TypeIdx, n: u32) -> Self::Output { let array_ty = self.array_type_at(type_index)?; let elem_ty = array_ty.element_type.unpack(); for _ in 0..n { @@ -3541,7 +3586,7 @@ where } self.push_concrete_ref(false, type_index) } - fn visit_array_new_data(&mut self, type_index: u32, data_index: u32) -> Self::Output { + fn visit_array_new_data(&mut self, type_index: TypeIdx, data_index: DataIdx) -> Self::Output { let array_ty = self.array_type_at(type_index)?; let elem_ty = array_ty.element_type.unpack(); match elem_ty { @@ -3556,7 +3601,7 @@ where self.pop_operand(Some(ValType::I32))?; self.push_concrete_ref(false, type_index) } - fn visit_array_new_elem(&mut self, type_index: u32, elem_index: u32) -> Self::Output { + fn visit_array_new_elem(&mut self, type_index: TypeIdx, elem_index: ElemIdx) -> Self::Output { let array_ty = self.array_type_at(type_index)?; let array_ref_ty = match array_ty.element_type.unpack() { ValType::Ref(rt) => rt, @@ -3580,7 +3625,7 @@ where self.pop_operand(Some(ValType::I32))?; self.push_concrete_ref(false, type_index) } - fn visit_array_get(&mut self, type_index: u32) -> Self::Output { + fn visit_array_get(&mut self, type_index: TypeIdx) -> Self::Output { let array_ty = self.array_type_at(type_index)?; let elem_ty = array_ty.element_type; if elem_ty.is_packed() { @@ -3593,7 +3638,7 @@ where self.pop_concrete_ref(true, type_index)?; self.push_operand(elem_ty.unpack()) } - fn visit_array_atomic_get(&mut self, _ordering: Ordering, type_index: u32) -> Self::Output { + fn visit_array_atomic_get(&mut self, _ordering: Ordering, type_index: TypeIdx) -> Self::Output { self.visit_array_get(type_index)?; // The `atomic` version has some additional type restrictions. let elem_ty = self.array_type_at(type_index)?.element_type; @@ -3612,7 +3657,7 @@ where } Ok(()) } - fn visit_array_get_s(&mut self, type_index: u32) -> Self::Output { + fn visit_array_get_s(&mut self, type_index: TypeIdx) -> Self::Output { let array_ty = self.array_type_at(type_index)?; let elem_ty = array_ty.element_type; if !elem_ty.is_packed() { @@ -3625,7 +3670,11 @@ where self.pop_concrete_ref(true, type_index)?; self.push_operand(elem_ty.unpack()) } - fn visit_array_atomic_get_s(&mut self, _ordering: Ordering, type_index: u32) -> Self::Output { + fn visit_array_atomic_get_s( + &mut self, + _ordering: Ordering, + type_index: TypeIdx, + ) -> Self::Output { self.visit_array_get_s(type_index)?; // This instruction has the same type restrictions as the non-`atomic` version. debug_assert!(matches!( @@ -3634,7 +3683,7 @@ where )); Ok(()) } - fn visit_array_get_u(&mut self, type_index: u32) -> Self::Output { + fn visit_array_get_u(&mut self, type_index: TypeIdx) -> Self::Output { let array_ty = self.array_type_at(type_index)?; let elem_ty = array_ty.element_type; if !elem_ty.is_packed() { @@ -3647,7 +3696,11 @@ where self.pop_concrete_ref(true, type_index)?; self.push_operand(elem_ty.unpack()) } - fn visit_array_atomic_get_u(&mut self, _ordering: Ordering, type_index: u32) -> Self::Output { + fn visit_array_atomic_get_u( + &mut self, + _ordering: Ordering, + type_index: TypeIdx, + ) -> Self::Output { self.visit_array_get_u(type_index)?; // This instruction has the same type restrictions as the non-`atomic` version. debug_assert!(matches!( @@ -3656,14 +3709,14 @@ where )); Ok(()) } - fn visit_array_set(&mut self, type_index: u32) -> Self::Output { + fn visit_array_set(&mut self, type_index: TypeIdx) -> Self::Output { let array_ty = self.mutable_array_type_at(type_index)?; self.pop_operand(Some(array_ty.element_type.unpack()))?; self.pop_operand(Some(ValType::I32))?; self.pop_concrete_ref(true, type_index)?; Ok(()) } - fn visit_array_atomic_set(&mut self, _ordering: Ordering, type_index: u32) -> Self::Output { + fn visit_array_atomic_set(&mut self, _ordering: Ordering, type_index: TypeIdx) -> Self::Output { self.visit_array_set(type_index)?; // The `atomic` version has some additional type restrictions. let elem_ty = self.array_type_at(type_index)?.element_type; @@ -3686,7 +3739,7 @@ where self.pop_maybe_shared_ref(AbstractHeapType::Array)?; self.push_operand(ValType::I32) } - fn visit_array_fill(&mut self, array_type_index: u32) -> Self::Output { + fn visit_array_fill(&mut self, array_type_index: TypeIdx) -> Self::Output { let array_ty = self.mutable_array_type_at(array_type_index)?; self.pop_operand(Some(ValType::I32))?; self.pop_operand(Some(array_ty.element_type.unpack()))?; @@ -3694,7 +3747,11 @@ where self.pop_concrete_ref(true, array_type_index)?; Ok(()) } - fn visit_array_copy(&mut self, type_index_dst: u32, type_index_src: u32) -> Self::Output { + fn visit_array_copy( + &mut self, + type_index_dst: TypeIdx, + type_index_src: TypeIdx, + ) -> Self::Output { let array_ty_dst = self.mutable_array_type_at(type_index_dst)?; let array_ty_src = self.array_type_at(type_index_src)?; match (array_ty_dst.element_type, array_ty_src.element_type) { @@ -3732,8 +3789,8 @@ where } fn visit_array_init_data( &mut self, - array_type_index: u32, - array_data_index: u32, + array_type_index: TypeIdx, + array_data_index: DataIdx, ) -> Self::Output { let array_ty = self.mutable_array_type_at(array_type_index)?; let val_ty = array_ty.element_type.unpack(); @@ -3751,7 +3808,7 @@ where self.pop_concrete_ref(true, array_type_index)?; Ok(()) } - fn visit_array_init_elem(&mut self, type_index: u32, elem_index: u32) -> Self::Output { + fn visit_array_init_elem(&mut self, type_index: TypeIdx, elem_index: ElemIdx) -> Self::Output { let array_ty = self.mutable_array_type_at(type_index)?; let array_ref_ty = match array_ty.element_type.unpack() { ValType::Ref(rt) => rt, @@ -3777,25 +3834,45 @@ where self.pop_concrete_ref(true, type_index)?; Ok(()) } - fn visit_array_atomic_rmw_add(&mut self, _ordering: Ordering, type_index: u32) -> Self::Output { + fn visit_array_atomic_rmw_add( + &mut self, + _ordering: Ordering, + type_index: TypeIdx, + ) -> Self::Output { self.check_array_atomic_rmw("add", type_index) } - fn visit_array_atomic_rmw_sub(&mut self, _ordering: Ordering, type_index: u32) -> Self::Output { + fn visit_array_atomic_rmw_sub( + &mut self, + _ordering: Ordering, + type_index: TypeIdx, + ) -> Self::Output { self.check_array_atomic_rmw("sub", type_index) } - fn visit_array_atomic_rmw_and(&mut self, _ordering: Ordering, type_index: u32) -> Self::Output { + fn visit_array_atomic_rmw_and( + &mut self, + _ordering: Ordering, + type_index: TypeIdx, + ) -> Self::Output { self.check_array_atomic_rmw("and", type_index) } - fn visit_array_atomic_rmw_or(&mut self, _ordering: Ordering, type_index: u32) -> Self::Output { + fn visit_array_atomic_rmw_or( + &mut self, + _ordering: Ordering, + type_index: TypeIdx, + ) -> Self::Output { self.check_array_atomic_rmw("or", type_index) } - fn visit_array_atomic_rmw_xor(&mut self, _ordering: Ordering, type_index: u32) -> Self::Output { + fn visit_array_atomic_rmw_xor( + &mut self, + _ordering: Ordering, + type_index: TypeIdx, + ) -> Self::Output { self.check_array_atomic_rmw("xor", type_index) } fn visit_array_atomic_rmw_xchg( &mut self, _ordering: Ordering, - type_index: u32, + type_index: TypeIdx, ) -> Self::Output { let field = self.mutable_array_type_at(type_index)?; let is_valid_type = match field.element_type { @@ -3821,7 +3898,7 @@ where fn visit_array_atomic_rmw_cmpxchg( &mut self, _ordering: Ordering, - type_index: u32, + type_index: TypeIdx, ) -> Self::Output { let field = self.mutable_array_type_at(type_index)?; let is_valid_type = match field.element_type { @@ -3893,7 +3970,7 @@ where } fn visit_br_on_cast( &mut self, - relative_depth: u32, + relative_depth: LabelIdx, mut from_ref_type: RefType, mut to_ref_type: RefType, ) -> Self::Output { @@ -3937,7 +4014,7 @@ where } fn visit_br_on_cast_fail( &mut self, - relative_depth: u32, + relative_depth: LabelIdx, mut from_ref_type: RefType, mut to_ref_type: RefType, ) -> Self::Output { @@ -4004,7 +4081,7 @@ where self.push_ctrl(FrameKind::LegacyTry, ty)?; Ok(()) } - fn visit_catch(&mut self, index: u32) -> Self::Output { + fn visit_catch(&mut self, index: TagIdx) -> Self::Output { let frame = self.pop_ctrl()?; if frame.kind != FrameKind::LegacyTry && frame.kind != FrameKind::LegacyCatch { bail!(self.offset, "catch found outside of an `try` block"); @@ -4026,7 +4103,7 @@ where } Ok(()) } - fn visit_rethrow(&mut self, relative_depth: u32) -> Self::Output { + fn visit_rethrow(&mut self, relative_depth: LabelIdx) -> Self::Output { // 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(relative_depth)?; @@ -4039,7 +4116,7 @@ where self.unreachable()?; Ok(()) } - fn visit_delegate(&mut self, relative_depth: u32) -> Self::Output { + fn visit_delegate(&mut self, relative_depth: LabelIdx) -> Self::Output { let frame = self.pop_ctrl()?; if frame.kind != FrameKind::LegacyTry { bail!(self.offset, "delegate found outside of an `try` block"); @@ -4070,14 +4147,14 @@ where }); Ok(()) } - fn visit_cont_new(&mut self, type_index: u32) -> Self::Output { + fn visit_cont_new(&mut self, type_index: TypeIdx) -> Self::Output { let cont_ty = self.cont_type_at(type_index)?; let rt = RefType::concrete(true, cont_ty.0); self.pop_ref(Some(rt))?; self.push_concrete_ref(false, type_index)?; Ok(()) } - fn visit_cont_bind(&mut self, argument_index: u32, result_index: u32) -> Self::Output { + fn visit_cont_bind(&mut self, argument_index: TypeIdx, result_index: TypeIdx) -> Self::Output { // [ts1 ts1'] -> [ts2] let arg_cont = self.cont_type_at(argument_index)?; let arg_func = self.func_type_of_cont_type(arg_cont); @@ -4114,7 +4191,7 @@ where Ok(()) } - fn visit_suspend(&mut self, tag_index: u32) -> Self::Output { + fn visit_suspend(&mut self, tag_index: TagIdx) -> Self::Output { let ft = &self.tag_at(tag_index)?; for &ty in ft.params().iter().rev() { self.pop_operand(Some(ty))?; @@ -4124,7 +4201,7 @@ where } Ok(()) } - fn visit_resume(&mut self, type_index: u32, table: ResumeTable) -> Self::Output { + fn visit_resume(&mut self, type_index: TypeIdx, table: ResumeTable) -> Self::Output { // [ts1] -> [ts2] let ft = self.check_resume_table(table, type_index)?; self.pop_concrete_ref(true, type_index)?; @@ -4141,8 +4218,8 @@ where } fn visit_resume_throw( &mut self, - type_index: u32, - tag_index: u32, + type_index: TypeIdx, + tag_index: TagIdx, table: ResumeTable, ) -> Self::Output { // [ts1] -> [ts2] @@ -4164,7 +4241,7 @@ where } Ok(()) } - fn visit_switch(&mut self, type_index: u32, tag_index: u32) -> Self::Output { + fn visit_switch(&mut self, type_index: TypeIdx, tag_index: TagIdx) -> Self::Output { // [t1* (ref null $ct2)] -> [te1*] let cont_ty = self.cont_type_at(type_index)?; let func_ty = self.func_type_of_cont_type(cont_ty); @@ -4307,7 +4384,7 @@ impl Locals { } self.first.push(ty); } - self.all.push((self.num_locals - 1, ty)); + self.all.push((LocalIdx(self.num_locals - 1), ty)); true } @@ -4318,14 +4395,14 @@ impl Locals { /// Returns the type of the local variable at the given index if any. #[inline] - pub(super) fn get(&self, idx: u32) -> Option { - match self.first.get(idx as usize) { + pub(super) fn get(&self, idx: LocalIdx) -> Option { + match self.first.get(idx) { Some(ty) => Some(*ty), None => self.get_bsearch(idx), } } - fn get_bsearch(&self, idx: u32) -> Option { + fn get_bsearch(&self, idx: LocalIdx) -> Option { match self.all.binary_search_by_key(&idx, |(idx, _)| *idx) { // If this index would be inserted at the end of the list, then the // index is out of bounds and we return an error. @@ -4345,18 +4422,18 @@ impl ModuleArity for WasmProposalValidator<'_, '_, R> where R: WasmModuleResources, { - fn tag_type_arity(&self, at: u32) -> Option<(u32, u32)> { + fn tag_type_arity(&self, at: TagIdx) -> Option<(u32, u32)> { self.0 .resources .tag_at(at) .map(|x| (x.params().len() as u32, x.results().len() as u32)) } - fn type_index_of_function(&self, function_idx: u32) -> Option { + fn type_index_of_function(&self, function_idx: FuncIdx) -> Option { self.0.resources.type_index_of_function(function_idx) } - fn sub_type_at(&self, type_idx: u32) -> Option<&SubType> { + fn sub_type_at(&self, type_idx: TypeIdx) -> Option<&SubType> { Some(self.0.sub_type_at(type_idx).ok()?) } @@ -4373,7 +4450,7 @@ where self.0.control.len() as u32 } - fn label_block(&self, depth: u32) -> Option<(BlockType, FrameKind)> { + fn label_block(&self, depth: LabelIdx) -> Option<(BlockType, FrameKind)> { self.0.jump(depth).ok() } } diff --git a/crates/wasmparser/src/validator/types.rs b/crates/wasmparser/src/validator/types.rs index 9898608bd5..fba3c84e91 100644 --- a/crates/wasmparser/src/validator/types.rs +++ b/crates/wasmparser/src/validator/types.rs @@ -15,6 +15,8 @@ use crate::{FuncType, HeapType, ValidatorId}; use alloc::sync::Arc; use core::ops::{Deref, DerefMut, Index, Range}; use core::{hash::Hash, mem}; +use index_vec::Idx; +use wasm_types::{ElemIdx, FuncIdx, GlobalIdx, MemIdx, TableIdx, TagIdx, TypeIdx}; /// A trait shared by all type identifiers. /// @@ -104,7 +106,7 @@ pub(crate) use define_type_id; #[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)] #[repr(C)] pub struct CoreTypeId { - index: u32, + index: TypeIdx, } #[test] @@ -116,7 +118,9 @@ impl TypeIdentifier for CoreTypeId { type Data = SubType; fn from_index(index: u32) -> Self { - CoreTypeId { index } + CoreTypeId { + index: TypeIdx(index), + } } fn list(types: &TypeList) -> &SnapshotList { @@ -128,7 +132,7 @@ impl TypeIdentifier for CoreTypeId { } fn index(&self) -> usize { - usize::try_from(self.index).unwrap() + self.index.index() } } @@ -358,7 +362,7 @@ impl<'a> TypesRef<'a> { /// Get the types within a rec group. pub fn rec_group_elements(&self, id: RecGroupId) -> impl ExactSizeIterator { let range = &self.list.rec_group_elements[id]; - (range.start.index..range.end.index).map(|index| CoreTypeId { index }) + (range.start.index.0..range.end.index.0).map(|index| CoreTypeId::from_index(index)) } /// Get the super type of the given type id, if any. @@ -376,9 +380,9 @@ impl<'a> TypesRef<'a> { /// # Panics /// /// This will panic if the `index` provided is out of bounds. - pub fn core_type_at_in_module(&self, index: u32) -> CoreTypeId { + pub fn core_type_at_in_module(&self, index: TypeIdx) -> CoreTypeId { match &self.kind { - TypesRefKind::Module(module) => module.types[index as usize].into(), + TypesRefKind::Module(module) => module.types[index].into(), #[cfg(feature = "component-model")] TypesRefKind::Component(_) => panic!("use `core_type_at_in_component` instead"), } @@ -401,13 +405,13 @@ impl<'a> TypesRef<'a> { /// # Panics /// /// This will panic if the `index` provided is out of bounds. - pub fn table_at(&self, index: u32) -> TableType { + pub fn table_at(&self, index: TableIdx) -> TableType { let tables = match &self.kind { TypesRefKind::Module(module) => &module.tables, #[cfg(feature = "component-model")] TypesRefKind::Component(component) => &component.core_tables, }; - tables[index as usize] + tables[index] } /// Returns the number of tables defined so far. @@ -424,14 +428,14 @@ impl<'a> TypesRef<'a> { /// # Panics /// /// This will panic if the `index` provided is out of bounds. - pub fn memory_at(&self, index: u32) -> MemoryType { + pub fn memory_at(&self, index: MemIdx) -> MemoryType { let memories = match &self.kind { TypesRefKind::Module(module) => &module.memories, #[cfg(feature = "component-model")] TypesRefKind::Component(component) => &component.core_memories, }; - memories[index as usize] + memories[index] } /// Returns the number of memories defined so far. @@ -448,14 +452,14 @@ impl<'a> TypesRef<'a> { /// # Panics /// /// This will panic if the `index` provided is out of bounds. - pub fn global_at(&self, index: u32) -> GlobalType { + pub fn global_at(&self, index: GlobalIdx) -> GlobalType { let globals = match &self.kind { TypesRefKind::Module(module) => &module.globals, #[cfg(feature = "component-model")] TypesRefKind::Component(component) => &component.core_globals, }; - globals[index as usize] + globals[index] } /// Returns the number of globals defined so far. @@ -472,13 +476,13 @@ impl<'a> TypesRef<'a> { /// # Panics /// /// This will panic if the `index` provided is out of bounds. - pub fn tag_at(&self, index: u32) -> CoreTypeId { + pub fn tag_at(&self, index: TagIdx) -> CoreTypeId { let tags = match &self.kind { TypesRefKind::Module(module) => &module.tags, #[cfg(feature = "component-model")] TypesRefKind::Component(component) => &component.core_tags, }; - tags[index as usize] + tags[index] } /// Returns the number of tags defined so far. @@ -495,11 +499,11 @@ impl<'a> TypesRef<'a> { /// # Panics /// /// This will panic if the `index` provided is out of bounds. - pub fn core_function_at(&self, index: u32) -> CoreTypeId { + pub fn core_function_at(&self, index: FuncIdx) -> CoreTypeId { match &self.kind { - TypesRefKind::Module(module) => module.types[module.functions[index as usize] as usize], + TypesRefKind::Module(module) => module.types[module.functions[index]], #[cfg(feature = "component-model")] - TypesRefKind::Component(component) => component.core_funcs[index as usize], + TypesRefKind::Component(component) => component.core_funcs[index], } } @@ -520,9 +524,9 @@ impl<'a> TypesRef<'a> { /// # Panics /// /// This will panic if the `index` provided is out of bounds. - pub fn element_at(&self, index: u32) -> RefType { + pub fn element_at(&self, index: ElemIdx) -> RefType { match &self.kind { - TypesRefKind::Module(module) => module.element_types[index as usize], + TypesRefKind::Module(module) => module.element_types[index], #[cfg(feature = "component-model")] TypesRefKind::Component(_) => { panic!("no elements on a component") @@ -543,11 +547,11 @@ impl<'a> TypesRef<'a> { pub fn entity_type_from_import(&self, import: &Import) -> Option { match &self.kind { TypesRefKind::Module(module) => Some(match import.ty { - TypeRef::Func(idx) => EntityType::Func(*module.types.get(idx as usize)?), + TypeRef::Func(idx) => EntityType::Func(*module.types.get(idx)?), TypeRef::Table(ty) => EntityType::Table(ty), TypeRef::Memory(ty) => EntityType::Memory(ty), TypeRef::Global(ty) => EntityType::Global(ty), - TypeRef::Tag(ty) => EntityType::Tag(*module.types.get(ty.func_type_idx as usize)?), + TypeRef::Tag(ty) => EntityType::Tag(*module.types.get(ty.func_type_idx)?), }), #[cfg(feature = "component-model")] TypesRefKind::Component(_) => None, @@ -558,21 +562,21 @@ impl<'a> TypesRef<'a> { pub fn entity_type_from_export(&self, export: &Export) -> Option { match &self.kind { TypesRefKind::Module(module) => Some(match export.kind { - ExternalKind::Func => EntityType::Func( - module.types[*module.functions.get(export.index as usize)? as usize], - ), + ExternalKind::Func => { + EntityType::Func(module.types[*module.functions.get(FuncIdx(export.index))?]) + } ExternalKind::Table => { - EntityType::Table(*module.tables.get(export.index as usize)?) + EntityType::Table(*module.tables.get(TableIdx(export.index))?) } ExternalKind::Memory => { - EntityType::Memory(*module.memories.get(export.index as usize)?) + EntityType::Memory(*module.memories.get(MemIdx(export.index))?) } ExternalKind::Global => { - EntityType::Global(*module.globals.get(export.index as usize)?) + EntityType::Global(*module.globals.get(GlobalIdx(export.index))?) + } + ExternalKind::Tag => { + EntityType::Tag(module.types[*module.functions.get(FuncIdx(export.index))?]) } - ExternalKind::Tag => EntityType::Tag( - module.types[*module.functions.get(export.index as usize)? as usize], - ), }), #[cfg(feature = "component-model")] TypesRefKind::Component(_) => None, @@ -909,7 +913,7 @@ impl TypeList { self.core_type_to_supertype .push(ty.supertype_idx.and_then(|idx| match idx.unpack() { UnpackedIndex::RecGroup(offset) => { - Some(CoreTypeId::from_index(start.index + offset)) + Some(CoreTypeId::from_index(start.index.0 + offset)) } UnpackedIndex::Id(id) => Some(id), // Only invalid wasm has this, at this point, so defer the @@ -921,7 +925,7 @@ impl TypeList { // `UnpackedIndex::Module` means that this is invalid wasm which // will get an error returned later. if let UnpackedIndex::RecGroup(offset) = index.unpack() { - *index = UnpackedIndex::Id(CoreTypeId::from_index(start.index + offset)) + *index = UnpackedIndex::Id(CoreTypeId::from_index(start.index.0 + offset)) .pack() .unwrap(); } diff --git a/crates/wasmprinter/Cargo.toml b/crates/wasmprinter/Cargo.toml index b868ce15a0..3af75b3256 100644 --- a/crates/wasmprinter/Cargo.toml +++ b/crates/wasmprinter/Cargo.toml @@ -18,7 +18,9 @@ workspace = true [dependencies] anyhow = { workspace = true } +index_vec = { workspace = true } termcolor = { workspace = true } +wasm-types = { workspace = true } wasmparser = { workspace = true, features = ['std', 'simd'] } [dev-dependencies] diff --git a/crates/wasmprinter/src/component.rs b/crates/wasmprinter/src/component.rs index 762af3f7ec..a9ffc97038 100644 --- a/crates/wasmprinter/src/component.rs +++ b/crates/wasmprinter/src/component.rs @@ -1,5 +1,10 @@ -use crate::{name_map, Naming, Printer, State}; +use crate::{ + name_map, ComponentFuncIdx, ComponentIdx, ComponentInstanceIdx, ComponentTypeIdx, + ComponentValueIdx, CoreModuleIdx, Naming, Printer, State, +}; use anyhow::{bail, Result}; +use index_vec::Idx; +use wasm_types::{CoreInstanceIdx, TypeIdx}; use wasmparser::*; impl Printer<'_, '_> { @@ -73,7 +78,7 @@ impl Printer<'_, '_> { self.start_group("core type ")?; self.print_name( &states.last().unwrap().core.type_names, - states.last().unwrap().core.types.len() as u32, + TypeIdx::from_usize(states.last().unwrap().core.types.len()), )?; self.print_module_type(states, decls.into_vec())?; self.end_group()?; // `core type` itself @@ -83,7 +88,11 @@ impl Printer<'_, '_> { Ok(()) } - pub(crate) fn print_component_type_ref(&mut self, state: &State, idx: u32) -> Result<()> { + pub(crate) fn print_component_type_ref( + &mut self, + state: &State, + idx: ComponentTypeIdx, + ) -> Result<()> { self.start_group("type ")?; self.print_idx(&state.component.type_names, idx)?; self.end_group()?; @@ -425,10 +434,13 @@ impl Printer<'_, '_> { self.result.write_str(" ")?; match kind { OuterAliasKind::Type => { - self.print_idx(&outer.core.type_names, index)?; + self.print_idx(&outer.core.type_names, TypeIdx(index))?; self.result.write_str(" ")?; self.start_group("type ")?; - self.print_name(&state.core.type_names, state.core.types.len() as u32)?; + self.print_name( + &state.core.type_names, + TypeIdx::from_usize(state.core.types.len()), + )?; } } self.end_group()?; // kind @@ -436,7 +448,9 @@ impl Printer<'_, '_> { let state = states.last_mut().unwrap(); match kind { - OuterAliasKind::Type => state.core.types.push(None), + OuterAliasKind::Type => { + state.core.types.push(None); + } } Ok(()) @@ -481,7 +495,7 @@ impl Printer<'_, '_> { self.start_group("type ")?; { let state = states.last_mut().unwrap(); - self.print_name(&state.component.type_names, state.component.types)?; + self.print_name(&state.component.type_names, state.component.type_idx)?; } match ty { ComponentType::Defined(ty) => { @@ -517,7 +531,7 @@ impl Printer<'_, '_> { } self.end_group()?; - states.last_mut().unwrap().component.types += 1; + states.last_mut().unwrap().component.type_idx.0 += 1; Ok(()) } @@ -574,9 +588,9 @@ impl Printer<'_, '_> { ComponentTypeRef::Module(idx) => { self.start_group("core module ")?; if index { - self.print_name(&state.core.module_names, state.core.modules as u32)?; + self.print_name(&state.core.module_names, state.core.module_idx)?; self.result.write_str(" ")?; - state.core.modules += 1; + state.core.module_idx.0 += 1; } self.print_core_type_ref(state, *idx)?; self.end_group()?; @@ -584,9 +598,9 @@ impl Printer<'_, '_> { ComponentTypeRef::Func(idx) => { self.start_group("func ")?; if index { - self.print_name(&state.component.func_names, state.component.funcs)?; + self.print_name(&state.component.func_names, state.component.func_idx)?; self.result.write_str(" ")?; - state.component.funcs += 1; + state.component.func_idx.0 += 1; } self.print_component_type_ref(state, *idx)?; self.end_group()?; @@ -594,9 +608,9 @@ impl Printer<'_, '_> { ComponentTypeRef::Value(ty) => { self.start_group("value ")?; if index { - self.print_name(&state.component.value_names, state.component.values)?; + self.print_name(&state.component.value_names, state.component.value_idx)?; self.result.write_str(" ")?; - state.component.values += 1; + state.component.value_idx.0 += 1; } match ty { ComponentValType::Primitive(ty) => self.print_primitive_val_type(ty)?, @@ -607,9 +621,9 @@ impl Printer<'_, '_> { ComponentTypeRef::Type(bounds) => { self.start_group("type ")?; if index { - self.print_name(&state.component.type_names, state.component.types)?; + self.print_name(&state.component.type_names, state.component.type_idx)?; self.result.write_str(" ")?; - state.component.types += 1; + state.component.type_idx.0 += 1; } match bounds { TypeBounds::Eq(idx) => { @@ -628,9 +642,12 @@ impl Printer<'_, '_> { ComponentTypeRef::Instance(idx) => { self.start_group("instance ")?; if index { - self.print_name(&state.component.instance_names, state.component.instances)?; + self.print_name( + &state.component.instance_names, + state.component.instance_idx, + )?; self.result.write_str(" ")?; - state.component.instances += 1; + state.component.instance_idx.0 += 1; } self.print_component_type_ref(state, *idx)?; self.end_group()?; @@ -638,9 +655,12 @@ impl Printer<'_, '_> { ComponentTypeRef::Component(idx) => { self.start_group("component ")?; if index { - self.print_name(&state.component.component_names, state.component.components)?; + self.print_name( + &state.component.component_names, + state.component.component_idx, + )?; self.result.write_str(" ")?; - state.component.components += 1; + state.component.component_idx.0 += 1; } self.print_component_type_ref(state, *idx)?; self.end_group()?; @@ -691,28 +711,34 @@ impl Printer<'_, '_> { ) -> Result<()> { match kind { ComponentExternalKind::Func => { - self.print_name(&state.component.func_names, state.component.funcs)?; - state.component.funcs += 1; + self.print_name(&state.component.func_names, state.component.func_idx)?; + state.component.func_idx.0 += 1; } ComponentExternalKind::Module => { - self.print_name(&state.core.module_names, state.core.modules)?; - state.core.modules += 1; + self.print_name(&state.core.module_names, state.core.module_idx)?; + state.core.module_idx.0 += 1; } ComponentExternalKind::Value => { - self.print_name(&state.component.value_names, state.component.values)?; - state.component.values += 1; + self.print_name(&state.component.value_names, state.component.value_idx)?; + state.component.value_idx.0 += 1; } ComponentExternalKind::Type => { - self.print_name(&state.component.type_names, state.component.types)?; - state.component.types += 1; + self.print_name(&state.component.type_names, state.component.type_idx)?; + state.component.type_idx.0 += 1; } ComponentExternalKind::Instance => { - self.print_name(&state.component.instance_names, state.component.instances)?; - state.component.instances += 1; + self.print_name( + &state.component.instance_names, + state.component.instance_idx, + )?; + state.component.instance_idx.0 += 1; } ComponentExternalKind::Component => { - self.print_name(&state.component.component_names, state.component.components)?; - state.component.components += 1; + self.print_name( + &state.component.component_names, + state.component.component_idx, + )?; + state.component.component_idx.0 += 1; } } Ok(()) @@ -754,22 +780,22 @@ impl Printer<'_, '_> { self.start_component_external_kind_group(kind)?; match kind { ComponentExternalKind::Module => { - self.print_idx(&state.core.module_names, index)?; + self.print_idx(&state.core.module_names, CoreModuleIdx(index))?; } ComponentExternalKind::Component => { - self.print_idx(&state.component.component_names, index)?; + self.print_idx(&state.component.component_names, ComponentIdx(index))?; } ComponentExternalKind::Instance => { - self.print_idx(&state.component.instance_names, index)?; + self.print_idx(&state.component.instance_names, ComponentInstanceIdx(index))?; } ComponentExternalKind::Func => { - self.print_idx(&state.component.func_names, index)?; + self.print_idx(&state.component.func_names, ComponentFuncIdx(index))?; } ComponentExternalKind::Value => { - self.print_idx(&state.component.value_names, index)?; + self.print_idx(&state.component.value_names, ComponentValueIdx(index))?; } ComponentExternalKind::Type => { - self.print_idx(&state.component.type_names, index)?; + self.print_idx(&state.component.type_names, ComponentTypeIdx(index))?; } } self.end_group()?; @@ -822,14 +848,14 @@ impl Printer<'_, '_> { body: &dyn Fn(&mut Self, &mut State) -> Result<()>, ) -> Result<()> { self.start_group("core func ")?; - self.print_name(&state.core.func_names, state.core.funcs)?; + self.print_name(&state.core.func_names, state.core.funcidx)?; self.result.write_str(" ")?; self.start_group(group)?; body(self, state)?; self.end_group()?; self.end_group()?; - debug_assert_eq!(state.core.func_to_type.len(), state.core.funcs as usize); - state.core.funcs += 1; + debug_assert_eq!(state.core.func_to_type.len(), state.core.funcidx.index()); + state.core.funcidx.0 += 1; state.core.func_to_type.push(None); Ok(()) } @@ -849,7 +875,7 @@ impl Printer<'_, '_> { options, } => { self.start_group("func ")?; - self.print_name(&state.component.func_names, state.component.funcs)?; + self.print_name(&state.component.func_names, state.component.func_idx)?; self.result.write_str(" ")?; self.start_group("type ")?; self.print_idx(&state.component.type_names, type_index)?; @@ -862,7 +888,7 @@ impl Printer<'_, '_> { self.print_canonical_options(state, &options)?; self.end_group()?; self.end_group()?; - state.component.funcs += 1; + state.component.func_idx.0 += 1; } CanonicalFunction::Lower { func_index, @@ -894,22 +920,22 @@ impl Printer<'_, '_> { func_ty_index: func_index, } => { self.start_group("core func ")?; - self.print_name(&state.core.func_names, state.core.funcs)?; + self.print_name(&state.core.func_names, state.core.funcidx)?; self.result.write_str(" ")?; self.start_group("canon thread.spawn ")?; self.print_idx(&state.core.type_names, func_index)?; self.end_group()?; self.end_group()?; - state.core.funcs += 1; + state.core.funcidx.0 += 1; } CanonicalFunction::ThreadAvailableParallelism => { self.start_group("core func ")?; - self.print_name(&state.core.func_names, state.core.funcs)?; + self.print_name(&state.core.func_names, state.core.funcidx)?; self.result.write_str(" ")?; self.start_group("canon thread.available_parallelism")?; self.end_group()?; self.end_group()?; - state.core.funcs += 1; + state.core.funcidx.0 += 1; } CanonicalFunction::TaskBackpressure => { self.print_intrinsic(state, "canon task.backpressure", &|_, _| Ok(()))?; @@ -1076,7 +1102,7 @@ impl Printer<'_, '_> { let (offset, instance) = instance?; self.newline(offset)?; self.start_group("core instance ")?; - self.print_name(&state.core.instance_names, state.core.instances)?; + self.print_name(&state.core.instance_names, state.core.instance_idx)?; match instance { Instance::Instantiate { module_index, args } => { self.result.write_str(" ")?; @@ -1087,14 +1113,14 @@ impl Printer<'_, '_> { self.print_instantiation_arg(state, arg)?; } self.end_group()?; - state.core.instances += 1; + state.core.instance_idx.0 += 1; } Instance::FromExports(exports) => { for export in exports.iter() { self.newline(offset)?; self.print_export(state, export)?; } - state.core.instances += 1; + state.core.instance_idx.0 += 1; } } self.end_group()?; @@ -1111,8 +1137,11 @@ impl Printer<'_, '_> { let (offset, instance) = instance?; self.newline(offset)?; self.start_group("instance ")?; - self.print_name(&state.component.instance_names, state.component.instances)?; - state.component.instances += 1; + self.print_name( + &state.component.instance_names, + state.component.instance_idx, + )?; + state.component.instance_idx.0 += 1; match instance { ComponentInstance::Instantiate { component_index, @@ -1150,7 +1179,7 @@ impl Printer<'_, '_> { match arg.kind { InstantiationArgKind::Instance => { self.start_group("instance ")?; - self.print_idx(&state.core.instance_names, arg.index)?; + self.print_idx(&state.core.instance_names, CoreInstanceIdx(arg.index))?; self.end_group()?; } } @@ -1192,10 +1221,10 @@ impl Printer<'_, '_> { self.result.write_str(" ")?; self.start_group("result ")?; self.start_group("value ")?; - self.print_name(&state.component.value_names, state.component.values)?; + self.print_name(&state.component.value_names, state.component.value_idx)?; self.end_group()?; self.end_group()?; - state.component.values += 1; + state.component.value_idx.0 += 1; } self.end_group()?; // start @@ -1253,37 +1282,37 @@ impl Printer<'_, '_> { match kind { ExternalKind::Func => { self.start_group("core func ")?; - self.print_name(&state.core.func_names, state.core.funcs)?; + self.print_name(&state.core.func_names, state.core.funcidx)?; self.end_group()?; - debug_assert_eq!(state.core.func_to_type.len(), state.core.funcs as usize); - state.core.funcs += 1; - state.core.func_to_type.push(None) + debug_assert_eq!(state.core.func_to_type.len(), state.core.funcidx.index()); + state.core.funcidx.0 += 1; + state.core.func_to_type.push(None); } ExternalKind::Table => { self.start_group("core table ")?; - self.print_name(&state.core.table_names, state.core.tables)?; + self.print_name(&state.core.table_names, state.core.tableidx)?; self.end_group()?; - state.core.tables += 1; + state.core.tableidx.0 += 1; } ExternalKind::Memory => { self.start_group("core memory ")?; - self.print_name(&state.core.memory_names, state.core.memories)?; + self.print_name(&state.core.memory_names, state.core.memidx)?; self.end_group()?; - state.core.memories += 1; + state.core.memidx.0 += 1; } ExternalKind::Global => { self.start_group("core global ")?; - self.print_name(&state.core.global_names, state.core.globals)?; + self.print_name(&state.core.global_names, state.core.globalidx)?; self.end_group()?; - state.core.globals += 1; + state.core.globalidx.0 += 1; } ExternalKind::Tag => { self.start_group("core tag ")?; - self.print_name(&state.core.tag_names, state.core.tags as u32)?; + self.print_name(&state.core.tag_names, state.core.tagidx)?; self.end_group()?; - debug_assert_eq!(state.core.tag_to_type.len(), state.core.tags as usize); - state.core.tags += 1; - state.core.tag_to_type.push(None) + debug_assert_eq!(state.core.tag_to_type.len(), state.core.tagidx.index()); + state.core.tagidx.0 += 1; + state.core.tag_to_type.push(None); } } self.end_group()?; // alias export @@ -1301,30 +1330,33 @@ impl Printer<'_, '_> { self.result.write_str(" ")?; match kind { ComponentOuterAliasKind::CoreModule => { - self.print_idx(&outer.core.module_names, index)?; + self.print_idx(&outer.core.module_names, CoreModuleIdx(index))?; self.result.write_str(" ")?; self.start_group("core module ")?; - self.print_name(&state.core.module_names, state.core.modules)?; + self.print_name(&state.core.module_names, state.core.module_idx)?; } ComponentOuterAliasKind::CoreType => { - self.print_idx(&outer.core.type_names, index)?; + self.print_idx(&outer.core.type_names, TypeIdx(index))?; self.result.write_str(" ")?; self.start_group("core type ")?; - self.print_name(&state.core.type_names, state.core.types.len() as u32)?; + self.print_name( + &state.core.type_names, + TypeIdx::from_usize(state.core.types.len()), + )?; } ComponentOuterAliasKind::Type => { - self.print_idx(&outer.component.type_names, index)?; + self.print_idx(&outer.component.type_names, ComponentTypeIdx(index))?; self.result.write_str(" ")?; self.start_group("type ")?; - self.print_name(&state.component.type_names, state.component.types)?; + self.print_name(&state.component.type_names, state.component.type_idx)?; } ComponentOuterAliasKind::Component => { - self.print_idx(&outer.component.component_names, index)?; + self.print_idx(&outer.component.component_names, ComponentIdx(index))?; self.result.write_str(" ")?; self.start_group("component ")?; self.print_name( &state.component.component_names, - state.component.components, + state.component.component_idx, )?; } } @@ -1333,10 +1365,12 @@ impl Printer<'_, '_> { let state = states.last_mut().unwrap(); match kind { - ComponentOuterAliasKind::CoreModule => state.core.modules += 1, - ComponentOuterAliasKind::CoreType => state.core.types.push(None), - ComponentOuterAliasKind::Type => state.component.types += 1, - ComponentOuterAliasKind::Component => state.component.components += 1, + ComponentOuterAliasKind::CoreModule => state.core.module_idx.0 += 1, + ComponentOuterAliasKind::CoreType => { + state.core.types.push(None); + } + ComponentOuterAliasKind::Type => state.component.type_idx.0 += 1, + ComponentOuterAliasKind::Component => state.component.component_idx.0 += 1, } } } diff --git a/crates/wasmprinter/src/lib.rs b/crates/wasmprinter/src/lib.rs index ac9deb254e..02bc9d4a50 100644 --- a/crates/wasmprinter/src/lib.rs +++ b/crates/wasmprinter/src/lib.rs @@ -9,6 +9,7 @@ #![deny(missing_docs)] use anyhow::{anyhow, bail, Context, Result}; +use index_vec::{Idx, IndexVec}; use operator::{OpPrinter, OperatorSeparator, OperatorState, PrintOperator, PrintOperatorFolded}; use std::collections::{HashMap, HashSet}; use std::fmt; @@ -16,8 +17,18 @@ use std::io; use std::marker; use std::mem; use std::path::Path; +use wasm_types::{ + AbsoluteLabelIdx, DataIdx, ElemIdx, FieldIdx, FuncIdx, GlobalIdx, LocalIdx, MemIdx, TableIdx, + TagIdx, TypeIdx, +}; use wasmparser::*; +#[cfg(feature = "component-model")] +use wasm_types::{ + ComponentFuncIdx, ComponentIdx, ComponentInstanceIdx, ComponentTypeIdx, ComponentValueIdx, + CoreInstanceIdx, CoreModuleIdx, +}; + const MAX_LOCALS: u32 = 50000; const MAX_NESTING_TO_PRINT: u32 = 50; const MAX_WASM_FUNCTIONS: u32 = 1_000_000; @@ -78,38 +89,38 @@ struct Printer<'cfg, 'env> { nesting: u32, line: usize, group_lines: Vec, - code_section_hints: Vec<(u32, Vec<(usize, BranchHint)>)>, + code_section_hints: Vec<(FuncIdx, Vec<(usize, BranchHint)>)>, } #[derive(Default)] struct CoreState { - types: Vec>, - funcs: u32, - func_to_type: Vec>, - memories: u32, - tags: u32, - tag_to_type: Vec>, - globals: u32, - tables: u32, + types: IndexVec>, + funcidx: FuncIdx, + func_to_type: IndexVec>, + memidx: MemIdx, + tagidx: TagIdx, + tag_to_type: IndexVec>, + globalidx: GlobalIdx, + tableidx: TableIdx, #[cfg(feature = "component-model")] - modules: u32, + module_idx: CoreModuleIdx, #[cfg(feature = "component-model")] - instances: u32, - func_names: NamingMap, - local_names: NamingMap<(u32, u32), NameLocal>, - label_names: NamingMap<(u32, u32), NameLabel>, - type_names: NamingMap, - field_names: NamingMap<(u32, u32), NameField>, - tag_names: NamingMap, - table_names: NamingMap, - memory_names: NamingMap, - global_names: NamingMap, - element_names: NamingMap, - data_names: NamingMap, + instance_idx: CoreInstanceIdx, + func_names: NamingMap, + local_names: NamingMap<(FuncIdx, LocalIdx), NameLocal>, + label_names: NamingMap<(FuncIdx, AbsoluteLabelIdx), NameLabel>, + type_names: NamingMap, + field_names: NamingMap<(TypeIdx, FieldIdx), NameField>, + tag_names: NamingMap, + table_names: NamingMap, + memory_names: NamingMap, + global_names: NamingMap, + element_names: NamingMap, + data_names: NamingMap, #[cfg(feature = "component-model")] - module_names: NamingMap, + module_names: NamingMap, #[cfg(feature = "component-model")] - instance_names: NamingMap, + instance_names: NamingMap, } /// A map of index-to-name for tracking what are the contents of the name @@ -138,16 +149,16 @@ impl Default for NamingMap { #[derive(Default)] #[cfg(feature = "component-model")] struct ComponentState { - types: u32, - funcs: u32, - instances: u32, - components: u32, - values: u32, - type_names: NamingMap, - func_names: NamingMap, - component_names: NamingMap, - instance_names: NamingMap, - value_names: NamingMap, + type_idx: ComponentTypeIdx, + func_idx: ComponentFuncIdx, + instance_idx: ComponentInstanceIdx, + component_idx: ComponentIdx, + value_idx: ComponentValueIdx, + type_names: NamingMap, + func_names: NamingMap, + component_names: NamingMap, + instance_names: NamingMap, + value_names: NamingMap, } struct State { @@ -441,7 +452,7 @@ impl Printer<'_, '_> { if states.len() > 1 { let parent = &states[states.len() - 2]; self.result.write_str(" ")?; - self.print_name(&parent.core.module_names, parent.core.modules)?; + self.print_name(&parent.core.module_names, parent.core.module_idx)?; } } Encoding::Component => { @@ -455,7 +466,7 @@ impl Printer<'_, '_> { self.result.write_str(" ")?; self.print_name( &parent.component.component_names, - parent.component.components, + parent.component.component_idx, )?; } } @@ -541,7 +552,7 @@ impl Printer<'_, '_> { ); } for ty in reader { - states.last_mut().unwrap().core.func_to_type.push(Some(ty?)) + states.last_mut().unwrap().core.func_to_type.push(Some(ty?)); } } Payload::TableSection(s) => { @@ -673,10 +684,10 @@ impl Printer<'_, '_> { if let Some(parent) = states.last_mut() { match state.encoding { Encoding::Module => { - parent.core.modules += 1; + parent.core.module_idx.0 += 1; } Encoding::Component => { - parent.component.components += 1; + parent.component.component_idx.0 += 1; } } parser = parsers.pop().unwrap(); @@ -730,11 +741,15 @@ impl Printer<'_, '_> { } fn register_names(&mut self, state: &mut State, names: NameSectionReader<'_>) -> Result<()> { - fn indirect_name_map( - into: &mut NamingMap<(u32, u32), K>, - names: IndirectNameMap<'_>, + fn indirect_name_map<'a, I, J, K>( + into: &mut NamingMap<(I, J), K>, + names: IndirectNameMap<'a, I, J>, name: &str, - ) -> Result<()> { + ) -> Result<()> + where + I: Idx + FromReader<'a>, + J: fmt::Display + Idx + FromReader<'a>, + { for indirect in names { let indirect = indirect?; let mut used = match name { @@ -812,7 +827,7 @@ impl Printer<'_, '_> { } else { self.start_group("type ")?; } - let ty_idx = state.core.types.len() as u32; + let ty_idx = TypeIdx::from_usize(state.core.types.len()); self.print_name(&state.core.type_names, ty_idx)?; self.result.write_str(" ")?; self.print_sub(state, &ty, ty_idx)?; @@ -821,7 +836,7 @@ impl Printer<'_, '_> { Ok(()) } - fn print_sub(&mut self, state: &State, ty: &SubType, ty_idx: u32) -> Result { + fn print_sub(&mut self, state: &State, ty: &SubType, ty_idx: TypeIdx) -> Result { let r = if !ty.is_final || !ty.supertype_idx.is_none() { self.start_group("sub")?; self.print_sub_type(state, ty)?; @@ -834,7 +849,12 @@ impl Printer<'_, '_> { Ok(r) } - fn print_composite(&mut self, state: &State, ty: &CompositeType, ty_idx: u32) -> Result { + fn print_composite( + &mut self, + state: &State, + ty: &CompositeType, + ty_idx: TypeIdx, + ) -> Result { if ty.shared { self.start_group("shared")?; self.result.write_str(" ")?; @@ -883,12 +903,12 @@ impl Printer<'_, '_> { fn print_core_functype_idx( &mut self, state: &State, - idx: u32, - names_for: Option, + idx: TypeIdx, + names_for: Option, ) -> Result> { self.print_core_type_ref(state, idx)?; - match state.core.types.get(idx as usize) { + match state.core.types.get(idx) { Some(Some(SubType { composite_type: CompositeType { @@ -907,7 +927,7 @@ impl Printer<'_, '_> { &mut self, state: &State, ty: &FuncType, - names_for: Option, + names_for: Option, ) -> Result { if !ty.params().is_empty() { self.result.write_str(" ")?; @@ -918,7 +938,7 @@ impl Printer<'_, '_> { // we need to be careful to terminate previous param blocks and open // a new one if that's the case with a named parameter. for (i, param) in ty.params().iter().enumerate() { - params.start_local(names_for, i as u32, self, state)?; + params.start_local(names_for, LocalIdx::from_usize(i), self, state)?; self.print_valtype(state, *param)?; params.end_local(self)?; } @@ -939,7 +959,7 @@ impl Printer<'_, '_> { &mut self, state: &State, ty: &FieldType, - ty_field_idx: Option<(u32, u32)>, + ty_field_idx: Option<(TypeIdx, FieldIdx)>, ) -> Result { self.result.write_str(" ")?; if let Some(idxs @ (_, field_idx)) = ty_field_idx { @@ -966,10 +986,19 @@ impl Printer<'_, '_> { self.print_field_type(state, &ty.0, None) } - fn print_struct_type(&mut self, state: &State, ty: &StructType, ty_idx: u32) -> Result { + fn print_struct_type( + &mut self, + state: &State, + ty: &StructType, + ty_idx: TypeIdx, + ) -> Result { for (field_index, field) in ty.fields.iter().enumerate() { self.result.write_str(" (field")?; - self.print_field_type(state, field, Some((ty_idx, field_index as u32)))?; + self.print_field_type( + state, + field, + Some((ty_idx, FieldIdx::from_usize(field_index))), + )?; self.result.write_str(")")?; } Ok(0) @@ -1092,21 +1121,21 @@ impl Printer<'_, '_> { self.print_import(state, &import, true)?; match import.ty { TypeRef::Func(idx) => { - debug_assert!(state.core.func_to_type.len() == state.core.funcs as usize); - state.core.funcs += 1; - state.core.func_to_type.push(Some(idx)) + debug_assert!(state.core.func_to_type.len() == state.core.funcidx.index()); + state.core.funcidx.0 += 1; + state.core.func_to_type.push(Some(idx)); } - TypeRef::Table(_) => state.core.tables += 1, - TypeRef::Memory(_) => state.core.memories += 1, + TypeRef::Table(_) => state.core.tableidx.0 += 1, + TypeRef::Memory(_) => state.core.memidx.0 += 1, TypeRef::Tag(TagType { kind: _, func_type_idx: idx, }) => { - debug_assert!(state.core.tag_to_type.len() == state.core.tags as usize); - state.core.tags += 1; - state.core.tag_to_type.push(Some(idx)) + debug_assert!(state.core.tag_to_type.len() == state.core.tagidx.index()); + state.core.tagidx.0 += 1; + state.core.tag_to_type.push(Some(idx)); } - TypeRef::Global(_) => state.core.globals += 1, + TypeRef::Global(_) => state.core.globalidx.0 += 1, } } Ok(()) @@ -1128,7 +1157,7 @@ impl Printer<'_, '_> { TypeRef::Func(f) => { self.start_group("func ")?; if index { - self.print_name(&state.core.func_names, state.core.funcs)?; + self.print_name(&state.core.func_names, state.core.funcidx)?; self.result.write_str(" ")?; } self.print_core_type_ref(state, *f)?; @@ -1145,7 +1174,7 @@ impl Printer<'_, '_> { fn print_table_type(&mut self, state: &State, ty: &TableType, index: bool) -> Result<()> { self.start_group("table ")?; if index { - self.print_name(&state.core.table_names, state.core.tables)?; + self.print_name(&state.core.table_names, state.core.tableidx)?; self.result.write_str(" ")?; } if ty.shared { @@ -1163,7 +1192,7 @@ impl Printer<'_, '_> { fn print_memory_type(&mut self, state: &State, ty: &MemoryType, index: bool) -> Result<()> { self.start_group("memory ")?; if index { - self.print_name(&state.core.memory_names, state.core.memories)?; + self.print_name(&state.core.memory_names, state.core.memidx)?; self.result.write_str(" ")?; } if ty.memory64 { @@ -1189,7 +1218,7 @@ impl Printer<'_, '_> { fn print_tag_type(&mut self, state: &State, ty: &TagType, index: bool) -> Result<()> { self.start_group("tag ")?; if index { - self.print_name(&state.core.tag_names, state.core.tags)?; + self.print_name(&state.core.tag_names, state.core.tagidx)?; self.result.write_str(" ")?; } self.print_core_functype_idx(state, ty.func_type_idx, None)?; @@ -1212,7 +1241,7 @@ impl Printer<'_, '_> { fn print_global_type(&mut self, state: &State, ty: &GlobalType, index: bool) -> Result<()> { self.start_group("global ")?; if index { - self.print_name(&state.core.global_names, state.core.globals)?; + self.print_name(&state.core.global_names, state.core.globalidx)?; self.result.write_str(" ")?; } if ty.shared || ty.mutable { @@ -1244,7 +1273,7 @@ impl Printer<'_, '_> { } } self.end_group()?; - state.core.tables += 1; + state.core.tableidx.0 += 1; } Ok(()) } @@ -1255,7 +1284,7 @@ impl Printer<'_, '_> { self.newline(offset)?; self.print_memory_type(state, &memory, true)?; self.end_group()?; - state.core.memories += 1; + state.core.memidx.0 += 1; } Ok(()) } @@ -1266,8 +1295,8 @@ impl Printer<'_, '_> { self.newline(offset)?; self.print_tag_type(state, &tag, true)?; self.end_group()?; - debug_assert!(state.core.tag_to_type.len() == state.core.tags as usize); - state.core.tags += 1; + debug_assert!(state.core.tag_to_type.len() == state.core.tagidx.index()); + state.core.tagidx.0 += 1; state.core.tag_to_type.push(Some(tag.func_type_idx)); } Ok(()) @@ -1281,7 +1310,7 @@ impl Printer<'_, '_> { self.result.write_str(" ")?; self.print_const_expr(state, &global.init_expr, self.config.fold_instructions)?; self.end_group()?; - state.core.globals += 1; + state.core.globalidx.0 += 1; } Ok(()) } @@ -1295,10 +1324,10 @@ impl Printer<'_, '_> { let offset = body.original_position(); self.newline(offset)?; self.start_group("func ")?; - let func_idx = state.core.funcs; + let func_idx = state.core.funcidx; self.print_name(&state.core.func_names, func_idx)?; self.result.write_str(" ")?; - let ty = match state.core.func_to_type.get(func_idx as usize) { + let ty = match state.core.func_to_type.get(func_idx) { Some(Some(x)) => *x, _ => panic!("invalid function type"), }; @@ -1323,14 +1352,14 @@ impl Printer<'_, '_> { } self.end_group()?; - state.core.funcs += 1; + state.core.funcidx.0 += 1; Ok(()) } fn print_func_body( &mut self, state: &mut State, - func_idx: u32, + func_idx: FuncIdx, params: u32, body: &mut BinaryReader<'_>, branch_hints: &[(usize, BranchHint)], @@ -1355,7 +1384,7 @@ impl Printer<'_, '_> { self.newline(offset)?; first = false; } - locals.start_local(Some(func_idx), params + local_idx, self, state)?; + locals.start_local(Some(func_idx), LocalIdx(params + local_idx), self, state)?; self.print_valtype(state, ty)?; locals.end_local(self)?; local_idx += 1; @@ -1464,19 +1493,19 @@ impl Printer<'_, '_> { match kind { ExternalKind::Func => { self.start_group("func ")?; - self.print_idx(&state.core.func_names, index)?; + self.print_idx(&state.core.func_names, FuncIdx(index))?; } ExternalKind::Table => { self.start_group("table ")?; - self.print_idx(&state.core.table_names, index)?; + self.print_idx(&state.core.table_names, TableIdx(index))?; } ExternalKind::Global => { self.start_group("global ")?; - self.print_idx(&state.core.global_names, index)?; + self.print_idx(&state.core.global_names, GlobalIdx(index))?; } ExternalKind::Memory => { self.start_group("memory ")?; - self.print_idx(&state.core.memory_names, index)?; + self.print_idx(&state.core.memory_names, MemIdx(index))?; } ExternalKind::Tag => { self.start_group("tag ")?; @@ -1487,21 +1516,25 @@ impl Printer<'_, '_> { Ok(()) } - fn print_core_type_ref(&mut self, state: &State, idx: u32) -> Result<()> { + fn print_core_type_ref(&mut self, state: &State, idx: TypeIdx) -> Result<()> { self.start_group("type ")?; self.print_idx(&state.core.type_names, idx)?; self.end_group()?; Ok(()) } - fn print_idx(&mut self, names: &NamingMap, idx: u32) -> Result<()> + fn print_idx(&mut self, names: &NamingMap, idx: I) -> Result<()> where + I: fmt::Display + Idx, K: NamingNamespace, { self._print_idx(&names.index_to_name, idx, K::desc()) } - fn _print_idx(&mut self, names: &HashMap, idx: u32, desc: &str) -> Result<()> { + fn _print_idx(&mut self, names: &HashMap, idx: I, desc: &str) -> Result<()> + where + I: fmt::Display + Idx, + { self.result.start_name()?; match names.get(&idx) { Some(name) => name.write_identifier(self)?, @@ -1512,7 +1545,7 @@ impl Printer<'_, '_> { Ok(()) } - fn print_local_idx(&mut self, state: &State, func: u32, idx: u32) -> Result<()> { + fn print_local_idx(&mut self, state: &State, func: FuncIdx, idx: LocalIdx) -> Result<()> { self.result.start_name()?; match state.core.local_names.index_to_name.get(&(func, idx)) { Some(name) => name.write_identifier(self)?, @@ -1523,7 +1556,7 @@ impl Printer<'_, '_> { Ok(()) } - fn print_field_idx(&mut self, state: &State, ty: u32, idx: u32) -> Result<()> { + fn print_field_idx(&mut self, state: &State, ty: TypeIdx, idx: FieldIdx) -> Result<()> { self.result.start_name()?; match state.core.field_names.index_to_name.get(&(ty, idx)) { Some(name) => name.write_identifier(self)?, @@ -1534,19 +1567,18 @@ impl Printer<'_, '_> { Ok(()) } - fn print_name(&mut self, names: &NamingMap, cur_idx: u32) -> Result<()> + fn print_name(&mut self, names: &NamingMap, cur_idx: I) -> Result<()> where + I: fmt::Display + Idx, K: NamingNamespace, { self._print_name(&names.index_to_name, cur_idx, K::desc()) } - fn _print_name( - &mut self, - names: &HashMap, - cur_idx: u32, - desc: &str, - ) -> Result<()> { + fn _print_name(&mut self, names: &HashMap, cur_idx: I, desc: &str) -> Result<()> + where + I: fmt::Display + Idx, + { self.result.start_name()?; match names.get(&cur_idx) { Some(name) => { @@ -1568,7 +1600,7 @@ impl Printer<'_, '_> { let (offset, mut elem) = elem?; self.newline(offset)?; self.start_group("elem ")?; - self.print_name(&state.core.element_names, i as u32)?; + self.print_name(&state.core.element_names, ElemIdx::from_usize(i))?; match &mut elem.kind { ElementKind::Passive => {} ElementKind::Declared => self.result.write_str(" declare")?, @@ -1618,7 +1650,7 @@ impl Printer<'_, '_> { let (offset, data) = data?; self.newline(offset)?; self.start_group("data ")?; - self.print_name(&state.core.data_names, i as u32)?; + self.print_name(&state.core.data_names, DataIdx::from_usize(i))?; self.result.write_str(" ")?; match &data.kind { DataKind::Passive => {} @@ -1626,7 +1658,7 @@ impl Printer<'_, '_> { memory_index, offset_expr, } => { - if *memory_index != 0 { + if *memory_index != MemIdx(0) { self.start_group("memory ")?; self.print_idx(&state.core.memory_names, *memory_index)?; self.end_group()?; @@ -1932,8 +1964,8 @@ impl NamedLocalPrinter { fn start_local( &mut self, - func: Option, - local: u32, + func: Option, + local: LocalIdx, dst: &mut Printer, state: &State, ) -> Result<()> { @@ -1941,7 +1973,7 @@ impl NamedLocalPrinter { .core .local_names .index_to_name - .get(&(func.unwrap_or(u32::MAX), local)); + .get(&(func.unwrap_or(FuncIdx(u32::MAX)), local)); // Named locals must be in their own group, so if we have a name we need // to terminate the previous group. @@ -2101,9 +2133,9 @@ impl Printer<'_, '_> { } impl Naming { - fn new<'a>( + fn new<'a, I: fmt::Display>( name: &'a str, - index: u32, + index: I, group: &str, used: Option<&mut HashSet<&'a str>>, ) -> Naming { @@ -2251,7 +2283,10 @@ naming_namespaces! { struct NameComponent => "component" } -fn name_map(into: &mut NamingMap, names: NameMap<'_>, name: &str) -> Result<()> { +fn name_map<'a, I, K>(into: &mut NamingMap, names: NameMap<'a, I>, name: &str) -> Result<()> +where + I: fmt::Display + Idx + FromReader<'a>, +{ let mut used = HashSet::new(); for naming in names { let naming = naming?; diff --git a/crates/wasmprinter/src/operator.rs b/crates/wasmprinter/src/operator.rs index a87df5066a..7b8c758d7d 100644 --- a/crates/wasmprinter/src/operator.rs +++ b/crates/wasmprinter/src/operator.rs @@ -1,6 +1,11 @@ use super::{Config, Print, PrintTermcolor, Printer, State}; use anyhow::{anyhow, bail, Result}; +use index_vec::Idx; use termcolor::{Ansi, NoColor}; +use wasm_types::{ + AbsoluteLabelIdx, DataIdx, ElemIdx, FuncIdx, GlobalIdx, LabelIdx, LocalIdx, MemIdx, TableIdx, + TagIdx, TypeIdx, +}; use wasmparser::VisitSimdOperator; use wasmparser::{ BinaryReader, BlockType, BrTable, Catch, CompositeInnerType, ContType, FrameKind, FuncType, @@ -11,8 +16,8 @@ use wasmparser::{ pub struct OperatorState { op_offset: usize, nesting_start: u32, - label: u32, - label_indices: Vec, + label: AbsoluteLabelIdx, + label_indices: Vec, sep: OperatorSeparator, } @@ -21,7 +26,7 @@ impl OperatorState { OperatorState { op_offset: 0, nesting_start: printer.nesting, - label: 0, + label: AbsoluteLabelIdx(0), label_indices: Vec::new(), sep, } @@ -136,7 +141,7 @@ impl<'printer, 'state, 'a, 'b> PrintOperator<'printer, 'state, 'a, 'b> { } fn blockty_without_label_comment(&mut self, ty: BlockType) -> Result { - let key = (self.state.core.funcs, self.operator_state.label); + let key = (self.state.core.funcidx, self.operator_state.label); let has_name = match self.state.core.label_names.index_to_name.get(&key) { Some(name) => { write!(self.printer.result, " ")?; @@ -179,7 +184,7 @@ impl<'printer, 'state, 'a, 'b> PrintOperator<'printer, 'state, 'a, 'b> { self.result().reset_color()?; } - self.operator_state.label += 1; + self.operator_state.label.0 += 1; Ok(()) } @@ -187,15 +192,15 @@ impl<'printer, 'state, 'a, 'b> PrintOperator<'printer, 'state, 'a, 'b> { self.printer.nesting - self.operator_state.nesting_start } - fn tag_index(&mut self, index: u32) -> Result<()> { + fn tag_index(&mut self, index: TagIdx) -> Result<()> { self.push_str(" ")?; self.printer.print_idx(&self.state.core.tag_names, index)?; Ok(()) } - fn relative_depth(&mut self, depth: u32) -> Result<()> { + fn relative_depth(&mut self, depth: LabelIdx) -> Result<()> { self.push_str(" ")?; - match self.cur_depth().checked_sub(depth) { + match self.cur_depth().checked_sub(depth.0) { // If this relative depth is in-range relative to the current depth, // then try to print a name for this label. Label names are tracked // as a stack where the depth matches `cur_depth` roughly, but label @@ -206,7 +211,7 @@ impl<'printer, 'state, 'a, 'b> PrintOperator<'printer, 'state, 'a, 'b> { .checked_sub(1) .and_then(|idx| self.operator_state.label_indices.get(idx as usize).copied()) .and_then(|label_idx| { - let key = (self.state.core.funcs, label_idx); + let key = (self.state.core.funcidx, label_idx); self.state.core.label_names.index_to_name.get(&key) }); @@ -220,7 +225,7 @@ impl<'printer, 'state, 'a, 'b> PrintOperator<'printer, 'state, 'a, 'b> { && self.operator_state.label_indices[i as usize..] .iter() .any(|other_label| { - let key = (self.state.core.funcs, *other_label); + let key = (self.state.core.funcidx, *other_label); if let Some(other) = self.state.core.label_names.index_to_name.get(&key) { if name.unwrap().name == other.name { @@ -283,65 +288,65 @@ impl<'printer, 'state, 'a, 'b> PrintOperator<'printer, 'state, 'a, 'b> { Ok(()) } - fn function_index(&mut self, idx: u32) -> Result<()> { + fn function_index(&mut self, idx: FuncIdx) -> Result<()> { self.push_str(" ")?; self.printer.print_idx(&self.state.core.func_names, idx) } - fn local_index(&mut self, idx: u32) -> Result<()> { + fn local_index(&mut self, idx: LocalIdx) -> Result<()> { self.push_str(" ")?; self.printer - .print_local_idx(self.state, self.state.core.funcs as u32, idx) + .print_local_idx(self.state, self.state.core.funcidx, idx) } - fn global_index(&mut self, idx: u32) -> Result<()> { + fn global_index(&mut self, idx: GlobalIdx) -> Result<()> { self.push_str(" ")?; self.printer.print_idx(&self.state.core.global_names, idx) } - fn table_index(&mut self, idx: u32) -> Result<()> { + fn table_index(&mut self, idx: TableIdx) -> Result<()> { self.push_str(" ")?; self.printer.print_idx(&self.state.core.table_names, idx) } - fn table(&mut self, idx: u32) -> Result<()> { + fn table(&mut self, idx: TableIdx) -> Result<()> { self.table_index(idx) } - fn memory_index(&mut self, idx: u32) -> Result<()> { + fn memory_index(&mut self, idx: MemIdx) -> Result<()> { self.push_str(" ")?; self.printer.print_idx(&self.state.core.memory_names, idx) } - fn type_index(&mut self, idx: u32) -> Result<()> { + fn type_index(&mut self, idx: TypeIdx) -> Result<()> { self.push_str(" ")?; self.printer.print_core_type_ref(self.state, idx) } - fn cont_type_index(&mut self, idx: u32) -> Result<()> { + fn cont_type_index(&mut self, idx: TypeIdx) -> Result<()> { self.push_str(" ")?; self.printer.print_idx(&self.state.core.type_names, idx) } - fn argument_index(&mut self, idx: u32) -> Result<()> { + fn argument_index(&mut self, idx: TypeIdx) -> Result<()> { self.cont_type_index(idx) } - fn result_index(&mut self, idx: u32) -> Result<()> { + fn result_index(&mut self, idx: TypeIdx) -> Result<()> { self.cont_type_index(idx) } - fn array_type_index(&mut self, idx: u32) -> Result<()> { + fn array_type_index(&mut self, idx: TypeIdx) -> Result<()> { self.push_str(" ")?; self.printer.print_idx(&self.state.core.type_names, idx) } - fn array_type_index_dst(&mut self, idx: u32) -> Result<()> { + fn array_type_index_dst(&mut self, idx: TypeIdx) -> Result<()> { self.push_str(" ")?; self.printer.print_idx(&self.state.core.type_names, idx) } - fn array_type_index_src(&mut self, idx: u32) -> Result<()> { + fn array_type_index_src(&mut self, idx: TypeIdx) -> Result<()> { self.push_str(" ")?; self.printer.print_idx(&self.state.core.type_names, idx) } @@ -351,7 +356,7 @@ impl<'printer, 'state, 'a, 'b> PrintOperator<'printer, 'state, 'a, 'b> { Ok(()) } - fn struct_type_index(&mut self, idx: u32) -> Result<()> { + fn struct_type_index(&mut self, idx: TypeIdx) -> Result<()> { self.push_str(" ")?; self.printer.print_idx(&self.state.core.type_names, idx) } @@ -366,22 +371,22 @@ impl<'printer, 'state, 'a, 'b> PrintOperator<'printer, 'state, 'a, 'b> { self.printer.print_reftype(self.state, ref_ty) } - fn data_index(&mut self, idx: u32) -> Result<()> { + fn data_index(&mut self, idx: DataIdx) -> Result<()> { self.push_str(" ")?; self.printer.print_idx(&self.state.core.data_names, idx) } - fn array_data_index(&mut self, idx: u32) -> Result<()> { + fn array_data_index(&mut self, idx: DataIdx) -> Result<()> { self.push_str(" ")?; self.printer.print_idx(&self.state.core.data_names, idx) } - fn elem_index(&mut self, idx: u32) -> Result<()> { + fn elem_index(&mut self, idx: ElemIdx) -> Result<()> { self.push_str(" ")?; self.printer.print_idx(&self.state.core.element_names, idx) } - fn array_elem_index(&mut self, idx: u32) -> Result<()> { + fn array_elem_index(&mut self, idx: ElemIdx) -> Result<()> { self.push_str(" ")?; self.printer.print_idx(&self.state.core.element_names, idx) } @@ -399,7 +404,7 @@ impl<'printer, 'state, 'a, 'b> PrintOperator<'printer, 'state, 'a, 'b> { } fn memarg(&mut self, memarg: MemArg) -> Result<()> { - if memarg.memory != 0 { + if memarg.memory != MemIdx(0) { self.memory_index(memarg.memory)?; } if memarg.offset != 0 { @@ -541,13 +546,13 @@ macro_rules! define_visit { // catch-all which prints each payload individually based on the name of the // payload field. (payload $self:ident CallIndirect $ty:ident $table:ident) => ( - if $table != 0 { + if $table != TableIdx(0) { $self.table_index($table)?; } $self.type_index($ty)?; ); (payload $self:ident ReturnCallIndirect $ty:ident $table:ident) => ( - if $table != 0 { + if $table != TableIdx(0) { $self.table_index($table)?; } $self.type_index($ty)?; @@ -571,46 +576,46 @@ macro_rules! define_visit { $self.printer.print_heaptype($self.state, $hty)?; ); (payload $self:ident TableInit $segment:ident $table:ident) => ( - if $table != 0 { + if $table != TableIdx(0) { $self.table_index($table)?; } $self.elem_index($segment)?; ); (payload $self:ident TableCopy $dst:ident $src:ident) => ( - if $src != 0 || $dst != 0 { + if $src != TableIdx(0) || $dst != TableIdx(0) { $self.table_index($dst)?; $self.table_index($src)?; } ); (payload $self:ident MemoryGrow $mem:ident) => ( - if $mem != 0 { + if $mem != MemIdx(0) { $self.memory_index($mem)?; } ); (payload $self:ident MemorySize $mem:ident) => ( - if $mem != 0 { + if $mem != MemIdx(0) { $self.memory_index($mem)?; } ); (payload $self:ident MemoryInit $segment:ident $mem:ident) => ( - if $mem != 0 { + if $mem != MemIdx(0) { $self.memory_index($mem)?; } $self.data_index($segment)?; ); (payload $self:ident MemoryCopy $dst:ident $src:ident) => ( - if $src != 0 || $dst != 0 { + if $src != MemIdx(0) || $dst != MemIdx(0) { $self.memory_index($dst)?; $self.memory_index($src)?; } ); (payload $self:ident MemoryFill $mem:ident) => ( - if $mem != 0 { + if $mem != MemIdx(0) { $self.memory_index($mem)?; } ); (payload $self:ident MemoryDiscard $mem:ident) => ( - if $mem != 0 { + if $mem != MemIdx(0) { $self.memory_index($mem)?; } ); @@ -1505,25 +1510,16 @@ impl OpPrinter for PrintOperatorFolded<'_, '_, '_, '_> { } impl ModuleArity for PrintOperatorFolded<'_, '_, '_, '_> { - fn tag_type_arity(&self, tag_idx: u32) -> Option<(u32, u32)> { - self.sub_type_arity( - self.sub_type_at( - *self - .state - .core - .tag_to_type - .get(tag_idx as usize)? - .as_ref()?, - )?, - ) + fn tag_type_arity(&self, tag_idx: TagIdx) -> Option<(u32, u32)> { + self.sub_type_arity(self.sub_type_at(*self.state.core.tag_to_type.get(tag_idx)?.as_ref()?)?) } - fn type_index_of_function(&self, func_idx: u32) -> Option { - *self.state.core.func_to_type.get(func_idx as usize)? + fn type_index_of_function(&self, func_idx: FuncIdx) -> Option { + *self.state.core.func_to_type.get(func_idx)? } - fn sub_type_at(&self, type_idx: u32) -> Option<&SubType> { - self.state.core.types.get(type_idx as usize)?.as_ref() + fn sub_type_at(&self, type_idx: TypeIdx) -> Option<&SubType> { + self.state.core.types.get(type_idx)?.as_ref() } fn func_type_of_cont_type(&self, c: &ContType) -> Option<&FuncType> { @@ -1543,12 +1539,12 @@ impl ModuleArity for PrintOperatorFolded<'_, '_, '_, '_> { self.control.len() as u32 } - fn label_block(&self, depth: u32) -> Option<(BlockType, FrameKind)> { + fn label_block(&self, depth: LabelIdx) -> Option<(BlockType, FrameKind)> { let cur_depth = self.printer.nesting - self.operator_state.nesting_start; if self.control.len() != cur_depth as usize + 1 { return None; } - match (self.control.len() - 1).checked_sub(depth as usize) { + match (self.control.len() - 1).checked_sub(depth.index()) { Some(i) => Some((self.control[i].ty, self.control[i].kind)), None => None, } @@ -1575,8 +1571,8 @@ impl<'printer, 'state, 'a, 'b> PrintOperatorFolded<'printer, 'state, 'a, 'b> { } // Set up the outermost block, representing the unnamed function label. - pub fn begin_function(&mut self, func_idx: u32) -> Result<()> { - match self.state.core.func_to_type.get(func_idx as usize) { + pub fn begin_function(&mut self, func_idx: FuncIdx) -> Result<()> { + match self.state.core.func_to_type.get(func_idx) { Some(Some(type_idx)) => self.control.push(Block { ty: BlockType::FuncType(*type_idx), kind: FrameKind::Block, diff --git a/crates/wast/Cargo.toml b/crates/wast/Cargo.toml index 845df843ad..b8ee9164f7 100644 --- a/crates/wast/Cargo.toml +++ b/crates/wast/Cargo.toml @@ -22,10 +22,12 @@ workspace = true [dependencies] bumpalo = "3.14.0" gimli = { workspace = true, optional = true } +index_vec = { workspace = true} leb128fmt = { workspace = true } memchr = "2.4.1" unicode-width = "0.2.0" wasm-encoder = { workspace = true, features = ['std'] } +wasm-types = { workspace = true } [dev-dependencies] anyhow = { workspace = true } diff --git a/crates/wast/src/component/alias.rs b/crates/wast/src/component/alias.rs index dffcda1445..2518560aaa 100644 --- a/crates/wast/src/component/alias.rs +++ b/crates/wast/src/component/alias.rs @@ -1,3 +1,5 @@ +use wasm_types::{ComponentInstanceIdx, CoreInstanceIdx}; + use crate::core::ExportKind; use crate::kw; use crate::parser::{Parse, Parser, Result}; @@ -9,7 +11,7 @@ use crate::token::{Id, Index, NameAnnotation, Span}; #[derive(Debug)] pub struct InlineExportAlias<'a, const CORE: bool> { /// The instance to alias the export from. - pub instance: Index<'a>, + pub instance: Index<'a, u32>, /// The name of the export to alias. pub name: &'a str, } @@ -231,7 +233,7 @@ pub enum AliasTarget<'a> { /// The alias is to an export of a component instance. Export { /// The component instance exporting the item. - instance: Index<'a>, + instance: Index<'a, ComponentInstanceIdx>, /// The name of the exported item to alias. name: &'a str, /// The export kind of the alias. @@ -240,7 +242,7 @@ pub enum AliasTarget<'a> { /// The alias is to an export of a module instance. CoreExport { /// The module instance exporting the item. - instance: Index<'a>, + instance: Index<'a, CoreInstanceIdx>, /// The name of the exported item to alias. name: &'a str, /// The export kind of the alias. @@ -249,9 +251,9 @@ pub enum AliasTarget<'a> { /// The alias is to an item from an outer component. Outer { /// The number of enclosing components to skip. - outer: Index<'a>, + outer: Index<'a, u32>, /// The index of the item being aliased. - index: Index<'a>, + index: Index<'a, u32>, /// The outer alias kind. kind: ComponentOuterAliasKind, }, diff --git a/crates/wast/src/component/expand.rs b/crates/wast/src/component/expand.rs index abd95bb88d..d5e564c88b 100644 --- a/crates/wast/src/component/expand.rs +++ b/crates/wast/src/component/expand.rs @@ -303,7 +303,7 @@ impl<'a> Expander<'a> { id: func.id, name: func.name, target: AliasTarget::CoreExport { - instance: a.instance, + instance: a.instance.into(), name: a.name, kind: core::ExportKind::Func, }, @@ -541,7 +541,7 @@ impl<'a> Expander<'a> { id: func.id, name: func.name, target: AliasTarget::Export { - instance: a.instance, + instance: a.instance.into(), name: a.name, kind: ComponentExportAliasKind::Func, }, diff --git a/crates/wast/src/component/export.rs b/crates/wast/src/component/export.rs index d9e2ae4b4c..0c6f43d9d0 100644 --- a/crates/wast/src/component/export.rs +++ b/crates/wast/src/component/export.rs @@ -2,6 +2,10 @@ use super::{ComponentExternName, ItemRef, ItemSigNoName}; use crate::kw; use crate::parser::{Cursor, Parse, Parser, Peek, Result}; use crate::token::{Id, Index, NameAnnotation, Span}; +use wasm_types::{ + ComponentFuncIdx, ComponentIdx, ComponentInstanceIdx, ComponentTypeIdx, ComponentValueIdx, + CoreModuleIdx, +}; /// An entry in a WebAssembly component's export section. #[derive(Debug)] @@ -60,17 +64,17 @@ pub enum ComponentExportKind<'a> { /// /// Note this isn't a core item ref as currently only /// components can export core modules. - CoreModule(ItemRef<'a, kw::module>), + CoreModule(ItemRef<'a, kw::module, CoreModuleIdx>), /// The export is a function. - Func(ItemRef<'a, kw::func>), + Func(ItemRef<'a, kw::func, ComponentFuncIdx>), /// The export is a value. - Value(ItemRef<'a, kw::value>), + Value(ItemRef<'a, kw::value, ComponentValueIdx>), /// The export is a type. - Type(ItemRef<'a, kw::r#type>), + Type(ItemRef<'a, kw::r#type, ComponentTypeIdx>), /// The export is a component. - Component(ItemRef<'a, kw::component>), + Component(ItemRef<'a, kw::component, ComponentIdx>), /// The export is an instance. - Instance(ItemRef<'a, kw::instance>), + Instance(ItemRef<'a, kw::instance, ComponentInstanceIdx>), } impl<'a> ComponentExportKind<'a> { @@ -160,7 +164,7 @@ impl Peek for ComponentExportKind<'_> { _ => return Ok(false), }; - Index::peek(cursor) + Index::::peek(cursor) } fn display() -> &'static str { diff --git a/crates/wast/src/component/func.rs b/crates/wast/src/component/func.rs index ee3e4dec3f..b8a45c9fd8 100644 --- a/crates/wast/src/component/func.rs +++ b/crates/wast/src/component/func.rs @@ -2,6 +2,7 @@ use crate::component::*; use crate::kw; use crate::parser::{Parse, Parser, Result}; use crate::token::{Id, Index, LParen, NameAnnotation, Span}; +use wasm_types::{ComponentFuncIdx, ComponentTypeIdx, FuncIdx, MemIdx, TypeIdx}; /// A declared core function. /// @@ -372,7 +373,7 @@ pub enum CanonicalFuncKind<'a> { #[derive(Debug)] pub struct CanonLift<'a> { /// The core function being lifted. - pub func: CoreItemRef<'a, kw::func>, + pub func: CoreItemRef<'a, kw::func, FuncIdx>, /// The canonical options for the lifting. pub opts: Vec>, } @@ -397,7 +398,7 @@ impl Default for CanonLift<'_> { Self { func: CoreItemRef { kind: kw::func(span), - idx: Index::Num(0, span), + idx: Index::Num(FuncIdx(0), span), export_name: None, }, opts: Vec::new(), @@ -409,7 +410,7 @@ impl Default for CanonLift<'_> { #[derive(Debug)] pub struct CanonLower<'a> { /// The function being lowered. - pub func: ItemRef<'a, kw::func>, + pub func: ItemRef<'a, kw::func, ComponentFuncIdx>, /// The canonical options for the lowering. pub opts: Vec>, } @@ -431,7 +432,7 @@ impl Default for CanonLower<'_> { Self { func: ItemRef { kind: kw::func(span), - idx: Index::Num(0, span), + idx: Index::Num(ComponentFuncIdx(0), span), export_names: Vec::new(), }, opts: Vec::new(), @@ -443,7 +444,7 @@ impl Default for CanonLower<'_> { #[derive(Debug)] pub struct CanonResourceNew<'a> { /// The resource type that this intrinsic creates an owned reference to. - pub ty: Index<'a>, + pub ty: Index<'a, ComponentTypeIdx>, } impl<'a> Parse<'a> for CanonResourceNew<'a> { @@ -460,7 +461,7 @@ impl<'a> Parse<'a> for CanonResourceNew<'a> { #[derive(Debug)] pub struct CanonResourceDrop<'a> { /// The resource type that this intrinsic is dropping. - pub ty: Index<'a>, + pub ty: Index<'a, ComponentTypeIdx>, } impl<'a> Parse<'a> for CanonResourceDrop<'a> { @@ -477,7 +478,7 @@ impl<'a> Parse<'a> for CanonResourceDrop<'a> { #[derive(Debug)] pub struct CanonResourceRep<'a> { /// The resource type that this intrinsic is accessing. - pub ty: Index<'a>, + pub ty: Index<'a, ComponentTypeIdx>, } impl<'a> Parse<'a> for CanonResourceRep<'a> { @@ -494,7 +495,7 @@ impl<'a> Parse<'a> for CanonResourceRep<'a> { #[derive(Debug)] pub struct CanonThreadSpawn<'a> { /// The function type that is being spawned. - pub ty: Index<'a>, + pub ty: Index<'a, TypeIdx>, } impl<'a> Parse<'a> for CanonThreadSpawn<'a> { @@ -549,7 +550,7 @@ pub struct CanonTaskWait<'a> { /// intrinsic. pub async_: bool, /// The memory to use when returning an event to the caller. - pub memory: CoreItemRef<'a, kw::memory>, + pub memory: CoreItemRef<'a, kw::memory, MemIdx>, } impl<'a> Parse<'a> for CanonTaskWait<'a> { @@ -572,7 +573,7 @@ pub struct CanonTaskPoll<'a> { /// intrinsic. pub async_: bool, /// The memory to use when returning an event to the caller. - pub memory: CoreItemRef<'a, kw::memory>, + pub memory: CoreItemRef<'a, kw::memory, MemIdx>, } impl<'a> Parse<'a> for CanonTaskPoll<'a> { @@ -609,7 +610,7 @@ impl<'a> Parse<'a> for CanonTaskYield { #[derive(Debug)] pub struct CanonStreamNew<'a> { /// The stream type to instantiate. - pub ty: Index<'a>, + pub ty: Index<'a, ComponentTypeIdx>, } impl<'a> Parse<'a> for CanonStreamNew<'a> { @@ -626,7 +627,7 @@ impl<'a> Parse<'a> for CanonStreamNew<'a> { #[derive(Debug)] pub struct CanonStreamRead<'a> { /// The stream type to instantiate. - pub ty: Index<'a>, + pub ty: Index<'a, ComponentTypeIdx>, /// The canonical options for storing values. pub opts: Vec>, } @@ -646,7 +647,7 @@ impl<'a> Parse<'a> for CanonStreamRead<'a> { #[derive(Debug)] pub struct CanonStreamWrite<'a> { /// The stream type to instantiate. - pub ty: Index<'a>, + pub ty: Index<'a, ComponentTypeIdx>, /// The canonical options for loading values. pub opts: Vec>, } @@ -666,7 +667,7 @@ impl<'a> Parse<'a> for CanonStreamWrite<'a> { #[derive(Debug)] pub struct CanonStreamCancelRead<'a> { /// The stream type to instantiate. - pub ty: Index<'a>, + pub ty: Index<'a, ComponentTypeIdx>, /// If false, block until cancel is finished; otherwise return BLOCKED if /// necessary. pub async_: bool, @@ -687,7 +688,7 @@ impl<'a> Parse<'a> for CanonStreamCancelRead<'a> { #[derive(Debug)] pub struct CanonStreamCancelWrite<'a> { /// The stream type to instantiate. - pub ty: Index<'a>, + pub ty: Index<'a, ComponentTypeIdx>, /// If false, block until cancel is finished; otherwise return BLOCKED if /// necessary. pub async_: bool, @@ -708,7 +709,7 @@ impl<'a> Parse<'a> for CanonStreamCancelWrite<'a> { #[derive(Debug)] pub struct CanonStreamCloseReadable<'a> { /// The stream type to close. - pub ty: Index<'a>, + pub ty: Index<'a, ComponentTypeIdx>, } impl<'a> Parse<'a> for CanonStreamCloseReadable<'a> { @@ -725,7 +726,7 @@ impl<'a> Parse<'a> for CanonStreamCloseReadable<'a> { #[derive(Debug)] pub struct CanonStreamCloseWritable<'a> { /// The stream type to close. - pub ty: Index<'a>, + pub ty: Index<'a, ComponentTypeIdx>, } impl<'a> Parse<'a> for CanonStreamCloseWritable<'a> { @@ -742,7 +743,7 @@ impl<'a> Parse<'a> for CanonStreamCloseWritable<'a> { #[derive(Debug)] pub struct CanonFutureNew<'a> { /// The future type to instantiate. - pub ty: Index<'a>, + pub ty: Index<'a, ComponentTypeIdx>, } impl<'a> Parse<'a> for CanonFutureNew<'a> { @@ -759,7 +760,7 @@ impl<'a> Parse<'a> for CanonFutureNew<'a> { #[derive(Debug)] pub struct CanonFutureRead<'a> { /// The future type to instantiate. - pub ty: Index<'a>, + pub ty: Index<'a, ComponentTypeIdx>, /// The canonical options for storing values. pub opts: Vec>, } @@ -779,7 +780,7 @@ impl<'a> Parse<'a> for CanonFutureRead<'a> { #[derive(Debug)] pub struct CanonFutureWrite<'a> { /// The future type to instantiate. - pub ty: Index<'a>, + pub ty: Index<'a, ComponentTypeIdx>, /// The canonical options for loading values. pub opts: Vec>, } @@ -799,7 +800,7 @@ impl<'a> Parse<'a> for CanonFutureWrite<'a> { #[derive(Debug)] pub struct CanonFutureCancelRead<'a> { /// The future type to instantiate. - pub ty: Index<'a>, + pub ty: Index<'a, ComponentTypeIdx>, /// If false, block until cancel is finished; otherwise return BLOCKED if /// necessary. pub async_: bool, @@ -820,7 +821,7 @@ impl<'a> Parse<'a> for CanonFutureCancelRead<'a> { #[derive(Debug)] pub struct CanonFutureCancelWrite<'a> { /// The future type to instantiate. - pub ty: Index<'a>, + pub ty: Index<'a, ComponentTypeIdx>, /// If false, block until cancel is finished; otherwise return BLOCKED if /// necessary. pub async_: bool, @@ -841,7 +842,7 @@ impl<'a> Parse<'a> for CanonFutureCancelWrite<'a> { #[derive(Debug)] pub struct CanonFutureCloseReadable<'a> { /// The future type to close. - pub ty: Index<'a>, + pub ty: Index<'a, ComponentTypeIdx>, } impl<'a> Parse<'a> for CanonFutureCloseReadable<'a> { @@ -858,7 +859,7 @@ impl<'a> Parse<'a> for CanonFutureCloseReadable<'a> { #[derive(Debug)] pub struct CanonFutureCloseWritable<'a> { /// The future type to close. - pub ty: Index<'a>, + pub ty: Index<'a, ComponentTypeIdx>, } impl<'a> Parse<'a> for CanonFutureCloseWritable<'a> { @@ -915,15 +916,15 @@ pub enum CanonOpt<'a> { /// Encode strings as "compact UTF-16". StringLatin1Utf16, /// Use the specified memory for canonical ABI memory access. - Memory(CoreItemRef<'a, kw::memory>), + Memory(CoreItemRef<'a, kw::memory, MemIdx>), /// Use the specified reallocation function for memory allocations. - Realloc(CoreItemRef<'a, kw::func>), + Realloc(CoreItemRef<'a, kw::func, FuncIdx>), /// Call the specified function after the lifted function has returned. - PostReturn(CoreItemRef<'a, kw::func>), + PostReturn(CoreItemRef<'a, kw::func, FuncIdx>), /// Use the async ABI for lifting or lowering. Async, /// Use the specified function to deliver async events to stackless coroutines. - Callback(CoreItemRef<'a, kw::func>), + Callback(CoreItemRef<'a, kw::func, FuncIdx>), } impl<'a> Parse<'a> for CanonOpt<'a> { @@ -953,17 +954,17 @@ impl<'a> Parse<'a> for CanonOpt<'a> { } else if l.peek::()? { parser.parse::()?; Ok(CanonOpt::Realloc( - parser.parse::>()?.0, + parser.parse::>()?.0, )) } else if l.peek::()? { parser.parse::()?; Ok(CanonOpt::PostReturn( - parser.parse::>()?.0, + parser.parse::>()?.0, )) } else if l.peek::()? { parser.parse::()?; Ok(CanonOpt::Callback( - parser.parse::>()?.0, + parser.parse::>()?.0, )) } else { Err(l.error()) @@ -975,7 +976,10 @@ impl<'a> Parse<'a> for CanonOpt<'a> { } } -fn parse_trailing_item_ref(kind: T, parser: Parser) -> Result> { +fn parse_trailing_item_ref<'a, T, I>(kind: T, parser: Parser<'a>) -> Result> +where + (I, Span): Parse<'a>, +{ Ok(CoreItemRef { kind, idx: parser.parse()?, diff --git a/crates/wast/src/component/import.rs b/crates/wast/src/component/import.rs index 81c8e5e406..f485eacaee 100644 --- a/crates/wast/src/component/import.rs +++ b/crates/wast/src/component/import.rs @@ -2,6 +2,7 @@ use crate::component::*; use crate::kw; use crate::parser::{Cursor, Parse, Parser, Peek, Result}; use crate::token::{Id, Index, LParen, NameAnnotation, Span}; +use wasm_types::ComponentTypeIdx; /// An `import` statement and entry in a WebAssembly component. #[derive(Debug)] @@ -134,7 +135,7 @@ pub enum ItemSigKind<'a> { #[derive(Debug)] pub enum TypeBounds<'a> { /// The equality type bounds. - Eq(Index<'a>), + Eq(Index<'a, ComponentTypeIdx>), /// A resource type is imported/exported, SubResource, } diff --git a/crates/wast/src/component/item_ref.rs b/crates/wast/src/component/item_ref.rs index cc8edc9b5b..8bad8e0253 100644 --- a/crates/wast/src/component/item_ref.rs +++ b/crates/wast/src/component/item_ref.rs @@ -1,5 +1,5 @@ use crate::parser::{Cursor, Parse, Parser, Peek, Result}; -use crate::token::Index; +use crate::token::{Index, Span}; fn peek(cursor: Cursor) -> Result { // This is a little fancy because when parsing something like: @@ -39,16 +39,19 @@ fn peek(cursor: Cursor) -> Result { /// Parses core item references. #[derive(Clone, Debug)] -pub struct CoreItemRef<'a, K> { +pub struct CoreItemRef<'a, K, I> { /// The item kind being parsed. pub kind: K, /// The item or instance reference. - pub idx: Index<'a>, + pub idx: Index<'a, I>, /// Export name to resolve the item from. pub export_name: Option<&'a str>, } -impl<'a, K: Parse<'a>> Parse<'a> for CoreItemRef<'a, K> { +impl<'a, K: Parse<'a>, I> Parse<'a> for CoreItemRef<'a, K, I> +where + (I, Span): Parse<'a>, +{ fn parse(parser: Parser<'a>) -> Result { // This does not parse the surrounding `(` and `)` because // core prefix is context dependent and only the caller knows if it should be @@ -64,7 +67,7 @@ impl<'a, K: Parse<'a>> Parse<'a> for CoreItemRef<'a, K> { } } -impl<'a, K: Peek> Peek for CoreItemRef<'a, K> { +impl<'a, K: Peek, I> Peek for CoreItemRef<'a, K, I> { fn peek(cursor: Cursor<'_>) -> Result { peek::(cursor) } @@ -76,16 +79,19 @@ impl<'a, K: Peek> Peek for CoreItemRef<'a, K> { /// Parses component item references. #[derive(Clone, Debug)] -pub struct ItemRef<'a, K> { +pub struct ItemRef<'a, K, I> { /// The item kind being parsed. pub kind: K, /// The item or instance reference. - pub idx: Index<'a>, + pub idx: Index<'a, I>, /// Export names to resolve the item from. pub export_names: Vec<&'a str>, } -impl<'a, K: Parse<'a>> Parse<'a> for ItemRef<'a, K> { +impl<'a, K: Parse<'a>, I> Parse<'a> for ItemRef<'a, K, I> +where + (I, Span): Parse<'a>, +{ fn parse(parser: Parser<'a>) -> Result { let kind = parser.parse::()?; let idx = parser.parse()?; @@ -101,7 +107,7 @@ impl<'a, K: Parse<'a>> Parse<'a> for ItemRef<'a, K> { } } -impl<'a, K: Peek> Peek for ItemRef<'a, K> { +impl<'a, K: Peek, I> Peek for ItemRef<'a, K, I> { fn peek(cursor: Cursor<'_>) -> Result { peek::(cursor) } @@ -113,14 +119,15 @@ impl<'a, K: Peek> Peek for ItemRef<'a, K> { /// Convenience structure to parse `$f` or `(item $f)`. #[derive(Clone, Debug)] -pub struct IndexOrRef<'a, K>(pub ItemRef<'a, K>); +pub struct IndexOrRef<'a, K, I>(pub ItemRef<'a, K, I>); -impl<'a, K> Parse<'a> for IndexOrRef<'a, K> +impl<'a, K, I> Parse<'a> for IndexOrRef<'a, K, I> where K: Parse<'a> + Default, + (I, Span): Parse<'a>, { fn parse(parser: Parser<'a>) -> Result { - if parser.peek::>()? { + if parser.peek::>()? { Ok(IndexOrRef(ItemRef { kind: K::default(), idx: parser.parse()?, @@ -134,14 +141,15 @@ where /// Convenience structure to parse `$f` or `(item $f)`. #[derive(Clone, Debug)] -pub struct IndexOrCoreRef<'a, K>(pub CoreItemRef<'a, K>); +pub struct IndexOrCoreRef<'a, K, I>(pub CoreItemRef<'a, K, I>); -impl<'a, K> Parse<'a> for IndexOrCoreRef<'a, K> +impl<'a, K, I> Parse<'a> for IndexOrCoreRef<'a, K, I> where K: Parse<'a> + Default, + (I, Span): Parse<'a>, { fn parse(parser: Parser<'a>) -> Result { - if parser.peek::>()? { + if parser.peek::>()? { Ok(IndexOrCoreRef(CoreItemRef { kind: K::default(), idx: parser.parse()?, diff --git a/crates/wast/src/component/resolve.rs b/crates/wast/src/component/resolve.rs index 5a61068c80..d34507fa98 100644 --- a/crates/wast/src/component/resolve.rs +++ b/crates/wast/src/component/resolve.rs @@ -5,6 +5,10 @@ use crate::names::Namespace; use crate::token::Span; use crate::token::{Id, Index}; use crate::Error; +use wasm_types::{ + ComponentFuncIdx, ComponentIdx, ComponentInstanceIdx, ComponentTypeIdx, ComponentValueIdx, + CoreInstanceIdx, CoreModuleIdx, FuncIdx, GlobalIdx, MemIdx, TableIdx, TagIdx, TypeIdx, +}; /// Resolve the fields of a component and everything nested within it, changing /// `Index::Id` to `Index::Num` and expanding alias syntax sugar. @@ -60,20 +64,20 @@ struct ComponentState<'a> { // with it information about the signature of the item in that namespace. // The signature is later used to synthesize the type of a component and // inject type annotations if necessary. - core_funcs: Namespace<'a>, - core_globals: Namespace<'a>, - core_tables: Namespace<'a>, - core_memories: Namespace<'a>, - core_types: Namespace<'a>, - core_tags: Namespace<'a>, - core_instances: Namespace<'a>, - core_modules: Namespace<'a>, - - funcs: Namespace<'a>, - types: Namespace<'a>, - instances: Namespace<'a>, - components: Namespace<'a>, - values: Namespace<'a>, + core_funcs: Namespace<'a, FuncIdx>, + core_globals: Namespace<'a, GlobalIdx>, + core_tables: Namespace<'a, TableIdx>, + core_memories: Namespace<'a, MemIdx>, + core_types: Namespace<'a, TypeIdx>, + core_tags: Namespace<'a, TagIdx>, + core_instances: Namespace<'a, CoreInstanceIdx>, + core_modules: Namespace<'a, CoreModuleIdx>, + + funcs: Namespace<'a, ComponentFuncIdx>, + types: Namespace<'a, ComponentTypeIdx>, + instances: Namespace<'a, ComponentInstanceIdx>, + components: Namespace<'a, ComponentIdx>, + values: Namespace<'a, ComponentValueIdx>, } impl<'a> ComponentState<'a> { @@ -944,21 +948,35 @@ impl<'a> ComponentState<'a> { /// Assign an index to the given field. fn register(&mut self, item: &ComponentField<'a>) -> Result<(), Error> { match item { - ComponentField::CoreModule(m) => self.core_modules.register(m.id, "core module")?, + ComponentField::CoreModule(m) => { + self.core_modules.register(m.id, "core module")?; + } ComponentField::CoreInstance(i) => { - self.core_instances.register(i.id, "core instance")? + self.core_instances.register(i.id, "core instance")?; } ComponentField::CoreType(ty) => match &ty.def { - CoreTypeDef::Def(_) => 0, // done above in `core_rec` - CoreTypeDef::Module(_) => self.core_types.register(ty.id, "core type")?, + CoreTypeDef::Def(_) => {} // done above in `core_rec` + CoreTypeDef::Module(_) => { + self.core_types.register(ty.id, "core type")?; + } }, - ComponentField::CoreRec(_) => 0, // done above in `core_rec` - ComponentField::Component(c) => self.components.register(c.id, "component")?, - ComponentField::Instance(i) => self.instances.register(i.id, "instance")?, - ComponentField::Alias(a) => self.register_alias(a)?, - ComponentField::Type(t) => self.types.register(t.id, "type")?, + ComponentField::CoreRec(_) => {} // done above in `core_rec` + ComponentField::Component(c) => { + self.components.register(c.id, "component")?; + } + ComponentField::Instance(i) => { + self.instances.register(i.id, "instance")?; + } + ComponentField::Alias(a) => { + self.register_alias(a)?; + } + ComponentField::Type(t) => { + self.types.register(t.id, "type")?; + } ComponentField::CanonicalFunc(f) => match &f.kind { - CanonicalFuncKind::Lift { .. } => self.funcs.register(f.id, "func")?, + CanonicalFuncKind::Lift { .. } => { + self.funcs.register(f.id, "func")?; + } CanonicalFuncKind::Lower(_) | CanonicalFuncKind::ResourceNew(_) | CanonicalFuncKind::ResourceRep(_) @@ -988,7 +1006,7 @@ impl<'a> ComponentState<'a> { | CanonicalFuncKind::ErrorContextNew(_) | CanonicalFuncKind::ErrorContextDebugMessage(_) | CanonicalFuncKind::ErrorContextDrop => { - self.core_funcs.register(f.id, "core func")? + self.core_funcs.register(f.id, "core func")?; } }, ComponentField::CoreFunc(_) | ComponentField::Func(_) => { @@ -1000,19 +1018,31 @@ impl<'a> ComponentState<'a> { } return Ok(()); } - ComponentField::Import(i) => self.register_item_sig(&i.item)?, + ComponentField::Import(i) => { + self.register_item_sig(&i.item)?; + } ComponentField::Export(e) => match &e.kind { ComponentExportKind::CoreModule(_) => { - self.core_modules.register(e.id, "core module")? + self.core_modules.register(e.id, "core module")?; + } + ComponentExportKind::Func(_) => { + self.funcs.register(e.id, "func")?; + } + ComponentExportKind::Instance(_) => { + self.instances.register(e.id, "instance")?; + } + ComponentExportKind::Value(_) => { + self.values.register(e.id, "value")?; + } + ComponentExportKind::Component(_) => { + self.components.register(e.id, "component")?; + } + ComponentExportKind::Type(_) => { + self.types.register(e.id, "type")?; } - ComponentExportKind::Func(_) => self.funcs.register(e.id, "func")?, - ComponentExportKind::Instance(_) => self.instances.register(e.id, "instance")?, - ComponentExportKind::Value(_) => self.values.register(e.id, "value")?, - ComponentExportKind::Component(_) => self.components.register(e.id, "component")?, - ComponentExportKind::Type(_) => self.types.register(e.id, "type")?, }, ComponentField::Custom(_) | ComponentField::Producers(_) => return Ok(()), - }; + } Ok(()) } diff --git a/crates/wast/src/component/types.rs b/crates/wast/src/component/types.rs index 23951f2164..e27a1dd2a3 100644 --- a/crates/wast/src/component/types.rs +++ b/crates/wast/src/component/types.rs @@ -7,6 +7,7 @@ use crate::parser::{Parse, Parser, Result}; use crate::token::Index; use crate::token::LParen; use crate::token::{Id, NameAnnotation, Span}; +use wasm_types::ComponentTypeIdx; /// A core type declaration. #[derive(Debug)] @@ -1014,7 +1015,7 @@ impl Default for CoreTypeUse<'_, T> { #[derive(Debug, Clone)] pub enum ComponentTypeUse<'a, T> { /// The type that we're referencing. - Ref(ItemRef<'a, kw::r#type>), + Ref(ItemRef<'a, kw::r#type, ComponentTypeIdx>), /// The inline type. Inline(T), } diff --git a/crates/wast/src/core/binary.rs b/crates/wast/src/core/binary.rs index 726691bb7f..cabebd9258 100644 --- a/crates/wast/src/core/binary.rs +++ b/crates/wast/src/core/binary.rs @@ -4,10 +4,16 @@ use crate::core::*; use crate::encode::Encode; use crate::token::*; use crate::Wat; +use index_vec::Idx; use std::borrow::Cow; use std::marker; #[cfg(feature = "dwarf")] use std::path::Path; +use wasm_types::{ + AbsoluteLabelIdx, ComponentFuncIdx, ComponentIdx, ComponentInstanceIdx, ComponentTypeIdx, + ComponentValueIdx, CoreInstanceIdx, CoreModuleIdx, DataIdx, ElemIdx, FieldIdx, FuncIdx, + GlobalIdx, LabelIdx, LocalIdx, MemIdx, TableIdx, TagIdx, TypeIdx, +}; /// Options that can be specified when encoding a component or a module to /// customize what the final binary looks like. @@ -163,7 +169,7 @@ pub(crate) fn encode( e.custom_sections(Before(Start)); if let Some(start) = start.get(0) { e.wasm.section(&wasm_encoder::StartSection { - function_index: start.unwrap_u32(), + function_index: start.unwrap_idx(), }); } e.custom_sections(After(Start)); @@ -178,10 +184,12 @@ pub(crate) fn encode( // be emitted depending on configuration settings. Note that `code_section` // will internally emit the branch hints section if necessary. let names = find_names(module_id, module_name, fields); - let num_import_funcs = imports - .iter() - .filter(|i| matches!(i.item.kind, ItemKind::Func(..))) - .count() as u32; + let num_import_funcs = FuncIdx::from_usize( + imports + .iter() + .filter(|i| matches!(i.item.kind, ItemKind::Func(..))) + .count(), + ); let mut dwarf = dwarf::Dwarf::new(num_import_funcs, opts, &names, &types); e.code_section(&funcs, num_import_funcs, dwarf.as_mut()); @@ -254,7 +262,7 @@ impl Encoder<'_> { fn code_section<'a>( &'a mut self, list: &[&'a Func<'_>], - mut func_index: u32, + mut func_index: FuncIdx, mut dwarf: Option<&mut dwarf::Dwarf>, ) { self.custom_sections(CustomPlace::Before(CustomPlaceAnchor::Code)); @@ -268,7 +276,7 @@ impl Encoder<'_> { if !hints.is_empty() { branch_hints.function_hints(func_index, hints.into_iter()); } - func_index += 1; + func_index.0 += 1; } // Branch hints section has to be inserted before the Code section @@ -387,7 +395,7 @@ impl TypeDef<'_> { wasm_encoder::SubType { composite_type, is_final: self.final_type.unwrap_or(true), - supertype_idx: self.parent.map(|i| i.unwrap_u32()), + supertype_idx: self.parent.map(|i| i.unwrap_idx()), } } } @@ -437,7 +445,7 @@ impl From> for wasm_encoder::HeapType { }; Self::Abstract { shared, ty } } - HeapType::Concrete(i) => Self::Concrete(i.unwrap_u32()), + HeapType::Concrete(i) => Self::Concrete(i.unwrap_idx()), } } } @@ -490,7 +498,7 @@ impl ItemKind<'_> { fn to_entity_type(&self) -> wasm_encoder::EntityType { use wasm_encoder::EntityType as ET; match self { - ItemKind::Func(t) => ET::Function(t.unwrap_u32()), + ItemKind::Func(t) => ET::Function(t.unwrap_idx()), ItemKind::Table(t) => ET::Table(t.to_table_type()), ItemKind::Memory(t) => ET::Memory(t.to_memory_type()), ItemKind::Global(t) => ET::Global(t.to_global_type()), @@ -538,18 +546,18 @@ impl TagType<'_> { match self { TagType::Exception(r) => wasm_encoder::TagType { kind: wasm_encoder::TagKind::Exception, - func_type_idx: r.unwrap_u32(), + func_type_idx: r.unwrap_idx(), }, } } } impl TypeUse<'_, T> { - fn unwrap_u32(&self) -> u32 { + fn unwrap_idx(&self) -> TypeIdx { self.index .as_ref() .expect("TypeUse should be filled in by this point") - .unwrap_u32() + .unwrap_idx() } } @@ -560,18 +568,18 @@ impl SectionItem for FuncSectionTy<'_> { const ANCHOR: CustomPlaceAnchor = CustomPlaceAnchor::Func; fn encode(&self, section: &mut wasm_encoder::FunctionSection) { - section.function(self.0.unwrap_u32()); + section.function(self.0.unwrap_idx()); } } -impl Encode for Index<'_> { +impl Encode for Index<'_, I> { fn encode(&self, e: &mut Vec) { - self.unwrap_u32().encode(e) + self.unwrap_idx().encode(e) } } -impl Index<'_> { - fn unwrap_u32(&self) -> u32 { +impl Index<'_, I> { + fn unwrap_idx(&self) -> I { match self { Index::Num(n, _) => *n, Index::Id(n) => panic!("unresolved index in emission: {:?}", n), @@ -579,8 +587,8 @@ impl Index<'_> { } } -impl From> for u32 { - fn from(i: Index<'_>) -> Self { +impl From> for u32 { + fn from(i: Index<'_, u32>) -> Self { match i { Index::Num(i, _) => i, Index::Id(_) => unreachable!("unresolved index in encoding: {:?}", i), @@ -588,6 +596,57 @@ impl From> for u32 { } } +macro_rules! impl_from_index { + ($i:ident) => { + impl From> for $i { + fn from(i: Index<'_, $i>) -> Self { + match i { + Index::Num(i, _) => i, + Index::Id(_) => unreachable!("unresolved index in encoding: {:?}", i), + } + } + } + + impl<'a> From> for Index<'a, $i> { + fn from(i: Index<'a, u32>) -> Self { + match i { + Index::Num(i, span) => Index::Num($i(i), span), + Index::Id(id) => Index::Id(id), + } + } + } + + impl<'a> From> for Index<'a, u32> { + fn from(i: Index<'a, $i>) -> Self { + match i { + Index::Num(i, span) => Index::Num(i.0, span), + Index::Id(id) => Index::Id(id), + } + } + } + }; +} + +impl_from_index!(TypeIdx); +impl_from_index!(FuncIdx); +impl_from_index!(TableIdx); +impl_from_index!(MemIdx); +impl_from_index!(TagIdx); +impl_from_index!(GlobalIdx); +impl_from_index!(ElemIdx); +impl_from_index!(DataIdx); +impl_from_index!(LocalIdx); +impl_from_index!(LabelIdx); +impl_from_index!(FieldIdx); +impl_from_index!(AbsoluteLabelIdx); +impl_from_index!(CoreModuleIdx); +impl_from_index!(CoreInstanceIdx); +impl_from_index!(ComponentTypeIdx); +impl_from_index!(ComponentFuncIdx); +impl_from_index!(ComponentIdx); +impl_from_index!(ComponentInstanceIdx); +impl_from_index!(ComponentValueIdx); + impl SectionItem for Table<'_> { type Section = wasm_encoder::TableSection; const ANCHOR: CustomPlaceAnchor = CustomPlaceAnchor::Table; @@ -646,7 +705,7 @@ impl SectionItem for Export<'_> { const ANCHOR: CustomPlaceAnchor = CustomPlaceAnchor::Export; fn encode(&self, section: &mut wasm_encoder::ExportSection) { - section.export(self.name, self.kind.into(), self.item.unwrap_u32()); + section.export(self.name, self.kind.into(), self.item.unwrap_idx()); } } @@ -671,7 +730,7 @@ impl SectionItem for Elem<'_> { let elements = match &self.payload { ElemPayload::Indices(v) => { - Elements::Functions(Cow::Owned(v.iter().map(|i| i.unwrap_u32()).collect())) + Elements::Functions(Cow::Owned(v.iter().map(|i| i.unwrap_idx()).collect())) } ElemPayload::Exprs { exprs, ty } => Elements::Expressions( (*ty).into(), @@ -681,7 +740,7 @@ impl SectionItem for Elem<'_> { match &self.kind { ElemKind::Active { table, offset } => { section.active( - table.map(|t| t.unwrap_u32()), + table.map(|t| t.unwrap_idx()), &offset.to_const_expr(), elements, ); @@ -710,7 +769,7 @@ impl SectionItem for Data<'_> { section.passive(data); } DataKind::Active { memory, offset } => { - section.active(memory.unwrap_u32(), &offset.to_const_expr(), data); + section.active(memory.unwrap_idx(), &offset.to_const_expr(), data); } } } @@ -813,7 +872,7 @@ impl Encode for BlockType<'_> { fn encode(&self, e: &mut Vec) { // block types using an index are encoded as an sleb, not a uleb if let Some(Index::Num(n, _)) = &self.ty.index { - return i64::from(*n).encode(e); + return i64::from(n.0).encode(e); } let ty = self .ty @@ -839,7 +898,7 @@ impl Encode for LaneArg { impl Encode for MemArg<'_> { fn encode(&self, e: &mut Vec) { match &self.memory { - Index::Num(0, _) => { + Index::Num(MemIdx(0), _) => { self.align.trailing_zeros().encode(e); self.offset.encode(e); } @@ -881,7 +940,7 @@ impl Encode for LoadOrStoreLane<'_> { impl Encode for CallIndirect<'_> { fn encode(&self, e: &mut Vec) { - self.ty.unwrap_u32().encode(e); + self.ty.unwrap_idx().encode(e); self.table.encode(e); } } @@ -948,25 +1007,25 @@ impl Encode for F64 { #[derive(Default)] struct Names<'a> { module: Option<&'a str>, - funcs: Vec<(u32, &'a str)>, - func_idx: u32, - locals: Vec<(u32, Vec<(u32, &'a str)>)>, - labels: Vec<(u32, Vec<(u32, &'a str)>)>, - globals: Vec<(u32, &'a str)>, - global_idx: u32, - memories: Vec<(u32, &'a str)>, - memory_idx: u32, - tables: Vec<(u32, &'a str)>, - table_idx: u32, - tags: Vec<(u32, &'a str)>, - tag_idx: u32, - types: Vec<(u32, &'a str)>, - type_idx: u32, - data: Vec<(u32, &'a str)>, - data_idx: u32, - elems: Vec<(u32, &'a str)>, - elem_idx: u32, - fields: Vec<(u32, Vec<(u32, &'a str)>)>, + funcs: Vec<(FuncIdx, &'a str)>, + func_idx: FuncIdx, + locals: Vec<(FuncIdx, Vec<(LocalIdx, &'a str)>)>, + labels: Vec<(FuncIdx, Vec<(LabelIdx, &'a str)>)>, + globals: Vec<(GlobalIdx, &'a str)>, + global_idx: GlobalIdx, + memories: Vec<(MemIdx, &'a str)>, + memory_idx: MemIdx, + tables: Vec<(TableIdx, &'a str)>, + table_idx: TableIdx, + tags: Vec<(TagIdx, &'a str)>, + tag_idx: TagIdx, + types: Vec<(TypeIdx, &'a str)>, + type_idx: TypeIdx, + data: Vec<(DataIdx, &'a str)>, + data_idx: DataIdx, + elems: Vec<(ElemIdx, &'a str)>, + elem_idx: ElemIdx, + fields: Vec<(TypeIdx, Vec<(FieldIdx, &'a str)>)>, } fn find_names<'a>( @@ -1032,27 +1091,36 @@ fn find_names<'a>( } for (kind, id, name, field) in names { + fn push<'a, 'b, I: Copy + AsMut>( + name: Option<&'b str>, + list: &mut Vec<(I, &'b str)>, + idx: &'a mut I, + ) -> &'a mut u32 { + if let Some(name) = name { + list.push((*idx, name)); + } + idx.as_mut() + } + + let name = get_name(id, name); // .. and using the kind we can figure out where to place this name - let (list, idx) = match kind { - Name::Func => (&mut ret.funcs, &mut ret.func_idx), - Name::Table => (&mut ret.tables, &mut ret.table_idx), - Name::Memory => (&mut ret.memories, &mut ret.memory_idx), - Name::Global => (&mut ret.globals, &mut ret.global_idx), - Name::Tag => (&mut ret.tags, &mut ret.tag_idx), - Name::Type => (&mut ret.types, &mut ret.type_idx), - Name::Elem => (&mut ret.elems, &mut ret.elem_idx), - Name::Data => (&mut ret.data, &mut ret.data_idx), + let idx = match kind { + Name::Func => push(name, &mut ret.funcs, &mut ret.func_idx), + Name::Table => push(name, &mut ret.tables, &mut ret.table_idx), + Name::Memory => push(name, &mut ret.memories, &mut ret.memory_idx), + Name::Global => push(name, &mut ret.globals, &mut ret.global_idx), + Name::Tag => push(name, &mut ret.tags, &mut ret.tag_idx), + Name::Type => push(name, &mut ret.types, &mut ret.type_idx), + Name::Elem => push(name, &mut ret.elems, &mut ret.elem_idx), + Name::Data => push(name, &mut ret.data, &mut ret.data_idx), }; - if let Some(name) = get_name(id, name) { - list.push((*idx, name)); - } // Handle module locals separately from above if let ModuleField::Func(f) = field { let mut local_names = Vec::new(); let mut label_names = Vec::new(); - let mut local_idx = 0; - let mut label_idx = 0; + let mut local_idx = LocalIdx(0); + let mut label_idx = LabelIdx(0); // Consult the inline type listed for local names of parameters. // This is specifically preserved during the name resolution @@ -1063,7 +1131,7 @@ fn find_names<'a>( if let Some(name) = get_name(id, name) { local_names.push((local_idx, name)); } - local_idx += 1; + local_idx.0 += 1; } } if let FuncKind::Inline { @@ -1074,7 +1142,7 @@ fn find_names<'a>( if let Some(name) = get_name(&local.id, &local.name) { local_names.push((local_idx, name)); } - local_idx += 1; + local_idx.0 += 1; } for i in expression.instrs.iter() { @@ -1087,17 +1155,17 @@ fn find_names<'a>( if let Some(name) = get_name(&block.label, &block.label_name) { label_names.push((label_idx, name)); } - label_idx += 1; + label_idx.0 += 1; } _ => {} } } } if local_names.len() > 0 { - ret.locals.push((*idx, local_names)); + ret.locals.push((FuncIdx(*idx), local_names)); } if label_names.len() > 0 { - ret.labels.push((*idx, label_names)); + ret.labels.push((FuncIdx(*idx), label_names)); } } @@ -1109,13 +1177,13 @@ fn find_names<'a>( InnerTypeKind::Struct(ty_struct) => { for (idx, field) in ty_struct.fields.iter().enumerate() { if let Some(name) = get_name(&field.id, &None) { - field_names.push((idx as u32, name)) + field_names.push((FieldIdx::from_usize(idx), name)) } } } } if field_names.len() > 0 { - ret.fields.push((*idx, field_names)) + ret.fields.push((TypeIdx(*idx), field_names)) } } @@ -1149,7 +1217,10 @@ impl Names<'_> { if let Some(id) = self.module { names.module(id); } - let name_map = |indices: &[(u32, &str)]| { + + fn name_map( + indices: &[(I, &str)], + ) -> Option> { if indices.is_empty() { return None; } @@ -1158,8 +1229,14 @@ impl Names<'_> { map.append(*idx, *name); } Some(map) - }; - let indirect_name_map = |indices: &[(u32, Vec<(u32, &str)>)]| { + } + + fn indirect_name_map< + I: Default + Idx + wasm_encoder::Encode, + J: Default + Idx + wasm_encoder::Encode, + >( + indices: &[(I, Vec<(J, &str)>)], + ) -> Option> { if indices.is_empty() { return None; } @@ -1170,7 +1247,8 @@ impl Names<'_> { } } Some(map) - }; + } + if let Some(map) = name_map(&self.funcs) { names.functions(&map); } @@ -1429,7 +1507,7 @@ impl Encode for ArrayCopy<'_> { } } -impl Encode for ArrayInit<'_> { +impl Encode for ArrayInit<'_, I> { fn encode(&self, e: &mut Vec) { self.array.encode(e); self.segment.encode(e); diff --git a/crates/wast/src/core/binary/dwarf.rs b/crates/wast/src/core/binary/dwarf.rs index b080f255c3..8270e5adcf 100644 --- a/crates/wast/src/core/binary/dwarf.rs +++ b/crates/wast/src/core/binary/dwarf.rs @@ -18,14 +18,16 @@ use gimli::write::{ Sections, UnitEntryId, Writer, }; use gimli::{Encoding, Format, LineEncoding, LittleEndian}; +use index_vec::Idx; use std::cmp::Ordering; use std::collections::HashMap; use std::path::Path; +use wasm_types::{FuncIdx, TypeIdx}; pub struct Dwarf<'a> { // Metadata configured at `Dwarf` creation time - func_names: HashMap, - func_imports: u32, + func_names: HashMap, + func_imports: FuncIdx, contents: &'a str, file_id: FileId, style: GenerateDwarf, @@ -34,7 +36,7 @@ pub struct Dwarf<'a> { dwarf: DwarfUnit, // Next function index when `start_func` is called - next_func: u32, + next_func: FuncIdx, // Current `DW_TAG_subprogram` that's being built as part of `start_func`. cur_subprogram: Option, @@ -66,7 +68,7 @@ impl<'a> Dwarf<'a> { /// * `names` - the `name` custom section for this module, used to name /// functions in DWARF. pub fn new( - func_imports: u32, + func_imports: FuncIdx, opts: &EncodeOptions<'a>, names: &Names<'a>, types: &'a [RecOrType<'a>], @@ -168,10 +170,10 @@ impl<'a> Dwarf<'a> { /// /// This will start a new line program for this function and additionally /// configure a new `DW_TAG_subprogram` for this new function. - pub fn start_func(&mut self, span: Span, ty: u32, locals: &[Local<'_>]) { + pub fn start_func(&mut self, span: Span, ty: TypeIdx, locals: &[Local<'_>]) { self.change_linecol(span); let addr = Address::Symbol { - symbol: (self.next_func - self.func_imports) as usize, + symbol: (self.next_func.0 - self.func_imports.0) as usize, addend: 0, }; self.dwarf.unit.line_program.begin_sequence(Some(addr)); @@ -201,7 +203,7 @@ impl<'a> Dwarf<'a> { self.cur_subprogram = Some(subprogram); self.cur_subprogram_instrs = 0; - self.next_func += 1; + self.next_func.0 += 1; } /// Adds `DW_TAG_formal_parameter` and `DW_TAG_variable` for all locals @@ -213,7 +215,7 @@ impl<'a> Dwarf<'a> { fn add_func_params_and_locals( &mut self, subprogram: UnitEntryId, - ty: u32, + ty: TypeIdx, locals: &[Local<'_>], ) { // Iterate through `self.types` which is what was encoded into the @@ -226,7 +228,7 @@ impl<'a> Dwarf<'a> { RecOrType::Type(t) => std::slice::from_ref(*t), RecOrType::Rec(r) => &r.types, }) - .nth(ty as usize); + .nth(ty.index()); let ty = match ty.map(|t| &t.def.kind) { Some(InnerTypeKind::Func(ty)) => ty, _ => return, diff --git a/crates/wast/src/core/binary/dwarf_disabled.rs b/crates/wast/src/core/binary/dwarf_disabled.rs index 214b9fb5ae..c2e0faf990 100644 --- a/crates/wast/src/core/binary/dwarf_disabled.rs +++ b/crates/wast/src/core/binary/dwarf_disabled.rs @@ -4,6 +4,7 @@ use crate::core::binary::{EncodeOptions, Encoder, Names, RecOrType}; use crate::core::Local; use crate::token::Span; +use wasm_types::{FuncIdx, TypeIdx}; pub struct Dwarf<'a> { uninhabited: &'a std::convert::Infallible, @@ -11,7 +12,7 @@ pub struct Dwarf<'a> { impl<'a> Dwarf<'a> { pub fn new( - _func_imports: u32, + _func_imports: FuncIdx, _opts: &EncodeOptions<'a>, _names: &Names<'a>, _types: &'a [RecOrType<'a>], @@ -19,7 +20,7 @@ impl<'a> Dwarf<'a> { None } - pub fn start_func(&mut self, _span: Span, _ty: u32, _locals: &[Local<'_>]) { + pub fn start_func(&mut self, _span: Span, _ty: TypeIdx, _locals: &[Local<'_>]) { match *self.uninhabited {} } diff --git a/crates/wast/src/core/export.rs b/crates/wast/src/core/export.rs index 19765d36df..d98877e2f7 100644 --- a/crates/wast/src/core/export.rs +++ b/crates/wast/src/core/export.rs @@ -12,7 +12,7 @@ pub struct Export<'a> { /// The kind of item being exported. pub kind: ExportKind, /// What's being exported from the module. - pub item: Index<'a>, + pub item: Index<'a, u32>, } /// Different kinds of elements that can be exported from a WebAssembly module, diff --git a/crates/wast/src/core/expr.rs b/crates/wast/src/core/expr.rs index 9fb25ffe52..82ad08d8d8 100644 --- a/crates/wast/src/core/expr.rs +++ b/crates/wast/src/core/expr.rs @@ -5,6 +5,10 @@ use crate::kw; use crate::parser::{Cursor, Parse, Parser, Result}; use crate::token::*; use std::mem; +use wasm_types::{ + DataIdx, ElemIdx, FieldIdx, FuncIdx, GlobalIdx, LabelIdx, LocalIdx, MemIdx, TableIdx, TagIdx, + TypeIdx, +}; /// An expression, or a list of instructions, in the WebAssembly text format. /// @@ -511,28 +515,28 @@ instructions! { Unreachable : [0x00] : "unreachable", Nop : [0x01] : "nop", - Br(Index<'a>) : [0x0c] : "br", - BrIf(Index<'a>) : [0x0d] : "br_if", + Br(Index<'a, LabelIdx>) : [0x0c] : "br", + BrIf(Index<'a, LabelIdx>) : [0x0d] : "br_if", BrTable(BrTableIndices<'a>) : [0x0e] : "br_table", Return : [0x0f] : "return", - Call(Index<'a>) : [0x10] : "call", + Call(Index<'a, FuncIdx>) : [0x10] : "call", CallIndirect(Box>) : [0x11] : "call_indirect", // tail-call proposal - ReturnCall(Index<'a>) : [0x12] : "return_call", + ReturnCall(Index<'a, FuncIdx>) : [0x12] : "return_call", ReturnCallIndirect(Box>) : [0x13] : "return_call_indirect", // function-references proposal - CallRef(Index<'a>) : [0x14] : "call_ref", - ReturnCallRef(Index<'a>) : [0x15] : "return_call_ref", + CallRef(Index<'a, TypeIdx>) : [0x14] : "call_ref", + ReturnCallRef(Index<'a, TypeIdx>) : [0x15] : "return_call_ref", Drop : [0x1a] : "drop", Select(SelectTypes<'a>) : [] : "select", - LocalGet(Index<'a>) : [0x20] : "local.get", - LocalSet(Index<'a>) : [0x21] : "local.set", - LocalTee(Index<'a>) : [0x22] : "local.tee", - GlobalGet(Index<'a>) : [0x23] : "global.get", - GlobalSet(Index<'a>) : [0x24] : "global.set", + LocalGet(Index<'a, LocalIdx>) : [0x20] : "local.get", + LocalSet(Index<'a, LocalIdx>) : [0x21] : "local.set", + LocalTee(Index<'a, LocalIdx>) : [0x22] : "local.tee", + GlobalGet(Index<'a, GlobalIdx>) : [0x23] : "global.get", + GlobalSet(Index<'a, GlobalIdx>) : [0x24] : "global.set", TableGet(TableArg<'a>) : [0x25] : "table.get", TableSet(TableArg<'a>) : [0x26] : "table.set", @@ -568,8 +572,8 @@ instructions! { MemoryCopy(MemoryCopy<'a>) : [0xfc, 0x0a] : "memory.copy", MemoryFill(MemoryArg<'a>) : [0xfc, 0x0b] : "memory.fill", MemoryDiscard(MemoryArg<'a>) : [0xfc, 0x12] : "memory.discard", - DataDrop(Index<'a>) : [0xfc, 0x09] : "data.drop", - ElemDrop(Index<'a>) : [0xfc, 0x0d] : "elem.drop", + DataDrop(Index<'a, DataIdx>) : [0xfc, 0x09] : "data.drop", + ElemDrop(Index<'a, ElemIdx>) : [0xfc, 0x0d] : "elem.drop", TableInit(TableInit<'a>) : [0xfc, 0x0c] : "table.init", TableCopy(TableCopy<'a>) : [0xfc, 0x0e] : "table.copy", TableFill(TableArg<'a>) : [0xfc, 0x11] : "table.fill", @@ -578,39 +582,39 @@ instructions! { RefNull(HeapType<'a>) : [0xd0] : "ref.null", RefIsNull : [0xd1] : "ref.is_null", - RefFunc(Index<'a>) : [0xd2] : "ref.func", + RefFunc(Index<'a, FuncIdx>) : [0xd2] : "ref.func", // function-references proposal RefAsNonNull : [0xd4] : "ref.as_non_null", - BrOnNull(Index<'a>) : [0xd5] : "br_on_null", - BrOnNonNull(Index<'a>) : [0xd6] : "br_on_non_null", + BrOnNull(Index<'a, LabelIdx>) : [0xd5] : "br_on_null", + BrOnNonNull(Index<'a, LabelIdx>) : [0xd6] : "br_on_non_null", // gc proposal: eqref RefEq : [0xd3] : "ref.eq", // gc proposal: struct - StructNew(Index<'a>) : [0xfb, 0x00] : "struct.new", - StructNewDefault(Index<'a>) : [0xfb, 0x01] : "struct.new_default", + StructNew(Index<'a, TypeIdx>) : [0xfb, 0x00] : "struct.new", + StructNewDefault(Index<'a, TypeIdx>) : [0xfb, 0x01] : "struct.new_default", StructGet(StructAccess<'a>) : [0xfb, 0x02] : "struct.get", StructGetS(StructAccess<'a>) : [0xfb, 0x03] : "struct.get_s", StructGetU(StructAccess<'a>) : [0xfb, 0x04] : "struct.get_u", StructSet(StructAccess<'a>) : [0xfb, 0x05] : "struct.set", // gc proposal: array - ArrayNew(Index<'a>) : [0xfb, 0x06] : "array.new", - ArrayNewDefault(Index<'a>) : [0xfb, 0x07] : "array.new_default", + ArrayNew(Index<'a, TypeIdx>) : [0xfb, 0x06] : "array.new", + ArrayNewDefault(Index<'a, TypeIdx>) : [0xfb, 0x07] : "array.new_default", ArrayNewFixed(ArrayNewFixed<'a>) : [0xfb, 0x08] : "array.new_fixed", ArrayNewData(ArrayNewData<'a>) : [0xfb, 0x09] : "array.new_data", ArrayNewElem(ArrayNewElem<'a>) : [0xfb, 0x0a] : "array.new_elem", - ArrayGet(Index<'a>) : [0xfb, 0x0b] : "array.get", - ArrayGetS(Index<'a>) : [0xfb, 0x0c] : "array.get_s", - ArrayGetU(Index<'a>) : [0xfb, 0x0d] : "array.get_u", - ArraySet(Index<'a>) : [0xfb, 0x0e] : "array.set", + ArrayGet(Index<'a, TypeIdx>) : [0xfb, 0x0b] : "array.get", + ArrayGetS(Index<'a, TypeIdx>) : [0xfb, 0x0c] : "array.get_s", + ArrayGetU(Index<'a, TypeIdx>) : [0xfb, 0x0d] : "array.get_u", + ArraySet(Index<'a, TypeIdx>) : [0xfb, 0x0e] : "array.set", ArrayLen : [0xfb, 0x0f] : "array.len", ArrayFill(ArrayFill<'a>) : [0xfb, 0x10] : "array.fill", ArrayCopy(ArrayCopy<'a>) : [0xfb, 0x11] : "array.copy", - ArrayInitData(ArrayInit<'a>) : [0xfb, 0x12] : "array.init_data", - ArrayInitElem(ArrayInit<'a>) : [0xfb, 0x13] : "array.init_elem", + ArrayInitData(ArrayInit<'a, DataIdx>) : [0xfb, 0x12] : "array.init_data", + ArrayInitElem(ArrayInit<'a, ElemIdx>) : [0xfb, 0x13] : "array.init_elem", // gc proposal, i31 RefI31 : [0xfb, 0x1c] : "ref.i31", @@ -859,15 +863,15 @@ instructions! { I64AtomicRmw32CmpxchgU(MemArg<4>) : [0xfe, 0x4e] : "i64.atomic.rmw32.cmpxchg_u", // proposal: shared-everything-threads - GlobalAtomicGet(Ordered>) : [0xfe, 0x4f] : "global.atomic.get", - GlobalAtomicSet(Ordered>) : [0xfe, 0x50] : "global.atomic.set", - GlobalAtomicRmwAdd(Ordered>) : [0xfe, 0x51] : "global.atomic.rmw.add", - GlobalAtomicRmwSub(Ordered>) : [0xfe, 0x52] : "global.atomic.rmw.sub", - GlobalAtomicRmwAnd(Ordered>) : [0xfe, 0x53] : "global.atomic.rmw.and", - GlobalAtomicRmwOr(Ordered>) : [0xfe, 0x54] : "global.atomic.rmw.or", - GlobalAtomicRmwXor(Ordered>) : [0xfe, 0x55] : "global.atomic.rmw.xor", - GlobalAtomicRmwXchg(Ordered>) : [0xfe, 0x56] : "global.atomic.rmw.xchg", - GlobalAtomicRmwCmpxchg(Ordered>) : [0xfe, 0x57] : "global.atomic.rmw.cmpxchg", + GlobalAtomicGet(Ordered>) : [0xfe, 0x4f] : "global.atomic.get", + GlobalAtomicSet(Ordered>) : [0xfe, 0x50] : "global.atomic.set", + GlobalAtomicRmwAdd(Ordered>) : [0xfe, 0x51] : "global.atomic.rmw.add", + GlobalAtomicRmwSub(Ordered>) : [0xfe, 0x52] : "global.atomic.rmw.sub", + GlobalAtomicRmwAnd(Ordered>) : [0xfe, 0x53] : "global.atomic.rmw.and", + GlobalAtomicRmwOr(Ordered>) : [0xfe, 0x54] : "global.atomic.rmw.or", + GlobalAtomicRmwXor(Ordered>) : [0xfe, 0x55] : "global.atomic.rmw.xor", + GlobalAtomicRmwXchg(Ordered>) : [0xfe, 0x56] : "global.atomic.rmw.xchg", + GlobalAtomicRmwCmpxchg(Ordered>) : [0xfe, 0x57] : "global.atomic.rmw.cmpxchg", TableAtomicGet(Ordered>) : [0xfe, 0x58] : "table.atomic.get", TableAtomicSet(Ordered>) : [0xfe, 0x59] : "table.atomic.set", TableAtomicRmwXchg(Ordered>) : [0xfe, 0x5a] : "table.atomic.rmw.xchg", @@ -883,17 +887,17 @@ instructions! { StructAtomicRmwXor(Ordered>) : [0xfe, 0x64] : "struct.atomic.rmw.xor", StructAtomicRmwXchg(Ordered>) : [0xfe, 0x65] : "struct.atomic.rmw.xchg", StructAtomicRmwCmpxchg(Ordered>) : [0xfe, 0x66] : "struct.atomic.rmw.cmpxchg", - ArrayAtomicGet(Ordered>) : [0xfe, 0x67] : "array.atomic.get", - ArrayAtomicGetS(Ordered>) : [0xfe, 0x68] : "array.atomic.get_s", - ArrayAtomicGetU(Ordered>) : [0xfe, 0x69] : "array.atomic.get_u", - ArrayAtomicSet(Ordered>) : [0xfe, 0x6a] : "array.atomic.set", - ArrayAtomicRmwAdd(Ordered>) : [0xfe, 0x6b] : "array.atomic.rmw.add", - ArrayAtomicRmwSub(Ordered>) : [0xfe, 0x6c] : "array.atomic.rmw.sub", - ArrayAtomicRmwAnd(Ordered>) : [0xfe, 0x6d] : "array.atomic.rmw.and", - ArrayAtomicRmwOr(Ordered>) : [0xfe, 0x6e] : "array.atomic.rmw.or", - ArrayAtomicRmwXor(Ordered>) : [0xfe, 0x6f] : "array.atomic.rmw.xor", - ArrayAtomicRmwXchg(Ordered>) : [0xfe, 0x70] : "array.atomic.rmw.xchg", - ArrayAtomicRmwCmpxchg(Ordered>) : [0xfe, 0x71] : "array.atomic.rmw.cmpxchg", + ArrayAtomicGet(Ordered>) : [0xfe, 0x67] : "array.atomic.get", + ArrayAtomicGetS(Ordered>) : [0xfe, 0x68] : "array.atomic.get_s", + ArrayAtomicGetU(Ordered>) : [0xfe, 0x69] : "array.atomic.get_u", + ArrayAtomicSet(Ordered>) : [0xfe, 0x6a] : "array.atomic.set", + ArrayAtomicRmwAdd(Ordered>) : [0xfe, 0x6b] : "array.atomic.rmw.add", + ArrayAtomicRmwSub(Ordered>) : [0xfe, 0x6c] : "array.atomic.rmw.sub", + ArrayAtomicRmwAnd(Ordered>) : [0xfe, 0x6d] : "array.atomic.rmw.and", + ArrayAtomicRmwOr(Ordered>) : [0xfe, 0x6e] : "array.atomic.rmw.or", + ArrayAtomicRmwXor(Ordered>) : [0xfe, 0x6f] : "array.atomic.rmw.xor", + ArrayAtomicRmwXchg(Ordered>) : [0xfe, 0x70] : "array.atomic.rmw.xchg", + ArrayAtomicRmwCmpxchg(Ordered>) : [0xfe, 0x71] : "array.atomic.rmw.cmpxchg", RefI31Shared : [0xfe, 0x72] : "ref.i31_shared", // proposal: simd @@ -1157,13 +1161,13 @@ instructions! { // Exception handling proposal ThrowRef : [0x0a] : "throw_ref", TryTable(TryTable<'a>) : [0x1f] : "try_table", - Throw(Index<'a>) : [0x08] : "throw", + Throw(Index<'a, TagIdx>) : [0x08] : "throw", // Deprecated exception handling opcodes Try(Box>) : [0x06] : "try", - Catch(Index<'a>) : [0x07] : "catch", - Rethrow(Index<'a>) : [0x09] : "rethrow", - Delegate(Index<'a>) : [0x18] : "delegate", + Catch(Index<'a, TagIdx>) : [0x07] : "catch", + Rethrow(Index<'a, LabelIdx>) : [0x09] : "rethrow", + Delegate(Index<'a, LabelIdx>) : [0x18] : "delegate", CatchAll : [0x19] : "catch_all", // Relaxed SIMD proposal @@ -1189,9 +1193,9 @@ instructions! { I32x4RelaxedDotI8x16I7x16AddS: [0xfd, 0x113]: "i32x4.relaxed_dot_i8x16_i7x16_add_s", // Stack switching proposal - ContNew(Index<'a>) : [0xe0] : "cont.new", + ContNew(Index<'a, TypeIdx>) : [0xe0] : "cont.new", ContBind(ContBind<'a>) : [0xe1] : "cont.bind", - Suspend(Index<'a>) : [0xe2] : "suspend", + Suspend(Index<'a, TagIdx>) : [0xe2] : "suspend", Resume(Resume<'a>) : [0xe3] : "resume", ResumeThrow(ResumeThrow<'a>) : [0xe4] : "resume_throw", Switch(Switch<'a>) : [0xe5] : "switch", @@ -1255,8 +1259,8 @@ impl<'a> Parse<'a> for BlockType<'a> { #[derive(Debug, Clone)] #[allow(missing_docs)] pub struct ContBind<'a> { - pub argument_index: Index<'a>, - pub result_index: Index<'a>, + pub argument_index: Index<'a, TypeIdx>, + pub result_index: Index<'a, TypeIdx>, } impl<'a> Parse<'a> for ContBind<'a> { @@ -1272,7 +1276,7 @@ impl<'a> Parse<'a> for ContBind<'a> { #[derive(Debug, Clone)] #[allow(missing_docs)] pub struct Resume<'a> { - pub type_index: Index<'a>, + pub type_index: Index<'a, TypeIdx>, pub table: ResumeTable<'a>, } @@ -1289,8 +1293,8 @@ impl<'a> Parse<'a> for Resume<'a> { #[derive(Debug, Clone)] #[allow(missing_docs)] pub struct ResumeThrow<'a> { - pub type_index: Index<'a>, - pub tag_index: Index<'a>, + pub type_index: Index<'a, TypeIdx>, + pub tag_index: Index<'a, TagIdx>, pub table: ResumeTable<'a>, } @@ -1308,8 +1312,8 @@ impl<'a> Parse<'a> for ResumeThrow<'a> { #[derive(Debug, Clone)] #[allow(missing_docs)] pub struct Switch<'a> { - pub type_index: Index<'a>, - pub tag_index: Index<'a>, + pub type_index: Index<'a, TypeIdx>, + pub tag_index: Index<'a, TagIdx>, } impl<'a> Parse<'a> for Switch<'a> { @@ -1332,8 +1336,13 @@ pub struct ResumeTable<'a> { #[derive(Debug, Clone)] #[allow(missing_docs)] pub enum Handle<'a> { - OnLabel { tag: Index<'a>, label: Index<'a> }, - OnSwitch { tag: Index<'a> }, + OnLabel { + tag: Index<'a, TagIdx>, + label: Index<'a, LabelIdx>, + }, + OnSwitch { + tag: Index<'a, TagIdx>, + }, } impl<'a> Parse<'a> for ResumeTable<'a> { @@ -1342,7 +1351,7 @@ impl<'a> Parse<'a> for ResumeTable<'a> { while parser.peek::()? && parser.peek2::()? { handlers.push(parser.parens(|p| { p.parse::()?; - let tag: Index<'a> = p.parse()?; + let tag: Index<'a, TagIdx> = p.parse()?; if p.peek::()? { p.parse::()?; Ok(Handle::OnSwitch { tag }) @@ -1406,9 +1415,9 @@ impl<'a> Parse<'a> for TryTable<'a> { #[allow(missing_docs)] pub enum TryTableCatchKind<'a> { // Catch a tagged exception, do not capture an exnref. - Catch(Index<'a>), + Catch(Index<'a, TagIdx>), // Catch a tagged exception, and capture the exnref. - CatchRef(Index<'a>), + CatchRef(Index<'a, TagIdx>), // Catch any exception, do not capture an exnref. CatchAll, // Catch any exception, and capture the exnref. @@ -1417,7 +1426,7 @@ pub enum TryTableCatchKind<'a> { impl<'a> TryTableCatchKind<'a> { #[allow(missing_docs)] - pub fn tag_index_mut(&mut self) -> Option<&mut Index<'a>> { + pub fn tag_index_mut(&mut self) -> Option<&mut Index<'a, TagIdx>> { match self { TryTableCatchKind::Catch(tag) | TryTableCatchKind::CatchRef(tag) => Some(tag), TryTableCatchKind::CatchAll | TryTableCatchKind::CatchAllRef => None, @@ -1429,21 +1438,21 @@ impl<'a> TryTableCatchKind<'a> { #[allow(missing_docs)] pub struct TryTableCatch<'a> { pub kind: TryTableCatchKind<'a>, - pub label: Index<'a>, + pub label: Index<'a, LabelIdx>, } /// Extra information associated with the `br_table` instruction. #[allow(missing_docs)] #[derive(Debug, Clone)] pub struct BrTableIndices<'a> { - pub labels: Vec>, - pub default: Index<'a>, + pub labels: Vec>, + pub default: Index<'a, LabelIdx>, } impl<'a> Parse<'a> for BrTableIndices<'a> { fn parse(parser: Parser<'a>) -> Result { let mut labels = vec![parser.parse()?]; - while parser.peek::()? { + while parser.peek::>()? { labels.push(parser.parse()?); } let default = labels.pop().unwrap(); @@ -1490,7 +1499,7 @@ pub struct MemArg<'a> { /// The offset, in bytes of this access. pub offset: u64, /// The memory index we're accessing - pub memory: Index<'a>, + pub memory: Index<'a, MemIdx>, } impl<'a> MemArg<'a> { @@ -1537,7 +1546,7 @@ impl<'a> MemArg<'a> { let memory = parser .parse::>()? - .unwrap_or_else(|| Index::Num(0, parser.prev_span())); + .unwrap_or_else(|| Index::Num(MemIdx(0), parser.prev_span())); let offset = parse_u64("offset", parser)?.unwrap_or(0); let align = match parse_u32("align", parser)? { Some(n) if !n.is_power_of_two() => { @@ -1600,7 +1609,7 @@ impl<'a> LoadOrStoreLane<'a> { MemArg { align: default_align, offset: 0, - memory: Index::Num(0, parser.prev_span()), + memory: Index::Num(MemIdx(0), parser.prev_span()), } }, lane: LaneArg::parse(parser)?, @@ -1612,7 +1621,7 @@ impl<'a> LoadOrStoreLane<'a> { #[derive(Debug, Clone)] pub struct CallIndirect<'a> { /// The table that this call is going to be indexing. - pub table: Index<'a>, + pub table: Index<'a, TableIdx>, /// Type type signature that this `call_indirect` instruction is using. pub ty: TypeUse<'a, FunctionType<'a>>, } @@ -1623,7 +1632,7 @@ impl<'a> Parse<'a> for CallIndirect<'a> { let table: Option<_> = parser.parse()?; let ty = parser.parse::>>()?; Ok(CallIndirect { - table: table.unwrap_or(Index::Num(0, prev_span)), + table: table.unwrap_or(Index::Num(TableIdx(0), prev_span)), ty: ty.into(), }) } @@ -1633,19 +1642,19 @@ impl<'a> Parse<'a> for CallIndirect<'a> { #[derive(Debug, Clone)] pub struct TableInit<'a> { /// The index of the table we're copying into. - pub table: Index<'a>, + pub table: Index<'a, TableIdx>, /// The index of the element segment we're copying into a table. - pub elem: Index<'a>, + pub elem: Index<'a, ElemIdx>, } impl<'a> Parse<'a> for TableInit<'a> { fn parse(parser: Parser<'a>) -> Result { let prev_span = parser.prev_span(); - let (elem, table) = if parser.peek2::()? { + let (elem, table) = if parser.peek2::>()? { let table = parser.parse()?; (parser.parse()?, table) } else { - (parser.parse()?, Index::Num(0, prev_span)) + (parser.parse()?, Index::Num(TableIdx(0), prev_span)) }; Ok(TableInit { table, elem }) } @@ -1655,9 +1664,9 @@ impl<'a> Parse<'a> for TableInit<'a> { #[derive(Debug, Clone)] pub struct TableCopy<'a> { /// The index of the destination table to copy into. - pub dst: Index<'a>, + pub dst: Index<'a, TableIdx>, /// The index of the source table to copy from. - pub src: Index<'a>, + pub src: Index<'a, TableIdx>, } impl<'a> Parse<'a> for TableCopy<'a> { @@ -1665,8 +1674,8 @@ impl<'a> Parse<'a> for TableCopy<'a> { let (dst, src) = match parser.parse::>()? { Some(dst) => (dst, parser.parse()?), None => ( - Index::Num(0, parser.prev_span()), - Index::Num(0, parser.prev_span()), + Index::Num(TableIdx(0), parser.prev_span()), + Index::Num(TableIdx(0), parser.prev_span()), ), }; Ok(TableCopy { dst, src }) @@ -1677,7 +1686,7 @@ impl<'a> Parse<'a> for TableCopy<'a> { #[derive(Debug, Clone)] pub struct TableArg<'a> { /// The index of the table argument. - pub dst: Index<'a>, + pub dst: Index<'a, TableIdx>, } // `TableArg` could be an unwrapped as an `Index` if not for this custom parse @@ -1687,7 +1696,7 @@ impl<'a> Parse<'a> for TableArg<'a> { let dst = if let Some(dst) = parser.parse()? { dst } else { - Index::Num(0, parser.prev_span()) + Index::Num(TableIdx(0), parser.prev_span()) }; Ok(TableArg { dst }) } @@ -1697,7 +1706,7 @@ impl<'a> Parse<'a> for TableArg<'a> { #[derive(Debug, Clone)] pub struct MemoryArg<'a> { /// The index of the memory space. - pub mem: Index<'a>, + pub mem: Index<'a, MemIdx>, } impl<'a> Parse<'a> for MemoryArg<'a> { @@ -1705,7 +1714,7 @@ impl<'a> Parse<'a> for MemoryArg<'a> { let mem = if let Some(mem) = parser.parse()? { mem } else { - Index::Num(0, parser.prev_span()) + Index::Num(MemIdx(0), parser.prev_span()) }; Ok(MemoryArg { mem }) } @@ -1715,19 +1724,19 @@ impl<'a> Parse<'a> for MemoryArg<'a> { #[derive(Debug, Clone)] pub struct MemoryInit<'a> { /// The index of the data segment we're copying into memory. - pub data: Index<'a>, + pub data: Index<'a, DataIdx>, /// The index of the memory we're copying into, - pub mem: Index<'a>, + pub mem: Index<'a, MemIdx>, } impl<'a> Parse<'a> for MemoryInit<'a> { fn parse(parser: Parser<'a>) -> Result { let prev_span = parser.prev_span(); - let (data, mem) = if parser.peek2::()? { + let (data, mem) = if parser.peek2::>()? { let memory = parser.parse()?; (parser.parse()?, memory) } else { - (parser.parse()?, Index::Num(0, prev_span)) + (parser.parse()?, Index::Num(MemIdx(0), prev_span)) }; Ok(MemoryInit { data, mem }) } @@ -1737,9 +1746,9 @@ impl<'a> Parse<'a> for MemoryInit<'a> { #[derive(Debug, Clone)] pub struct MemoryCopy<'a> { /// The index of the memory we're copying from. - pub src: Index<'a>, + pub src: Index<'a, MemIdx>, /// The index of the memory we're copying to. - pub dst: Index<'a>, + pub dst: Index<'a, MemIdx>, } impl<'a> Parse<'a> for MemoryCopy<'a> { @@ -1747,8 +1756,8 @@ impl<'a> Parse<'a> for MemoryCopy<'a> { let (src, dst) = match parser.parse()? { Some(dst) => (parser.parse()?, dst), None => ( - Index::Num(0, parser.prev_span()), - Index::Num(0, parser.prev_span()), + Index::Num(MemIdx(0), parser.prev_span()), + Index::Num(MemIdx(0), parser.prev_span()), ), }; Ok(MemoryCopy { src, dst }) @@ -1759,9 +1768,9 @@ impl<'a> Parse<'a> for MemoryCopy<'a> { #[derive(Debug, Clone)] pub struct StructAccess<'a> { /// The index of the struct type we're accessing. - pub r#struct: Index<'a>, + pub r#struct: Index<'a, TypeIdx>, /// The index of the field of the struct we're accessing - pub field: Index<'a>, + pub field: Index<'a, FieldIdx>, } impl<'a> Parse<'a> for StructAccess<'a> { @@ -1777,7 +1786,7 @@ impl<'a> Parse<'a> for StructAccess<'a> { #[derive(Debug, Clone)] pub struct ArrayFill<'a> { /// The index of the array type we're filling. - pub array: Index<'a>, + pub array: Index<'a, TypeIdx>, } impl<'a> Parse<'a> for ArrayFill<'a> { @@ -1792,9 +1801,9 @@ impl<'a> Parse<'a> for ArrayFill<'a> { #[derive(Debug, Clone)] pub struct ArrayCopy<'a> { /// The index of the array type we're copying to. - pub dest_array: Index<'a>, + pub dest_array: Index<'a, TypeIdx>, /// The index of the array type we're copying from. - pub src_array: Index<'a>, + pub src_array: Index<'a, TypeIdx>, } impl<'a> Parse<'a> for ArrayCopy<'a> { @@ -1808,14 +1817,17 @@ impl<'a> Parse<'a> for ArrayCopy<'a> { /// Extra data associated with the `array.init_[data/elem]` instruction #[derive(Debug, Clone)] -pub struct ArrayInit<'a> { +pub struct ArrayInit<'a, I> { /// The index of the array type we're initializing. - pub array: Index<'a>, + pub array: Index<'a, TypeIdx>, /// The index of the data or elem segment we're reading from. - pub segment: Index<'a>, + pub segment: Index<'a, I>, } -impl<'a> Parse<'a> for ArrayInit<'a> { +impl<'a, I> Parse<'a> for ArrayInit<'a, I> +where + (I, Span): Parse<'a>, +{ fn parse(parser: Parser<'a>) -> Result { Ok(ArrayInit { array: parser.parse()?, @@ -1828,7 +1840,7 @@ impl<'a> Parse<'a> for ArrayInit<'a> { #[derive(Debug, Clone)] pub struct ArrayNewFixed<'a> { /// The index of the array type we're accessing. - pub array: Index<'a>, + pub array: Index<'a, TypeIdx>, /// The amount of values to initialize the array with. pub length: u32, } @@ -1846,9 +1858,9 @@ impl<'a> Parse<'a> for ArrayNewFixed<'a> { #[derive(Debug, Clone)] pub struct ArrayNewData<'a> { /// The index of the array type we're accessing. - pub array: Index<'a>, + pub array: Index<'a, TypeIdx>, /// The data segment to initialize from. - pub data_idx: Index<'a>, + pub data_idx: Index<'a, DataIdx>, } impl<'a> Parse<'a> for ArrayNewData<'a> { @@ -1864,9 +1876,9 @@ impl<'a> Parse<'a> for ArrayNewData<'a> { #[derive(Debug, Clone)] pub struct ArrayNewElem<'a> { /// The index of the array type we're accessing. - pub array: Index<'a>, + pub array: Index<'a, TypeIdx>, /// The elem segment to initialize from. - pub elem_idx: Index<'a>, + pub elem_idx: Index<'a, ElemIdx>, } impl<'a> Parse<'a> for ArrayNewElem<'a> { @@ -1912,7 +1924,7 @@ impl<'a> Parse<'a> for RefTest<'a> { #[derive(Debug, Clone)] pub struct BrOnCast<'a> { /// The label to branch to. - pub label: Index<'a>, + pub label: Index<'a, LabelIdx>, /// The type we're casting from. pub from_type: RefType<'a>, /// The type we're casting to. @@ -1933,7 +1945,7 @@ impl<'a> Parse<'a> for BrOnCast<'a> { #[derive(Debug, Clone)] pub struct BrOnCastFail<'a> { /// The label to branch to. - pub label: Index<'a>, + pub label: Index<'a, LabelIdx>, /// The type we're casting from. pub from_type: RefType<'a>, /// The type we're casting to. diff --git a/crates/wast/src/core/memory.rs b/crates/wast/src/core/memory.rs index abf2a299da..6201d5e444 100644 --- a/crates/wast/src/core/memory.rs +++ b/crates/wast/src/core/memory.rs @@ -2,6 +2,7 @@ use crate::core::*; use crate::kw; use crate::parser::{Lookahead1, Parse, Parser, Peek, Result}; use crate::token::*; +use wasm_types::MemIdx; /// A defined WebAssembly memory instance inside of a module. #[derive(Debug)] @@ -130,7 +131,7 @@ pub enum DataKind<'a> { /// memory on module instantiation. Active { /// The memory that this `Data` will be associated with. - memory: Index<'a>, + memory: Index<'a, MemIdx>, /// Initial offset to load this data segment at offset: Expression<'a>, @@ -149,7 +150,7 @@ impl<'a> Parse<'a> for Data<'a> { // ... and otherwise we must be attached to a particular memory as well // as having an initialization offset. } else { - let memory = if parser.peek::()? { + let memory = if parser.peek::()? { // FIXME: this is only here to accomodate // proposals/threads/imports.wast at this current moment in // time, this probably should get removed when the threads @@ -161,7 +162,7 @@ impl<'a> Parse<'a> for Data<'a> { p.parse() })? } else { - Index::Num(0, span) + Index::Num(MemIdx(0), span) }; let offset = parser.parens(|parser| { if parser.peek::()? { diff --git a/crates/wast/src/core/module.rs b/crates/wast/src/core/module.rs index e80719630b..64d7204603 100644 --- a/crates/wast/src/core/module.rs +++ b/crates/wast/src/core/module.rs @@ -3,6 +3,7 @@ use crate::core::*; use crate::parser::{Parse, Parser, Result}; use crate::token::{Id, Index, NameAnnotation, Span}; use crate::{annotation, kw}; +use wasm_types::FuncIdx; pub use crate::core::resolve::Names; @@ -151,7 +152,7 @@ pub enum ModuleField<'a> { Memory(Memory<'a>), Global(Global<'a>), Export(Export<'a>), - Start(Index<'a>), + Start(Index<'a, FuncIdx>), Elem(Elem<'a>), Data(Data<'a>), Tag(Tag<'a>), diff --git a/crates/wast/src/core/resolve/mod.rs b/crates/wast/src/core/resolve/mod.rs index 63c6729db9..dacd1d2991 100644 --- a/crates/wast/src/core/resolve/mod.rs +++ b/crates/wast/src/core/resolve/mod.rs @@ -1,6 +1,7 @@ use crate::core::*; use crate::token::Index; use crate::{gensym, Error}; +use wasm_types::{FuncIdx, GlobalIdx, MemIdx, TableIdx}; mod deinline_import_export; mod names; @@ -75,8 +76,8 @@ impl<'a> Names<'a> { /// If `idx` is a `Num`, it is ignored, but if it's an `Id` then it will be /// looked up in the function namespace and converted to a `Num`. If the /// `Id` is not defined then an error will be returned. - pub fn resolve_func(&self, idx: &mut Index<'a>) -> Result<(), Error> { - self.resolver.resolve(idx, Ns::Func)?; + pub fn resolve_func(&self, idx: &mut Index<'a, FuncIdx>) -> Result<(), Error> { + self.resolver.resolve_funcidx(idx)?; Ok(()) } @@ -85,8 +86,8 @@ impl<'a> Names<'a> { /// If `idx` is a `Num`, it is ignored, but if it's an `Id` then it will be /// looked up in the memory namespace and converted to a `Num`. If the /// `Id` is not defined then an error will be returned. - pub fn resolve_memory(&self, idx: &mut Index<'a>) -> Result<(), Error> { - self.resolver.resolve(idx, Ns::Memory)?; + pub fn resolve_memory(&self, idx: &mut Index<'a, MemIdx>) -> Result<(), Error> { + self.resolver.resolve_memidx(idx)?; Ok(()) } @@ -95,8 +96,8 @@ impl<'a> Names<'a> { /// If `idx` is a `Num`, it is ignored, but if it's an `Id` then it will be /// looked up in the table namespace and converted to a `Num`. If the /// `Id` is not defined then an error will be returned. - pub fn resolve_table(&self, idx: &mut Index<'a>) -> Result<(), Error> { - self.resolver.resolve(idx, Ns::Table)?; + pub fn resolve_table(&self, idx: &mut Index<'a, TableIdx>) -> Result<(), Error> { + self.resolver.resolve_tableidx(idx)?; Ok(()) } @@ -105,8 +106,8 @@ impl<'a> Names<'a> { /// If `idx` is a `Num`, it is ignored, but if it's an `Id` then it will be /// looked up in the global namespace and converted to a `Num`. If the /// `Id` is not defined then an error will be returned. - pub fn resolve_global(&self, idx: &mut Index<'a>) -> Result<(), Error> { - self.resolver.resolve(idx, Ns::Global)?; + pub fn resolve_global(&self, idx: &mut Index<'a, GlobalIdx>) -> Result<(), Error> { + self.resolver.resolve_globalidx(idx)?; Ok(()) } } diff --git a/crates/wast/src/core/resolve/names.rs b/crates/wast/src/core/resolve/names.rs index 4d9450fc87..8265298184 100644 --- a/crates/wast/src/core/resolve/names.rs +++ b/crates/wast/src/core/resolve/names.rs @@ -1,9 +1,13 @@ -use crate::core::resolve::Ns; use crate::core::*; use crate::names::{resolve_error, Namespace}; use crate::token::{Id, Index}; use crate::Error; +use index_vec::{Idx, IndexVec}; use std::collections::HashMap; +use wasm_types::{ + DataIdx, ElemIdx, FieldIdx, FuncIdx, GlobalIdx, LabelIdx, LocalIdx, MemIdx, TableIdx, TagIdx, + TypeIdx, +}; pub fn resolve<'a>(fields: &mut Vec>) -> Result, Error> { let mut resolver = Resolver::default(); @@ -18,16 +22,16 @@ pub struct Resolver<'a> { // information about the signature of the item in that namespace. The // signature is later used to synthesize the type of a module and inject // type annotations if necessary. - funcs: Namespace<'a>, - globals: Namespace<'a>, - tables: Namespace<'a>, - memories: Namespace<'a>, - types: Namespace<'a>, - tags: Namespace<'a>, - datas: Namespace<'a>, - elems: Namespace<'a>, - fields: HashMap>, - type_info: Vec>, + funcs: Namespace<'a, FuncIdx>, + globals: Namespace<'a, GlobalIdx>, + tables: Namespace<'a, TableIdx>, + memories: Namespace<'a, MemIdx>, + types: Namespace<'a, TypeIdx>, + tags: Namespace<'a, TagIdx>, + datas: Namespace<'a, DataIdx>, + elems: Namespace<'a, ElemIdx>, + fields: HashMap>, + type_info: IndexVec>, } impl<'a> Resolver<'a> { @@ -60,7 +64,7 @@ impl<'a> Resolver<'a> { self.fields .entry(type_index) .or_insert(Namespace::default()) - .register_specific(id, i as u32, "field")?; + .register_specific(id, FieldIdx::from_usize(i), "field")?; } } } @@ -77,7 +81,9 @@ impl<'a> Resolver<'a> { let results = f.results.clone(); self.type_info.push(TypeInfo::Func { params, results }); } - _ => self.type_info.push(TypeInfo::Other), + _ => { + self.type_info.push(TypeInfo::Other); + } } Ok(()) @@ -86,16 +92,34 @@ impl<'a> Resolver<'a> { fn register(&mut self, item: &ModuleField<'a>) -> Result<(), Error> { match item { ModuleField::Import(i) => match &i.item.kind { - ItemKind::Func(_) => self.funcs.register(i.item.id, "func")?, - ItemKind::Memory(_) => self.memories.register(i.item.id, "memory")?, - ItemKind::Table(_) => self.tables.register(i.item.id, "table")?, - ItemKind::Global(_) => self.globals.register(i.item.id, "global")?, - ItemKind::Tag(_) => self.tags.register(i.item.id, "tag")?, + ItemKind::Func(_) => { + self.funcs.register(i.item.id, "func")?; + } + ItemKind::Memory(_) => { + self.memories.register(i.item.id, "memory")?; + } + ItemKind::Table(_) => { + self.tables.register(i.item.id, "table")?; + } + ItemKind::Global(_) => { + self.globals.register(i.item.id, "global")?; + } + ItemKind::Tag(_) => { + self.tags.register(i.item.id, "tag")?; + } }, - ModuleField::Global(i) => self.globals.register(i.id, "global")?, - ModuleField::Memory(i) => self.memories.register(i.id, "memory")?, - ModuleField::Func(i) => self.funcs.register(i.id, "func")?, - ModuleField::Table(i) => self.tables.register(i.id, "table")?, + ModuleField::Global(i) => { + self.globals.register(i.id, "global")?; + } + ModuleField::Memory(i) => { + self.memories.register(i.id, "memory")?; + } + ModuleField::Func(i) => { + self.funcs.register(i.id, "func")?; + } + ModuleField::Table(i) => { + self.tables.register(i.id, "table")?; + } ModuleField::Type(i) => { return self.register_type(i); @@ -106,9 +130,15 @@ impl<'a> Resolver<'a> { } return Ok(()); } - ModuleField::Elem(e) => self.elems.register(e.id, "elem")?, - ModuleField::Data(d) => self.datas.register(d.id, "data")?, - ModuleField::Tag(t) => self.tags.register(t.id, "tag")?, + ModuleField::Elem(e) => { + self.elems.register(e.id, "elem")?; + } + ModuleField::Data(d) => { + self.datas.register(d.id, "data")?; + } + ModuleField::Tag(t) => { + self.tags.register(t.id, "tag")?; + } // These fields don't define any items in any index space. ModuleField::Export(_) | ModuleField::Start(_) | ModuleField::Custom(_) => { @@ -156,7 +186,7 @@ impl<'a> Resolver<'a> { scope.register(*id, "local")?; } } else if let Some(TypeInfo::Func { params, .. }) = - self.type_info.get(n as usize) + self.type_info.get(n.index()) { for _ in 0..params.len() { scope.register(None, "local")?; @@ -185,7 +215,7 @@ impl<'a> Resolver<'a> { match &mut e.kind { ElemKind::Active { table, offset } => { if let Some(table) = table { - self.resolve(table, Ns::Table)?; + self.resolve_tableidx(table)?; } self.resolve_expr(offset)?; } @@ -194,7 +224,7 @@ impl<'a> Resolver<'a> { match &mut e.payload { ElemPayload::Indices(elems) => { for idx in elems { - self.resolve(idx, Ns::Func)?; + self.resolve_funcidx(idx)?; } } ElemPayload::Exprs { exprs, ty } => { @@ -209,28 +239,45 @@ impl<'a> Resolver<'a> { ModuleField::Data(d) => { if let DataKind::Active { memory, offset } = &mut d.kind { - self.resolve(memory, Ns::Memory)?; + self.resolve_memidx(memory)?; self.resolve_expr(offset)?; } Ok(()) } ModuleField::Start(i) => { - self.resolve(i, Ns::Func)?; + self.resolve_funcidx(i)?; Ok(()) } ModuleField::Export(e) => { - self.resolve( - &mut e.item, - match e.kind { - ExportKind::Func => Ns::Func, - ExportKind::Table => Ns::Table, - ExportKind::Memory => Ns::Memory, - ExportKind::Global => Ns::Global, - ExportKind::Tag => Ns::Tag, - }, - )?; + match e.kind { + ExportKind::Func => { + let mut i = e.item.into(); + self.resolve_funcidx(&mut i)?; + e.item = i.into(); + } + ExportKind::Table => { + let mut i = e.item.into(); + self.resolve_tableidx(&mut i)?; + e.item = i.into(); + } + ExportKind::Memory => { + let mut i = e.item.into(); + self.resolve_memidx(&mut i)?; + e.item = i.into(); + } + ExportKind::Global => { + let mut i = e.item.into(); + self.resolve_globalidx(&mut i)?; + e.item = i.into(); + } + ExportKind::Tag => { + let mut i = e.item.into(); + self.resolve_tagidx(&mut i)?; + e.item = i.into(); + } + } Ok(()) } @@ -282,12 +329,12 @@ impl<'a> Resolver<'a> { fn resolve_type_use<'b, T>( &self, ty: &'b mut TypeUse<'a, T>, - ) -> Result<(&'b Index<'a>, Option), Error> + ) -> Result<(&'b Index<'a, TypeIdx>, Option), Error> where T: TypeReference<'a>, { let idx = ty.index.as_mut().unwrap(); - self.resolve(idx, Ns::Type)?; + self.resolve_typeidx(idx)?; // If the type was listed inline *and* it was specified via a type index // we need to assert they're the same. @@ -306,15 +353,28 @@ impl<'a> Resolver<'a> { ExprResolver::new(self, Namespace::default()).resolve(expr) } - pub fn resolve(&self, idx: &mut Index<'a>, ns: Ns) -> Result { - match ns { - Ns::Func => self.funcs.resolve(idx, "func"), - Ns::Table => self.tables.resolve(idx, "table"), - Ns::Global => self.globals.resolve(idx, "global"), - Ns::Memory => self.memories.resolve(idx, "memory"), - Ns::Tag => self.tags.resolve(idx, "tag"), - Ns::Type => self.types.resolve(idx, "type"), - } + pub fn resolve_funcidx(&self, idx: &mut Index<'a, FuncIdx>) -> Result { + self.funcs.resolve(idx, "func") + } + + pub fn resolve_tableidx(&self, idx: &mut Index<'a, TableIdx>) -> Result { + self.tables.resolve(idx, "table") + } + + pub fn resolve_globalidx(&self, idx: &mut Index<'a, GlobalIdx>) -> Result { + self.globals.resolve(idx, "global") + } + + pub fn resolve_memidx(&self, idx: &mut Index<'a, MemIdx>) -> Result { + self.memories.resolve(idx, "memory") + } + + pub fn resolve_tagidx(&self, idx: &mut Index<'a, TagIdx>) -> Result { + self.tags.resolve(idx, "tag") + } + + pub fn resolve_typeidx(&self, idx: &mut Index<'a, TypeIdx>) -> Result { + self.types.resolve(idx, "type") } fn resolve_type(&self, ty: &mut Type<'a>) -> Result<(), Error> { @@ -342,12 +402,15 @@ struct ExprResolver<'a, 'b> { resolver: &'b Resolver<'a>, // Scopes tracks the local namespace and dynamically grows as we enter/exit // `let` blocks - scopes: Vec>, + scopes: Vec>, blocks: Vec>, } impl<'a, 'b> ExprResolver<'a, 'b> { - fn new(resolver: &'b Resolver<'a>, initial_scope: Namespace<'a>) -> ExprResolver<'a, 'b> { + fn new( + resolver: &'b Resolver<'a>, + initial_scope: Namespace<'a, LocalIdx>, + ) -> ExprResolver<'a, 'b> { ExprResolver { resolver, scopes: vec![initial_scope], @@ -385,20 +448,20 @@ impl<'a, 'b> ExprResolver<'a, 'b> { use Instruction::*; if let Some(m) = instr.memarg_mut() { - self.resolver.resolve(&mut m.memory, Ns::Memory)?; + self.resolver.resolve_memidx(&mut m.memory)?; } match instr { MemorySize(i) | MemoryGrow(i) | MemoryFill(i) | MemoryDiscard(i) => { - self.resolver.resolve(&mut i.mem, Ns::Memory)?; + self.resolver.resolve_memidx(&mut i.mem)?; } MemoryInit(i) => { self.resolver.datas.resolve(&mut i.data, "data")?; - self.resolver.resolve(&mut i.mem, Ns::Memory)?; + self.resolver.resolve_memidx(&mut i.mem)?; } MemoryCopy(i) => { - self.resolver.resolve(&mut i.src, Ns::Memory)?; - self.resolver.resolve(&mut i.dst, Ns::Memory)?; + self.resolver.resolve_memidx(&mut i.src)?; + self.resolver.resolve_memidx(&mut i.dst)?; } DataDrop(i) => { self.resolver.datas.resolve(i, "data")?; @@ -406,30 +469,30 @@ impl<'a, 'b> ExprResolver<'a, 'b> { TableInit(i) => { self.resolver.elems.resolve(&mut i.elem, "elem")?; - self.resolver.resolve(&mut i.table, Ns::Table)?; + self.resolver.resolve_tableidx(&mut i.table)?; } ElemDrop(i) => { self.resolver.elems.resolve(i, "elem")?; } TableCopy(i) => { - self.resolver.resolve(&mut i.dst, Ns::Table)?; - self.resolver.resolve(&mut i.src, Ns::Table)?; + self.resolver.resolve_tableidx(&mut i.dst)?; + self.resolver.resolve_tableidx(&mut i.src)?; } TableFill(i) | TableSet(i) | TableGet(i) | TableSize(i) | TableGrow(i) => { - self.resolver.resolve(&mut i.dst, Ns::Table)?; + self.resolver.resolve_tableidx(&mut i.dst)?; } TableAtomicGet(i) | TableAtomicSet(i) | TableAtomicRmwXchg(i) | TableAtomicRmwCmpxchg(i) => { - self.resolver.resolve(&mut i.inner.dst, Ns::Table)?; + self.resolver.resolve_tableidx(&mut i.inner.dst)?; } GlobalSet(i) | GlobalGet(i) => { - self.resolver.resolve(i, Ns::Global)?; + self.resolver.resolve_globalidx(i)?; } GlobalAtomicSet(i) @@ -441,7 +504,7 @@ impl<'a, 'b> ExprResolver<'a, 'b> { | GlobalAtomicRmwXor(i) | GlobalAtomicRmwXchg(i) | GlobalAtomicRmwCmpxchg(i) => { - self.resolver.resolve(&mut i.inner, Ns::Global)?; + self.resolver.resolve_globalidx(&mut i.inner)?; } LocalSet(i) | LocalGet(i) | LocalTee(i) => { @@ -465,16 +528,16 @@ impl<'a, 'b> ExprResolver<'a, 'b> { } Call(i) | RefFunc(i) | ReturnCall(i) => { - self.resolver.resolve(i, Ns::Func)?; + self.resolver.resolve_funcidx(i)?; } CallIndirect(c) | ReturnCallIndirect(c) => { - self.resolver.resolve(&mut c.table, Ns::Table)?; + self.resolver.resolve_tableidx(&mut c.table)?; self.resolver.resolve_type_use(&mut c.ty)?; } CallRef(i) | ReturnCallRef(i) => { - self.resolver.resolve(i, Ns::Type)?; + self.resolver.resolve_typeidx(i)?; } Block(bt) | If(bt) | Loop(bt) | Try(bt) => { @@ -488,7 +551,7 @@ impl<'a, 'b> ExprResolver<'a, 'b> { self.resolve_block_type(&mut try_table.block)?; for catch in &mut try_table.catches { if let Some(tag) = catch.kind.tag_index_mut() { - self.resolver.resolve(tag, Ns::Tag)?; + self.resolver.resolve_tagidx(tag)?; } self.resolve_label(&mut catch.label)?; } @@ -544,7 +607,7 @@ impl<'a, 'b> ExprResolver<'a, 'b> { } Throw(i) | Catch(i) => { - self.resolver.resolve(i, Ns::Tag)?; + self.resolver.resolve_tagidx(i)?; } Rethrow(i) => { @@ -585,7 +648,7 @@ impl<'a, 'b> ExprResolver<'a, 'b> { StructNew(i) | StructNewDefault(i) | ArrayNew(i) | ArrayNewDefault(i) | ArrayGet(i) | ArrayGetS(i) | ArrayGetU(i) | ArraySet(i) => { - self.resolver.resolve(i, Ns::Type)?; + self.resolver.resolve_typeidx(i)?; } StructSet(s) | StructGet(s) | StructGetS(s) | StructGetU(s) => { @@ -607,29 +670,29 @@ impl<'a, 'b> ExprResolver<'a, 'b> { } ArrayNewFixed(a) => { - self.resolver.resolve(&mut a.array, Ns::Type)?; + self.resolver.resolve_typeidx(&mut a.array)?; } ArrayNewData(a) => { - self.resolver.resolve(&mut a.array, Ns::Type)?; + self.resolver.resolve_typeidx(&mut a.array)?; self.resolver.datas.resolve(&mut a.data_idx, "data")?; } ArrayNewElem(a) => { - self.resolver.resolve(&mut a.array, Ns::Type)?; + self.resolver.resolve_typeidx(&mut a.array)?; self.resolver.elems.resolve(&mut a.elem_idx, "elem")?; } ArrayFill(a) => { - self.resolver.resolve(&mut a.array, Ns::Type)?; + self.resolver.resolve_typeidx(&mut a.array)?; } ArrayCopy(a) => { - self.resolver.resolve(&mut a.dest_array, Ns::Type)?; - self.resolver.resolve(&mut a.src_array, Ns::Type)?; + self.resolver.resolve_typeidx(&mut a.dest_array)?; + self.resolver.resolve_typeidx(&mut a.src_array)?; } ArrayInitData(a) => { - self.resolver.resolve(&mut a.array, Ns::Type)?; + self.resolver.resolve_typeidx(&mut a.array)?; self.resolver.datas.resolve(&mut a.segment, "data")?; } ArrayInitElem(a) => { - self.resolver.resolve(&mut a.array, Ns::Type)?; + self.resolver.resolve_typeidx(&mut a.array)?; self.resolver.elems.resolve(&mut a.segment, "elem")?; } @@ -644,33 +707,33 @@ impl<'a, 'b> ExprResolver<'a, 'b> { | ArrayAtomicRmwXor(i) | ArrayAtomicRmwXchg(i) | ArrayAtomicRmwCmpxchg(i) => { - self.resolver.resolve(&mut i.inner, Ns::Type)?; + self.resolver.resolve_typeidx(&mut i.inner)?; } RefNull(ty) => self.resolver.resolve_heaptype(ty)?, ContNew(ty) => { - self.resolver.resolve(ty, Ns::Type)?; + self.resolver.resolve_typeidx(ty)?; } ContBind(cb) => { - self.resolver.resolve(&mut cb.argument_index, Ns::Type)?; - self.resolver.resolve(&mut cb.result_index, Ns::Type)?; + self.resolver.resolve_typeidx(&mut cb.argument_index)?; + self.resolver.resolve_typeidx(&mut cb.result_index)?; } Suspend(ty) => { - self.resolver.resolve(ty, Ns::Tag)?; + self.resolver.resolve_tagidx(ty)?; } Resume(r) => { - self.resolver.resolve(&mut r.type_index, Ns::Type)?; + self.resolver.resolve_typeidx(&mut r.type_index)?; self.resolve_resume_table(&mut r.table)?; } ResumeThrow(rt) => { - self.resolver.resolve(&mut rt.type_index, Ns::Type)?; - self.resolver.resolve(&mut rt.tag_index, Ns::Tag)?; + self.resolver.resolve_typeidx(&mut rt.type_index)?; + self.resolver.resolve_tagidx(&mut rt.tag_index)?; self.resolve_resume_table(&mut rt.table)?; } Switch(s) => { - self.resolver.resolve(&mut s.type_index, Ns::Type)?; - self.resolver.resolve(&mut s.tag_index, Ns::Tag)?; + self.resolver.resolve_typeidx(&mut s.type_index)?; + self.resolver.resolve_tagidx(&mut s.tag_index)?; } _ => {} @@ -682,18 +745,18 @@ impl<'a, 'b> ExprResolver<'a, 'b> { for handle in &mut table.handlers { match handle { Handle::OnLabel { tag, label } => { - self.resolver.resolve(tag, Ns::Tag)?; + self.resolver.resolve_tagidx(tag)?; self.resolve_label(label)?; } Handle::OnSwitch { tag } => { - self.resolver.resolve(tag, Ns::Tag)?; + self.resolver.resolve_tagidx(tag)?; } } } Ok(()) } - fn resolve_label(&self, label: &mut Index<'a>) -> Result<(), Error> { + fn resolve_label(&self, label: &mut Index<'a, LabelIdx>) -> Result<(), Error> { let id = match label { Index::Num(..) => return Ok(()), Index::Id(id) => *id, @@ -707,7 +770,7 @@ impl<'a, 'b> ExprResolver<'a, 'b> { .find(|(_, l)| *l == id); match idx { Some((idx, _)) => { - *label = Index::Num(idx as u32, id.span()); + *label = Index::Num(LabelIdx::from_usize(idx), id.span()); Ok(()) } None => Err(resolve_error(id, "label")), @@ -715,7 +778,7 @@ impl<'a, 'b> ExprResolver<'a, 'b> { } fn resolve_field(&self, s: &mut StructAccess<'a>) -> Result<(), Error> { - let type_index = self.resolver.resolve(&mut s.r#struct, Ns::Type)?; + let type_index = self.resolver.resolve_typeidx(&mut s.r#struct)?; if let Index::Id(field_id) = s.field { self.resolver .fields @@ -736,17 +799,17 @@ enum TypeInfo<'a> { } trait TypeReference<'a> { - fn check_matches(&mut self, idx: &Index<'a>, cx: &Resolver<'a>) -> Result<(), Error>; + fn check_matches(&mut self, idx: &Index<'a, TypeIdx>, cx: &Resolver<'a>) -> Result<(), Error>; fn resolve(&mut self, cx: &Resolver<'a>) -> Result<(), Error>; } impl<'a> TypeReference<'a> for FunctionType<'a> { - fn check_matches(&mut self, idx: &Index<'a>, cx: &Resolver<'a>) -> Result<(), Error> { + fn check_matches(&mut self, idx: &Index<'a, TypeIdx>, cx: &Resolver<'a>) -> Result<(), Error> { let n = match idx { Index::Num(n, _) => *n, Index::Id(_) => panic!("expected `Num`"), }; - let (params, results) = match cx.type_info.get(n as usize) { + let (params, results) = match cx.type_info.get(n) { Some(TypeInfo::Func { params, results }) => (params, results), _ => return Ok(()), }; @@ -791,7 +854,7 @@ impl<'a> TypeReference<'a> for FunctionType<'a> { } pub(crate) trait ResolveCoreType<'a> { - fn resolve_type_name(&mut self, name: &mut Index<'a>) -> Result; + fn resolve_type_name(&mut self, name: &mut Index<'a, TypeIdx>) -> Result; fn resolve_type(&mut self, ty: &mut Type<'a>) -> Result<(), Error> { self.resolve_type_def(&mut ty.def)?; @@ -859,7 +922,7 @@ pub(crate) trait ResolveCoreType<'a> { } impl<'a> ResolveCoreType<'a> for &Resolver<'a> { - fn resolve_type_name(&mut self, name: &mut Index<'a>) -> Result { - self.resolve(name, Ns::Type) + fn resolve_type_name(&mut self, name: &mut Index<'a, TypeIdx>) -> Result { + self.resolve_typeidx(name) } } diff --git a/crates/wast/src/core/resolve/types.rs b/crates/wast/src/core/resolve/types.rs index 7a7e36c9d2..33f19e8d36 100644 --- a/crates/wast/src/core/resolve/types.rs +++ b/crates/wast/src/core/resolve/types.rs @@ -2,6 +2,7 @@ use crate::core::*; use crate::gensym; use crate::token::{Index, Span}; use std::collections::HashMap; +use wasm_types::TypeIdx; pub fn expand<'a>(fields: &mut Vec>) { let mut expander = Expander::default(); @@ -13,7 +14,7 @@ pub(crate) struct Expander<'a> { // Maps used to "intern" types. These maps are populated as type annotations // are seen and inline type annotations use previously defined ones if // there's a match. - func_type_to_idx: HashMap, Index<'a>>, + func_type_to_idx: HashMap, Index<'a, TypeIdx>>, /// Fields, during processing, which should be prepended to the /// currently-being-processed field. This should always be empty after @@ -181,7 +182,7 @@ impl<'a> Expander<'a> { } } - fn expand_type_use(&mut self, item: &mut TypeUse<'a, T>) -> Index<'a> + fn expand_type_use(&mut self, item: &mut TypeUse<'a, T>) -> Index<'a, TypeIdx> where T: TypeReference<'a>, { @@ -201,7 +202,7 @@ impl<'a> Expander<'a> { idx } - fn key_to_idx(&mut self, span: Span, key: impl TypeKey<'a>) -> Index<'a> { + fn key_to_idx(&mut self, span: Span, key: impl TypeKey<'a>) -> Index<'a, TypeIdx> { // First see if this `key` already exists in the type definitions we've // seen so far... if let Some(idx) = key.lookup(self) { @@ -232,9 +233,9 @@ pub(crate) trait TypeReference<'a>: Default { } pub(crate) trait TypeKey<'a> { - fn lookup(&self, cx: &Expander<'a>) -> Option>; + fn lookup(&self, cx: &Expander<'a>) -> Option>; fn to_def(&self, span: Span, shared: bool) -> TypeDef<'a>; - fn insert(&self, cx: &mut Expander<'a>, id: Index<'a>); + fn insert(&self, cx: &mut Expander<'a>, id: Index<'a, TypeIdx>); } pub(crate) type FuncKey<'a> = (Box<[ValType<'a>]>, Box<[ValType<'a>]>); @@ -252,7 +253,7 @@ impl<'a> TypeReference<'a> for FunctionType<'a> { } impl<'a> TypeKey<'a> for FuncKey<'a> { - fn lookup(&self, cx: &Expander<'a>) -> Option> { + fn lookup(&self, cx: &Expander<'a>) -> Option> { cx.func_type_to_idx.get(self).cloned() } @@ -268,7 +269,7 @@ impl<'a> TypeKey<'a> for FuncKey<'a> { } } - fn insert(&self, cx: &mut Expander<'a>, idx: Index<'a>) { + fn insert(&self, cx: &mut Expander<'a>, idx: Index<'a, TypeIdx>) { cx.func_type_to_idx.entry(self.clone()).or_insert(idx); } } diff --git a/crates/wast/src/core/table.rs b/crates/wast/src/core/table.rs index de2970f196..8f28980d7b 100644 --- a/crates/wast/src/core/table.rs +++ b/crates/wast/src/core/table.rs @@ -2,6 +2,7 @@ use crate::core::*; use crate::kw; use crate::parser::{Parse, Parser, Peek, Result}; use crate::token::{Id, Index, LParen, NameAnnotation, Span}; +use wasm_types::{FuncIdx, TableIdx}; /// A WebAssembly `table` directive in a module. #[derive(Debug)] @@ -149,7 +150,7 @@ pub enum ElemKind<'a> { /// An active segment associated with a table. Active { /// The table this `elem` is initializing. - table: Option>, + table: Option>, /// The offset within `table` that we'll initialize at. offset: Expression<'a>, }, @@ -159,7 +160,7 @@ pub enum ElemKind<'a> { #[derive(Debug)] pub enum ElemPayload<'a> { /// This element segment has a contiguous list of function indices - Indices(Vec>), + Indices(Vec>), /// This element segment has a list of optional function indices, /// represented as expressions using `ref.func` and `ref.null`. diff --git a/crates/wast/src/core/types.rs b/crates/wast/src/core/types.rs index ad8511fdd4..208ec3ae91 100644 --- a/crates/wast/src/core/types.rs +++ b/crates/wast/src/core/types.rs @@ -5,6 +5,7 @@ use crate::parser::{Cursor, Parse, Parser, Peek, Result}; use crate::token::{Id, Index, LParen, NameAnnotation, Span}; use crate::Error; use std::mem; +use wasm_types::TypeIdx; /// The value types for a wasm module. #[allow(missing_docs)] @@ -67,13 +68,13 @@ pub enum HeapType<'a> { Abstract { shared: bool, ty: AbstractHeapType }, /// A reference to a concrete function, struct, or array type defined by /// Wasm: `ref T`. This is part of the function references and GC proposals. - Concrete(Index<'a>), + Concrete(Index<'a, TypeIdx>), } impl<'a> Parse<'a> for HeapType<'a> { fn parse(parser: Parser<'a>) -> Result { let mut l = parser.lookahead1(); - if l.peek::()? { + if l.peek::>()? { Ok(HeapType::Concrete(parser.parse()?)) } else if l.peek::()? { parser.parens(|p| { @@ -886,7 +887,7 @@ impl<'a> Parse<'a> for ArrayType<'a> { /// A continuation type. #[derive(Clone, Debug)] -pub struct ContType<'a>(pub Index<'a>); +pub struct ContType<'a>(pub Index<'a, TypeIdx>); impl<'a> Parse<'a> for ContType<'a> { fn parse(parser: Parser<'a>) -> Result { @@ -956,7 +957,7 @@ pub struct TypeDef<'a> { /// Whether the type is shared or not. pub shared: bool, /// The declared parent type of this definition. - pub parent: Option>, + pub parent: Option>, /// Whether this type is final or not. By default types are final. pub final_type: Option, } @@ -985,7 +986,7 @@ impl<'a> Parse<'a> for TypeDef<'a> { Some(false) }; - let parent = if parser.peek::>()? { + let parent = if parser.peek::>()? { parser.parse()? } else { None @@ -1068,7 +1069,7 @@ impl<'a> Parse<'a> for Rec<'a> { #[derive(Clone, Debug)] pub struct TypeUse<'a, T> { /// The type that we're referencing, if it was present. - pub index: Option>, + pub index: Option>, /// The inline type, if present. pub inline: Option, } @@ -1076,7 +1077,7 @@ pub struct TypeUse<'a, T> { impl<'a, T> TypeUse<'a, T> { /// Constructs a new instance of `TypeUse` without an inline definition but /// with an index specified. - pub fn new_with_index(idx: Index<'a>) -> TypeUse<'a, T> { + pub fn new_with_index(idx: Index<'a, TypeIdx>) -> TypeUse<'a, T> { TypeUse { index: Some(idx), inline: None, diff --git a/crates/wast/src/core/wast.rs b/crates/wast/src/core/wast.rs index d71350f7cf..dfe001f93d 100644 --- a/crates/wast/src/core/wast.rs +++ b/crates/wast/src/core/wast.rs @@ -2,6 +2,7 @@ use crate::core::{HeapType, V128Const}; use crate::kw; use crate::parser::{Cursor, Parse, Parser, Peek, Result}; use crate::token::{Index, F32, F64}; +use wasm_types::FuncIdx; /// Expression that can be used inside of `invoke` expressions for core wasm /// functions. @@ -79,7 +80,7 @@ pub enum WastRetCore<'a> { /// A non-null anyref is expected which should contain the specified host value. RefHost(u32), /// A non-null funcref is expected. - RefFunc(Option>), + RefFunc(Option>), /// A non-null anyref is expected. RefAny, /// A non-null eqref is expected. diff --git a/crates/wast/src/encode.rs b/crates/wast/src/encode.rs index 43db4f6bdc..5b59ad26be 100644 --- a/crates/wast/src/encode.rs +++ b/crates/wast/src/encode.rs @@ -1,3 +1,9 @@ +use wasm_types::{ + AbsoluteLabelIdx, ComponentFuncIdx, ComponentIdx, ComponentInstanceIdx, ComponentTypeIdx, + ComponentValueIdx, CoreInstanceIdx, CoreModuleIdx, DataIdx, ElemIdx, FieldIdx, FuncIdx, + GlobalIdx, LabelIdx, LocalIdx, MemIdx, TableIdx, TagIdx, TypeIdx, +}; + pub(crate) trait Encode { fn encode(&self, e: &mut Vec); } @@ -56,6 +62,120 @@ impl Encode for u32 { } } +impl Encode for TypeIdx { + fn encode(&self, e: &mut Vec) { + self.0.encode(e); + } +} + +impl Encode for FuncIdx { + fn encode(&self, e: &mut Vec) { + self.0.encode(e); + } +} + +impl Encode for TableIdx { + fn encode(&self, e: &mut Vec) { + self.0.encode(e); + } +} + +impl Encode for MemIdx { + fn encode(&self, e: &mut Vec) { + self.0.encode(e); + } +} + +impl Encode for TagIdx { + fn encode(&self, e: &mut Vec) { + self.0.encode(e); + } +} + +impl Encode for GlobalIdx { + fn encode(&self, e: &mut Vec) { + self.0.encode(e); + } +} + +impl Encode for ElemIdx { + fn encode(&self, e: &mut Vec) { + self.0.encode(e); + } +} + +impl Encode for DataIdx { + fn encode(&self, e: &mut Vec) { + self.0.encode(e); + } +} + +impl Encode for LocalIdx { + fn encode(&self, e: &mut Vec) { + self.0.encode(e); + } +} + +impl Encode for LabelIdx { + fn encode(&self, e: &mut Vec) { + self.0.encode(e); + } +} + +impl Encode for FieldIdx { + fn encode(&self, e: &mut Vec) { + self.0.encode(e); + } +} + +impl Encode for AbsoluteLabelIdx { + fn encode(&self, e: &mut Vec) { + self.0.encode(e); + } +} + +impl Encode for CoreModuleIdx { + fn encode(&self, e: &mut Vec) { + self.0.encode(e); + } +} + +impl Encode for CoreInstanceIdx { + fn encode(&self, e: &mut Vec) { + self.0.encode(e); + } +} + +impl Encode for ComponentTypeIdx { + fn encode(&self, e: &mut Vec) { + self.0.encode(e); + } +} + +impl Encode for ComponentFuncIdx { + fn encode(&self, e: &mut Vec) { + self.0.encode(e); + } +} + +impl Encode for ComponentIdx { + fn encode(&self, e: &mut Vec) { + self.0.encode(e); + } +} + +impl Encode for ComponentInstanceIdx { + fn encode(&self, e: &mut Vec) { + self.0.encode(e); + } +} + +impl Encode for ComponentValueIdx { + fn encode(&self, e: &mut Vec) { + self.0.encode(e); + } +} + impl Encode for i32 { fn encode(&self, e: &mut Vec) { let (value, pos) = leb128fmt::encode_s32(*self).unwrap(); diff --git a/crates/wast/src/names.rs b/crates/wast/src/names.rs index 859c61f1be..d963ec74c0 100644 --- a/crates/wast/src/names.rs +++ b/crates/wast/src/names.rs @@ -1,15 +1,16 @@ use crate::token::{Id, Index}; use crate::Error; +use index_vec::Idx; use std::collections::HashMap; #[derive(Default)] -pub struct Namespace<'a> { - names: HashMap, u32>, - count: u32, +pub struct Namespace<'a, I> { + names: HashMap, I>, + count: I, } -impl<'a> Namespace<'a> { - pub fn register(&mut self, name: Option>, desc: &str) -> Result { +impl<'a, I: Idx> Namespace<'a, I> { + pub fn register(&mut self, name: Option>, desc: &str) -> Result { let index = self.alloc(); if let Some(name) = name { if let Some(_prev) = self.names.insert(name, index) { @@ -22,13 +23,13 @@ impl<'a> Namespace<'a> { Ok(index) } - pub fn alloc(&mut self) -> u32 { + pub fn alloc(&mut self) -> I { let index = self.count; - self.count += 1; + self.count = I::from_usize(self.count.index() + 1); index } - pub fn register_specific(&mut self, name: Id<'a>, index: u32, desc: &str) -> Result<(), Error> { + pub fn register_specific(&mut self, name: Id<'a>, index: I, desc: &str) -> Result<(), Error> { if let Some(_prev) = self.names.insert(name, index) { return Err(Error::new( name.span(), @@ -41,7 +42,7 @@ impl<'a> Namespace<'a> { Ok(()) } - pub fn resolve(&self, idx: &mut Index<'a>, desc: &str) -> Result { + pub fn resolve(&self, idx: &mut Index<'a, I>, desc: &str) -> Result { let id = match idx { Index::Num(n, _) => return Ok(*n), Index::Id(id) => id, diff --git a/crates/wast/src/token.rs b/crates/wast/src/token.rs index be6c6ac658..65b765e99d 100644 --- a/crates/wast/src/token.rs +++ b/crates/wast/src/token.rs @@ -8,6 +8,11 @@ use crate::parser::{Cursor, Parse, Parser, Peek, Result}; use std::fmt; use std::hash::{Hash, Hasher}; use std::str; +use wasm_types::{ + AbsoluteLabelIdx, ComponentFuncIdx, ComponentIdx, ComponentInstanceIdx, ComponentTypeIdx, + ComponentValueIdx, CoreInstanceIdx, CoreModuleIdx, DataIdx, ElemIdx, FieldIdx, FuncIdx, + GlobalIdx, LabelIdx, LocalIdx, MemIdx, TableIdx, TagIdx, TypeIdx, +}; /// A position in the original source stream, used to render errors. #[derive(Copy, Clone, Debug, PartialOrd, Ord, PartialEq, Eq, Hash)] @@ -161,16 +166,16 @@ impl Peek for Id<'_> { /// The emission phase of a module will ensure that `Index::Id` is never used /// and switch them all to `Index::Num`. #[derive(Copy, Clone, Debug)] -pub enum Index<'a> { +pub enum Index<'a, I> { /// A numerical index that this references. The index space this is /// referencing is implicit based on where this [`Index`] is stored. - Num(u32, Span), + Num(I, Span), /// A human-readable identifier this references. Like `Num`, the namespace /// this references is based on where this is stored. Id(Id<'a>), } -impl Index<'_> { +impl Index<'_, I> { /// Returns the source location where this `Index` was defined. pub fn span(&self) -> Span { match self { @@ -185,7 +190,10 @@ impl Index<'_> { } } -impl<'a> Parse<'a> for Index<'a> { +impl<'a, I> Parse<'a> for Index<'a, I> +where + (I, Span): Parse<'a>, +{ fn parse(parser: Parser<'a>) -> Result { if parser.peek::()? { Ok(Index::Id(parser.parse()?)) @@ -200,7 +208,7 @@ impl<'a> Parse<'a> for Index<'a> { } } -impl Peek for Index<'_> { +impl Peek for Index<'_, I> { fn peek(cursor: Cursor<'_>) -> Result { Ok(u32::peek(cursor)? || Id::peek(cursor)?) } @@ -210,14 +218,14 @@ impl Peek for Index<'_> { } } -impl<'a> From> for Index<'a> { - fn from(id: Id<'a>) -> Index<'a> { +impl<'a, I> From> for Index<'a, I> { + fn from(id: Id<'a>) -> Index<'a, I> { Index::Id(id) } } -impl PartialEq for Index<'_> { - fn eq(&self, other: &Index<'_>) -> bool { +impl PartialEq for Index<'_, I> { + fn eq(&self, other: &Index<'_, I>) -> bool { match (self, other) { (Index::Num(a, _), Index::Num(b, _)) => a == b, (Index::Id(a), Index::Id(b)) => a == b, @@ -226,9 +234,9 @@ impl PartialEq for Index<'_> { } } -impl Eq for Index<'_> {} +impl Eq for Index<'_, I> {} -impl Hash for Index<'_> { +impl Hash for Index<'_, I> { fn hash(&self, hasher: &mut H) { match self { Index::Num(a, _) => { @@ -246,12 +254,15 @@ impl Hash for Index<'_> { /// Parses `(func $foo)` #[derive(Clone, Debug)] #[allow(missing_docs)] -pub struct ItemRef<'a, K> { +pub struct ItemRef<'a, K, I> { pub kind: K, - pub idx: Index<'a>, + pub idx: Index<'a, I>, } -impl<'a, K: Parse<'a>> Parse<'a> for ItemRef<'a, K> { +impl<'a, K: Parse<'a>, I> Parse<'a> for ItemRef<'a, K, I> +where + (I, Span): Parse<'a>, +{ fn parse(parser: Parser<'a>) -> Result { parser.parens(|parser| { let kind = parser.parse::()?; @@ -261,7 +272,7 @@ impl<'a, K: Parse<'a>> Parse<'a> for ItemRef<'a, K> { } } -impl<'a, K: Peek> Peek for ItemRef<'a, K> { +impl<'a, K: Peek, I> Peek for ItemRef<'a, K, I> { fn peek(cursor: Cursor<'_>) -> Result { match cursor.lparen()? { Some(remaining) => K::peek(remaining), @@ -347,6 +358,39 @@ integers! { i8(u8) i16(u16) i32(u32) i64(u64) } +macro_rules! indices { + ($($i:ident)*) => ($( + impl<'a> Parse<'a> for $i { + fn parse(parser: Parser<'a>) -> Result { + u32::parse(parser).map($i) + } + } + + impl<'a> Parse<'a> for ($i, Span) { + fn parse(parser: Parser<'a>) -> Result { + <(u32, Span)>::parse(parser).map(|(i, span)| ($i(i), span)) + } + } + + impl Peek for $i { + fn peek(cursor: Cursor<'_>) -> Result { + cursor.peek_integer() + } + + fn display() -> &'static str { + stringify!($i) + } + } + )*) +} + +indices! { + TypeIdx FuncIdx TableIdx MemIdx TagIdx GlobalIdx ElemIdx DataIdx LocalIdx LabelIdx FieldIdx + AbsoluteLabelIdx + CoreModuleIdx CoreInstanceIdx + ComponentTypeIdx ComponentFuncIdx ComponentIdx ComponentInstanceIdx ComponentValueIdx +} + impl<'a> Parse<'a> for &'a [u8] { fn parse(parser: Parser<'a>) -> Result { parser.step(|c| {