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