Skip to main content

wasmparser/
lib.rs

1/* Copyright 2017 Mozilla Foundation
2 *
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 *     http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16//! A simple event-driven library for parsing WebAssembly binary files
17//! (or streams).
18//!
19//! The parser library reports events as they happen and only stores
20//! parsing information for a brief period of time, making it very fast
21//! and memory-efficient. The event-driven model, however, has some drawbacks.
22//! If you need random access to the entire WebAssembly data-structure,
23//! this is not the right library for you. You could however, build such
24//! a data-structure using this library.
25//!
26//! To get started, create a [`Parser`] using [`Parser::new`] and then follow
27//! the examples documented for [`Parser::parse`] or [`Parser::parse_all`].
28
29#![deny(missing_docs)]
30#![no_std]
31#![cfg_attr(docsrs, feature(doc_cfg))]
32
33extern crate alloc;
34#[cfg(feature = "std")]
35#[macro_use]
36extern crate std;
37
38/// A small "prelude" to use throughout this crate.
39///
40/// This crate is tagged with `#![no_std]` meaning that we get libcore's prelude
41/// by default. This crate also uses `alloc`, however, and common types there
42/// like `String`. This custom prelude helps bring those types into scope to
43/// avoid having to import each of them manually.
44mod prelude {
45    pub use alloc::borrow::ToOwned;
46    pub use alloc::boxed::Box;
47    pub use alloc::format;
48    pub use alloc::string::{String, ToString};
49    pub use alloc::vec;
50    pub use alloc::vec::Vec;
51
52    #[cfg(all(feature = "validate", feature = "component-model"))]
53    pub use crate::collections::IndexSet;
54    #[cfg(feature = "validate")]
55    pub use crate::collections::{IndexMap, Map, Set};
56}
57
58/// A helper macro which is used to itself define further macros below.
59///
60/// This is a little complicated, so first off sorry about that. The idea here
61/// though is that there's one source of truth for the listing of instructions
62/// in `wasmparser` and this is the one location. All other locations should be
63/// derivative from this. As this one source of truth it has all instructions
64/// from all proposals all grouped together. Down below though, for compile
65/// time, currently the simd instructions are split out into their own macro.
66/// The structure/syntax of this macro is to facilitate easily splitting out
67/// entire groups of instructions.
68///
69/// This is used below to define more macros.
70macro_rules! _for_each_operator_group {
71    ($mac:ident) => {
72        $mac! {
73            @mvp {
74                Unreachable => visit_unreachable (arity 0 -> 0)
75                Nop => visit_nop (arity 0 -> 0)
76                Block { blockty: $crate::BlockType } => visit_block (arity custom)
77                Loop { blockty: $crate::BlockType } => visit_loop (arity custom)
78                If { blockty: $crate::BlockType } => visit_if (arity custom)
79                Else => visit_else (arity custom)
80                End => visit_end (arity custom)
81                Br { relative_depth: u32 } => visit_br (arity custom)
82                BrIf { relative_depth: u32 } => visit_br_if (arity custom)
83                BrTable { targets: $crate::BrTable<'a> } => visit_br_table (arity custom)
84                Return => visit_return (arity custom)
85                Call { function_index: u32 } => visit_call (arity custom)
86                CallIndirect { type_index: u32, table_index: u32 } => visit_call_indirect (arity custom)
87                Drop => visit_drop (arity 1 -> 0)
88                Select => visit_select (arity 3 -> 1)
89                LocalGet { local_index: u32 } => visit_local_get (arity 0 -> 1)
90                LocalSet { local_index: u32 } => visit_local_set (arity 1 -> 0)
91                LocalTee { local_index: u32 } => visit_local_tee (arity 1 -> 1)
92                GlobalGet { global_index: u32 } => visit_global_get (arity 0 -> 1)
93                GlobalSet { global_index: u32 } => visit_global_set (arity 1 -> 0)
94                I32Load { memarg: $crate::MemArg } => visit_i32_load (arity 1 -> 1)
95                I64Load { memarg: $crate::MemArg } => visit_i64_load (arity 1 -> 1)
96                F32Load { memarg: $crate::MemArg } => visit_f32_load (arity 1 -> 1)
97                F64Load { memarg: $crate::MemArg } => visit_f64_load (arity 1 -> 1)
98                I32Load8S { memarg: $crate::MemArg } => visit_i32_load8_s (arity 1 -> 1)
99                I32Load8U { memarg: $crate::MemArg } => visit_i32_load8_u (arity 1 -> 1)
100                I32Load16S { memarg: $crate::MemArg } => visit_i32_load16_s (arity 1 -> 1)
101                I32Load16U { memarg: $crate::MemArg } => visit_i32_load16_u (arity 1 -> 1)
102                I64Load8S { memarg: $crate::MemArg } => visit_i64_load8_s (arity 1 -> 1)
103                I64Load8U { memarg: $crate::MemArg } => visit_i64_load8_u (arity 1 -> 1)
104                I64Load16S { memarg: $crate::MemArg } => visit_i64_load16_s (arity 1 -> 1)
105                I64Load16U { memarg: $crate::MemArg } => visit_i64_load16_u (arity 1 -> 1)
106                I64Load32S { memarg: $crate::MemArg } => visit_i64_load32_s (arity 1 -> 1)
107                I64Load32U { memarg: $crate::MemArg } => visit_i64_load32_u (arity 1 -> 1)
108                I32Store { memarg: $crate::MemArg } => visit_i32_store (arity 2 -> 0)
109                I64Store { memarg: $crate::MemArg } => visit_i64_store (arity 2 -> 0)
110                F32Store { memarg: $crate::MemArg } => visit_f32_store (arity 2 -> 0)
111                F64Store { memarg: $crate::MemArg } => visit_f64_store (arity 2 -> 0)
112                I32Store8 { memarg: $crate::MemArg } => visit_i32_store8 (arity 2 -> 0)
113                I32Store16 { memarg: $crate::MemArg } => visit_i32_store16 (arity 2 -> 0)
114                I64Store8 { memarg: $crate::MemArg } => visit_i64_store8 (arity 2 -> 0)
115                I64Store16 { memarg: $crate::MemArg } => visit_i64_store16 (arity 2 -> 0)
116                I64Store32 { memarg: $crate::MemArg } => visit_i64_store32 (arity 2 -> 0)
117                MemorySize { mem: u32 } => visit_memory_size (arity 0 -> 1)
118                MemoryGrow { mem: u32 } => visit_memory_grow (arity 1 -> 1)
119                I32Const { value: i32 } => visit_i32_const (arity 0 -> 1)
120                I64Const { value: i64 } => visit_i64_const (arity 0 -> 1)
121                F32Const { value: $crate::Ieee32 } => visit_f32_const (arity 0 -> 1)
122                F64Const { value: $crate::Ieee64 } => visit_f64_const (arity 0 -> 1)
123                I32Eqz => visit_i32_eqz (arity 1 -> 1)
124                I32Eq => visit_i32_eq (arity 2 -> 1)
125                I32Ne => visit_i32_ne (arity 2 -> 1)
126                I32LtS => visit_i32_lt_s (arity 2 -> 1)
127                I32LtU => visit_i32_lt_u (arity 2 -> 1)
128                I32GtS => visit_i32_gt_s (arity 2 -> 1)
129                I32GtU => visit_i32_gt_u (arity 2 -> 1)
130                I32LeS => visit_i32_le_s (arity 2 -> 1)
131                I32LeU => visit_i32_le_u (arity 2 -> 1)
132                I32GeS => visit_i32_ge_s (arity 2 -> 1)
133                I32GeU => visit_i32_ge_u (arity 2 -> 1)
134                I64Eqz => visit_i64_eqz (arity 1 -> 1)
135                I64Eq => visit_i64_eq (arity 2 -> 1)
136                I64Ne => visit_i64_ne (arity 2 -> 1)
137                I64LtS => visit_i64_lt_s (arity 2 -> 1)
138                I64LtU => visit_i64_lt_u (arity 2 -> 1)
139                I64GtS => visit_i64_gt_s (arity 2 -> 1)
140                I64GtU => visit_i64_gt_u (arity 2 -> 1)
141                I64LeS => visit_i64_le_s (arity 2 -> 1)
142                I64LeU => visit_i64_le_u (arity 2 -> 1)
143                I64GeS => visit_i64_ge_s (arity 2 -> 1)
144                I64GeU => visit_i64_ge_u (arity 2 -> 1)
145                F32Eq => visit_f32_eq (arity 2 -> 1)
146                F32Ne => visit_f32_ne (arity 2 -> 1)
147                F32Lt => visit_f32_lt (arity 2 -> 1)
148                F32Gt => visit_f32_gt (arity 2 -> 1)
149                F32Le => visit_f32_le (arity 2 -> 1)
150                F32Ge => visit_f32_ge (arity 2 -> 1)
151                F64Eq => visit_f64_eq (arity 2 -> 1)
152                F64Ne => visit_f64_ne (arity 2 -> 1)
153                F64Lt => visit_f64_lt (arity 2 -> 1)
154                F64Gt => visit_f64_gt (arity 2 -> 1)
155                F64Le => visit_f64_le (arity 2 -> 1)
156                F64Ge => visit_f64_ge (arity 2 -> 1)
157                I32Clz => visit_i32_clz (arity 1 -> 1)
158                I32Ctz => visit_i32_ctz (arity 1 -> 1)
159                I32Popcnt => visit_i32_popcnt (arity 1 -> 1)
160                I32Add => visit_i32_add (arity 2 -> 1)
161                I32Sub => visit_i32_sub (arity 2 -> 1)
162                I32Mul => visit_i32_mul (arity 2 -> 1)
163                I32DivS => visit_i32_div_s (arity 2 -> 1)
164                I32DivU => visit_i32_div_u (arity 2 -> 1)
165                I32RemS => visit_i32_rem_s (arity 2 -> 1)
166                I32RemU => visit_i32_rem_u (arity 2 -> 1)
167                I32And => visit_i32_and (arity 2 -> 1)
168                I32Or => visit_i32_or (arity 2 -> 1)
169                I32Xor => visit_i32_xor (arity 2 -> 1)
170                I32Shl => visit_i32_shl (arity 2 -> 1)
171                I32ShrS => visit_i32_shr_s (arity 2 -> 1)
172                I32ShrU => visit_i32_shr_u (arity 2 -> 1)
173                I32Rotl => visit_i32_rotl (arity 2 -> 1)
174                I32Rotr => visit_i32_rotr (arity 2 -> 1)
175                I64Clz => visit_i64_clz (arity 1 -> 1)
176                I64Ctz => visit_i64_ctz (arity 1 -> 1)
177                I64Popcnt => visit_i64_popcnt (arity 1 -> 1)
178                I64Add => visit_i64_add (arity 2 -> 1)
179                I64Sub => visit_i64_sub (arity 2 -> 1)
180                I64Mul => visit_i64_mul (arity 2 -> 1)
181                I64DivS => visit_i64_div_s (arity 2 -> 1)
182                I64DivU => visit_i64_div_u (arity 2 -> 1)
183                I64RemS => visit_i64_rem_s (arity 2 -> 1)
184                I64RemU => visit_i64_rem_u (arity 2 -> 1)
185                I64And => visit_i64_and (arity 2 -> 1)
186                I64Or => visit_i64_or (arity 2 -> 1)
187                I64Xor => visit_i64_xor (arity 2 -> 1)
188                I64Shl => visit_i64_shl (arity 2 -> 1)
189                I64ShrS => visit_i64_shr_s (arity 2 -> 1)
190                I64ShrU => visit_i64_shr_u (arity 2 -> 1)
191                I64Rotl => visit_i64_rotl (arity 2 -> 1)
192                I64Rotr => visit_i64_rotr (arity 2 -> 1)
193                F32Abs => visit_f32_abs (arity 1 -> 1)
194                F32Neg => visit_f32_neg (arity 1 -> 1)
195                F32Ceil => visit_f32_ceil (arity 1 -> 1)
196                F32Floor => visit_f32_floor (arity 1 -> 1)
197                F32Trunc => visit_f32_trunc (arity 1 -> 1)
198                F32Nearest => visit_f32_nearest (arity 1 -> 1)
199                F32Sqrt => visit_f32_sqrt (arity 1 -> 1)
200                F32Add => visit_f32_add (arity 2 -> 1)
201                F32Sub => visit_f32_sub (arity 2 -> 1)
202                F32Mul => visit_f32_mul (arity 2 -> 1)
203                F32Div => visit_f32_div (arity 2 -> 1)
204                F32Min => visit_f32_min (arity 2 -> 1)
205                F32Max => visit_f32_max (arity 2 -> 1)
206                F32Copysign => visit_f32_copysign (arity 2 -> 1)
207                F64Abs => visit_f64_abs (arity 1 -> 1)
208                F64Neg => visit_f64_neg (arity 1 -> 1)
209                F64Ceil => visit_f64_ceil (arity 1 -> 1)
210                F64Floor => visit_f64_floor (arity 1 -> 1)
211                F64Trunc => visit_f64_trunc (arity 1 -> 1)
212                F64Nearest => visit_f64_nearest (arity 1 -> 1)
213                F64Sqrt => visit_f64_sqrt (arity 1 -> 1)
214                F64Add => visit_f64_add (arity 2 -> 1)
215                F64Sub => visit_f64_sub (arity 2 -> 1)
216                F64Mul => visit_f64_mul (arity 2 -> 1)
217                F64Div => visit_f64_div (arity 2 -> 1)
218                F64Min => visit_f64_min (arity 2 -> 1)
219                F64Max => visit_f64_max (arity 2 -> 1)
220                F64Copysign => visit_f64_copysign (arity 2 -> 1)
221                I32WrapI64 => visit_i32_wrap_i64 (arity 1 -> 1)
222                I32TruncF32S => visit_i32_trunc_f32_s (arity 1 -> 1)
223                I32TruncF32U => visit_i32_trunc_f32_u (arity 1 -> 1)
224                I32TruncF64S => visit_i32_trunc_f64_s (arity 1 -> 1)
225                I32TruncF64U => visit_i32_trunc_f64_u (arity 1 -> 1)
226                I64ExtendI32S => visit_i64_extend_i32_s (arity 1 -> 1)
227                I64ExtendI32U => visit_i64_extend_i32_u (arity 1 -> 1)
228                I64TruncF32S => visit_i64_trunc_f32_s (arity 1 -> 1)
229                I64TruncF32U => visit_i64_trunc_f32_u (arity 1 -> 1)
230                I64TruncF64S => visit_i64_trunc_f64_s (arity 1 -> 1)
231                I64TruncF64U => visit_i64_trunc_f64_u (arity 1 -> 1)
232                F32ConvertI32S => visit_f32_convert_i32_s (arity 1 -> 1)
233                F32ConvertI32U => visit_f32_convert_i32_u (arity 1 -> 1)
234                F32ConvertI64S => visit_f32_convert_i64_s (arity 1 -> 1)
235                F32ConvertI64U => visit_f32_convert_i64_u (arity 1 -> 1)
236                F32DemoteF64 => visit_f32_demote_f64 (arity 1 -> 1)
237                F64ConvertI32S => visit_f64_convert_i32_s (arity 1 -> 1)
238                F64ConvertI32U => visit_f64_convert_i32_u (arity 1 -> 1)
239                F64ConvertI64S => visit_f64_convert_i64_s (arity 1 -> 1)
240                F64ConvertI64U => visit_f64_convert_i64_u (arity 1 -> 1)
241                F64PromoteF32 => visit_f64_promote_f32 (arity 1 -> 1)
242                I32ReinterpretF32 => visit_i32_reinterpret_f32 (arity 1 -> 1)
243                I64ReinterpretF64 => visit_i64_reinterpret_f64 (arity 1 -> 1)
244                F32ReinterpretI32 => visit_f32_reinterpret_i32 (arity 1 -> 1)
245                F64ReinterpretI64 => visit_f64_reinterpret_i64 (arity 1 -> 1)
246            }
247
248            @sign_extension {
249                I32Extend8S => visit_i32_extend8_s (arity 1 -> 1)
250                I32Extend16S => visit_i32_extend16_s (arity 1 -> 1)
251                I64Extend8S => visit_i64_extend8_s (arity 1 -> 1)
252                I64Extend16S => visit_i64_extend16_s (arity 1 -> 1)
253                I64Extend32S => visit_i64_extend32_s (arity 1 -> 1)
254            }
255
256            // 0xFB prefixed operators
257            // Garbage Collection
258            // http://github.com/WebAssembly/gc
259            @gc {
260                RefEq => visit_ref_eq (arity 2 -> 1)
261                StructNew { struct_type_index: u32 } => visit_struct_new (arity custom)
262                StructNewDefault { struct_type_index: u32 } => visit_struct_new_default (arity 0 -> 1)
263                StructGet { struct_type_index: u32, field_index: u32 } => visit_struct_get (arity 1 -> 1)
264                StructGetS { struct_type_index: u32, field_index: u32 } => visit_struct_get_s (arity 1 -> 1)
265                StructGetU { struct_type_index: u32, field_index: u32 } => visit_struct_get_u (arity 1 -> 1)
266                StructSet { struct_type_index: u32, field_index: u32 } => visit_struct_set (arity 2 -> 0)
267                ArrayNew { array_type_index: u32 } => visit_array_new (arity 2 -> 1)
268                ArrayNewDefault { array_type_index: u32 } => visit_array_new_default (arity 1 -> 1)
269                ArrayNewFixed { array_type_index: u32, array_size: u32 } => visit_array_new_fixed (arity custom)
270                ArrayNewData { array_type_index: u32, array_data_index: u32 } => visit_array_new_data (arity 2 -> 1)
271                ArrayNewElem { array_type_index: u32, array_elem_index: u32 } => visit_array_new_elem (arity 2 -> 1)
272                ArrayGet { array_type_index: u32 } => visit_array_get (arity 2 -> 1)
273                ArrayGetS { array_type_index: u32 } => visit_array_get_s (arity 2 -> 1)
274                ArrayGetU { array_type_index: u32 } => visit_array_get_u (arity 2 -> 1)
275                ArraySet { array_type_index: u32 } => visit_array_set (arity 3 -> 0)
276                ArrayLen => visit_array_len (arity 1 -> 1)
277                ArrayFill { array_type_index: u32 } => visit_array_fill (arity 4 -> 0)
278                ArrayCopy { array_type_index_dst: u32, array_type_index_src: u32 } => visit_array_copy (arity 5 -> 0)
279                ArrayInitData { array_type_index: u32, array_data_index: u32 } => visit_array_init_data (arity 4 -> 0)
280                ArrayInitElem { array_type_index: u32, array_elem_index: u32 } => visit_array_init_elem (arity 4 -> 0)
281                RefTestNonNull { hty: $crate::HeapType } => visit_ref_test_non_null (arity 1 -> 1)
282                RefTestNullable { hty: $crate::HeapType } => visit_ref_test_nullable (arity 1 -> 1)
283                RefCastNonNull { hty: $crate::HeapType } => visit_ref_cast_non_null (arity 1 -> 1)
284                RefCastNullable { hty: $crate::HeapType } => visit_ref_cast_nullable (arity 1 -> 1)
285                BrOnCast {
286                    relative_depth: u32,
287                    from_ref_type: $crate::RefType,
288                    to_ref_type: $crate::RefType
289                } => visit_br_on_cast (arity custom)
290                BrOnCastFail {
291                    relative_depth: u32,
292                    from_ref_type: $crate::RefType,
293                    to_ref_type: $crate::RefType
294                } => visit_br_on_cast_fail (arity custom)
295                AnyConvertExtern => visit_any_convert_extern  (arity 1 -> 1)
296                ExternConvertAny => visit_extern_convert_any (arity 1 -> 1)
297                RefI31 => visit_ref_i31 (arity 1 -> 1)
298                I31GetS => visit_i31_get_s (arity 1 -> 1)
299                I31GetU => visit_i31_get_u (arity 1 -> 1)
300            }
301
302            @custom_descriptors {
303                StructNewDesc { struct_type_index: u32 } => visit_struct_new_desc (arity custom)
304                StructNewDefaultDesc { struct_type_index: u32 } => visit_struct_new_default_desc (arity 1 -> 1)
305                RefGetDesc { type_index: u32 } => visit_ref_get_desc (arity 1 -> 1)
306                RefCastDescEqNonNull { hty: $crate::HeapType } => visit_ref_cast_desc_eq_non_null (arity 2 -> 1)
307                RefCastDescEqNullable { hty: $crate::HeapType } => visit_ref_cast_desc_eq_nullable (arity 2 -> 1)
308                BrOnCastDescEq {
309                    relative_depth: u32,
310                    from_ref_type: $crate::RefType,
311                    to_ref_type: $crate::RefType
312                } => visit_br_on_cast_desc_eq (arity custom)
313                BrOnCastDescEqFail {
314                    relative_depth: u32,
315                    from_ref_type: $crate::RefType,
316                    to_ref_type: $crate::RefType
317                } => visit_br_on_cast_desc_eq_fail (arity custom)
318            }
319
320            // 0xFC operators
321            // Non-trapping Float-to-int Conversions
322            // https://github.com/WebAssembly/nontrapping-float-to-int-conversions
323            @saturating_float_to_int {
324                I32TruncSatF32S => visit_i32_trunc_sat_f32_s (arity 1 -> 1)
325                I32TruncSatF32U => visit_i32_trunc_sat_f32_u (arity 1 -> 1)
326                I32TruncSatF64S => visit_i32_trunc_sat_f64_s (arity 1 -> 1)
327                I32TruncSatF64U => visit_i32_trunc_sat_f64_u (arity 1 -> 1)
328                I64TruncSatF32S => visit_i64_trunc_sat_f32_s (arity 1 -> 1)
329                I64TruncSatF32U => visit_i64_trunc_sat_f32_u (arity 1 -> 1)
330                I64TruncSatF64S => visit_i64_trunc_sat_f64_s (arity 1 -> 1)
331                I64TruncSatF64U => visit_i64_trunc_sat_f64_u (arity 1 -> 1)
332            }
333
334            // 0xFC prefixed operators
335            // bulk memory operations
336            // https://github.com/WebAssembly/bulk-memory-operations
337            @bulk_memory {
338                MemoryInit { data_index: u32, mem: u32 } => visit_memory_init (arity 3 -> 0)
339                DataDrop { data_index: u32 } => visit_data_drop (arity 0 -> 0)
340                MemoryCopy { dst_mem: u32, src_mem: u32 } => visit_memory_copy (arity 3 -> 0)
341                MemoryFill { mem: u32 } => visit_memory_fill (arity 3 -> 0)
342                TableInit { elem_index: u32, table: u32 } => visit_table_init (arity 3 -> 0)
343                ElemDrop { elem_index: u32 } => visit_elem_drop (arity 0 -> 0)
344                TableCopy { dst_table: u32, src_table: u32 } => visit_table_copy (arity 3 -> 0)
345            }
346
347            // 0xFC prefixed operators
348            // reference-types
349            // https://github.com/WebAssembly/reference-types
350            @reference_types {
351                TypedSelect { ty: $crate::ValType } => visit_typed_select (arity 3 -> 1)
352                // multi-result select is currently invalid, but can be parsed and printed
353                TypedSelectMulti { tys: Vec<$crate::ValType> } => visit_typed_select_multi (arity custom)
354                RefNull { hty: $crate::HeapType } => visit_ref_null (arity 0 -> 1)
355                RefIsNull => visit_ref_is_null (arity 1 -> 1)
356                RefFunc { function_index: u32 } => visit_ref_func (arity 0 -> 1)
357                TableFill { table: u32 } => visit_table_fill (arity 3 -> 0)
358                TableGet { table: u32 } => visit_table_get (arity 1 -> 1)
359                TableSet { table: u32 } => visit_table_set (arity 2 -> 0)
360                TableGrow { table: u32 } => visit_table_grow (arity 2 -> 1)
361                TableSize { table: u32 } => visit_table_size (arity 0 -> 1)
362            }
363
364            // Wasm tail-call proposal
365            // https://github.com/WebAssembly/tail-call
366            @tail_call {
367                ReturnCall { function_index: u32 } => visit_return_call (arity custom)
368                ReturnCallIndirect { type_index: u32, table_index: u32 } => visit_return_call_indirect (arity custom)
369            }
370
371            // OxFC prefixed operators
372            // memory control (experimental)
373            // https://github.com/WebAssembly/design/issues/1439
374            @memory_control {
375                MemoryDiscard { mem: u32 } => visit_memory_discard (arity 2 -> 0)
376            }
377
378            // 0xFE prefixed operators
379            // threads
380            // https://github.com/WebAssembly/threads
381            @threads {
382                MemoryAtomicNotify { memarg: $crate::MemArg } => visit_memory_atomic_notify (arity 2 -> 1)
383                MemoryAtomicWait32 { memarg: $crate::MemArg } => visit_memory_atomic_wait32 (arity 3 -> 1)
384                MemoryAtomicWait64 { memarg: $crate::MemArg } => visit_memory_atomic_wait64 (arity 3 -> 1)
385                AtomicFence => visit_atomic_fence (arity 0 -> 0)
386                I32AtomicLoad { memarg: $crate::MemArg } => visit_i32_atomic_load (arity 1 -> 1)
387                I64AtomicLoad { memarg: $crate::MemArg } => visit_i64_atomic_load (arity 1 -> 1)
388                I32AtomicLoad8U { memarg: $crate::MemArg } => visit_i32_atomic_load8_u (arity 1 -> 1)
389                I32AtomicLoad16U { memarg: $crate::MemArg } => visit_i32_atomic_load16_u (arity 1 -> 1)
390                I64AtomicLoad8U { memarg: $crate::MemArg } => visit_i64_atomic_load8_u (arity 1 -> 1)
391                I64AtomicLoad16U { memarg: $crate::MemArg } => visit_i64_atomic_load16_u (arity 1 -> 1)
392                I64AtomicLoad32U { memarg: $crate::MemArg } => visit_i64_atomic_load32_u (arity 1 -> 1)
393                I32AtomicStore { memarg: $crate::MemArg } => visit_i32_atomic_store (arity 2 -> 0)
394                I64AtomicStore { memarg: $crate::MemArg } => visit_i64_atomic_store (arity 2 -> 0)
395                I32AtomicStore8 { memarg: $crate::MemArg } => visit_i32_atomic_store8 (arity 2 -> 0)
396                I32AtomicStore16 { memarg: $crate::MemArg } => visit_i32_atomic_store16 (arity 2 -> 0)
397                I64AtomicStore8 { memarg: $crate::MemArg } => visit_i64_atomic_store8 (arity 2 -> 0)
398                I64AtomicStore16 { memarg: $crate::MemArg } => visit_i64_atomic_store16 (arity 2 -> 0)
399                I64AtomicStore32 { memarg: $crate::MemArg } => visit_i64_atomic_store32 (arity 2 -> 0)
400                I32AtomicRmwAdd { memarg: $crate::MemArg } => visit_i32_atomic_rmw_add (arity 2 -> 1)
401                I64AtomicRmwAdd { memarg: $crate::MemArg } => visit_i64_atomic_rmw_add (arity 2 -> 1)
402                I32AtomicRmw8AddU { memarg: $crate::MemArg } => visit_i32_atomic_rmw8_add_u (arity 2 -> 1)
403                I32AtomicRmw16AddU { memarg: $crate::MemArg } => visit_i32_atomic_rmw16_add_u (arity 2 -> 1)
404                I64AtomicRmw8AddU { memarg: $crate::MemArg } => visit_i64_atomic_rmw8_add_u (arity 2 -> 1)
405                I64AtomicRmw16AddU { memarg: $crate::MemArg } => visit_i64_atomic_rmw16_add_u (arity 2 -> 1)
406                I64AtomicRmw32AddU { memarg: $crate::MemArg } => visit_i64_atomic_rmw32_add_u (arity 2 -> 1)
407                I32AtomicRmwSub { memarg: $crate::MemArg } => visit_i32_atomic_rmw_sub (arity 2 -> 1)
408                I64AtomicRmwSub { memarg: $crate::MemArg } => visit_i64_atomic_rmw_sub (arity 2 -> 1)
409                I32AtomicRmw8SubU { memarg: $crate::MemArg } => visit_i32_atomic_rmw8_sub_u (arity 2 -> 1)
410                I32AtomicRmw16SubU { memarg: $crate::MemArg } => visit_i32_atomic_rmw16_sub_u (arity 2 -> 1)
411                I64AtomicRmw8SubU { memarg: $crate::MemArg } => visit_i64_atomic_rmw8_sub_u (arity 2 -> 1)
412                I64AtomicRmw16SubU { memarg: $crate::MemArg } => visit_i64_atomic_rmw16_sub_u (arity 2 -> 1)
413                I64AtomicRmw32SubU { memarg: $crate::MemArg } => visit_i64_atomic_rmw32_sub_u (arity 2 -> 1)
414                I32AtomicRmwAnd { memarg: $crate::MemArg } => visit_i32_atomic_rmw_and (arity 2 -> 1)
415                I64AtomicRmwAnd { memarg: $crate::MemArg } => visit_i64_atomic_rmw_and (arity 2 -> 1)
416                I32AtomicRmw8AndU { memarg: $crate::MemArg } => visit_i32_atomic_rmw8_and_u (arity 2 -> 1)
417                I32AtomicRmw16AndU { memarg: $crate::MemArg } => visit_i32_atomic_rmw16_and_u (arity 2 -> 1)
418                I64AtomicRmw8AndU { memarg: $crate::MemArg } => visit_i64_atomic_rmw8_and_u (arity 2 -> 1)
419                I64AtomicRmw16AndU { memarg: $crate::MemArg } => visit_i64_atomic_rmw16_and_u (arity 2 -> 1)
420                I64AtomicRmw32AndU { memarg: $crate::MemArg } => visit_i64_atomic_rmw32_and_u (arity 2 -> 1)
421                I32AtomicRmwOr { memarg: $crate::MemArg } => visit_i32_atomic_rmw_or (arity 2 -> 1)
422                I64AtomicRmwOr { memarg: $crate::MemArg } => visit_i64_atomic_rmw_or (arity 2 -> 1)
423                I32AtomicRmw8OrU { memarg: $crate::MemArg } => visit_i32_atomic_rmw8_or_u (arity 2 -> 1)
424                I32AtomicRmw16OrU { memarg: $crate::MemArg } => visit_i32_atomic_rmw16_or_u (arity 2 -> 1)
425                I64AtomicRmw8OrU { memarg: $crate::MemArg } => visit_i64_atomic_rmw8_or_u (arity 2 -> 1)
426                I64AtomicRmw16OrU { memarg: $crate::MemArg } => visit_i64_atomic_rmw16_or_u (arity 2 -> 1)
427                I64AtomicRmw32OrU { memarg: $crate::MemArg } => visit_i64_atomic_rmw32_or_u (arity 2 -> 1)
428                I32AtomicRmwXor { memarg: $crate::MemArg } => visit_i32_atomic_rmw_xor (arity 2 -> 1)
429                I64AtomicRmwXor { memarg: $crate::MemArg } => visit_i64_atomic_rmw_xor (arity 2 -> 1)
430                I32AtomicRmw8XorU { memarg: $crate::MemArg } => visit_i32_atomic_rmw8_xor_u (arity 2 -> 1)
431                I32AtomicRmw16XorU { memarg: $crate::MemArg } => visit_i32_atomic_rmw16_xor_u (arity 2 -> 1)
432                I64AtomicRmw8XorU { memarg: $crate::MemArg } => visit_i64_atomic_rmw8_xor_u (arity 2 -> 1)
433                I64AtomicRmw16XorU { memarg: $crate::MemArg } => visit_i64_atomic_rmw16_xor_u (arity 2 -> 1)
434                I64AtomicRmw32XorU { memarg: $crate::MemArg } => visit_i64_atomic_rmw32_xor_u (arity 2 -> 1)
435                I32AtomicRmwXchg { memarg: $crate::MemArg } => visit_i32_atomic_rmw_xchg (arity 2 -> 1)
436                I64AtomicRmwXchg { memarg: $crate::MemArg } => visit_i64_atomic_rmw_xchg (arity 2 -> 1)
437                I32AtomicRmw8XchgU { memarg: $crate::MemArg } => visit_i32_atomic_rmw8_xchg_u (arity 2 -> 1)
438                I32AtomicRmw16XchgU { memarg: $crate::MemArg } => visit_i32_atomic_rmw16_xchg_u (arity 2 -> 1)
439                I64AtomicRmw8XchgU { memarg: $crate::MemArg } => visit_i64_atomic_rmw8_xchg_u (arity 2 -> 1)
440                I64AtomicRmw16XchgU { memarg: $crate::MemArg } => visit_i64_atomic_rmw16_xchg_u (arity 2 -> 1)
441                I64AtomicRmw32XchgU { memarg: $crate::MemArg } => visit_i64_atomic_rmw32_xchg_u (arity 2 -> 1)
442                I32AtomicRmwCmpxchg { memarg: $crate::MemArg } => visit_i32_atomic_rmw_cmpxchg (arity 3 -> 1)
443                I64AtomicRmwCmpxchg { memarg: $crate::MemArg } => visit_i64_atomic_rmw_cmpxchg (arity 3 -> 1)
444                I32AtomicRmw8CmpxchgU { memarg: $crate::MemArg } => visit_i32_atomic_rmw8_cmpxchg_u (arity 3 -> 1)
445                I32AtomicRmw16CmpxchgU { memarg: $crate::MemArg } => visit_i32_atomic_rmw16_cmpxchg_u (arity 3 -> 1)
446                I64AtomicRmw8CmpxchgU { memarg: $crate::MemArg } => visit_i64_atomic_rmw8_cmpxchg_u (arity 3 -> 1)
447                I64AtomicRmw16CmpxchgU { memarg: $crate::MemArg } => visit_i64_atomic_rmw16_cmpxchg_u (arity 3 -> 1)
448                I64AtomicRmw32CmpxchgU { memarg: $crate::MemArg } => visit_i64_atomic_rmw32_cmpxchg_u (arity 3 -> 1)
449            }
450
451            // 0xFD operators
452            // 128-bit SIMD
453            // - https://github.com/webassembly/simd
454            // - https://webassembly.github.io/simd/core/binary/instructions.html
455            @simd {
456                V128Load { memarg: $crate::MemArg } => visit_v128_load (arity 1 -> 1)
457                V128Load8x8S { memarg: $crate::MemArg } => visit_v128_load8x8_s (arity 1 -> 1)
458                V128Load8x8U { memarg: $crate::MemArg } => visit_v128_load8x8_u (arity 1 -> 1)
459                V128Load16x4S { memarg: $crate::MemArg } => visit_v128_load16x4_s (arity 1 -> 1)
460                V128Load16x4U { memarg: $crate::MemArg } => visit_v128_load16x4_u (arity 1 -> 1)
461                V128Load32x2S { memarg: $crate::MemArg } => visit_v128_load32x2_s (arity 1 -> 1)
462                V128Load32x2U { memarg: $crate::MemArg } => visit_v128_load32x2_u (arity 1 -> 1)
463                V128Load8Splat { memarg: $crate::MemArg } => visit_v128_load8_splat (arity 1 -> 1)
464                V128Load16Splat { memarg: $crate::MemArg } => visit_v128_load16_splat (arity 1 -> 1)
465                V128Load32Splat { memarg: $crate::MemArg } => visit_v128_load32_splat (arity 1 -> 1)
466                V128Load64Splat { memarg: $crate::MemArg } => visit_v128_load64_splat (arity 1 -> 1)
467                V128Load32Zero { memarg: $crate::MemArg } => visit_v128_load32_zero (arity 1 -> 1)
468                V128Load64Zero { memarg: $crate::MemArg } => visit_v128_load64_zero (arity 1 -> 1)
469                V128Store { memarg: $crate::MemArg } => visit_v128_store (arity 2 -> 0)
470                V128Load8Lane { memarg: $crate::MemArg, lane: u8 } => visit_v128_load8_lane (arity 2 -> 1)
471                V128Load16Lane { memarg: $crate::MemArg, lane: u8 } => visit_v128_load16_lane (arity 2 -> 1)
472                V128Load32Lane { memarg: $crate::MemArg, lane: u8 } => visit_v128_load32_lane (arity 2 -> 1)
473                V128Load64Lane { memarg: $crate::MemArg, lane: u8 } => visit_v128_load64_lane (arity 2 -> 1)
474                V128Store8Lane { memarg: $crate::MemArg, lane: u8 } => visit_v128_store8_lane (arity 2 -> 0)
475                V128Store16Lane { memarg: $crate::MemArg, lane: u8 } => visit_v128_store16_lane (arity 2 -> 0)
476                V128Store32Lane { memarg: $crate::MemArg, lane: u8 } => visit_v128_store32_lane (arity 2 -> 0)
477                V128Store64Lane { memarg: $crate::MemArg, lane: u8 } => visit_v128_store64_lane (arity 2 -> 0)
478                V128Const { value: $crate::V128 } => visit_v128_const (arity 0 -> 1)
479                I8x16Shuffle { lanes: [u8; 16] } => visit_i8x16_shuffle (arity 2 -> 1)
480                I8x16ExtractLaneS { lane: u8 } => visit_i8x16_extract_lane_s (arity 1 -> 1)
481                I8x16ExtractLaneU { lane: u8 } => visit_i8x16_extract_lane_u (arity 1 -> 1)
482                I8x16ReplaceLane { lane: u8 } => visit_i8x16_replace_lane (arity 2 -> 1)
483                I16x8ExtractLaneS { lane: u8 } => visit_i16x8_extract_lane_s (arity 1 -> 1)
484                I16x8ExtractLaneU { lane: u8 } => visit_i16x8_extract_lane_u (arity 1 -> 1)
485                I16x8ReplaceLane { lane: u8 } => visit_i16x8_replace_lane (arity 2 -> 1)
486                I32x4ExtractLane { lane: u8 } => visit_i32x4_extract_lane (arity 1 -> 1)
487                I32x4ReplaceLane { lane: u8 } => visit_i32x4_replace_lane (arity 2 -> 1)
488                I64x2ExtractLane { lane: u8 } => visit_i64x2_extract_lane (arity 1 -> 1)
489                I64x2ReplaceLane { lane: u8 } => visit_i64x2_replace_lane (arity 2 -> 1)
490                F32x4ExtractLane { lane: u8 } => visit_f32x4_extract_lane (arity 1 -> 1)
491                F32x4ReplaceLane { lane: u8 } => visit_f32x4_replace_lane (arity 2 -> 1)
492                F64x2ExtractLane { lane: u8 } => visit_f64x2_extract_lane (arity 1 -> 1)
493                F64x2ReplaceLane { lane: u8 } => visit_f64x2_replace_lane (arity 2 -> 1)
494                I8x16Swizzle => visit_i8x16_swizzle (arity 2 -> 1)
495                I8x16Splat => visit_i8x16_splat (arity 1 -> 1)
496                I16x8Splat => visit_i16x8_splat (arity 1 -> 1)
497                I32x4Splat => visit_i32x4_splat (arity 1 -> 1)
498                I64x2Splat => visit_i64x2_splat (arity 1 -> 1)
499                F32x4Splat => visit_f32x4_splat (arity 1 -> 1)
500                F64x2Splat => visit_f64x2_splat (arity 1 -> 1)
501                I8x16Eq => visit_i8x16_eq (arity 2 -> 1)
502                I8x16Ne => visit_i8x16_ne (arity 2 -> 1)
503                I8x16LtS => visit_i8x16_lt_s (arity 2 -> 1)
504                I8x16LtU => visit_i8x16_lt_u (arity 2 -> 1)
505                I8x16GtS => visit_i8x16_gt_s (arity 2 -> 1)
506                I8x16GtU => visit_i8x16_gt_u (arity 2 -> 1)
507                I8x16LeS => visit_i8x16_le_s (arity 2 -> 1)
508                I8x16LeU => visit_i8x16_le_u (arity 2 -> 1)
509                I8x16GeS => visit_i8x16_ge_s (arity 2 -> 1)
510                I8x16GeU => visit_i8x16_ge_u (arity 2 -> 1)
511                I16x8Eq => visit_i16x8_eq (arity 2 -> 1)
512                I16x8Ne => visit_i16x8_ne (arity 2 -> 1)
513                I16x8LtS => visit_i16x8_lt_s (arity 2 -> 1)
514                I16x8LtU => visit_i16x8_lt_u (arity 2 -> 1)
515                I16x8GtS => visit_i16x8_gt_s (arity 2 -> 1)
516                I16x8GtU => visit_i16x8_gt_u (arity 2 -> 1)
517                I16x8LeS => visit_i16x8_le_s (arity 2 -> 1)
518                I16x8LeU => visit_i16x8_le_u (arity 2 -> 1)
519                I16x8GeS => visit_i16x8_ge_s (arity 2 -> 1)
520                I16x8GeU => visit_i16x8_ge_u (arity 2 -> 1)
521                I32x4Eq => visit_i32x4_eq (arity 2 -> 1)
522                I32x4Ne => visit_i32x4_ne (arity 2 -> 1)
523                I32x4LtS => visit_i32x4_lt_s (arity 2 -> 1)
524                I32x4LtU => visit_i32x4_lt_u (arity 2 -> 1)
525                I32x4GtS => visit_i32x4_gt_s (arity 2 -> 1)
526                I32x4GtU => visit_i32x4_gt_u (arity 2 -> 1)
527                I32x4LeS => visit_i32x4_le_s (arity 2 -> 1)
528                I32x4LeU => visit_i32x4_le_u (arity 2 -> 1)
529                I32x4GeS => visit_i32x4_ge_s (arity 2 -> 1)
530                I32x4GeU => visit_i32x4_ge_u (arity 2 -> 1)
531                I64x2Eq => visit_i64x2_eq (arity 2 -> 1)
532                I64x2Ne => visit_i64x2_ne (arity 2 -> 1)
533                I64x2LtS => visit_i64x2_lt_s (arity 2 -> 1)
534                I64x2GtS => visit_i64x2_gt_s (arity 2 -> 1)
535                I64x2LeS => visit_i64x2_le_s (arity 2 -> 1)
536                I64x2GeS => visit_i64x2_ge_s (arity 2 -> 1)
537                F32x4Eq => visit_f32x4_eq (arity 2 -> 1)
538                F32x4Ne => visit_f32x4_ne (arity 2 -> 1)
539                F32x4Lt => visit_f32x4_lt (arity 2 -> 1)
540                F32x4Gt => visit_f32x4_gt (arity 2 -> 1)
541                F32x4Le => visit_f32x4_le (arity 2 -> 1)
542                F32x4Ge => visit_f32x4_ge (arity 2 -> 1)
543                F64x2Eq => visit_f64x2_eq (arity 2 -> 1)
544                F64x2Ne => visit_f64x2_ne (arity 2 -> 1)
545                F64x2Lt => visit_f64x2_lt (arity 2 -> 1)
546                F64x2Gt => visit_f64x2_gt (arity 2 -> 1)
547                F64x2Le => visit_f64x2_le (arity 2 -> 1)
548                F64x2Ge => visit_f64x2_ge (arity 2 -> 1)
549                V128Not => visit_v128_not (arity 1 -> 1)
550                V128And => visit_v128_and (arity 2 -> 1)
551                V128AndNot => visit_v128_andnot (arity 2 -> 1)
552                V128Or => visit_v128_or (arity 2 -> 1)
553                V128Xor => visit_v128_xor (arity 2 -> 1)
554                V128Bitselect => visit_v128_bitselect (arity 3 -> 1)
555                V128AnyTrue => visit_v128_any_true (arity 1 -> 1)
556                I8x16Abs => visit_i8x16_abs (arity 1 -> 1)
557                I8x16Neg => visit_i8x16_neg (arity 1 -> 1)
558                I8x16Popcnt => visit_i8x16_popcnt (arity 1 -> 1)
559                I8x16AllTrue => visit_i8x16_all_true (arity 1 -> 1)
560                I8x16Bitmask => visit_i8x16_bitmask (arity 1 -> 1)
561                I8x16NarrowI16x8S => visit_i8x16_narrow_i16x8_s (arity 2 -> 1)
562                I8x16NarrowI16x8U => visit_i8x16_narrow_i16x8_u (arity 2 -> 1)
563                I8x16Shl => visit_i8x16_shl (arity 2 -> 1)
564                I8x16ShrS => visit_i8x16_shr_s (arity 2 -> 1)
565                I8x16ShrU => visit_i8x16_shr_u (arity 2 -> 1)
566                I8x16Add => visit_i8x16_add (arity 2 -> 1)
567                I8x16AddSatS => visit_i8x16_add_sat_s (arity 2 -> 1)
568                I8x16AddSatU => visit_i8x16_add_sat_u (arity 2 -> 1)
569                I8x16Sub => visit_i8x16_sub (arity 2 -> 1)
570                I8x16SubSatS => visit_i8x16_sub_sat_s (arity 2 -> 1)
571                I8x16SubSatU => visit_i8x16_sub_sat_u (arity 2 -> 1)
572                I8x16MinS => visit_i8x16_min_s (arity 2 -> 1)
573                I8x16MinU => visit_i8x16_min_u (arity 2 -> 1)
574                I8x16MaxS => visit_i8x16_max_s (arity 2 -> 1)
575                I8x16MaxU => visit_i8x16_max_u (arity 2 -> 1)
576                I8x16AvgrU => visit_i8x16_avgr_u (arity 2 -> 1)
577                I16x8ExtAddPairwiseI8x16S => visit_i16x8_extadd_pairwise_i8x16_s (arity 1 -> 1)
578                I16x8ExtAddPairwiseI8x16U => visit_i16x8_extadd_pairwise_i8x16_u (arity 1 -> 1)
579                I16x8Abs => visit_i16x8_abs (arity 1 -> 1)
580                I16x8Neg => visit_i16x8_neg (arity 1 -> 1)
581                I16x8Q15MulrSatS => visit_i16x8_q15mulr_sat_s (arity 2 -> 1)
582                I16x8AllTrue => visit_i16x8_all_true (arity 1 -> 1)
583                I16x8Bitmask => visit_i16x8_bitmask (arity 1 -> 1)
584                I16x8NarrowI32x4S => visit_i16x8_narrow_i32x4_s (arity 2 -> 1)
585                I16x8NarrowI32x4U => visit_i16x8_narrow_i32x4_u (arity 2 -> 1)
586                I16x8ExtendLowI8x16S => visit_i16x8_extend_low_i8x16_s (arity 1 -> 1)
587                I16x8ExtendHighI8x16S => visit_i16x8_extend_high_i8x16_s (arity 1 -> 1)
588                I16x8ExtendLowI8x16U => visit_i16x8_extend_low_i8x16_u (arity 1 -> 1)
589                I16x8ExtendHighI8x16U => visit_i16x8_extend_high_i8x16_u (arity 1 -> 1)
590                I16x8Shl => visit_i16x8_shl (arity 2 -> 1)
591                I16x8ShrS => visit_i16x8_shr_s (arity 2 -> 1)
592                I16x8ShrU => visit_i16x8_shr_u (arity 2 -> 1)
593                I16x8Add => visit_i16x8_add (arity 2 -> 1)
594                I16x8AddSatS => visit_i16x8_add_sat_s (arity 2 -> 1)
595                I16x8AddSatU => visit_i16x8_add_sat_u (arity 2 -> 1)
596                I16x8Sub => visit_i16x8_sub (arity 2 -> 1)
597                I16x8SubSatS => visit_i16x8_sub_sat_s (arity 2 -> 1)
598                I16x8SubSatU => visit_i16x8_sub_sat_u (arity 2 -> 1)
599                I16x8Mul => visit_i16x8_mul (arity 2 -> 1)
600                I16x8MinS => visit_i16x8_min_s (arity 2 -> 1)
601                I16x8MinU => visit_i16x8_min_u (arity 2 -> 1)
602                I16x8MaxS => visit_i16x8_max_s (arity 2 -> 1)
603                I16x8MaxU => visit_i16x8_max_u (arity 2 -> 1)
604                I16x8AvgrU => visit_i16x8_avgr_u (arity 2 -> 1)
605                I16x8ExtMulLowI8x16S => visit_i16x8_extmul_low_i8x16_s (arity 2 -> 1)
606                I16x8ExtMulHighI8x16S => visit_i16x8_extmul_high_i8x16_s (arity 2 -> 1)
607                I16x8ExtMulLowI8x16U => visit_i16x8_extmul_low_i8x16_u (arity 2 -> 1)
608                I16x8ExtMulHighI8x16U => visit_i16x8_extmul_high_i8x16_u (arity 2 -> 1)
609                I32x4ExtAddPairwiseI16x8S => visit_i32x4_extadd_pairwise_i16x8_s (arity 1 -> 1)
610                I32x4ExtAddPairwiseI16x8U => visit_i32x4_extadd_pairwise_i16x8_u (arity 1 -> 1)
611                I32x4Abs => visit_i32x4_abs (arity 1 -> 1)
612                I32x4Neg => visit_i32x4_neg (arity 1 -> 1)
613                I32x4AllTrue => visit_i32x4_all_true (arity 1 -> 1)
614                I32x4Bitmask => visit_i32x4_bitmask (arity 1 -> 1)
615                I32x4ExtendLowI16x8S => visit_i32x4_extend_low_i16x8_s (arity 1 -> 1)
616                I32x4ExtendHighI16x8S => visit_i32x4_extend_high_i16x8_s (arity 1 -> 1)
617                I32x4ExtendLowI16x8U => visit_i32x4_extend_low_i16x8_u (arity 1 -> 1)
618                I32x4ExtendHighI16x8U => visit_i32x4_extend_high_i16x8_u (arity 1 -> 1)
619                I32x4Shl => visit_i32x4_shl (arity 2 -> 1)
620                I32x4ShrS => visit_i32x4_shr_s (arity 2 -> 1)
621                I32x4ShrU => visit_i32x4_shr_u (arity 2 -> 1)
622                I32x4Add => visit_i32x4_add (arity 2 -> 1)
623                I32x4Sub => visit_i32x4_sub (arity 2 -> 1)
624                I32x4Mul => visit_i32x4_mul (arity 2 -> 1)
625                I32x4MinS => visit_i32x4_min_s (arity 2 -> 1)
626                I32x4MinU => visit_i32x4_min_u (arity 2 -> 1)
627                I32x4MaxS => visit_i32x4_max_s (arity 2 -> 1)
628                I32x4MaxU => visit_i32x4_max_u (arity 2 -> 1)
629                I32x4DotI16x8S => visit_i32x4_dot_i16x8_s (arity 2 -> 1)
630                I32x4ExtMulLowI16x8S => visit_i32x4_extmul_low_i16x8_s (arity 2 -> 1)
631                I32x4ExtMulHighI16x8S => visit_i32x4_extmul_high_i16x8_s (arity 2 -> 1)
632                I32x4ExtMulLowI16x8U => visit_i32x4_extmul_low_i16x8_u (arity 2 -> 1)
633                I32x4ExtMulHighI16x8U => visit_i32x4_extmul_high_i16x8_u (arity 2 -> 1)
634                I64x2Abs => visit_i64x2_abs (arity 1 -> 1)
635                I64x2Neg => visit_i64x2_neg (arity 1 -> 1)
636                I64x2AllTrue => visit_i64x2_all_true (arity 1 -> 1)
637                I64x2Bitmask => visit_i64x2_bitmask (arity 1 -> 1)
638                I64x2ExtendLowI32x4S => visit_i64x2_extend_low_i32x4_s (arity 1 -> 1)
639                I64x2ExtendHighI32x4S => visit_i64x2_extend_high_i32x4_s (arity 1 -> 1)
640                I64x2ExtendLowI32x4U => visit_i64x2_extend_low_i32x4_u (arity 1 -> 1)
641                I64x2ExtendHighI32x4U => visit_i64x2_extend_high_i32x4_u (arity 1 -> 1)
642                I64x2Shl => visit_i64x2_shl (arity 2 -> 1)
643                I64x2ShrS => visit_i64x2_shr_s (arity 2 -> 1)
644                I64x2ShrU => visit_i64x2_shr_u (arity 2 -> 1)
645                I64x2Add => visit_i64x2_add (arity 2 -> 1)
646                I64x2Sub => visit_i64x2_sub (arity 2 -> 1)
647                I64x2Mul => visit_i64x2_mul (arity 2 -> 1)
648                I64x2ExtMulLowI32x4S => visit_i64x2_extmul_low_i32x4_s (arity 2 -> 1)
649                I64x2ExtMulHighI32x4S => visit_i64x2_extmul_high_i32x4_s (arity 2 -> 1)
650                I64x2ExtMulLowI32x4U => visit_i64x2_extmul_low_i32x4_u (arity 2 -> 1)
651                I64x2ExtMulHighI32x4U => visit_i64x2_extmul_high_i32x4_u (arity 2 -> 1)
652                F32x4Ceil => visit_f32x4_ceil (arity 1 -> 1)
653                F32x4Floor => visit_f32x4_floor (arity 1 -> 1)
654                F32x4Trunc => visit_f32x4_trunc (arity 1 -> 1)
655                F32x4Nearest => visit_f32x4_nearest (arity 1 -> 1)
656                F32x4Abs => visit_f32x4_abs (arity 1 -> 1)
657                F32x4Neg => visit_f32x4_neg (arity 1 -> 1)
658                F32x4Sqrt => visit_f32x4_sqrt (arity 1 -> 1)
659                F32x4Add => visit_f32x4_add (arity 2 -> 1)
660                F32x4Sub => visit_f32x4_sub (arity 2 -> 1)
661                F32x4Mul => visit_f32x4_mul (arity 2 -> 1)
662                F32x4Div => visit_f32x4_div (arity 2 -> 1)
663                F32x4Min => visit_f32x4_min (arity 2 -> 1)
664                F32x4Max => visit_f32x4_max (arity 2 -> 1)
665                F32x4PMin => visit_f32x4_pmin (arity 2 -> 1)
666                F32x4PMax => visit_f32x4_pmax (arity 2 -> 1)
667                F64x2Ceil => visit_f64x2_ceil (arity 1 -> 1)
668                F64x2Floor => visit_f64x2_floor (arity 1 -> 1)
669                F64x2Trunc => visit_f64x2_trunc (arity 1 -> 1)
670                F64x2Nearest => visit_f64x2_nearest (arity 1 -> 1)
671                F64x2Abs => visit_f64x2_abs (arity 1 -> 1)
672                F64x2Neg => visit_f64x2_neg (arity 1 -> 1)
673                F64x2Sqrt => visit_f64x2_sqrt (arity 1 -> 1)
674                F64x2Add => visit_f64x2_add (arity 2 -> 1)
675                F64x2Sub => visit_f64x2_sub (arity 2 -> 1)
676                F64x2Mul => visit_f64x2_mul (arity 2 -> 1)
677                F64x2Div => visit_f64x2_div (arity 2 -> 1)
678                F64x2Min => visit_f64x2_min (arity 2 -> 1)
679                F64x2Max => visit_f64x2_max (arity 2 -> 1)
680                F64x2PMin => visit_f64x2_pmin (arity 2 -> 1)
681                F64x2PMax => visit_f64x2_pmax (arity 2 -> 1)
682                I32x4TruncSatF32x4S => visit_i32x4_trunc_sat_f32x4_s (arity 1 -> 1)
683                I32x4TruncSatF32x4U => visit_i32x4_trunc_sat_f32x4_u (arity 1 -> 1)
684                F32x4ConvertI32x4S => visit_f32x4_convert_i32x4_s (arity 1 -> 1)
685                F32x4ConvertI32x4U => visit_f32x4_convert_i32x4_u (arity 1 -> 1)
686                I32x4TruncSatF64x2SZero => visit_i32x4_trunc_sat_f64x2_s_zero (arity 1 -> 1)
687                I32x4TruncSatF64x2UZero => visit_i32x4_trunc_sat_f64x2_u_zero (arity 1 -> 1)
688                F64x2ConvertLowI32x4S => visit_f64x2_convert_low_i32x4_s (arity 1 -> 1)
689                F64x2ConvertLowI32x4U => visit_f64x2_convert_low_i32x4_u (arity 1 -> 1)
690                F32x4DemoteF64x2Zero => visit_f32x4_demote_f64x2_zero (arity 1 -> 1)
691                F64x2PromoteLowF32x4 => visit_f64x2_promote_low_f32x4 (arity 1 -> 1)
692            }
693
694            // Relaxed SIMD operators
695            // https://github.com/WebAssembly/relaxed-simd
696            @relaxed_simd {
697                I8x16RelaxedSwizzle => visit_i8x16_relaxed_swizzle (arity 2 -> 1)
698                I32x4RelaxedTruncF32x4S => visit_i32x4_relaxed_trunc_f32x4_s (arity 1 -> 1)
699                I32x4RelaxedTruncF32x4U => visit_i32x4_relaxed_trunc_f32x4_u (arity 1 -> 1)
700                I32x4RelaxedTruncF64x2SZero => visit_i32x4_relaxed_trunc_f64x2_s_zero (arity 1 -> 1)
701                I32x4RelaxedTruncF64x2UZero => visit_i32x4_relaxed_trunc_f64x2_u_zero (arity 1 -> 1)
702                F32x4RelaxedMadd => visit_f32x4_relaxed_madd (arity 3 -> 1)
703                F32x4RelaxedNmadd => visit_f32x4_relaxed_nmadd (arity 3 -> 1)
704                F64x2RelaxedMadd => visit_f64x2_relaxed_madd  (arity 3 -> 1)
705                F64x2RelaxedNmadd => visit_f64x2_relaxed_nmadd (arity 3 -> 1)
706                I8x16RelaxedLaneselect => visit_i8x16_relaxed_laneselect (arity 3 -> 1)
707                I16x8RelaxedLaneselect => visit_i16x8_relaxed_laneselect (arity 3 -> 1)
708                I32x4RelaxedLaneselect => visit_i32x4_relaxed_laneselect (arity 3 -> 1)
709                I64x2RelaxedLaneselect => visit_i64x2_relaxed_laneselect (arity 3 -> 1)
710                F32x4RelaxedMin => visit_f32x4_relaxed_min (arity 2 -> 1)
711                F32x4RelaxedMax => visit_f32x4_relaxed_max (arity 2 -> 1)
712                F64x2RelaxedMin => visit_f64x2_relaxed_min (arity 2 -> 1)
713                F64x2RelaxedMax => visit_f64x2_relaxed_max (arity 2 -> 1)
714                I16x8RelaxedQ15mulrS => visit_i16x8_relaxed_q15mulr_s (arity 2 -> 1)
715                I16x8RelaxedDotI8x16I7x16S => visit_i16x8_relaxed_dot_i8x16_i7x16_s (arity 2 -> 1)
716                I32x4RelaxedDotI8x16I7x16AddS => visit_i32x4_relaxed_dot_i8x16_i7x16_add_s (arity 3 -> 1)
717            }
718
719            @exceptions {
720                TryTable { try_table: $crate::TryTable } => visit_try_table (arity custom)
721                Throw { tag_index: u32 } => visit_throw (arity custom)
722                ThrowRef => visit_throw_ref (arity 1 -> 0)
723            }
724            // Deprecated old instructions from the exceptions proposal
725            @legacy_exceptions {
726                Try { blockty: $crate::BlockType } => visit_try (arity custom)
727                Catch { tag_index: u32 } => visit_catch (arity custom)
728                Rethrow { relative_depth: u32 } => visit_rethrow (arity 0 -> 0)
729                Delegate { relative_depth: u32 } => visit_delegate (arity custom)
730                CatchAll => visit_catch_all (arity custom)
731            }
732
733            // Also 0xFE prefixed operators
734            // shared-everything threads
735            // https://github.com/WebAssembly/shared-everything-threads
736            @shared_everything_threads {
737                GlobalAtomicGet { ordering: $crate::Ordering, global_index: u32 } => visit_global_atomic_get (arity 0 -> 1)
738                GlobalAtomicSet { ordering: $crate::Ordering, global_index: u32 } => visit_global_atomic_set (arity 1 -> 0)
739                GlobalAtomicRmwAdd { ordering: $crate::Ordering, global_index: u32 } => visit_global_atomic_rmw_add (arity 1 -> 1)
740                GlobalAtomicRmwSub { ordering: $crate::Ordering, global_index: u32 } => visit_global_atomic_rmw_sub (arity 1 -> 1)
741                GlobalAtomicRmwAnd { ordering: $crate::Ordering, global_index: u32 } => visit_global_atomic_rmw_and (arity 1 -> 1)
742                GlobalAtomicRmwOr { ordering: $crate::Ordering, global_index: u32 } => visit_global_atomic_rmw_or (arity 1 -> 1)
743                GlobalAtomicRmwXor { ordering: $crate::Ordering, global_index: u32 } => visit_global_atomic_rmw_xor (arity 1 -> 1)
744                GlobalAtomicRmwXchg { ordering: $crate::Ordering, global_index: u32 } => visit_global_atomic_rmw_xchg (arity 1 -> 1)
745                GlobalAtomicRmwCmpxchg { ordering: $crate::Ordering, global_index: u32 } => visit_global_atomic_rmw_cmpxchg (arity 2 -> 1)
746                TableAtomicGet { ordering: $crate::Ordering, table_index: u32 } => visit_table_atomic_get (arity 1 -> 1)
747                TableAtomicSet { ordering: $crate::Ordering, table_index: u32 } => visit_table_atomic_set (arity 2 -> 0)
748                TableAtomicRmwXchg { ordering: $crate::Ordering, table_index: u32 } => visit_table_atomic_rmw_xchg (arity 2 -> 1)
749                TableAtomicRmwCmpxchg { ordering: $crate::Ordering, table_index: u32 } => visit_table_atomic_rmw_cmpxchg (arity 3 -> 1)
750                StructAtomicGet { ordering: $crate::Ordering, struct_type_index: u32, field_index: u32  } => visit_struct_atomic_get (arity 1 -> 1)
751                StructAtomicGetS { ordering: $crate::Ordering, struct_type_index: u32, field_index: u32  } => visit_struct_atomic_get_s (arity 1 -> 1)
752                StructAtomicGetU { ordering: $crate::Ordering, struct_type_index: u32, field_index: u32  } => visit_struct_atomic_get_u (arity 1 -> 1)
753                StructAtomicSet { ordering: $crate::Ordering, struct_type_index: u32, field_index: u32  } => visit_struct_atomic_set (arity 2 -> 0)
754                StructAtomicRmwAdd { ordering: $crate::Ordering, struct_type_index: u32, field_index: u32  } => visit_struct_atomic_rmw_add (arity 2 -> 1)
755                StructAtomicRmwSub { ordering: $crate::Ordering, struct_type_index: u32, field_index: u32  } => visit_struct_atomic_rmw_sub (arity 2 -> 1)
756                StructAtomicRmwAnd { ordering: $crate::Ordering, struct_type_index: u32, field_index: u32  } => visit_struct_atomic_rmw_and (arity 2 -> 1)
757                StructAtomicRmwOr { ordering: $crate::Ordering, struct_type_index: u32, field_index: u32  } => visit_struct_atomic_rmw_or (arity 2 -> 1)
758                StructAtomicRmwXor { ordering: $crate::Ordering, struct_type_index: u32, field_index: u32  } => visit_struct_atomic_rmw_xor (arity 2 -> 1)
759                StructAtomicRmwXchg { ordering: $crate::Ordering, struct_type_index: u32, field_index: u32  } => visit_struct_atomic_rmw_xchg (arity 2 -> 1)
760                StructAtomicRmwCmpxchg { ordering: $crate::Ordering, struct_type_index: u32, field_index: u32  } => visit_struct_atomic_rmw_cmpxchg (arity 3 -> 1)
761                ArrayAtomicGet { ordering: $crate::Ordering, array_type_index: u32 } => visit_array_atomic_get (arity 2 -> 1)
762                ArrayAtomicGetS { ordering: $crate::Ordering, array_type_index: u32 } => visit_array_atomic_get_s (arity 2 -> 1)
763                ArrayAtomicGetU { ordering: $crate::Ordering, array_type_index: u32 } => visit_array_atomic_get_u (arity 2 -> 1)
764                ArrayAtomicSet { ordering: $crate::Ordering, array_type_index: u32 } => visit_array_atomic_set (arity 3 -> 0)
765                ArrayAtomicRmwAdd { ordering: $crate::Ordering, array_type_index: u32 } => visit_array_atomic_rmw_add (arity 3 -> 1)
766                ArrayAtomicRmwSub { ordering: $crate::Ordering, array_type_index: u32 } => visit_array_atomic_rmw_sub (arity 3 -> 1)
767                ArrayAtomicRmwAnd { ordering: $crate::Ordering, array_type_index: u32 } => visit_array_atomic_rmw_and (arity 3 -> 1)
768                ArrayAtomicRmwOr { ordering: $crate::Ordering, array_type_index: u32 } => visit_array_atomic_rmw_or (arity 3 -> 1)
769                ArrayAtomicRmwXor { ordering: $crate::Ordering, array_type_index: u32 } => visit_array_atomic_rmw_xor (arity 3 -> 1)
770                ArrayAtomicRmwXchg { ordering: $crate::Ordering, array_type_index: u32 } => visit_array_atomic_rmw_xchg (arity 3 -> 1)
771                ArrayAtomicRmwCmpxchg { ordering: $crate::Ordering, array_type_index: u32 } => visit_array_atomic_rmw_cmpxchg (arity 4 -> 1)
772                RefI31Shared => visit_ref_i31_shared (arity 1 -> 1)
773            }
774
775            // Typed Function references
776            @function_references {
777                CallRef { type_index: u32 } => visit_call_ref (arity custom)
778                ReturnCallRef { type_index: u32 } => visit_return_call_ref (arity custom)
779                RefAsNonNull => visit_ref_as_non_null (arity 1 -> 1)
780                BrOnNull { relative_depth: u32 } => visit_br_on_null (arity custom)
781                BrOnNonNull { relative_depth: u32 } => visit_br_on_non_null (arity custom)
782            }
783
784            // Stack switching
785            @stack_switching {
786                ContNew { cont_type_index: u32 } => visit_cont_new (arity 1 -> 1)
787                ContBind { argument_index: u32, result_index: u32 } => visit_cont_bind (arity custom)
788                Suspend { tag_index: u32 } => visit_suspend (arity custom)
789                Resume { cont_type_index: u32, resume_table: $crate::ResumeTable } => visit_resume (arity custom)
790                ResumeThrow { cont_type_index: u32, tag_index: u32, resume_table: $crate::ResumeTable } => visit_resume_throw (arity custom)
791                ResumeThrowRef { cont_type_index: u32, resume_table: $crate::ResumeTable } => visit_resume_throw_ref (arity custom)
792                Switch { cont_type_index: u32, tag_index: u32 } => visit_switch (arity custom)
793            }
794
795            @wide_arithmetic {
796                I64Add128 => visit_i64_add128 (arity 4 -> 2)
797                I64Sub128 => visit_i64_sub128 (arity 4 -> 2)
798                I64MulWideS => visit_i64_mul_wide_s (arity 2 -> 2)
799                I64MulWideU => visit_i64_mul_wide_u (arity 2 -> 2)
800            }
801        }
802    };
803}
804
805/// Helper macro to define a `_for_each_non_simd_operator` which receives
806/// the syntax of each instruction individually, but only the non-simd
807/// operators.
808macro_rules! define_for_each_non_simd_operator {
809    // Switch from `_for_each_operator_group` syntax to this macro's syntax to
810    // be a "tt muncher macro"
811    (@ $($t:tt)*) => {define_for_each_non_simd_operator!(filter [] @ $($t)*);};
812
813    // filter out simd/relaxed-simd proposals
814    (filter $filter:tt @simd $simd:tt $($rest:tt)*) => {
815        define_for_each_non_simd_operator!(filter $filter $($rest)*);
816    };
817    (filter $filter:tt @relaxed_simd $simd:tt $($rest:tt)*) => {
818        define_for_each_non_simd_operator!(filter $filter $($rest)*);
819    };
820
821    // For all other proposals add in tokens where the `@proposal` is prepended
822    // before each instruction.
823    (
824        filter [$($t:tt)*]
825        @$proposal:ident {
826            $( $op:ident $({ $($arg:ident: $argty:ty),* })? => $visit:ident ($($ann:tt)*) )*
827        }
828        $($rest:tt)*
829    ) => {
830        define_for_each_non_simd_operator!(
831            filter [
832                $($t)*
833                $( @$proposal $op $({ $($arg: $argty),* })? => $visit ($($ann)*) )*
834            ]
835            $($rest)*
836        );
837    };
838
839    // At the end the `$t` list here is how we want to define
840    // `_for_each_non_simd_operator`, so define the macro with these tokens.
841    (filter [$($t:tt)*]) => {
842        #[macro_export]
843        #[doc(hidden)]
844        macro_rules! _for_each_visit_operator_impl {
845            ($m:ident) => {
846                $m! { $($t)* }
847            }
848        }
849
850        // When simd is disabled then this macro is additionally the
851        // `for_each_operator!` macro implementation
852        #[cfg(not(feature = "simd"))]
853        #[doc(hidden)]
854        pub use _for_each_visit_operator_impl as _for_each_operator_impl;
855    };
856}
857_for_each_operator_group!(define_for_each_non_simd_operator);
858
859/// When the simd feature is enabled then `_for_each_operator_impl` is defined
860/// to be the same as the above `define_for_each_non_simd_operator` macro except
861/// with all proposals thrown in.
862#[cfg(feature = "simd")]
863macro_rules! define_for_each_operator_impl_with_simd {
864    (
865        $(
866            @$proposal:ident {
867                $( $op:ident $({ $($arg:ident: $argty:ty),* })? => $visit:ident ($($ann:tt)*) )*
868            }
869        )*
870    ) => {
871        #[macro_export]
872        #[doc(hidden)]
873        macro_rules! _for_each_operator_impl {
874            ($m:ident) => {
875                $m! {
876                    $(
877                        $(
878                            @$proposal $op $({$($arg: $argty),*})? => $visit ($($ann)*)
879                        )*
880                    )*
881                }
882            }
883        }
884    };
885}
886#[cfg(feature = "simd")]
887_for_each_operator_group!(define_for_each_operator_impl_with_simd);
888
889/// Helper macro to define the `_for_each_simd_operator_impl` macro.
890///
891/// This is basically the same as `define_for_each_non_simd_operator` above
892/// except that it's filtering on different proposals.
893#[cfg(feature = "simd")]
894macro_rules! define_for_each_simd_operator {
895    // Switch to "tt muncher" mode
896    (@ $($t:tt)*) => {define_for_each_simd_operator!(filter [] @ $($t)*);};
897
898    // Collect the `@simd` and `@relaxed_simd` proposals.
899    (
900        filter [$($t:tt)*]
901        @simd {
902            $( $op:ident $({ $($arg:ident: $argty:ty),* })? => $visit:ident ($($ann:tt)*) )*
903        }
904        $($rest:tt)*
905    ) => {
906        define_for_each_simd_operator!(
907            filter [
908                $($t)*
909                $( @simd $op $({ $($arg: $argty),* })? => $visit ($($ann)*) )*
910            ]
911            $($rest)*
912        );
913    };
914    (
915        filter [$($t:tt)*]
916        @relaxed_simd {
917            $( $op:ident $({ $($arg:ident: $argty:ty),* })? => $visit:ident ($($ann:tt)*) )*
918        }
919        $($rest:tt)*
920    ) => {
921        define_for_each_simd_operator!(
922            filter [
923                $($t)*
924                $( @relaxed_simd $op $({ $($arg: $argty),* })? => $visit ($($ann)*) )*
925            ]
926            $($rest)*
927        );
928    };
929
930    // Skip all other proposals.
931    (filter $filter:tt @$proposal:ident $instrs:tt $($rest:tt)*) => {
932        define_for_each_simd_operator!(filter $filter $($rest)*);
933    };
934
935    // Base case to define the base macro.
936    (filter [$($t:tt)*]) => {
937        #[macro_export]
938        #[doc(hidden)]
939        macro_rules! _for_each_visit_simd_operator_impl {
940            ($m:ident) => {
941                $m! { $($t)* }
942            }
943        }
944    };
945}
946#[cfg(feature = "simd")]
947_for_each_operator_group!(define_for_each_simd_operator);
948
949/// Used to implement routines for the [`Operator`] enum.
950///
951/// A helper macro to conveniently iterate over all opcodes recognized by this
952/// crate. This can be used to work with either the [`Operator`] enumeration or
953/// the [`VisitOperator`] trait if your use case uniformly handles all operators
954/// the same way.
955///
956/// It is also possible to specialize handling of operators depending on the
957/// Wasm proposal from which they are originating.
958///
959/// This is an "iterator macro" where this macro is invoked with the name of
960/// another macro, and then that macro is invoked with the list of all
961/// operators.
962///
963/// The list of specializable Wasm proposals is as follows:
964///
965/// - `@mvp`: Denoting a Wasm operator from the initial Wasm MVP version.
966/// - `@exceptions`: [Wasm `exception-handling` proposal]
967/// - `@tail_call`: [Wasm `tail-calls` proposal]
968/// - `@reference_types`: [Wasm `reference-types` proposal]
969/// - `@sign_extension`: [Wasm `sign-extension-ops` proposal]
970/// - `@saturating_float_to_int`: [Wasm `non_trapping_float-to-int-conversions` proposal]
971/// - `@bulk_memory `:[Wasm `bulk-memory` proposal]
972/// - `@simd`: [Wasm `simd` proposal]
973/// - `@relaxed_simd`: [Wasm `relaxed-simd` proposal]
974/// - `@threads`: [Wasm `threads` proposal]
975/// - `@gc`: [Wasm `gc` proposal]
976/// - `@stack_switching`: [Wasm `stack-switching` proposal]
977/// - `@wide_arithmetic`: [Wasm `wide-arithmetic` proposal]
978/// - `@custom_descriptors` : [Wasm `custom-descriptors` proposal]
979///
980/// [Wasm `exception-handling` proposal]:
981/// https://github.com/WebAssembly/exception-handling
982///
983/// [Wasm `tail-calls` proposal]:
984/// https://github.com/WebAssembly/tail-call
985///
986/// [Wasm `reference-types` proposal]:
987/// https://github.com/WebAssembly/reference-types
988///
989/// [Wasm `sign-extension-ops` proposal]:
990/// https://github.com/WebAssembly/sign-extension-ops
991///
992/// [Wasm `non_trapping_float-to-int-conversions` proposal]:
993/// https://github.com/WebAssembly/nontrapping-float-to-int-conversions
994///
995/// [Wasm `bulk-memory` proposal]:
996/// https://github.com/WebAssembly/bulk-memory-operations
997///
998/// [Wasm `simd` proposal]:
999/// https://github.com/webassembly/simd
1000///
1001/// [Wasm `relaxed-simd` proposal]:
1002/// https://github.com/WebAssembly/relaxed-simd
1003///
1004/// [Wasm `threads` proposal]:
1005/// https://github.com/webassembly/threads
1006///
1007/// [Wasm `gc` proposal]:
1008/// https://github.com/WebAssembly/gc
1009///
1010/// [Wasm `stack-switching` proposal]:
1011/// https://github.com/WebAssembly/stack-switching
1012///
1013/// [Wasm `wide-arithmetic` proposal]:
1014/// https://github.com/WebAssembly/wide-arithmetic
1015///
1016/// ```
1017/// fn do_nothing(op: &wasmparser::Operator) {
1018///     macro_rules! define_match_operator {
1019///         // The outer layer of repetition represents how all operators are
1020///         // provided to the macro at the same time.
1021///         //
1022///         // The `$proposal` identifier indicates the Wasm proposals from which
1023///         // the Wasm operator is originating.
1024///         // For example to specialize the macro match arm for Wasm SIMD proposal
1025///         // operators you could write `@simd` instead of `@$proposal:ident` to
1026///         // only catch those operators.
1027///         //
1028///         // The `$op` name is bound to the `Operator` variant name. The
1029///         // payload of the operator is optionally specified (the `$(...)?`
1030///         // clause) since not all instructions have payloads. Within the payload
1031///         // each argument is named and has its type specified.
1032///         //
1033///         // The `$visit` name is bound to the corresponding name in the
1034///         // `VisitOperator` trait that this corresponds to.
1035///         //
1036///         // The `$ann` annotations give information about the operator's type (e.g. binary i32 or arity 2 -> 1).
1037///         ($( @$proposal:ident $op:ident $({ $($arg:ident: $argty:ty),* })? => $visit:ident ($($ann:tt)*))*) => {
1038///             match op {
1039///                 $(
1040///                     wasmparser::Operator::$op $( { $($arg),* } )? => {
1041///                         // do nothing for this example
1042///                     }
1043///                 )*
1044///                 _ => unreachable!(), // required because `Operator` enum is non-exhaustive
1045///             }
1046///         }
1047///     }
1048///     wasmparser::for_each_operator!(define_match_operator);
1049/// }
1050/// ```
1051///
1052/// If you only wanted to visit the initial base set of wasm instructions, for
1053/// example, you could do:
1054///
1055/// ```
1056/// fn is_mvp_operator(op: &wasmparser::Operator) -> bool {
1057///     macro_rules! define_match_operator {
1058///         // delegate the macro invocation to sub-invocations of this macro to
1059///         // deal with each instruction on a case-by-case basis.
1060///         ($( @$proposal:ident $op:ident $({ $($arg:ident: $argty:ty),* })? => $visit:ident ($($ann:tt)*))*) => {
1061///             match op {
1062///                 $(
1063///                     wasmparser::Operator::$op $( { $($arg),* } )? => {
1064///                         define_match_operator!(impl_one @$proposal)
1065///                     }
1066///                 )*
1067///                 _ => unreachable!(), // required because `Operator` enum is non-exhaustive
1068///             }
1069///         };
1070///
1071///         (impl_one @mvp) => { true };
1072///         (impl_one @$proposal:ident) => { false };
1073///     }
1074///     wasmparser::for_each_operator!(define_match_operator)
1075/// }
1076/// ```
1077#[doc(inline)]
1078pub use _for_each_operator_impl as for_each_operator;
1079
1080/// Used to implement the [`VisitOperator`] trait.
1081///
1082/// A helper macro to conveniently iterate over all opcodes recognized by this
1083/// crate. This can be used to work with either the [`Operator`] enumeration or
1084/// the [`VisitOperator`] trait if your use case uniformly handles all operators
1085/// the same way.
1086///
1087/// It is also possible to specialize handling of operators depending on the
1088/// Wasm proposal from which they are originating.
1089///
1090/// This is an "iterator macro" where this macro is invoked with the name of
1091/// another macro, and then that macro is invoked with the list of all
1092/// operators.
1093///
1094/// The list of specializable Wasm proposals is as follows:
1095///
1096/// - `@mvp`: Denoting a Wasm operator from the initial Wasm MVP version.
1097/// - `@exceptions`: [Wasm `exception-handling` proposal]
1098/// - `@tail_call`: [Wasm `tail-calls` proposal]
1099/// - `@reference_types`: [Wasm `reference-types` proposal]
1100/// - `@sign_extension`: [Wasm `sign-extension-ops` proposal]
1101/// - `@saturating_float_to_int`: [Wasm `non_trapping_float-to-int-conversions` proposal]
1102/// - `@bulk_memory `:[Wasm `bulk-memory` proposal]
1103/// - `@threads`: [Wasm `threads` proposal]
1104/// - `@gc`: [Wasm `gc` proposal]
1105/// - `@stack_switching`: [Wasm `stack-switching` proposal]
1106/// - `@wide_arithmetic`: [Wasm `wide-arithmetic` proposal]
1107///
1108/// Note that this macro does not iterate over the SIMD-related proposals. Those
1109/// are provided in [`VisitSimdOperator`] and [`for_each_visit_simd_operator`].
1110/// This macro only handles non-SIMD related operators and so users wanting to
1111/// handle the SIMD-class of operators need to use that trait/macro as well.
1112///
1113/// [Wasm `exception-handling` proposal]:
1114/// https://github.com/WebAssembly/exception-handling
1115///
1116/// [Wasm `tail-calls` proposal]:
1117/// https://github.com/WebAssembly/tail-call
1118///
1119/// [Wasm `reference-types` proposal]:
1120/// https://github.com/WebAssembly/reference-types
1121///
1122/// [Wasm `sign-extension-ops` proposal]:
1123/// https://github.com/WebAssembly/sign-extension-ops
1124///
1125/// [Wasm `non_trapping_float-to-int-conversions` proposal]:
1126/// https://github.com/WebAssembly/nontrapping-float-to-int-conversions
1127///
1128/// [Wasm `bulk-memory` proposal]:
1129/// https://github.com/WebAssembly/bulk-memory-operations
1130/// [Wasm `simd` proposal]:
1131/// https://github.com/webassembly/simd
1132///
1133/// [Wasm `relaxed-simd` proposal]:
1134/// https://github.com/WebAssembly/relaxed-simd
1135///
1136/// [Wasm `threads` proposal]:
1137/// https://github.com/webassembly/threads
1138///
1139/// [Wasm `gc` proposal]:
1140/// https://github.com/WebAssembly/gc
1141///
1142/// [Wasm `stack-switching` proposal]:
1143/// https://github.com/WebAssembly/stack-switching
1144///
1145/// [Wasm `wide-arithmetic` proposal]:
1146/// https://github.com/WebAssembly/wide-arithmetic
1147///
1148/// ```
1149/// macro_rules! define_visit_operator {
1150///     // The outer layer of repetition represents how all operators are
1151///     // provided to the macro at the same time.
1152///     //
1153///     // The `$proposal` identifier indicates the Wasm proposals from which
1154///     // the Wasm operator is originating.
1155///     // For example to specialize the macro match arm for Wasm `gc` proposal
1156///     // operators you could write `@gc` instead of `@$proposal:ident` to
1157///     // only catch those operators.
1158///     //
1159///     // The `$op` name is bound to the `Operator` variant name. The
1160///     // payload of the operator is optionally specified (the `$(...)?`
1161///     // clause) since not all instructions have payloads. Within the payload
1162///     // each argument is named and has its type specified.
1163///     //
1164///     // The `$visit` name is bound to the corresponding name in the
1165///     // `VisitOperator` trait that this corresponds to.
1166///     //
1167///     // The `$ann` annotations give information about the operator's type (e.g. binary i32 or arity 2 -> 1).
1168///     ($( @$proposal:ident $op:ident $({ $($arg:ident: $argty:ty),* })? => $visit:ident ($($ann:tt)*))*) => {
1169///         $(
1170///             fn $visit(&mut self $($(,$arg: $argty)*)?) {
1171///                 // do nothing for this example
1172///             }
1173///         )*
1174///     }
1175/// }
1176///
1177/// pub struct VisitAndDoNothing;
1178///
1179/// impl<'a> wasmparser::VisitOperator<'a> for VisitAndDoNothing {
1180///     type Output = ();
1181///
1182///     wasmparser::for_each_visit_operator!(define_visit_operator);
1183/// }
1184/// ```
1185///
1186/// If you only wanted to visit the initial base set of wasm instructions, for
1187/// example, you could do:
1188///
1189/// ```
1190/// macro_rules! visit_only_mvp {
1191///     // delegate the macro invocation to sub-invocations of this macro to
1192///     // deal with each instruction on a case-by-case basis.
1193///     ($( @$proposal:ident $op:ident $({ $($arg:ident: $argty:ty),* })? => $visit:ident ($($ann:tt)*))*) => {
1194///         $(
1195///             visit_only_mvp!(visit_one @$proposal $op $({ $($arg: $argty),* })? => $visit);
1196///         )*
1197///     };
1198///
1199///     // MVP instructions are defined manually, so do nothing.
1200///     (visit_one @mvp $($rest:tt)*) => {};
1201///
1202///     // Non-MVP instructions all return `false` here. The exact type depends
1203///     // on `type Output` in the trait implementation below. You could change
1204///     // it to `Result<()>` for example and return an error here too.
1205///     (visit_one @$proposal:ident $op:ident $({ $($arg:ident: $argty:ty),* })? => $visit:ident) => {
1206///         fn $visit(&mut self $($(,$arg: $argty)*)?) -> bool {
1207///             false
1208///         }
1209///     }
1210/// }
1211/// # // to get this example to compile another macro is used here to define
1212/// # // visit methods for all mvp operators.
1213/// # macro_rules! visit_mvp {
1214/// #     ($( @$proposal:ident $op:ident $({ $($arg:ident: $argty:ty),* })? => $visit:ident ($($ann:tt)*))*) => {
1215/// #         $(
1216/// #             visit_mvp!(visit_one @$proposal $op $({ $($arg: $argty),* })? => $visit);
1217/// #         )*
1218/// #     };
1219/// #     (visit_one @mvp $op:ident $({ $($arg:ident: $argty:ty),* })? => $visit:ident) => {
1220/// #         fn $visit(&mut self $($(,$arg: $argty)*)?) -> bool {
1221/// #             true
1222/// #         }
1223/// #     };
1224/// #     (visit_one @$proposal:ident $($rest:tt)*) => {};
1225/// # }
1226///
1227/// pub struct VisitOnlyMvp;
1228///
1229/// impl<'a> wasmparser::VisitOperator<'a> for VisitOnlyMvp {
1230///     type Output = bool;
1231///
1232///     wasmparser::for_each_visit_operator!(visit_only_mvp);
1233/// #   wasmparser::for_each_visit_operator!(visit_mvp);
1234///
1235///     // manually define `visit_*` for all MVP operators here
1236/// }
1237/// ```
1238#[doc(inline)]
1239pub use _for_each_visit_operator_impl as for_each_visit_operator;
1240
1241/// Used to implement the [`VisitSimdOperator`] trait.
1242///
1243/// The list of specializable Wasm proposals is as follows:
1244///
1245/// - `@simd`: [Wasm `simd` proposal]
1246/// - `@relaxed_simd`: [Wasm `relaxed-simd` proposal]
1247///
1248/// For more information about the structure and use of this macro please
1249/// refer to the documentation of the [`for_each_operator`] macro.
1250///
1251/// [Wasm `simd` proposal]:
1252/// https://github.com/webassembly/simd
1253///
1254/// [Wasm `relaxed-simd` proposal]:
1255/// https://github.com/WebAssembly/relaxed-simd
1256///
1257/// [`VisitSimdOperator`]: crate::VisitSimdOperator
1258///
1259/// ```
1260/// # macro_rules! define_visit_operator {
1261/// #     ($( @$proposal:ident $op:ident $({ $($arg:ident: $argty:ty),* })? => $visit:ident ($($ann:tt)*))*) => {
1262/// #         $( fn $visit(&mut self $($(,$arg: $argty)*)?) {} )*
1263/// #     }
1264/// # }
1265/// pub struct VisitAndDoNothing;
1266///
1267/// impl<'a> wasmparser::VisitOperator<'a> for VisitAndDoNothing {
1268///     type Output = ();
1269///
1270///     // implement all the visit methods ..
1271///     # wasmparser::for_each_visit_operator!(define_visit_operator);
1272/// }
1273///
1274/// macro_rules! define_visit_simd_operator {
1275///     // The outer layer of repetition represents how all operators are
1276///     // provided to the macro at the same time.
1277///     //
1278///     // The `$proposal` identifier is either `@simd` or `@relaxed_simd`.
1279///     //
1280///     // The shape of this macro is identical to [`for_each_visit_operator`].
1281///     // Please refer to its documentation if you want to learn more.
1282///     ($( @$proposal:ident $op:ident $({ $($arg:ident: $argty:ty),* })? => $visit:ident ($($ann:tt)*))*) => {
1283///         $(
1284///             fn $visit(&mut self $($(,$arg: $argty)*)?) {
1285///                 // do nothing for this example
1286///             }
1287///         )*
1288///     }
1289/// }
1290///
1291/// impl<'a> wasmparser::VisitSimdOperator<'a> for VisitAndDoNothing {
1292///     wasmparser::for_each_visit_simd_operator!(define_visit_simd_operator);
1293/// }
1294/// ```
1295#[cfg(feature = "simd")]
1296#[doc(inline)]
1297pub use _for_each_visit_simd_operator_impl as for_each_visit_simd_operator;
1298
1299macro_rules! format_err {
1300    ($offset:expr, $($arg:tt)*) => {
1301        crate::BinaryReaderError::fmt(format_args!($($arg)*), $offset)
1302    }
1303}
1304
1305macro_rules! bail {
1306    ($($arg:tt)*) => {return Err(format_err!($($arg)*))}
1307}
1308
1309#[cfg(all(feature = "component-model", feature = "validate"))] // Only used in component-model code right now.
1310macro_rules! ensure {
1311    ($cond:expr, $($arg:tt)*) => {
1312        if !$cond {
1313            bail!($($arg)*);
1314        }
1315    }
1316}
1317
1318pub use crate::arity::*;
1319pub use crate::binary_reader::{BinaryReader, BinaryReaderError, Result};
1320pub use crate::features::*;
1321pub use crate::parser::*;
1322pub use crate::readers::*;
1323
1324mod arity;
1325mod binary_reader;
1326mod features;
1327mod limits;
1328mod parser;
1329mod readers;
1330
1331#[cfg(feature = "validate")]
1332mod resources;
1333#[cfg(feature = "validate")]
1334mod validator;
1335#[cfg(feature = "validate")]
1336pub use crate::resources::*;
1337#[cfg(feature = "validate")]
1338pub use crate::validator::*;
1339
1340#[cfg(feature = "validate")]
1341pub mod collections;