wast/core/
expr.rs

1use crate::annotation;
2use crate::core::*;
3use crate::encode::Encode;
4use crate::kw;
5use crate::lexer::{Lexer, Token, TokenKind};
6use crate::parser::{Parse, Parser, Result};
7use crate::token::*;
8use std::mem;
9
10/// An expression, or a list of instructions, in the WebAssembly text format.
11///
12/// This expression type will parse s-expression-folded instructions into a flat
13/// list of instructions for emission later on. The implicit `end` instruction
14/// at the end of an expression is not included in the `instrs` field.
15#[derive(Debug)]
16#[allow(missing_docs)]
17pub struct Expression<'a> {
18    /// Instructions in this expression.
19    pub instrs: Box<[Instruction<'a>]>,
20
21    /// Branch hints, if any, found while parsing instructions.
22    pub branch_hints: Box<[BranchHint]>,
23
24    /// Optionally parsed spans of all instructions in `instrs`.
25    ///
26    /// This value is `None` as it's disabled by default. This can be enabled
27    /// through the
28    /// [`ParseBuffer::track_instr_spans`](crate::parser::ParseBuffer::track_instr_spans)
29    /// function.
30    ///
31    /// This is not tracked by default due to the memory overhead and limited
32    /// use of this field.
33    pub instr_spans: Option<Box<[Span]>>,
34}
35
36/// A `@metadata.code.branch_hint` in the code, associated with a If or BrIf
37/// This instruction is a placeholder and won't produce anything. Its purpose
38/// is to store the offset of the following instruction and check that
39/// it's followed by `br_if` or `if`.
40#[derive(Debug)]
41pub struct BranchHint {
42    /// Index of instructions in `instrs` field of `Expression` that this hint
43    /// applies to.
44    pub instr_index: usize,
45    /// The value of this branch hint
46    pub value: u32,
47}
48
49impl<'a> Parse<'a> for Expression<'a> {
50    fn parse(parser: Parser<'a>) -> Result<Self> {
51        let mut exprs = ExpressionParser::new(parser);
52        exprs.parse(parser)?;
53        Ok(Expression {
54            instrs: exprs.raw_instrs.into(),
55            branch_hints: exprs.branch_hints.into(),
56            instr_spans: exprs.spans.map(|s| s.into()),
57        })
58    }
59}
60
61impl<'a> Expression<'a> {
62    /// Creates an expression from the single `instr` specified.
63    pub fn one(instr: Instruction<'a>) -> Expression<'a> {
64        Expression {
65            instrs: [instr].into(),
66            branch_hints: Box::new([]),
67            instr_spans: None,
68        }
69    }
70
71    /// Parse an expression formed from a single folded instruction.
72    ///
73    /// Attempts to parse an expression formed from a single folded instruction.
74    ///
75    /// This method will mutate the state of `parser` after attempting to parse
76    /// the expression. If an error happens then it is likely fatal and
77    /// there is no guarantee of how many tokens have been consumed from
78    /// `parser`.
79    ///
80    /// # Errors
81    ///
82    /// This function will return an error if the expression could not be
83    /// parsed. Note that creating an [`crate::Error`] is not exactly a cheap
84    /// operation, so [`crate::Error`] is typically fatal and propagated all the
85    /// way back to the top parse call site.
86    pub fn parse_folded_instruction(parser: Parser<'a>) -> Result<Self> {
87        let mut exprs = ExpressionParser::new(parser);
88        exprs.parse_folded_instruction(parser)?;
89        Ok(Expression {
90            instrs: exprs.raw_instrs.into(),
91            branch_hints: exprs.branch_hints.into(),
92            instr_spans: exprs.spans.map(|s| s.into()),
93        })
94    }
95}
96
97/// Helper struct used to parse an `Expression` with helper methods and such.
98///
99/// The primary purpose of this is to avoid defining expression parsing as a
100/// call-thread-stack recursive function. Since we're parsing user input that
101/// runs the risk of blowing the call stack, so we want to be sure to use a heap
102/// stack structure wherever possible.
103struct ExpressionParser<'a> {
104    /// The flat list of instructions that we've parsed so far, and will
105    /// eventually become the final `Expression`.
106    ///
107    /// Appended to with `push_instr` to ensure that this is the same length of
108    /// `spans` if `spans` is used.
109    raw_instrs: Vec<Instruction<'a>>,
110
111    /// Descriptor of all our nested s-expr blocks. This only happens when
112    /// instructions themselves are nested.
113    stack: Vec<Level<'a>>,
114
115    /// Related to the branch hints proposal.
116    /// Will be used later to collect the offsets in the final binary.
117    /// <(index of branch instructions, BranchHintAnnotation)>
118    branch_hints: Vec<BranchHint>,
119
120    /// Storage for all span information in `raw_instrs`. Optionally disabled to
121    /// reduce memory consumption of parsing expressions.
122    spans: Option<Vec<Span>>,
123}
124
125enum Paren {
126    None,
127    Left,
128    Right(Span),
129}
130
131/// A "kind" of nested block that we can be parsing inside of.
132enum Level<'a> {
133    /// This is a normal `block` or `loop` or similar, where the instruction
134    /// payload here is pushed when the block is exited.
135    EndWith(Instruction<'a>, Option<Span>),
136
137    /// This is a pretty special variant which means that we're parsing an `if`
138    /// statement, and the state of the `if` parsing is tracked internally in
139    /// the payload.
140    If(If<'a>),
141
142    /// This means we're either parsing inside of `(then ...)` or `(else ...)`
143    /// which don't correspond to terminating instructions, we're just in a
144    /// nested block.
145    IfArm,
146
147    /// This means we are finishing the parsing of a branch hint annotation.
148    BranchHint,
149}
150
151/// Possible states of "what is currently being parsed?" in an `if` expression.
152enum If<'a> {
153    /// Only the `if` instruction has been parsed, next thing to parse is the
154    /// clause, if any, of the `if` instruction.
155    ///
156    /// This parse ends when `(then ...)` is encountered.
157    Clause(Instruction<'a>, Span),
158    /// Currently parsing the `then` block, and afterwards a closing paren is
159    /// required or an `(else ...)` expression.
160    Then,
161    /// Parsing the `else` expression, nothing can come after.
162    Else,
163}
164
165impl<'a> ExpressionParser<'a> {
166    fn new(parser: Parser<'a>) -> ExpressionParser<'a> {
167        ExpressionParser {
168            raw_instrs: Vec::new(),
169            stack: Vec::new(),
170            branch_hints: Vec::new(),
171            spans: if parser.track_instr_spans() {
172                Some(Vec::new())
173            } else {
174                None
175            },
176        }
177    }
178
179    fn parse(&mut self, parser: Parser<'a>) -> Result<()> {
180        // Here we parse instructions in a loop, and we do not recursively
181        // invoke this parse function to avoid blowing the stack on
182        // deeply-recursive parses.
183        //
184        // Our loop generally only finishes once there's no more input left int
185        // the `parser`. If there's some unclosed delimiters though (on our
186        // `stack`), then we also keep parsing to generate error messages if
187        // there's no input left.
188        while !parser.is_empty() || !self.stack.is_empty() {
189            // As a small ease-of-life adjustment here, if we're parsing inside
190            // of an `if block then we require that all sub-components are
191            // s-expressions surrounded by `(` and `)`, so verify that here.
192            if let Some(Level::If(_)) = self.stack.last() {
193                if !parser.is_empty() && !parser.peek::<LParen>()? {
194                    return Err(parser.error("expected `(`"));
195                }
196            }
197
198            match self.paren(parser)? {
199                // No parenthesis seen? Then we just parse the next instruction
200                // and move on.
201                Paren::None => {
202                    let span = parser.cur_span();
203                    self.push_instr(parser.parse()?, span);
204                }
205
206                // If we see a left-parenthesis then things are a little
207                // special. We handle block-like instructions specially
208                // (`block`, `loop`, and `if`), and otherwise all other
209                // instructions simply get appended once we reach the end of the
210                // s-expression.
211                //
212                // In all cases here we push something onto the `stack` to get
213                // popped when the `)` character is seen.
214                Paren::Left => {
215                    // First up is handling `if` parsing, which is funky in a
216                    // whole bunch of ways. See the method internally for more
217                    // information.
218                    if self.handle_if_lparen(parser)? {
219                        continue;
220                    }
221
222                    // Handle the case of a branch hint annotation
223                    if parser.peek::<annotation::metadata_code_branch_hint>()? {
224                        self.parse_branch_hint(parser)?;
225                        self.stack.push(Level::BranchHint);
226                        continue;
227                    }
228
229                    let span = parser.cur_span();
230                    match parser.parse()? {
231                        // If block/loop show up then we just need to be sure to
232                        // push an `end` instruction whenever the `)` token is
233                        // seen
234                        i @ Instruction::Block(_)
235                        | i @ Instruction::Loop(_)
236                        | i @ Instruction::TryTable(_) => {
237                            self.push_instr(i, span);
238                            self.stack
239                                .push(Level::EndWith(Instruction::End(None), None));
240                        }
241
242                        // Parsing an `if` instruction is super tricky, so we
243                        // push an `If` scope and we let all our scope-based
244                        // parsing handle the remaining items.
245                        i @ Instruction::If(_) => {
246                            self.stack.push(Level::If(If::Clause(i, span)));
247                        }
248
249                        // Anything else means that we're parsing a nested form
250                        // such as `(i32.add ...)` which means that the
251                        // instruction we parsed will be coming at the end.
252                        other => self.stack.push(Level::EndWith(other, Some(span))),
253                    }
254                }
255
256                // If we registered a `)` token as being seen, then we're
257                // guaranteed there's an item in the `stack` stack for us to
258                // pop. We peel that off and take a look at what it says to do.
259                Paren::Right(span) => match self.stack.pop().unwrap() {
260                    Level::EndWith(i, s) => self.push_instr(i, s.unwrap_or(span)),
261                    Level::IfArm => {}
262                    Level::BranchHint => {}
263
264                    // If an `if` statement hasn't parsed the clause or `then`
265                    // block, then that's an error because there weren't enough
266                    // items in the `if` statement. Otherwise we're just careful
267                    // to terminate with an `end` instruction.
268                    Level::If(If::Clause(..)) => {
269                        return Err(parser.error("previous `if` had no `then`"));
270                    }
271                    Level::If(_) => {
272                        self.push_instr(Instruction::End(None), span);
273                    }
274                },
275            }
276        }
277        Ok(())
278    }
279
280    fn parse_folded_instruction(&mut self, parser: Parser<'a>) -> Result<()> {
281        let mut done = false;
282        while !done {
283            match self.paren(parser)? {
284                Paren::Left => {
285                    let span = parser.cur_span();
286                    self.stack.push(Level::EndWith(parser.parse()?, Some(span)));
287                }
288                Paren::Right(span) => {
289                    let (top_instr, span) = match self.stack.pop().unwrap() {
290                        Level::EndWith(i, s) => (i, s.unwrap_or(span)),
291                        _ => panic!("unknown level type"),
292                    };
293                    self.push_instr(top_instr, span);
294                    if self.stack.is_empty() {
295                        done = true;
296                    }
297                }
298                Paren::None => {
299                    return Err(parser.error("expected to continue a folded instruction"));
300                }
301            }
302        }
303        Ok(())
304    }
305
306    /// Parses either `(`, `)`, or nothing.
307    fn paren(&self, parser: Parser<'a>) -> Result<Paren> {
308        parser.step(|cursor| {
309            Ok(match cursor.lparen()? {
310                Some(rest) => (Paren::Left, rest),
311                None if self.stack.is_empty() => (Paren::None, cursor),
312                None => match cursor.rparen()? {
313                    Some(rest) => (Paren::Right(cursor.cur_span()), rest),
314                    None => (Paren::None, cursor),
315                },
316            })
317        })
318    }
319
320    /// State transitions with parsing an `if` statement.
321    ///
322    /// The syntactical form of an `if` statement looks like:
323    ///
324    /// ```wat
325    /// (if ($clause)... (then $then) (else $else))
326    /// ```
327    ///
328    /// THis method is called after a `(` is parsed within the `(if ...` block.
329    /// This determines what to do next.
330    ///
331    /// Returns `true` if the rest of the arm above should be skipped, or
332    /// `false` if we should parse the next item as an instruction (because we
333    /// didn't handle the lparen here).
334    fn handle_if_lparen(&mut self, parser: Parser<'a>) -> Result<bool> {
335        // Only execute the code below if there's an `If` listed last.
336        let i = match self.stack.last_mut() {
337            Some(Level::If(i)) => i,
338            _ => return Ok(false),
339        };
340
341        match i {
342            // If the clause is still being parsed then interpret this `(` as a
343            // folded instruction unless it starts with `then`, in which case
344            // this transitions to the `Then` state and a new level has been
345            // reached.
346            If::Clause(if_instr, if_instr_span) => {
347                if !parser.peek::<kw::then>()? {
348                    return Ok(false);
349                }
350                parser.parse::<kw::then>()?;
351                let instr = mem::replace(if_instr, Instruction::End(None));
352                let span = *if_instr_span;
353                *i = If::Then;
354                self.push_instr(instr, span);
355                self.stack.push(Level::IfArm);
356                Ok(true)
357            }
358
359            // Previously we were parsing the `(then ...)` clause so this next
360            // `(` must be followed by `else`.
361            If::Then => {
362                let span = parser.parse::<kw::r#else>()?.0;
363                *i = If::Else;
364                self.push_instr(Instruction::Else(None), span);
365                self.stack.push(Level::IfArm);
366                Ok(true)
367            }
368
369            // If after a `(else ...` clause is parsed there's another `(` then
370            // that's not syntactically allowed.
371            If::Else => Err(parser.error("unexpected token: too many payloads inside of `(if)`")),
372        }
373    }
374
375    fn parse_branch_hint(&mut self, parser: Parser<'a>) -> Result<()> {
376        parser.parse::<annotation::metadata_code_branch_hint>()?;
377
378        let hint = parser.parse::<String>()?;
379
380        let value = match hint.as_bytes() {
381            [0] => 0,
382            [1] => 1,
383            _ => return Err(parser.error("invalid value for branch hint")),
384        };
385
386        self.branch_hints.push(BranchHint {
387            instr_index: self.raw_instrs.len(),
388            value,
389        });
390        Ok(())
391    }
392
393    fn push_instr(&mut self, instr: Instruction<'a>, span: Span) {
394        self.raw_instrs.push(instr);
395        if let Some(spans) = &mut self.spans {
396            spans.push(span);
397        }
398    }
399}
400
401// TODO: document this obscenity
402macro_rules! instructions {
403    (pub enum Instruction<'a> {
404        $(
405            $(#[$doc:meta])*
406            $name:ident $(($($arg:tt)*))? : [$($binary:tt)*] : $instr:tt $( | $deprecated:tt )?,
407        )*
408    }) => (
409        /// A listing of all WebAssembly instructions that can be in a module
410        /// that this crate currently parses.
411        #[derive(Debug, Clone)]
412        #[allow(missing_docs)]
413        pub enum Instruction<'a> {
414            $(
415                $(#[$doc])*
416                $name $(( instructions!(@ty $($arg)*) ))?,
417            )*
418        }
419
420        #[allow(non_snake_case)]
421        impl<'a> Parse<'a> for Instruction<'a> {
422            fn parse(parser: Parser<'a>) -> Result<Self> {
423                $(
424                    fn $name<'a>(_parser: Parser<'a>) -> Result<Instruction<'a>> {
425                        Ok(Instruction::$name $((
426                            instructions!(@parse _parser $($arg)*)?
427                        ))?)
428                    }
429                )*
430                let parse_remainder = parser.step(|c| {
431                    let (kw, rest) = match c.keyword() ?{
432                        Some(pair) => pair,
433                        None => return Err(c.error("expected an instruction")),
434                    };
435                    match kw {
436                        $($instr $( | $deprecated )?=> Ok(($name as fn(_) -> _, rest)),)*
437                        _ => return Err(c.error("unknown operator or unexpected token")),
438                    }
439                })?;
440                parse_remainder(parser)
441            }
442        }
443
444        impl Encode for Instruction<'_> {
445            #[allow(non_snake_case, unused_lifetimes)]
446            fn encode(&self, v: &mut Vec<u8>) {
447                match self {
448                    $(
449                        Instruction::$name $((instructions!(@first x $($arg)*)))? => {
450                            fn encode<'a>($(arg: &instructions!(@ty $($arg)*),)? v: &mut Vec<u8>) {
451                                instructions!(@encode v $($binary)*);
452                                $(<instructions!(@ty $($arg)*) as Encode>::encode(arg, v);)?
453                            }
454                            encode($( instructions!(@first x $($arg)*), )? v)
455                        }
456                    )*
457                }
458            }
459        }
460
461        impl<'a> Instruction<'a> {
462            /// Returns the associated [`MemArg`] if one is available for this
463            /// instruction.
464            #[allow(unused_variables, non_snake_case)]
465            pub fn memarg_mut(&mut self) -> Option<&mut MemArg<'a>> {
466                match self {
467                    $(
468                        Instruction::$name $((instructions!(@memarg_binding a $($arg)*)))? => {
469                            instructions!(@get_memarg a $($($arg)*)?)
470                        }
471                    )*
472                }
473            }
474        }
475    );
476
477    (@ty MemArg<$amt:tt>) => (MemArg<'a>);
478    (@ty LoadOrStoreLane<$amt:tt>) => (LoadOrStoreLane<'a>);
479    (@ty $other:ty) => ($other);
480
481    (@first $first:ident $($t:tt)*) => ($first);
482
483    (@parse $parser:ident MemArg<$amt:tt>) => (MemArg::parse($parser, $amt));
484    (@parse $parser:ident MemArg) => (compile_error!("must specify `MemArg` default"));
485    (@parse $parser:ident LoadOrStoreLane<$amt:tt>) => (LoadOrStoreLane::parse($parser, $amt));
486    (@parse $parser:ident LoadOrStoreLane) => (compile_error!("must specify `LoadOrStoreLane` default"));
487    (@parse $parser:ident $other:ty) => ($parser.parse::<$other>());
488
489    // simd opcodes prefixed with `0xfd` get a varuint32 encoding for their payload
490    (@encode $dst:ident 0xfd, $simd:tt) => ({
491        $dst.push(0xfd);
492        <u32 as Encode>::encode(&$simd, $dst);
493    });
494    (@encode $dst:ident $($bytes:tt)*) => ($dst.extend_from_slice(&[$($bytes)*]););
495
496    (@get_memarg $name:ident MemArg<$amt:tt>) => (Some($name));
497    (@get_memarg $name:ident LoadOrStoreLane<$amt:tt>) => (Some(&mut $name.memarg));
498    (@get_memarg $($other:tt)*) => (None);
499
500    (@memarg_binding $name:ident MemArg<$amt:tt>) => ($name);
501    (@memarg_binding $name:ident LoadOrStoreLane<$amt:tt>) => ($name);
502    (@memarg_binding $name:ident $other:ty) => (_);
503}
504
505instructions! {
506    pub enum Instruction<'a> {
507        Block(Box<BlockType<'a>>) : [0x02] : "block",
508        If(Box<BlockType<'a>>) : [0x04] : "if",
509        Else(Option<Id<'a>>) : [0x05] : "else",
510        Loop(Box<BlockType<'a>>) : [0x03] : "loop",
511        End(Option<Id<'a>>) : [0x0b] : "end",
512
513        Unreachable : [0x00] : "unreachable",
514        Nop : [0x01] : "nop",
515        Br(Index<'a>) : [0x0c] : "br",
516        BrIf(Index<'a>) : [0x0d] : "br_if",
517        BrTable(BrTableIndices<'a>) : [0x0e] : "br_table",
518        Return : [0x0f] : "return",
519        Call(Index<'a>) : [0x10] : "call",
520        CallIndirect(Box<CallIndirect<'a>>) : [0x11] : "call_indirect",
521
522        // tail-call proposal
523        ReturnCall(Index<'a>) : [0x12] : "return_call",
524        ReturnCallIndirect(Box<CallIndirect<'a>>) : [0x13] : "return_call_indirect",
525
526        // function-references proposal
527        CallRef(Index<'a>) : [0x14] : "call_ref",
528        ReturnCallRef(Index<'a>) : [0x15] : "return_call_ref",
529
530        Drop : [0x1a] : "drop",
531        Select(SelectTypes<'a>) : [] : "select",
532        LocalGet(Index<'a>) : [0x20] : "local.get",
533        LocalSet(Index<'a>) : [0x21] : "local.set",
534        LocalTee(Index<'a>) : [0x22] : "local.tee",
535        GlobalGet(Index<'a>) : [0x23] : "global.get",
536        GlobalSet(Index<'a>) : [0x24] : "global.set",
537
538        TableGet(TableArg<'a>) : [0x25] : "table.get",
539        TableSet(TableArg<'a>) : [0x26] : "table.set",
540
541        I32Load(MemArg<4>) : [0x28] : "i32.load",
542        I64Load(MemArg<8>) : [0x29] : "i64.load",
543        F32Load(MemArg<4>) : [0x2a] : "f32.load",
544        F64Load(MemArg<8>) : [0x2b] : "f64.load",
545        I32Load8s(MemArg<1>) : [0x2c] : "i32.load8_s",
546        I32Load8u(MemArg<1>) : [0x2d] : "i32.load8_u",
547        I32Load16s(MemArg<2>) : [0x2e] : "i32.load16_s",
548        I32Load16u(MemArg<2>) : [0x2f] : "i32.load16_u",
549        I64Load8s(MemArg<1>) : [0x30] : "i64.load8_s",
550        I64Load8u(MemArg<1>) : [0x31] : "i64.load8_u",
551        I64Load16s(MemArg<2>) : [0x32] : "i64.load16_s",
552        I64Load16u(MemArg<2>) : [0x33] : "i64.load16_u",
553        I64Load32s(MemArg<4>) : [0x34] : "i64.load32_s",
554        I64Load32u(MemArg<4>) : [0x35] : "i64.load32_u",
555        I32Store(MemArg<4>) : [0x36] : "i32.store",
556        I64Store(MemArg<8>) : [0x37] : "i64.store",
557        F32Store(MemArg<4>) : [0x38] : "f32.store",
558        F64Store(MemArg<8>) : [0x39] : "f64.store",
559        I32Store8(MemArg<1>) : [0x3a] : "i32.store8",
560        I32Store16(MemArg<2>) : [0x3b] : "i32.store16",
561        I64Store8(MemArg<1>) : [0x3c] : "i64.store8",
562        I64Store16(MemArg<2>) : [0x3d] : "i64.store16",
563        I64Store32(MemArg<4>) : [0x3e] : "i64.store32",
564
565        // Lots of bulk memory proposal here as well
566        MemorySize(MemoryArg<'a>) : [0x3f] : "memory.size",
567        MemoryGrow(MemoryArg<'a>) : [0x40] : "memory.grow",
568        MemoryInit(MemoryInit<'a>) : [0xfc, 0x08] : "memory.init",
569        MemoryCopy(MemoryCopy<'a>) : [0xfc, 0x0a] : "memory.copy",
570        MemoryFill(MemoryArg<'a>) : [0xfc, 0x0b] : "memory.fill",
571        MemoryDiscard(MemoryArg<'a>) : [0xfc, 0x12] : "memory.discard",
572        DataDrop(Index<'a>) : [0xfc, 0x09] : "data.drop",
573        ElemDrop(Index<'a>) : [0xfc, 0x0d] : "elem.drop",
574        TableInit(TableInit<'a>) : [0xfc, 0x0c] : "table.init",
575        TableCopy(TableCopy<'a>) : [0xfc, 0x0e] : "table.copy",
576        TableFill(TableArg<'a>) : [0xfc, 0x11] : "table.fill",
577        TableSize(TableArg<'a>) : [0xfc, 0x10] : "table.size",
578        TableGrow(TableArg<'a>) : [0xfc, 0x0f] : "table.grow",
579
580        RefNull(HeapType<'a>) : [0xd0] : "ref.null",
581        RefIsNull : [0xd1] : "ref.is_null",
582        RefFunc(Index<'a>) : [0xd2] : "ref.func",
583
584        // function-references proposal
585        RefAsNonNull : [0xd4] : "ref.as_non_null",
586        BrOnNull(Index<'a>) : [0xd5] : "br_on_null",
587        BrOnNonNull(Index<'a>) : [0xd6] : "br_on_non_null",
588
589        // gc proposal: eqref
590        RefEq : [0xd3] : "ref.eq",
591
592        // gc proposal: struct
593        StructNew(Index<'a>) : [0xfb, 0x00] : "struct.new",
594        StructNewDefault(Index<'a>) : [0xfb, 0x01] : "struct.new_default",
595        StructGet(StructAccess<'a>) : [0xfb, 0x02] : "struct.get",
596        StructGetS(StructAccess<'a>) : [0xfb, 0x03] : "struct.get_s",
597        StructGetU(StructAccess<'a>) : [0xfb, 0x04] : "struct.get_u",
598        StructSet(StructAccess<'a>) : [0xfb, 0x05] : "struct.set",
599
600        // gc proposal: array
601        ArrayNew(Index<'a>) : [0xfb, 0x06] : "array.new",
602        ArrayNewDefault(Index<'a>) : [0xfb, 0x07] : "array.new_default",
603        ArrayNewFixed(ArrayNewFixed<'a>) : [0xfb, 0x08] : "array.new_fixed",
604        ArrayNewData(ArrayNewData<'a>) : [0xfb, 0x09] : "array.new_data",
605        ArrayNewElem(ArrayNewElem<'a>) : [0xfb, 0x0a] : "array.new_elem",
606        ArrayGet(Index<'a>) : [0xfb, 0x0b] : "array.get",
607        ArrayGetS(Index<'a>) : [0xfb, 0x0c] : "array.get_s",
608        ArrayGetU(Index<'a>) : [0xfb, 0x0d] : "array.get_u",
609        ArraySet(Index<'a>) : [0xfb, 0x0e] : "array.set",
610        ArrayLen : [0xfb, 0x0f] : "array.len",
611        ArrayFill(ArrayFill<'a>) : [0xfb, 0x10] : "array.fill",
612        ArrayCopy(ArrayCopy<'a>) : [0xfb, 0x11] : "array.copy",
613        ArrayInitData(ArrayInit<'a>) : [0xfb, 0x12] : "array.init_data",
614        ArrayInitElem(ArrayInit<'a>) : [0xfb, 0x13] : "array.init_elem",
615
616        // gc proposal, i31
617        RefI31 : [0xfb, 0x1c] : "ref.i31",
618        I31GetS : [0xfb, 0x1d] : "i31.get_s",
619        I31GetU : [0xfb, 0x1e] : "i31.get_u",
620
621        // gc proposal, concrete casting
622        RefTest(RefTest<'a>) : [] : "ref.test",
623        RefCast(RefCast<'a>) : [] : "ref.cast",
624        BrOnCast(Box<BrOnCast<'a>>) : [] : "br_on_cast",
625        BrOnCastFail(Box<BrOnCastFail<'a>>) : [] : "br_on_cast_fail",
626
627        // gc proposal extern/any coercion operations
628        AnyConvertExtern : [0xfb, 0x1a] : "any.convert_extern",
629        ExternConvertAny : [0xfb, 0x1b] : "extern.convert_any",
630
631        I32Const(i32) : [0x41] : "i32.const",
632        I64Const(i64) : [0x42] : "i64.const",
633        F32Const(F32) : [0x43] : "f32.const",
634        F64Const(F64) : [0x44] : "f64.const",
635
636        I32Clz : [0x67] : "i32.clz",
637        I32Ctz : [0x68] : "i32.ctz",
638        I32Popcnt : [0x69] : "i32.popcnt",
639        I32Add : [0x6a] : "i32.add",
640        I32Sub : [0x6b] : "i32.sub",
641        I32Mul : [0x6c] : "i32.mul",
642        I32DivS : [0x6d] : "i32.div_s",
643        I32DivU : [0x6e] : "i32.div_u",
644        I32RemS : [0x6f] : "i32.rem_s",
645        I32RemU : [0x70] : "i32.rem_u",
646        I32And : [0x71] : "i32.and",
647        I32Or : [0x72] : "i32.or",
648        I32Xor : [0x73] : "i32.xor",
649        I32Shl : [0x74] : "i32.shl",
650        I32ShrS : [0x75] : "i32.shr_s",
651        I32ShrU : [0x76] : "i32.shr_u",
652        I32Rotl : [0x77] : "i32.rotl",
653        I32Rotr : [0x78] : "i32.rotr",
654
655        I64Clz : [0x79] : "i64.clz",
656        I64Ctz : [0x7a] : "i64.ctz",
657        I64Popcnt : [0x7b] : "i64.popcnt",
658        I64Add : [0x7c] : "i64.add",
659        I64Sub : [0x7d] : "i64.sub",
660        I64Mul : [0x7e] : "i64.mul",
661        I64DivS : [0x7f] : "i64.div_s",
662        I64DivU : [0x80] : "i64.div_u",
663        I64RemS : [0x81] : "i64.rem_s",
664        I64RemU : [0x82] : "i64.rem_u",
665        I64And : [0x83] : "i64.and",
666        I64Or : [0x84] : "i64.or",
667        I64Xor : [0x85] : "i64.xor",
668        I64Shl : [0x86] : "i64.shl",
669        I64ShrS : [0x87] : "i64.shr_s",
670        I64ShrU : [0x88] : "i64.shr_u",
671        I64Rotl : [0x89] : "i64.rotl",
672        I64Rotr : [0x8a] : "i64.rotr",
673
674        F32Abs : [0x8b] : "f32.abs",
675        F32Neg : [0x8c] : "f32.neg",
676        F32Ceil : [0x8d] : "f32.ceil",
677        F32Floor : [0x8e] : "f32.floor",
678        F32Trunc : [0x8f] : "f32.trunc",
679        F32Nearest : [0x90] : "f32.nearest",
680        F32Sqrt : [0x91] : "f32.sqrt",
681        F32Add : [0x92] : "f32.add",
682        F32Sub : [0x93] : "f32.sub",
683        F32Mul : [0x94] : "f32.mul",
684        F32Div : [0x95] : "f32.div",
685        F32Min : [0x96] : "f32.min",
686        F32Max : [0x97] : "f32.max",
687        F32Copysign : [0x98] : "f32.copysign",
688
689        F64Abs : [0x99] : "f64.abs",
690        F64Neg : [0x9a] : "f64.neg",
691        F64Ceil : [0x9b] : "f64.ceil",
692        F64Floor : [0x9c] : "f64.floor",
693        F64Trunc : [0x9d] : "f64.trunc",
694        F64Nearest : [0x9e] : "f64.nearest",
695        F64Sqrt : [0x9f] : "f64.sqrt",
696        F64Add : [0xa0] : "f64.add",
697        F64Sub : [0xa1] : "f64.sub",
698        F64Mul : [0xa2] : "f64.mul",
699        F64Div : [0xa3] : "f64.div",
700        F64Min : [0xa4] : "f64.min",
701        F64Max : [0xa5] : "f64.max",
702        F64Copysign : [0xa6] : "f64.copysign",
703
704        I32Eqz : [0x45] : "i32.eqz",
705        I32Eq : [0x46] : "i32.eq",
706        I32Ne : [0x47] : "i32.ne",
707        I32LtS : [0x48] : "i32.lt_s",
708        I32LtU : [0x49] : "i32.lt_u",
709        I32GtS : [0x4a] : "i32.gt_s",
710        I32GtU : [0x4b] : "i32.gt_u",
711        I32LeS : [0x4c] : "i32.le_s",
712        I32LeU : [0x4d] : "i32.le_u",
713        I32GeS : [0x4e] : "i32.ge_s",
714        I32GeU : [0x4f] : "i32.ge_u",
715
716        I64Eqz : [0x50] : "i64.eqz",
717        I64Eq : [0x51] : "i64.eq",
718        I64Ne : [0x52] : "i64.ne",
719        I64LtS : [0x53] : "i64.lt_s",
720        I64LtU : [0x54] : "i64.lt_u",
721        I64GtS : [0x55] : "i64.gt_s",
722        I64GtU : [0x56] : "i64.gt_u",
723        I64LeS : [0x57] : "i64.le_s",
724        I64LeU : [0x58] : "i64.le_u",
725        I64GeS : [0x59] : "i64.ge_s",
726        I64GeU : [0x5a] : "i64.ge_u",
727
728        F32Eq : [0x5b] : "f32.eq",
729        F32Ne : [0x5c] : "f32.ne",
730        F32Lt : [0x5d] : "f32.lt",
731        F32Gt : [0x5e] : "f32.gt",
732        F32Le : [0x5f] : "f32.le",
733        F32Ge : [0x60] : "f32.ge",
734
735        F64Eq : [0x61] : "f64.eq",
736        F64Ne : [0x62] : "f64.ne",
737        F64Lt : [0x63] : "f64.lt",
738        F64Gt : [0x64] : "f64.gt",
739        F64Le : [0x65] : "f64.le",
740        F64Ge : [0x66] : "f64.ge",
741
742        I32WrapI64 : [0xa7] : "i32.wrap_i64",
743        I32TruncF32S : [0xa8] : "i32.trunc_f32_s",
744        I32TruncF32U : [0xa9] : "i32.trunc_f32_u",
745        I32TruncF64S : [0xaa] : "i32.trunc_f64_s",
746        I32TruncF64U : [0xab] : "i32.trunc_f64_u",
747        I64ExtendI32S : [0xac] : "i64.extend_i32_s",
748        I64ExtendI32U : [0xad] : "i64.extend_i32_u",
749        I64TruncF32S : [0xae] : "i64.trunc_f32_s",
750        I64TruncF32U : [0xaf] : "i64.trunc_f32_u",
751        I64TruncF64S : [0xb0] : "i64.trunc_f64_s",
752        I64TruncF64U : [0xb1] : "i64.trunc_f64_u",
753        F32ConvertI32S : [0xb2] : "f32.convert_i32_s",
754        F32ConvertI32U : [0xb3] : "f32.convert_i32_u",
755        F32ConvertI64S : [0xb4] : "f32.convert_i64_s",
756        F32ConvertI64U : [0xb5] : "f32.convert_i64_u",
757        F32DemoteF64 : [0xb6] : "f32.demote_f64",
758        F64ConvertI32S : [0xb7] : "f64.convert_i32_s",
759        F64ConvertI32U : [0xb8] : "f64.convert_i32_u",
760        F64ConvertI64S : [0xb9] : "f64.convert_i64_s",
761        F64ConvertI64U : [0xba] : "f64.convert_i64_u",
762        F64PromoteF32 : [0xbb] : "f64.promote_f32",
763        I32ReinterpretF32 : [0xbc] : "i32.reinterpret_f32",
764        I64ReinterpretF64 : [0xbd] : "i64.reinterpret_f64",
765        F32ReinterpretI32 : [0xbe] : "f32.reinterpret_i32",
766        F64ReinterpretI64 : [0xbf] : "f64.reinterpret_i64",
767
768        // non-trapping float to int
769        I32TruncSatF32S : [0xfc, 0x00] : "i32.trunc_sat_f32_s",
770        I32TruncSatF32U : [0xfc, 0x01] : "i32.trunc_sat_f32_u",
771        I32TruncSatF64S : [0xfc, 0x02] : "i32.trunc_sat_f64_s",
772        I32TruncSatF64U : [0xfc, 0x03] : "i32.trunc_sat_f64_u",
773        I64TruncSatF32S : [0xfc, 0x04] : "i64.trunc_sat_f32_s",
774        I64TruncSatF32U : [0xfc, 0x05] : "i64.trunc_sat_f32_u",
775        I64TruncSatF64S : [0xfc, 0x06] : "i64.trunc_sat_f64_s",
776        I64TruncSatF64U : [0xfc, 0x07] : "i64.trunc_sat_f64_u",
777
778        // sign extension proposal
779        I32Extend8S : [0xc0] : "i32.extend8_s",
780        I32Extend16S : [0xc1] : "i32.extend16_s",
781        I64Extend8S : [0xc2] : "i64.extend8_s",
782        I64Extend16S : [0xc3] : "i64.extend16_s",
783        I64Extend32S : [0xc4] : "i64.extend32_s",
784
785        // atomics proposal
786        MemoryAtomicNotify(MemArg<4>) : [0xfe, 0x00] : "memory.atomic.notify",
787        MemoryAtomicWait32(MemArg<4>) : [0xfe, 0x01] : "memory.atomic.wait32",
788        MemoryAtomicWait64(MemArg<8>) : [0xfe, 0x02] : "memory.atomic.wait64",
789        AtomicFence : [0xfe, 0x03, 0x00] : "atomic.fence",
790
791        I32AtomicLoad(MemArg<4>) : [0xfe, 0x10] : "i32.atomic.load",
792        I64AtomicLoad(MemArg<8>) : [0xfe, 0x11] : "i64.atomic.load",
793        I32AtomicLoad8u(MemArg<1>) : [0xfe, 0x12] : "i32.atomic.load8_u",
794        I32AtomicLoad16u(MemArg<2>) : [0xfe, 0x13] : "i32.atomic.load16_u",
795        I64AtomicLoad8u(MemArg<1>) : [0xfe, 0x14] : "i64.atomic.load8_u",
796        I64AtomicLoad16u(MemArg<2>) : [0xfe, 0x15] : "i64.atomic.load16_u",
797        I64AtomicLoad32u(MemArg<4>) : [0xfe, 0x16] : "i64.atomic.load32_u",
798        I32AtomicStore(MemArg<4>) : [0xfe, 0x17] : "i32.atomic.store",
799        I64AtomicStore(MemArg<8>) : [0xfe, 0x18] : "i64.atomic.store",
800        I32AtomicStore8(MemArg<1>) : [0xfe, 0x19] : "i32.atomic.store8",
801        I32AtomicStore16(MemArg<2>) : [0xfe, 0x1a] : "i32.atomic.store16",
802        I64AtomicStore8(MemArg<1>) : [0xfe, 0x1b] : "i64.atomic.store8",
803        I64AtomicStore16(MemArg<2>) : [0xfe, 0x1c] : "i64.atomic.store16",
804        I64AtomicStore32(MemArg<4>) : [0xfe, 0x1d] : "i64.atomic.store32",
805
806        I32AtomicRmwAdd(MemArg<4>) : [0xfe, 0x1e] : "i32.atomic.rmw.add",
807        I64AtomicRmwAdd(MemArg<8>) : [0xfe, 0x1f] : "i64.atomic.rmw.add",
808        I32AtomicRmw8AddU(MemArg<1>) : [0xfe, 0x20] : "i32.atomic.rmw8.add_u",
809        I32AtomicRmw16AddU(MemArg<2>) : [0xfe, 0x21] : "i32.atomic.rmw16.add_u",
810        I64AtomicRmw8AddU(MemArg<1>) : [0xfe, 0x22] : "i64.atomic.rmw8.add_u",
811        I64AtomicRmw16AddU(MemArg<2>) : [0xfe, 0x23] : "i64.atomic.rmw16.add_u",
812        I64AtomicRmw32AddU(MemArg<4>) : [0xfe, 0x24] : "i64.atomic.rmw32.add_u",
813
814        I32AtomicRmwSub(MemArg<4>) : [0xfe, 0x25] : "i32.atomic.rmw.sub",
815        I64AtomicRmwSub(MemArg<8>) : [0xfe, 0x26] : "i64.atomic.rmw.sub",
816        I32AtomicRmw8SubU(MemArg<1>) : [0xfe, 0x27] : "i32.atomic.rmw8.sub_u",
817        I32AtomicRmw16SubU(MemArg<2>) : [0xfe, 0x28] : "i32.atomic.rmw16.sub_u",
818        I64AtomicRmw8SubU(MemArg<1>) : [0xfe, 0x29] : "i64.atomic.rmw8.sub_u",
819        I64AtomicRmw16SubU(MemArg<2>) : [0xfe, 0x2a] : "i64.atomic.rmw16.sub_u",
820        I64AtomicRmw32SubU(MemArg<4>) : [0xfe, 0x2b] : "i64.atomic.rmw32.sub_u",
821
822        I32AtomicRmwAnd(MemArg<4>) : [0xfe, 0x2c] : "i32.atomic.rmw.and",
823        I64AtomicRmwAnd(MemArg<8>) : [0xfe, 0x2d] : "i64.atomic.rmw.and",
824        I32AtomicRmw8AndU(MemArg<1>) : [0xfe, 0x2e] : "i32.atomic.rmw8.and_u",
825        I32AtomicRmw16AndU(MemArg<2>) : [0xfe, 0x2f] : "i32.atomic.rmw16.and_u",
826        I64AtomicRmw8AndU(MemArg<1>) : [0xfe, 0x30] : "i64.atomic.rmw8.and_u",
827        I64AtomicRmw16AndU(MemArg<2>) : [0xfe, 0x31] : "i64.atomic.rmw16.and_u",
828        I64AtomicRmw32AndU(MemArg<4>) : [0xfe, 0x32] : "i64.atomic.rmw32.and_u",
829
830        I32AtomicRmwOr(MemArg<4>) : [0xfe, 0x33] : "i32.atomic.rmw.or",
831        I64AtomicRmwOr(MemArg<8>) : [0xfe, 0x34] : "i64.atomic.rmw.or",
832        I32AtomicRmw8OrU(MemArg<1>) : [0xfe, 0x35] : "i32.atomic.rmw8.or_u",
833        I32AtomicRmw16OrU(MemArg<2>) : [0xfe, 0x36] : "i32.atomic.rmw16.or_u",
834        I64AtomicRmw8OrU(MemArg<1>) : [0xfe, 0x37] : "i64.atomic.rmw8.or_u",
835        I64AtomicRmw16OrU(MemArg<2>) : [0xfe, 0x38] : "i64.atomic.rmw16.or_u",
836        I64AtomicRmw32OrU(MemArg<4>) : [0xfe, 0x39] : "i64.atomic.rmw32.or_u",
837
838        I32AtomicRmwXor(MemArg<4>) : [0xfe, 0x3a] : "i32.atomic.rmw.xor",
839        I64AtomicRmwXor(MemArg<8>) : [0xfe, 0x3b] : "i64.atomic.rmw.xor",
840        I32AtomicRmw8XorU(MemArg<1>) : [0xfe, 0x3c] : "i32.atomic.rmw8.xor_u",
841        I32AtomicRmw16XorU(MemArg<2>) : [0xfe, 0x3d] : "i32.atomic.rmw16.xor_u",
842        I64AtomicRmw8XorU(MemArg<1>) : [0xfe, 0x3e] : "i64.atomic.rmw8.xor_u",
843        I64AtomicRmw16XorU(MemArg<2>) : [0xfe, 0x3f] : "i64.atomic.rmw16.xor_u",
844        I64AtomicRmw32XorU(MemArg<4>) : [0xfe, 0x40] : "i64.atomic.rmw32.xor_u",
845
846        I32AtomicRmwXchg(MemArg<4>) : [0xfe, 0x41] : "i32.atomic.rmw.xchg",
847        I64AtomicRmwXchg(MemArg<8>) : [0xfe, 0x42] : "i64.atomic.rmw.xchg",
848        I32AtomicRmw8XchgU(MemArg<1>) : [0xfe, 0x43] : "i32.atomic.rmw8.xchg_u",
849        I32AtomicRmw16XchgU(MemArg<2>) : [0xfe, 0x44] : "i32.atomic.rmw16.xchg_u",
850        I64AtomicRmw8XchgU(MemArg<1>) : [0xfe, 0x45] : "i64.atomic.rmw8.xchg_u",
851        I64AtomicRmw16XchgU(MemArg<2>) : [0xfe, 0x46] : "i64.atomic.rmw16.xchg_u",
852        I64AtomicRmw32XchgU(MemArg<4>) : [0xfe, 0x47] : "i64.atomic.rmw32.xchg_u",
853
854        I32AtomicRmwCmpxchg(MemArg<4>) : [0xfe, 0x48] : "i32.atomic.rmw.cmpxchg",
855        I64AtomicRmwCmpxchg(MemArg<8>) : [0xfe, 0x49] : "i64.atomic.rmw.cmpxchg",
856        I32AtomicRmw8CmpxchgU(MemArg<1>) : [0xfe, 0x4a] : "i32.atomic.rmw8.cmpxchg_u",
857        I32AtomicRmw16CmpxchgU(MemArg<2>) : [0xfe, 0x4b] : "i32.atomic.rmw16.cmpxchg_u",
858        I64AtomicRmw8CmpxchgU(MemArg<1>) : [0xfe, 0x4c] : "i64.atomic.rmw8.cmpxchg_u",
859        I64AtomicRmw16CmpxchgU(MemArg<2>) : [0xfe, 0x4d] : "i64.atomic.rmw16.cmpxchg_u",
860        I64AtomicRmw32CmpxchgU(MemArg<4>) : [0xfe, 0x4e] : "i64.atomic.rmw32.cmpxchg_u",
861
862        // proposal: shared-everything-threads
863        GlobalAtomicGet(Ordered<Index<'a>>) : [0xfe, 0x4f] : "global.atomic.get",
864        GlobalAtomicSet(Ordered<Index<'a>>) : [0xfe, 0x50] : "global.atomic.set",
865        GlobalAtomicRmwAdd(Ordered<Index<'a>>) : [0xfe, 0x51] : "global.atomic.rmw.add",
866        GlobalAtomicRmwSub(Ordered<Index<'a>>) : [0xfe, 0x52] : "global.atomic.rmw.sub",
867        GlobalAtomicRmwAnd(Ordered<Index<'a>>) : [0xfe, 0x53] : "global.atomic.rmw.and",
868        GlobalAtomicRmwOr(Ordered<Index<'a>>) : [0xfe, 0x54] : "global.atomic.rmw.or",
869        GlobalAtomicRmwXor(Ordered<Index<'a>>) : [0xfe, 0x55] : "global.atomic.rmw.xor",
870        GlobalAtomicRmwXchg(Ordered<Index<'a>>) : [0xfe, 0x56] : "global.atomic.rmw.xchg",
871        GlobalAtomicRmwCmpxchg(Ordered<Index<'a>>) : [0xfe, 0x57] : "global.atomic.rmw.cmpxchg",
872        TableAtomicGet(Ordered<TableArg<'a>>) : [0xfe, 0x58] : "table.atomic.get",
873        TableAtomicSet(Ordered<TableArg<'a>>) : [0xfe, 0x59] : "table.atomic.set",
874        TableAtomicRmwXchg(Ordered<TableArg<'a>>) : [0xfe, 0x5a] : "table.atomic.rmw.xchg",
875        TableAtomicRmwCmpxchg(Ordered<TableArg<'a>>) : [0xfe, 0x5b] : "table.atomic.rmw.cmpxchg",
876        StructAtomicGet(Ordered<StructAccess<'a>>) : [0xfe, 0x5c] : "struct.atomic.get",
877        StructAtomicGetS(Ordered<StructAccess<'a>>) : [0xfe, 0x5d] : "struct.atomic.get_s",
878        StructAtomicGetU(Ordered<StructAccess<'a>>) : [0xfe, 0x5e] : "struct.atomic.get_u",
879        StructAtomicSet(Ordered<StructAccess<'a>>) : [0xfe, 0x5f] : "struct.atomic.set",
880        StructAtomicRmwAdd(Ordered<StructAccess<'a>>) : [0xfe, 0x60] : "struct.atomic.rmw.add",
881        StructAtomicRmwSub(Ordered<StructAccess<'a>>) : [0xfe, 0x61] : "struct.atomic.rmw.sub",
882        StructAtomicRmwAnd(Ordered<StructAccess<'a>>) : [0xfe, 0x62] : "struct.atomic.rmw.and",
883        StructAtomicRmwOr(Ordered<StructAccess<'a>>) : [0xfe, 0x63] : "struct.atomic.rmw.or",
884        StructAtomicRmwXor(Ordered<StructAccess<'a>>) : [0xfe, 0x64] : "struct.atomic.rmw.xor",
885        StructAtomicRmwXchg(Ordered<StructAccess<'a>>) : [0xfe, 0x65] : "struct.atomic.rmw.xchg",
886        StructAtomicRmwCmpxchg(Ordered<StructAccess<'a>>) : [0xfe, 0x66] : "struct.atomic.rmw.cmpxchg",
887        ArrayAtomicGet(Ordered<Index<'a>>) : [0xfe, 0x67] : "array.atomic.get",
888        ArrayAtomicGetS(Ordered<Index<'a>>) : [0xfe, 0x68] : "array.atomic.get_s",
889        ArrayAtomicGetU(Ordered<Index<'a>>) : [0xfe, 0x69] : "array.atomic.get_u",
890        ArrayAtomicSet(Ordered<Index<'a>>) : [0xfe, 0x6a] : "array.atomic.set",
891        ArrayAtomicRmwAdd(Ordered<Index<'a>>) : [0xfe, 0x6b] : "array.atomic.rmw.add",
892        ArrayAtomicRmwSub(Ordered<Index<'a>>) : [0xfe, 0x6c] : "array.atomic.rmw.sub",
893        ArrayAtomicRmwAnd(Ordered<Index<'a>>) : [0xfe, 0x6d] : "array.atomic.rmw.and",
894        ArrayAtomicRmwOr(Ordered<Index<'a>>) : [0xfe, 0x6e] : "array.atomic.rmw.or",
895        ArrayAtomicRmwXor(Ordered<Index<'a>>) : [0xfe, 0x6f] : "array.atomic.rmw.xor",
896        ArrayAtomicRmwXchg(Ordered<Index<'a>>) : [0xfe, 0x70] : "array.atomic.rmw.xchg",
897        ArrayAtomicRmwCmpxchg(Ordered<Index<'a>>) : [0xfe, 0x71] : "array.atomic.rmw.cmpxchg",
898        RefI31Shared : [0xfe, 0x72] : "ref.i31_shared",
899
900        // proposal: simd
901        //
902        // https://webassembly.github.io/simd/core/binary/instructions.html
903        V128Load(MemArg<16>) : [0xfd, 0] : "v128.load",
904        V128Load8x8S(MemArg<8>) : [0xfd, 1] : "v128.load8x8_s",
905        V128Load8x8U(MemArg<8>) : [0xfd, 2] : "v128.load8x8_u",
906        V128Load16x4S(MemArg<8>) : [0xfd, 3] : "v128.load16x4_s",
907        V128Load16x4U(MemArg<8>) : [0xfd, 4] : "v128.load16x4_u",
908        V128Load32x2S(MemArg<8>) : [0xfd, 5] : "v128.load32x2_s",
909        V128Load32x2U(MemArg<8>) : [0xfd, 6] : "v128.load32x2_u",
910        V128Load8Splat(MemArg<1>) : [0xfd, 7] : "v128.load8_splat",
911        V128Load16Splat(MemArg<2>) : [0xfd, 8] : "v128.load16_splat",
912        V128Load32Splat(MemArg<4>) : [0xfd, 9] : "v128.load32_splat",
913        V128Load64Splat(MemArg<8>) : [0xfd, 10] : "v128.load64_splat",
914        V128Load32Zero(MemArg<4>) : [0xfd, 92] : "v128.load32_zero",
915        V128Load64Zero(MemArg<8>) : [0xfd, 93] : "v128.load64_zero",
916        V128Store(MemArg<16>) : [0xfd, 11] : "v128.store",
917
918        V128Load8Lane(LoadOrStoreLane<1>) : [0xfd, 84] : "v128.load8_lane",
919        V128Load16Lane(LoadOrStoreLane<2>) : [0xfd, 85] : "v128.load16_lane",
920        V128Load32Lane(LoadOrStoreLane<4>) : [0xfd, 86] : "v128.load32_lane",
921        V128Load64Lane(LoadOrStoreLane<8>): [0xfd, 87] : "v128.load64_lane",
922        V128Store8Lane(LoadOrStoreLane<1>) : [0xfd, 88] : "v128.store8_lane",
923        V128Store16Lane(LoadOrStoreLane<2>) : [0xfd, 89] : "v128.store16_lane",
924        V128Store32Lane(LoadOrStoreLane<4>) : [0xfd, 90] : "v128.store32_lane",
925        V128Store64Lane(LoadOrStoreLane<8>) : [0xfd, 91] : "v128.store64_lane",
926
927        V128Const(V128Const) : [0xfd, 12] : "v128.const",
928        I8x16Shuffle(I8x16Shuffle) : [0xfd, 13] : "i8x16.shuffle",
929
930        I8x16ExtractLaneS(LaneArg) : [0xfd, 21] : "i8x16.extract_lane_s",
931        I8x16ExtractLaneU(LaneArg) : [0xfd, 22] : "i8x16.extract_lane_u",
932        I8x16ReplaceLane(LaneArg) : [0xfd, 23] : "i8x16.replace_lane",
933        I16x8ExtractLaneS(LaneArg) : [0xfd, 24] : "i16x8.extract_lane_s",
934        I16x8ExtractLaneU(LaneArg) : [0xfd, 25] : "i16x8.extract_lane_u",
935        I16x8ReplaceLane(LaneArg) : [0xfd, 26] : "i16x8.replace_lane",
936        I32x4ExtractLane(LaneArg) : [0xfd, 27] : "i32x4.extract_lane",
937        I32x4ReplaceLane(LaneArg) : [0xfd, 28] : "i32x4.replace_lane",
938        I64x2ExtractLane(LaneArg) : [0xfd, 29] : "i64x2.extract_lane",
939        I64x2ReplaceLane(LaneArg) : [0xfd, 30] : "i64x2.replace_lane",
940        F32x4ExtractLane(LaneArg) : [0xfd, 31] : "f32x4.extract_lane",
941        F32x4ReplaceLane(LaneArg) : [0xfd, 32] : "f32x4.replace_lane",
942        F64x2ExtractLane(LaneArg) : [0xfd, 33] : "f64x2.extract_lane",
943        F64x2ReplaceLane(LaneArg) : [0xfd, 34] : "f64x2.replace_lane",
944
945        I8x16Swizzle : [0xfd, 14] : "i8x16.swizzle",
946        I8x16Splat : [0xfd, 15] : "i8x16.splat",
947        I16x8Splat : [0xfd, 16] : "i16x8.splat",
948        I32x4Splat : [0xfd, 17] : "i32x4.splat",
949        I64x2Splat : [0xfd, 18] : "i64x2.splat",
950        F32x4Splat : [0xfd, 19] : "f32x4.splat",
951        F64x2Splat : [0xfd, 20] : "f64x2.splat",
952
953        I8x16Eq : [0xfd, 35] : "i8x16.eq",
954        I8x16Ne : [0xfd, 36] : "i8x16.ne",
955        I8x16LtS : [0xfd, 37] : "i8x16.lt_s",
956        I8x16LtU : [0xfd, 38] : "i8x16.lt_u",
957        I8x16GtS : [0xfd, 39] : "i8x16.gt_s",
958        I8x16GtU : [0xfd, 40] : "i8x16.gt_u",
959        I8x16LeS : [0xfd, 41] : "i8x16.le_s",
960        I8x16LeU : [0xfd, 42] : "i8x16.le_u",
961        I8x16GeS : [0xfd, 43] : "i8x16.ge_s",
962        I8x16GeU : [0xfd, 44] : "i8x16.ge_u",
963
964        I16x8Eq : [0xfd, 45] : "i16x8.eq",
965        I16x8Ne : [0xfd, 46] : "i16x8.ne",
966        I16x8LtS : [0xfd, 47] : "i16x8.lt_s",
967        I16x8LtU : [0xfd, 48] : "i16x8.lt_u",
968        I16x8GtS : [0xfd, 49] : "i16x8.gt_s",
969        I16x8GtU : [0xfd, 50] : "i16x8.gt_u",
970        I16x8LeS : [0xfd, 51] : "i16x8.le_s",
971        I16x8LeU : [0xfd, 52] : "i16x8.le_u",
972        I16x8GeS : [0xfd, 53] : "i16x8.ge_s",
973        I16x8GeU : [0xfd, 54] : "i16x8.ge_u",
974
975        I32x4Eq : [0xfd, 55] : "i32x4.eq",
976        I32x4Ne : [0xfd, 56] : "i32x4.ne",
977        I32x4LtS : [0xfd, 57] : "i32x4.lt_s",
978        I32x4LtU : [0xfd, 58] : "i32x4.lt_u",
979        I32x4GtS : [0xfd, 59] : "i32x4.gt_s",
980        I32x4GtU : [0xfd, 60] : "i32x4.gt_u",
981        I32x4LeS : [0xfd, 61] : "i32x4.le_s",
982        I32x4LeU : [0xfd, 62] : "i32x4.le_u",
983        I32x4GeS : [0xfd, 63] : "i32x4.ge_s",
984        I32x4GeU : [0xfd, 64] : "i32x4.ge_u",
985
986        I64x2Eq : [0xfd, 214] : "i64x2.eq",
987        I64x2Ne : [0xfd, 215] : "i64x2.ne",
988        I64x2LtS : [0xfd, 216] : "i64x2.lt_s",
989        I64x2GtS : [0xfd, 217] : "i64x2.gt_s",
990        I64x2LeS : [0xfd, 218] : "i64x2.le_s",
991        I64x2GeS : [0xfd, 219] : "i64x2.ge_s",
992
993        F32x4Eq : [0xfd, 65] : "f32x4.eq",
994        F32x4Ne : [0xfd, 66] : "f32x4.ne",
995        F32x4Lt : [0xfd, 67] : "f32x4.lt",
996        F32x4Gt : [0xfd, 68] : "f32x4.gt",
997        F32x4Le : [0xfd, 69] : "f32x4.le",
998        F32x4Ge : [0xfd, 70] : "f32x4.ge",
999
1000        F64x2Eq : [0xfd, 71] : "f64x2.eq",
1001        F64x2Ne : [0xfd, 72] : "f64x2.ne",
1002        F64x2Lt : [0xfd, 73] : "f64x2.lt",
1003        F64x2Gt : [0xfd, 74] : "f64x2.gt",
1004        F64x2Le : [0xfd, 75] : "f64x2.le",
1005        F64x2Ge : [0xfd, 76] : "f64x2.ge",
1006
1007        V128Not : [0xfd, 77] : "v128.not",
1008        V128And : [0xfd, 78] : "v128.and",
1009        V128Andnot : [0xfd, 79] : "v128.andnot",
1010        V128Or : [0xfd, 80] : "v128.or",
1011        V128Xor : [0xfd, 81] : "v128.xor",
1012        V128Bitselect : [0xfd, 82] : "v128.bitselect",
1013        V128AnyTrue : [0xfd, 83] : "v128.any_true",
1014
1015        I8x16Abs : [0xfd, 96] : "i8x16.abs",
1016        I8x16Neg : [0xfd, 97] : "i8x16.neg",
1017        I8x16Popcnt : [0xfd, 98] : "i8x16.popcnt",
1018        I8x16AllTrue : [0xfd, 99] : "i8x16.all_true",
1019        I8x16Bitmask : [0xfd, 100] : "i8x16.bitmask",
1020        I8x16NarrowI16x8S : [0xfd, 101] : "i8x16.narrow_i16x8_s",
1021        I8x16NarrowI16x8U : [0xfd, 102] : "i8x16.narrow_i16x8_u",
1022        I8x16Shl : [0xfd, 107] : "i8x16.shl",
1023        I8x16ShrS : [0xfd, 108] : "i8x16.shr_s",
1024        I8x16ShrU : [0xfd, 109] : "i8x16.shr_u",
1025        I8x16Add : [0xfd, 110] : "i8x16.add",
1026        I8x16AddSatS : [0xfd, 111] : "i8x16.add_sat_s",
1027        I8x16AddSatU : [0xfd, 112] : "i8x16.add_sat_u",
1028        I8x16Sub : [0xfd, 113] : "i8x16.sub",
1029        I8x16SubSatS : [0xfd, 114] : "i8x16.sub_sat_s",
1030        I8x16SubSatU : [0xfd, 115] : "i8x16.sub_sat_u",
1031        I8x16MinS : [0xfd, 118] : "i8x16.min_s",
1032        I8x16MinU : [0xfd, 119] : "i8x16.min_u",
1033        I8x16MaxS : [0xfd, 120] : "i8x16.max_s",
1034        I8x16MaxU : [0xfd, 121] : "i8x16.max_u",
1035        I8x16AvgrU : [0xfd, 123] : "i8x16.avgr_u",
1036
1037        I16x8ExtAddPairwiseI8x16S : [0xfd, 124] : "i16x8.extadd_pairwise_i8x16_s",
1038        I16x8ExtAddPairwiseI8x16U : [0xfd, 125] : "i16x8.extadd_pairwise_i8x16_u",
1039        I16x8Abs : [0xfd, 128] : "i16x8.abs",
1040        I16x8Neg : [0xfd, 129] : "i16x8.neg",
1041        I16x8Q15MulrSatS : [0xfd, 130] : "i16x8.q15mulr_sat_s",
1042        I16x8AllTrue : [0xfd, 131] : "i16x8.all_true",
1043        I16x8Bitmask : [0xfd, 132] : "i16x8.bitmask",
1044        I16x8NarrowI32x4S : [0xfd, 133] : "i16x8.narrow_i32x4_s",
1045        I16x8NarrowI32x4U : [0xfd, 134] : "i16x8.narrow_i32x4_u",
1046        I16x8ExtendLowI8x16S : [0xfd, 135] : "i16x8.extend_low_i8x16_s",
1047        I16x8ExtendHighI8x16S : [0xfd, 136] : "i16x8.extend_high_i8x16_s",
1048        I16x8ExtendLowI8x16U : [0xfd, 137] : "i16x8.extend_low_i8x16_u",
1049        I16x8ExtendHighI8x16u : [0xfd, 138] : "i16x8.extend_high_i8x16_u",
1050        I16x8Shl : [0xfd, 139] : "i16x8.shl",
1051        I16x8ShrS : [0xfd, 140] : "i16x8.shr_s",
1052        I16x8ShrU : [0xfd, 141] : "i16x8.shr_u",
1053        I16x8Add : [0xfd, 142] : "i16x8.add",
1054        I16x8AddSatS : [0xfd, 143] : "i16x8.add_sat_s",
1055        I16x8AddSatU : [0xfd, 144] : "i16x8.add_sat_u",
1056        I16x8Sub : [0xfd, 145] : "i16x8.sub",
1057        I16x8SubSatS : [0xfd, 146] : "i16x8.sub_sat_s",
1058        I16x8SubSatU : [0xfd, 147] : "i16x8.sub_sat_u",
1059        I16x8Mul : [0xfd, 149] : "i16x8.mul",
1060        I16x8MinS : [0xfd, 150] : "i16x8.min_s",
1061        I16x8MinU : [0xfd, 151] : "i16x8.min_u",
1062        I16x8MaxS : [0xfd, 152] : "i16x8.max_s",
1063        I16x8MaxU : [0xfd, 153] : "i16x8.max_u",
1064        I16x8AvgrU : [0xfd, 155] : "i16x8.avgr_u",
1065        I16x8ExtMulLowI8x16S : [0xfd, 156] : "i16x8.extmul_low_i8x16_s",
1066        I16x8ExtMulHighI8x16S : [0xfd, 157] : "i16x8.extmul_high_i8x16_s",
1067        I16x8ExtMulLowI8x16U : [0xfd, 158] : "i16x8.extmul_low_i8x16_u",
1068        I16x8ExtMulHighI8x16U : [0xfd, 159] : "i16x8.extmul_high_i8x16_u",
1069
1070        I32x4ExtAddPairwiseI16x8S : [0xfd, 126] : "i32x4.extadd_pairwise_i16x8_s",
1071        I32x4ExtAddPairwiseI16x8U : [0xfd, 127] : "i32x4.extadd_pairwise_i16x8_u",
1072        I32x4Abs : [0xfd, 160] : "i32x4.abs",
1073        I32x4Neg : [0xfd, 161] : "i32x4.neg",
1074        I32x4AllTrue : [0xfd, 163] : "i32x4.all_true",
1075        I32x4Bitmask : [0xfd, 164] : "i32x4.bitmask",
1076        I32x4ExtendLowI16x8S : [0xfd, 167] : "i32x4.extend_low_i16x8_s",
1077        I32x4ExtendHighI16x8S : [0xfd, 168] : "i32x4.extend_high_i16x8_s",
1078        I32x4ExtendLowI16x8U : [0xfd, 169] : "i32x4.extend_low_i16x8_u",
1079        I32x4ExtendHighI16x8U : [0xfd, 170] : "i32x4.extend_high_i16x8_u",
1080        I32x4Shl : [0xfd, 171] : "i32x4.shl",
1081        I32x4ShrS : [0xfd, 172] : "i32x4.shr_s",
1082        I32x4ShrU : [0xfd, 173] : "i32x4.shr_u",
1083        I32x4Add : [0xfd, 174] : "i32x4.add",
1084        I32x4Sub : [0xfd, 177] : "i32x4.sub",
1085        I32x4Mul : [0xfd, 181] : "i32x4.mul",
1086        I32x4MinS : [0xfd, 182] : "i32x4.min_s",
1087        I32x4MinU : [0xfd, 183] : "i32x4.min_u",
1088        I32x4MaxS : [0xfd, 184] : "i32x4.max_s",
1089        I32x4MaxU : [0xfd, 185] : "i32x4.max_u",
1090        I32x4DotI16x8S : [0xfd, 186] : "i32x4.dot_i16x8_s",
1091        I32x4ExtMulLowI16x8S : [0xfd, 188] : "i32x4.extmul_low_i16x8_s",
1092        I32x4ExtMulHighI16x8S : [0xfd, 189] : "i32x4.extmul_high_i16x8_s",
1093        I32x4ExtMulLowI16x8U : [0xfd, 190] : "i32x4.extmul_low_i16x8_u",
1094        I32x4ExtMulHighI16x8U : [0xfd, 191] : "i32x4.extmul_high_i16x8_u",
1095
1096        I64x2Abs : [0xfd, 192] : "i64x2.abs",
1097        I64x2Neg : [0xfd, 193] : "i64x2.neg",
1098        I64x2AllTrue : [0xfd, 195] : "i64x2.all_true",
1099        I64x2Bitmask : [0xfd, 196] : "i64x2.bitmask",
1100        I64x2ExtendLowI32x4S : [0xfd, 199] : "i64x2.extend_low_i32x4_s",
1101        I64x2ExtendHighI32x4S : [0xfd, 200] : "i64x2.extend_high_i32x4_s",
1102        I64x2ExtendLowI32x4U : [0xfd, 201] : "i64x2.extend_low_i32x4_u",
1103        I64x2ExtendHighI32x4U : [0xfd, 202] : "i64x2.extend_high_i32x4_u",
1104        I64x2Shl : [0xfd, 203] : "i64x2.shl",
1105        I64x2ShrS : [0xfd, 204] : "i64x2.shr_s",
1106        I64x2ShrU : [0xfd, 205] : "i64x2.shr_u",
1107        I64x2Add : [0xfd, 206] : "i64x2.add",
1108        I64x2Sub : [0xfd, 209] : "i64x2.sub",
1109        I64x2Mul : [0xfd, 213] : "i64x2.mul",
1110        I64x2ExtMulLowI32x4S : [0xfd, 220] : "i64x2.extmul_low_i32x4_s",
1111        I64x2ExtMulHighI32x4S : [0xfd, 221] : "i64x2.extmul_high_i32x4_s",
1112        I64x2ExtMulLowI32x4U : [0xfd, 222] : "i64x2.extmul_low_i32x4_u",
1113        I64x2ExtMulHighI32x4U : [0xfd, 223] : "i64x2.extmul_high_i32x4_u",
1114
1115        F32x4Ceil : [0xfd, 103] : "f32x4.ceil",
1116        F32x4Floor : [0xfd, 104] : "f32x4.floor",
1117        F32x4Trunc : [0xfd, 105] : "f32x4.trunc",
1118        F32x4Nearest : [0xfd, 106] : "f32x4.nearest",
1119        F32x4Abs : [0xfd, 224] : "f32x4.abs",
1120        F32x4Neg : [0xfd, 225] : "f32x4.neg",
1121        F32x4Sqrt : [0xfd, 227] : "f32x4.sqrt",
1122        F32x4Add : [0xfd, 228] : "f32x4.add",
1123        F32x4Sub : [0xfd, 229] : "f32x4.sub",
1124        F32x4Mul : [0xfd, 230] : "f32x4.mul",
1125        F32x4Div : [0xfd, 231] : "f32x4.div",
1126        F32x4Min : [0xfd, 232] : "f32x4.min",
1127        F32x4Max : [0xfd, 233] : "f32x4.max",
1128        F32x4PMin : [0xfd, 234] : "f32x4.pmin",
1129        F32x4PMax : [0xfd, 235] : "f32x4.pmax",
1130
1131        F64x2Ceil : [0xfd, 116] : "f64x2.ceil",
1132        F64x2Floor : [0xfd, 117] : "f64x2.floor",
1133        F64x2Trunc : [0xfd, 122] : "f64x2.trunc",
1134        F64x2Nearest : [0xfd, 148] : "f64x2.nearest",
1135        F64x2Abs : [0xfd, 236] : "f64x2.abs",
1136        F64x2Neg : [0xfd, 237] : "f64x2.neg",
1137        F64x2Sqrt : [0xfd, 239] : "f64x2.sqrt",
1138        F64x2Add : [0xfd, 240] : "f64x2.add",
1139        F64x2Sub : [0xfd, 241] : "f64x2.sub",
1140        F64x2Mul : [0xfd, 242] : "f64x2.mul",
1141        F64x2Div : [0xfd, 243] : "f64x2.div",
1142        F64x2Min : [0xfd, 244] : "f64x2.min",
1143        F64x2Max : [0xfd, 245] : "f64x2.max",
1144        F64x2PMin : [0xfd, 246] : "f64x2.pmin",
1145        F64x2PMax : [0xfd, 247] : "f64x2.pmax",
1146
1147        I32x4TruncSatF32x4S : [0xfd, 248] : "i32x4.trunc_sat_f32x4_s",
1148        I32x4TruncSatF32x4U : [0xfd, 249] : "i32x4.trunc_sat_f32x4_u",
1149        F32x4ConvertI32x4S : [0xfd, 250] : "f32x4.convert_i32x4_s",
1150        F32x4ConvertI32x4U : [0xfd, 251] : "f32x4.convert_i32x4_u",
1151        I32x4TruncSatF64x2SZero : [0xfd, 252] : "i32x4.trunc_sat_f64x2_s_zero",
1152        I32x4TruncSatF64x2UZero : [0xfd, 253] : "i32x4.trunc_sat_f64x2_u_zero",
1153        F64x2ConvertLowI32x4S : [0xfd, 254] : "f64x2.convert_low_i32x4_s",
1154        F64x2ConvertLowI32x4U : [0xfd, 255] : "f64x2.convert_low_i32x4_u",
1155        F32x4DemoteF64x2Zero : [0xfd, 94] : "f32x4.demote_f64x2_zero",
1156        F64x2PromoteLowF32x4 : [0xfd, 95] : "f64x2.promote_low_f32x4",
1157
1158        // Exception handling proposal
1159        ThrowRef : [0x0a] : "throw_ref",
1160        TryTable(TryTable<'a>) : [0x1f] : "try_table",
1161        Throw(Index<'a>) : [0x08] : "throw",
1162
1163        // Deprecated exception handling opcodes
1164        Try(Box<BlockType<'a>>) : [0x06] : "try",
1165        Catch(Index<'a>) : [0x07] : "catch",
1166        Rethrow(Index<'a>) : [0x09] : "rethrow",
1167        Delegate(Index<'a>) : [0x18] : "delegate",
1168        CatchAll : [0x19] : "catch_all",
1169
1170        // Relaxed SIMD proposal
1171        I8x16RelaxedSwizzle : [0xfd, 0x100]: "i8x16.relaxed_swizzle",
1172        I32x4RelaxedTruncF32x4S : [0xfd, 0x101]: "i32x4.relaxed_trunc_f32x4_s",
1173        I32x4RelaxedTruncF32x4U : [0xfd, 0x102]: "i32x4.relaxed_trunc_f32x4_u",
1174        I32x4RelaxedTruncF64x2SZero : [0xfd, 0x103]: "i32x4.relaxed_trunc_f64x2_s_zero",
1175        I32x4RelaxedTruncF64x2UZero : [0xfd, 0x104]: "i32x4.relaxed_trunc_f64x2_u_zero",
1176        F32x4RelaxedMadd : [0xfd, 0x105]: "f32x4.relaxed_madd",
1177        F32x4RelaxedNmadd : [0xfd, 0x106]: "f32x4.relaxed_nmadd",
1178        F64x2RelaxedMadd : [0xfd, 0x107]: "f64x2.relaxed_madd",
1179        F64x2RelaxedNmadd : [0xfd, 0x108]: "f64x2.relaxed_nmadd",
1180        I8x16RelaxedLaneselect : [0xfd, 0x109]: "i8x16.relaxed_laneselect",
1181        I16x8RelaxedLaneselect : [0xfd, 0x10A]: "i16x8.relaxed_laneselect",
1182        I32x4RelaxedLaneselect : [0xfd, 0x10B]: "i32x4.relaxed_laneselect",
1183        I64x2RelaxedLaneselect : [0xfd, 0x10C]: "i64x2.relaxed_laneselect",
1184        F32x4RelaxedMin : [0xfd, 0x10D]: "f32x4.relaxed_min",
1185        F32x4RelaxedMax : [0xfd, 0x10E]: "f32x4.relaxed_max",
1186        F64x2RelaxedMin : [0xfd, 0x10F]: "f64x2.relaxed_min",
1187        F64x2RelaxedMax : [0xfd, 0x110]: "f64x2.relaxed_max",
1188        I16x8RelaxedQ15mulrS: [0xfd, 0x111]: "i16x8.relaxed_q15mulr_s",
1189        I16x8RelaxedDotI8x16I7x16S: [0xfd, 0x112]: "i16x8.relaxed_dot_i8x16_i7x16_s",
1190        I32x4RelaxedDotI8x16I7x16AddS: [0xfd, 0x113]: "i32x4.relaxed_dot_i8x16_i7x16_add_s",
1191
1192        // Stack switching proposal
1193        ContNew(Index<'a>)             : [0xe0] : "cont.new",
1194        ContBind(ContBind<'a>)         : [0xe1] : "cont.bind",
1195        Suspend(Index<'a>)             : [0xe2] : "suspend",
1196        Resume(Resume<'a>)             : [0xe3] : "resume",
1197        ResumeThrow(ResumeThrow<'a>)   : [0xe4] : "resume_throw",
1198        Switch(Switch<'a>)             : [0xe5] : "switch",
1199
1200        // Wide arithmetic proposal
1201        I64Add128   : [0xfc, 19] : "i64.add128",
1202        I64Sub128   : [0xfc, 20] : "i64.sub128",
1203        I64MulWideS : [0xfc, 21] : "i64.mul_wide_s",
1204        I64MulWideU : [0xfc, 22] : "i64.mul_wide_u",
1205
1206        // Custom descriptors
1207        StructNewDesc(Index<'a>) : [0xfb, 32] : "struct.new_desc",
1208        StructNewDefaultDesc(Index<'a>) : [0xfb, 33] : "struct.new_default_desc",
1209        RefGetDesc(Index<'a>): [0xfb, 34] : "ref.get_desc",
1210        RefCastDesc(RefCastDesc<'a>) : [] : "ref.cast_desc",
1211        BrOnCastDesc(Box<BrOnCastDesc<'a>>) : [] : "br_on_cast_desc",
1212        BrOnCastDescFail(Box<BrOnCastDescFail<'a>>) : [] : "br_on_cast_desc_fail",
1213    }
1214}
1215
1216// As shown in #1095 the size of this variant is somewhat performance-sensitive
1217// since big `*.wat` files will have a lot of these. This is a small ratchet to
1218// make sure that this enum doesn't become larger than it already is, although
1219// ideally it also wouldn't be as large as it is now.
1220#[test]
1221fn assert_instruction_not_too_large() {
1222    let size = std::mem::size_of::<Instruction<'_>>();
1223    let pointer = std::mem::size_of::<u64>();
1224    assert!(size <= pointer * 11);
1225}
1226
1227impl<'a> Instruction<'a> {
1228    pub(crate) fn needs_data_count(&self) -> bool {
1229        match self {
1230            Instruction::MemoryInit(_)
1231            | Instruction::DataDrop(_)
1232            | Instruction::ArrayNewData(_)
1233            | Instruction::ArrayInitData(_) => true,
1234            _ => false,
1235        }
1236    }
1237}
1238
1239/// Extra information associated with block-related instructions.
1240///
1241/// This is used to label blocks and also annotate what types are expected for
1242/// the block.
1243#[derive(Debug, Clone)]
1244#[allow(missing_docs)]
1245pub struct BlockType<'a> {
1246    pub label: Option<Id<'a>>,
1247    pub label_name: Option<NameAnnotation<'a>>,
1248    pub ty: TypeUse<'a, FunctionType<'a>>,
1249}
1250
1251impl<'a> Parse<'a> for BlockType<'a> {
1252    fn parse(parser: Parser<'a>) -> Result<Self> {
1253        Ok(BlockType {
1254            label: parser.parse()?,
1255            label_name: parser.parse()?,
1256            ty: parser
1257                .parse::<TypeUse<'a, FunctionTypeNoNames<'a>>>()?
1258                .into(),
1259        })
1260    }
1261}
1262
1263/// Extra information associated with the cont.bind instruction
1264#[derive(Debug, Clone)]
1265#[allow(missing_docs)]
1266pub struct ContBind<'a> {
1267    pub argument_index: Index<'a>,
1268    pub result_index: Index<'a>,
1269}
1270
1271impl<'a> Parse<'a> for ContBind<'a> {
1272    fn parse(parser: Parser<'a>) -> Result<Self> {
1273        Ok(ContBind {
1274            argument_index: parser.parse()?,
1275            result_index: parser.parse()?,
1276        })
1277    }
1278}
1279
1280/// Extra information associated with the resume instruction
1281#[derive(Debug, Clone)]
1282#[allow(missing_docs)]
1283pub struct Resume<'a> {
1284    pub type_index: Index<'a>,
1285    pub table: ResumeTable<'a>,
1286}
1287
1288impl<'a> Parse<'a> for Resume<'a> {
1289    fn parse(parser: Parser<'a>) -> Result<Self> {
1290        Ok(Resume {
1291            type_index: parser.parse()?,
1292            table: parser.parse()?,
1293        })
1294    }
1295}
1296
1297/// Extra information associated with the resume_throw instruction
1298#[derive(Debug, Clone)]
1299#[allow(missing_docs)]
1300pub struct ResumeThrow<'a> {
1301    pub type_index: Index<'a>,
1302    pub tag_index: Index<'a>,
1303    pub table: ResumeTable<'a>,
1304}
1305
1306impl<'a> Parse<'a> for ResumeThrow<'a> {
1307    fn parse(parser: Parser<'a>) -> Result<Self> {
1308        Ok(ResumeThrow {
1309            type_index: parser.parse()?,
1310            tag_index: parser.parse()?,
1311            table: parser.parse()?,
1312        })
1313    }
1314}
1315
1316/// Extra information associated with the switch instruction
1317#[derive(Debug, Clone)]
1318#[allow(missing_docs)]
1319pub struct Switch<'a> {
1320    pub type_index: Index<'a>,
1321    pub tag_index: Index<'a>,
1322}
1323
1324impl<'a> Parse<'a> for Switch<'a> {
1325    fn parse(parser: Parser<'a>) -> Result<Self> {
1326        Ok(Switch {
1327            type_index: parser.parse()?,
1328            tag_index: parser.parse()?,
1329        })
1330    }
1331}
1332
1333/// A representation of resume tables
1334#[derive(Debug, Clone)]
1335#[allow(missing_docs)]
1336pub struct ResumeTable<'a> {
1337    pub handlers: Vec<Handle<'a>>,
1338}
1339
1340/// A representation of resume table entries
1341#[derive(Debug, Clone)]
1342#[allow(missing_docs)]
1343pub enum Handle<'a> {
1344    OnLabel { tag: Index<'a>, label: Index<'a> },
1345    OnSwitch { tag: Index<'a> },
1346}
1347
1348impl<'a> Parse<'a> for ResumeTable<'a> {
1349    fn parse(parser: Parser<'a>) -> Result<Self> {
1350        let mut handlers = Vec::new();
1351        while parser.peek::<LParen>()? && parser.peek2::<kw::on>()? {
1352            handlers.push(parser.parens(|p| {
1353                p.parse::<kw::on>()?;
1354                let tag: Index<'a> = p.parse()?;
1355                if p.peek::<kw::switch>()? {
1356                    p.parse::<kw::switch>()?;
1357                    Ok(Handle::OnSwitch { tag })
1358                } else {
1359                    Ok(Handle::OnLabel {
1360                        tag,
1361                        label: p.parse()?,
1362                    })
1363                }
1364            })?);
1365        }
1366        Ok(ResumeTable { handlers })
1367    }
1368}
1369
1370#[derive(Debug, Clone)]
1371#[allow(missing_docs)]
1372pub struct TryTable<'a> {
1373    pub block: Box<BlockType<'a>>,
1374    pub catches: Vec<TryTableCatch<'a>>,
1375}
1376
1377impl<'a> Parse<'a> for TryTable<'a> {
1378    fn parse(parser: Parser<'a>) -> Result<Self> {
1379        let block = parser.parse()?;
1380
1381        let mut catches = Vec::new();
1382        while parser.peek::<LParen>()?
1383            && (parser.peek2::<kw::catch>()?
1384                || parser.peek2::<kw::catch_ref>()?
1385                || parser.peek2::<kw::catch_all>()?
1386                || parser.peek2::<kw::catch_all_ref>()?)
1387        {
1388            catches.push(parser.parens(|p| {
1389                let kind = if parser.peek::<kw::catch_ref>()? {
1390                    p.parse::<kw::catch_ref>()?;
1391                    TryTableCatchKind::CatchRef(p.parse()?)
1392                } else if parser.peek::<kw::catch>()? {
1393                    p.parse::<kw::catch>()?;
1394                    TryTableCatchKind::Catch(p.parse()?)
1395                } else if parser.peek::<kw::catch_all>()? {
1396                    p.parse::<kw::catch_all>()?;
1397                    TryTableCatchKind::CatchAll
1398                } else {
1399                    p.parse::<kw::catch_all_ref>()?;
1400                    TryTableCatchKind::CatchAllRef
1401                };
1402
1403                Ok(TryTableCatch {
1404                    kind,
1405                    label: p.parse()?,
1406                })
1407            })?);
1408        }
1409
1410        Ok(TryTable { block, catches })
1411    }
1412}
1413
1414#[derive(Debug, Clone)]
1415#[allow(missing_docs)]
1416pub enum TryTableCatchKind<'a> {
1417    // Catch a tagged exception, do not capture an exnref.
1418    Catch(Index<'a>),
1419    // Catch a tagged exception, and capture the exnref.
1420    CatchRef(Index<'a>),
1421    // Catch any exception, do not capture an exnref.
1422    CatchAll,
1423    // Catch any exception, and capture the exnref.
1424    CatchAllRef,
1425}
1426
1427impl<'a> TryTableCatchKind<'a> {
1428    #[allow(missing_docs)]
1429    pub fn tag_index_mut(&mut self) -> Option<&mut Index<'a>> {
1430        match self {
1431            TryTableCatchKind::Catch(tag) | TryTableCatchKind::CatchRef(tag) => Some(tag),
1432            TryTableCatchKind::CatchAll | TryTableCatchKind::CatchAllRef => None,
1433        }
1434    }
1435}
1436
1437#[derive(Debug, Clone)]
1438#[allow(missing_docs)]
1439pub struct TryTableCatch<'a> {
1440    pub kind: TryTableCatchKind<'a>,
1441    pub label: Index<'a>,
1442}
1443
1444/// Extra information associated with the `br_table` instruction.
1445#[allow(missing_docs)]
1446#[derive(Debug, Clone)]
1447pub struct BrTableIndices<'a> {
1448    pub labels: Vec<Index<'a>>,
1449    pub default: Index<'a>,
1450}
1451
1452impl<'a> Parse<'a> for BrTableIndices<'a> {
1453    fn parse(parser: Parser<'a>) -> Result<Self> {
1454        let mut labels = vec![parser.parse()?];
1455        while parser.peek::<Index>()? {
1456            labels.push(parser.parse()?);
1457        }
1458        let default = labels.pop().unwrap();
1459        Ok(BrTableIndices { labels, default })
1460    }
1461}
1462
1463/// Payload for lane-related instructions. Unsigned with no + prefix.
1464#[derive(Debug, Clone)]
1465pub struct LaneArg {
1466    /// The lane argument.
1467    pub lane: u8,
1468}
1469
1470impl<'a> Parse<'a> for LaneArg {
1471    fn parse(parser: Parser<'a>) -> Result<Self> {
1472        let lane = parser.step(|c| {
1473            if let Some((i, rest)) = c.integer()? {
1474                if i.sign() == None {
1475                    let (src, radix) = i.val();
1476                    let val = u8::from_str_radix(src, radix)
1477                        .map_err(|_| c.error("malformed lane index"))?;
1478                    Ok((val, rest))
1479                } else {
1480                    Err(c.error("unexpected token"))
1481                }
1482            } else {
1483                Err(c.error("expected a lane index"))
1484            }
1485        })?;
1486        Ok(LaneArg { lane })
1487    }
1488}
1489
1490/// Payload for memory-related instructions indicating offset/alignment of
1491/// memory accesses.
1492#[derive(Debug, Clone)]
1493pub struct MemArg<'a> {
1494    /// The alignment of this access.
1495    ///
1496    /// This is not stored as a log, this is the actual alignment (e.g. 1, 2, 4,
1497    /// 8, etc).
1498    pub align: u64,
1499    /// The offset, in bytes of this access.
1500    pub offset: u64,
1501    /// The memory index we're accessing
1502    pub memory: Index<'a>,
1503}
1504
1505impl<'a> MemArg<'a> {
1506    fn parse(parser: Parser<'a>, default_align: u64) -> Result<Self> {
1507        fn parse_field(name: &str, parser: Parser<'_>) -> Result<Option<u64>> {
1508            parser.step(|c| {
1509                let (kw, rest) = match c.keyword()? {
1510                    Some(p) => p,
1511                    None => return Ok((None, c)),
1512                };
1513                if !kw.starts_with(name) {
1514                    return Ok((None, c));
1515                }
1516                let kw = &kw[name.len()..];
1517                if !kw.starts_with('=') {
1518                    return Ok((None, c));
1519                }
1520                let num = &kw[1..];
1521                let lexer = Lexer::new(num);
1522                let mut pos = 0;
1523                if let Ok(Some(
1524                    token @ Token {
1525                        kind: TokenKind::Integer(integer_kind),
1526                        ..
1527                    },
1528                )) = lexer.parse(&mut pos)
1529                {
1530                    let int = token.integer(lexer.input(), integer_kind);
1531                    let (s, base) = int.val();
1532                    let value = u64::from_str_radix(s, base);
1533                    return match value {
1534                        Ok(n) => Ok((Some(n), rest)),
1535                        Err(_) => Err(c.error("u64 constant out of range")),
1536                    };
1537                }
1538                Err(c.error("expected u64 integer constant"))
1539            })
1540        }
1541
1542        let memory = parser
1543            .parse::<Option<_>>()?
1544            .unwrap_or_else(|| Index::Num(0, parser.prev_span()));
1545        let offset = parse_field("offset", parser)?.unwrap_or(0);
1546        let align = match parse_field("align", parser)? {
1547            Some(n) if !n.is_power_of_two() => {
1548                return Err(parser.error("alignment must be a power of two"));
1549            }
1550            n => n.unwrap_or(default_align),
1551        };
1552
1553        Ok(MemArg {
1554            offset,
1555            align,
1556            memory,
1557        })
1558    }
1559}
1560
1561/// Extra data associated with the `loadN_lane` and `storeN_lane` instructions.
1562#[derive(Debug, Clone)]
1563pub struct LoadOrStoreLane<'a> {
1564    /// The memory argument for this instruction.
1565    pub memarg: MemArg<'a>,
1566    /// The lane argument for this instruction.
1567    pub lane: LaneArg,
1568}
1569
1570impl<'a> LoadOrStoreLane<'a> {
1571    fn parse(parser: Parser<'a>, default_align: u64) -> Result<Self> {
1572        // This is sort of funky. The first integer we see could be the lane
1573        // index, but it could also be the memory index. To determine what it is
1574        // then if we see a second integer we need to look further.
1575        let has_memarg = parser.step(|c| match c.integer()? {
1576            Some((_, after_int)) => {
1577                // Two integers in a row? That means that the first one is the
1578                // memory index and the second must be the lane index.
1579                if after_int.integer()?.is_some() {
1580                    return Ok((true, c));
1581                }
1582
1583                // If the first integer is trailed by `offset=...` or
1584                // `align=...` then this is definitely a memarg.
1585                if let Some((kw, _)) = after_int.keyword()? {
1586                    if kw.starts_with("offset=") || kw.starts_with("align=") {
1587                        return Ok((true, c));
1588                    }
1589                }
1590
1591                // Otherwise the first integer was trailed by something that
1592                // didn't look like a memarg, so this must be the lane index.
1593                Ok((false, c))
1594            }
1595
1596            // Not an integer here? That must mean that this must be the memarg
1597            // first followed by the trailing index.
1598            None => Ok((true, c)),
1599        })?;
1600        Ok(LoadOrStoreLane {
1601            memarg: if has_memarg {
1602                MemArg::parse(parser, default_align)?
1603            } else {
1604                MemArg {
1605                    align: default_align,
1606                    offset: 0,
1607                    memory: Index::Num(0, parser.prev_span()),
1608                }
1609            },
1610            lane: LaneArg::parse(parser)?,
1611        })
1612    }
1613}
1614
1615/// Extra data associated with the `call_indirect` instruction.
1616#[derive(Debug, Clone)]
1617pub struct CallIndirect<'a> {
1618    /// The table that this call is going to be indexing.
1619    pub table: Index<'a>,
1620    /// Type type signature that this `call_indirect` instruction is using.
1621    pub ty: TypeUse<'a, FunctionType<'a>>,
1622}
1623
1624impl<'a> Parse<'a> for CallIndirect<'a> {
1625    fn parse(parser: Parser<'a>) -> Result<Self> {
1626        let prev_span = parser.prev_span();
1627        let table: Option<_> = parser.parse()?;
1628        let ty = parser.parse::<TypeUse<'a, FunctionTypeNoNames<'a>>>()?;
1629        Ok(CallIndirect {
1630            table: table.unwrap_or(Index::Num(0, prev_span)),
1631            ty: ty.into(),
1632        })
1633    }
1634}
1635
1636/// Extra data associated with the `table.init` instruction
1637#[derive(Debug, Clone)]
1638pub struct TableInit<'a> {
1639    /// The index of the table we're copying into.
1640    pub table: Index<'a>,
1641    /// The index of the element segment we're copying into a table.
1642    pub elem: Index<'a>,
1643}
1644
1645impl<'a> Parse<'a> for TableInit<'a> {
1646    fn parse(parser: Parser<'a>) -> Result<Self> {
1647        let prev_span = parser.prev_span();
1648        let (elem, table) = if parser.peek2::<Index>()? {
1649            let table = parser.parse()?;
1650            (parser.parse()?, table)
1651        } else {
1652            (parser.parse()?, Index::Num(0, prev_span))
1653        };
1654        Ok(TableInit { table, elem })
1655    }
1656}
1657
1658/// Extra data associated with the `table.copy` instruction.
1659#[derive(Debug, Clone)]
1660pub struct TableCopy<'a> {
1661    /// The index of the destination table to copy into.
1662    pub dst: Index<'a>,
1663    /// The index of the source table to copy from.
1664    pub src: Index<'a>,
1665}
1666
1667impl<'a> Parse<'a> for TableCopy<'a> {
1668    fn parse(parser: Parser<'a>) -> Result<Self> {
1669        let (dst, src) = match parser.parse::<Option<_>>()? {
1670            Some(dst) => (dst, parser.parse()?),
1671            None => (
1672                Index::Num(0, parser.prev_span()),
1673                Index::Num(0, parser.prev_span()),
1674            ),
1675        };
1676        Ok(TableCopy { dst, src })
1677    }
1678}
1679
1680/// Extra data associated with unary table instructions.
1681#[derive(Debug, Clone)]
1682pub struct TableArg<'a> {
1683    /// The index of the table argument.
1684    pub dst: Index<'a>,
1685}
1686
1687// `TableArg` could be an unwrapped as an `Index` if not for this custom parse
1688// behavior: if we cannot parse a table index, we default to table `0`.
1689impl<'a> Parse<'a> for TableArg<'a> {
1690    fn parse(parser: Parser<'a>) -> Result<Self> {
1691        let dst = if let Some(dst) = parser.parse()? {
1692            dst
1693        } else {
1694            Index::Num(0, parser.prev_span())
1695        };
1696        Ok(TableArg { dst })
1697    }
1698}
1699
1700/// Extra data associated with unary memory instructions.
1701#[derive(Debug, Clone)]
1702pub struct MemoryArg<'a> {
1703    /// The index of the memory space.
1704    pub mem: Index<'a>,
1705}
1706
1707impl<'a> Parse<'a> for MemoryArg<'a> {
1708    fn parse(parser: Parser<'a>) -> Result<Self> {
1709        let mem = if let Some(mem) = parser.parse()? {
1710            mem
1711        } else {
1712            Index::Num(0, parser.prev_span())
1713        };
1714        Ok(MemoryArg { mem })
1715    }
1716}
1717
1718/// Extra data associated with the `memory.init` instruction
1719#[derive(Debug, Clone)]
1720pub struct MemoryInit<'a> {
1721    /// The index of the data segment we're copying into memory.
1722    pub data: Index<'a>,
1723    /// The index of the memory we're copying into,
1724    pub mem: Index<'a>,
1725}
1726
1727impl<'a> Parse<'a> for MemoryInit<'a> {
1728    fn parse(parser: Parser<'a>) -> Result<Self> {
1729        let prev_span = parser.prev_span();
1730        let (data, mem) = if parser.peek2::<Index>()? {
1731            let memory = parser.parse()?;
1732            (parser.parse()?, memory)
1733        } else {
1734            (parser.parse()?, Index::Num(0, prev_span))
1735        };
1736        Ok(MemoryInit { data, mem })
1737    }
1738}
1739
1740/// Extra data associated with the `memory.copy` instruction
1741#[derive(Debug, Clone)]
1742pub struct MemoryCopy<'a> {
1743    /// The index of the memory we're copying from.
1744    pub src: Index<'a>,
1745    /// The index of the memory we're copying to.
1746    pub dst: Index<'a>,
1747}
1748
1749impl<'a> Parse<'a> for MemoryCopy<'a> {
1750    fn parse(parser: Parser<'a>) -> Result<Self> {
1751        let (src, dst) = match parser.parse()? {
1752            Some(dst) => (parser.parse()?, dst),
1753            None => (
1754                Index::Num(0, parser.prev_span()),
1755                Index::Num(0, parser.prev_span()),
1756            ),
1757        };
1758        Ok(MemoryCopy { src, dst })
1759    }
1760}
1761
1762/// Extra data associated with the `struct.get/set` instructions
1763#[derive(Debug, Clone)]
1764pub struct StructAccess<'a> {
1765    /// The index of the struct type we're accessing.
1766    pub r#struct: Index<'a>,
1767    /// The index of the field of the struct we're accessing
1768    pub field: Index<'a>,
1769}
1770
1771impl<'a> Parse<'a> for StructAccess<'a> {
1772    fn parse(parser: Parser<'a>) -> Result<Self> {
1773        Ok(StructAccess {
1774            r#struct: parser.parse()?,
1775            field: parser.parse()?,
1776        })
1777    }
1778}
1779
1780/// Extra data associated with the `array.fill` instruction
1781#[derive(Debug, Clone)]
1782pub struct ArrayFill<'a> {
1783    /// The index of the array type we're filling.
1784    pub array: Index<'a>,
1785}
1786
1787impl<'a> Parse<'a> for ArrayFill<'a> {
1788    fn parse(parser: Parser<'a>) -> Result<Self> {
1789        Ok(ArrayFill {
1790            array: parser.parse()?,
1791        })
1792    }
1793}
1794
1795/// Extra data associated with the `array.copy` instruction
1796#[derive(Debug, Clone)]
1797pub struct ArrayCopy<'a> {
1798    /// The index of the array type we're copying to.
1799    pub dest_array: Index<'a>,
1800    /// The index of the array type we're copying from.
1801    pub src_array: Index<'a>,
1802}
1803
1804impl<'a> Parse<'a> for ArrayCopy<'a> {
1805    fn parse(parser: Parser<'a>) -> Result<Self> {
1806        Ok(ArrayCopy {
1807            dest_array: parser.parse()?,
1808            src_array: parser.parse()?,
1809        })
1810    }
1811}
1812
1813/// Extra data associated with the `array.init_[data/elem]` instruction
1814#[derive(Debug, Clone)]
1815pub struct ArrayInit<'a> {
1816    /// The index of the array type we're initializing.
1817    pub array: Index<'a>,
1818    /// The index of the data or elem segment we're reading from.
1819    pub segment: Index<'a>,
1820}
1821
1822impl<'a> Parse<'a> for ArrayInit<'a> {
1823    fn parse(parser: Parser<'a>) -> Result<Self> {
1824        Ok(ArrayInit {
1825            array: parser.parse()?,
1826            segment: parser.parse()?,
1827        })
1828    }
1829}
1830
1831/// Extra data associated with the `array.new_fixed` instruction
1832#[derive(Debug, Clone)]
1833pub struct ArrayNewFixed<'a> {
1834    /// The index of the array type we're accessing.
1835    pub array: Index<'a>,
1836    /// The amount of values to initialize the array with.
1837    pub length: u32,
1838}
1839
1840impl<'a> Parse<'a> for ArrayNewFixed<'a> {
1841    fn parse(parser: Parser<'a>) -> Result<Self> {
1842        Ok(ArrayNewFixed {
1843            array: parser.parse()?,
1844            length: parser.parse()?,
1845        })
1846    }
1847}
1848
1849/// Extra data associated with the `array.new_data` instruction
1850#[derive(Debug, Clone)]
1851pub struct ArrayNewData<'a> {
1852    /// The index of the array type we're accessing.
1853    pub array: Index<'a>,
1854    /// The data segment to initialize from.
1855    pub data_idx: Index<'a>,
1856}
1857
1858impl<'a> Parse<'a> for ArrayNewData<'a> {
1859    fn parse(parser: Parser<'a>) -> Result<Self> {
1860        Ok(ArrayNewData {
1861            array: parser.parse()?,
1862            data_idx: parser.parse()?,
1863        })
1864    }
1865}
1866
1867/// Extra data associated with the `array.new_elem` instruction
1868#[derive(Debug, Clone)]
1869pub struct ArrayNewElem<'a> {
1870    /// The index of the array type we're accessing.
1871    pub array: Index<'a>,
1872    /// The elem segment to initialize from.
1873    pub elem_idx: Index<'a>,
1874}
1875
1876impl<'a> Parse<'a> for ArrayNewElem<'a> {
1877    fn parse(parser: Parser<'a>) -> Result<Self> {
1878        Ok(ArrayNewElem {
1879            array: parser.parse()?,
1880            elem_idx: parser.parse()?,
1881        })
1882    }
1883}
1884
1885/// Extra data associated with the `ref.cast` instruction
1886#[derive(Debug, Clone)]
1887pub struct RefCast<'a> {
1888    /// The type to cast to.
1889    pub r#type: RefType<'a>,
1890}
1891
1892impl<'a> Parse<'a> for RefCast<'a> {
1893    fn parse(parser: Parser<'a>) -> Result<Self> {
1894        Ok(RefCast {
1895            r#type: parser.parse()?,
1896        })
1897    }
1898}
1899
1900/// Extra data associated with the `ref.test` instruction
1901#[derive(Debug, Clone)]
1902pub struct RefTest<'a> {
1903    /// The type to test for.
1904    pub r#type: RefType<'a>,
1905}
1906
1907impl<'a> Parse<'a> for RefTest<'a> {
1908    fn parse(parser: Parser<'a>) -> Result<Self> {
1909        Ok(RefTest {
1910            r#type: parser.parse()?,
1911        })
1912    }
1913}
1914
1915/// Extra data associated with the `br_on_cast` instruction
1916#[derive(Debug, Clone)]
1917pub struct BrOnCast<'a> {
1918    /// The label to branch to.
1919    pub label: Index<'a>,
1920    /// The type we're casting from.
1921    pub from_type: RefType<'a>,
1922    /// The type we're casting to.
1923    pub to_type: RefType<'a>,
1924}
1925
1926impl<'a> Parse<'a> for BrOnCast<'a> {
1927    fn parse(parser: Parser<'a>) -> Result<Self> {
1928        Ok(BrOnCast {
1929            label: parser.parse()?,
1930            from_type: parser.parse()?,
1931            to_type: parser.parse()?,
1932        })
1933    }
1934}
1935
1936/// Extra data associated with the `br_on_cast_fail` instruction
1937#[derive(Debug, Clone)]
1938pub struct BrOnCastFail<'a> {
1939    /// The label to branch to.
1940    pub label: Index<'a>,
1941    /// The type we're casting from.
1942    pub from_type: RefType<'a>,
1943    /// The type we're casting to.
1944    pub to_type: RefType<'a>,
1945}
1946
1947impl<'a> Parse<'a> for BrOnCastFail<'a> {
1948    fn parse(parser: Parser<'a>) -> Result<Self> {
1949        Ok(BrOnCastFail {
1950            label: parser.parse()?,
1951            from_type: parser.parse()?,
1952            to_type: parser.parse()?,
1953        })
1954    }
1955}
1956
1957/// Extra data associated with the `ref.cast_desc` instruction
1958#[derive(Debug, Clone)]
1959pub struct RefCastDesc<'a> {
1960    /// The type to cast to.
1961    pub r#type: RefType<'a>,
1962}
1963
1964impl<'a> Parse<'a> for RefCastDesc<'a> {
1965    fn parse(parser: Parser<'a>) -> Result<Self> {
1966        Ok(RefCastDesc {
1967            r#type: parser.parse()?,
1968        })
1969    }
1970}
1971
1972/// Extra data associated with the `br_on_cast_desc` instruction
1973#[derive(Debug, Clone)]
1974pub struct BrOnCastDesc<'a> {
1975    /// The label to branch to.
1976    pub label: Index<'a>,
1977    /// The type we're casting from.
1978    pub from_type: RefType<'a>,
1979    /// The type we're casting to.
1980    pub to_type: RefType<'a>,
1981}
1982
1983impl<'a> Parse<'a> for BrOnCastDesc<'a> {
1984    fn parse(parser: Parser<'a>) -> Result<Self> {
1985        Ok(BrOnCastDesc {
1986            label: parser.parse()?,
1987            from_type: parser.parse()?,
1988            to_type: parser.parse()?,
1989        })
1990    }
1991}
1992
1993/// Extra data associated with the `br_on_cast_desc_fail` instruction
1994#[derive(Debug, Clone)]
1995pub struct BrOnCastDescFail<'a> {
1996    /// The label to branch to.
1997    pub label: Index<'a>,
1998    /// The type we're casting from.
1999    pub from_type: RefType<'a>,
2000    /// The type we're casting to.
2001    pub to_type: RefType<'a>,
2002}
2003
2004impl<'a> Parse<'a> for BrOnCastDescFail<'a> {
2005    fn parse(parser: Parser<'a>) -> Result<Self> {
2006        Ok(BrOnCastDescFail {
2007            label: parser.parse()?,
2008            from_type: parser.parse()?,
2009            to_type: parser.parse()?,
2010        })
2011    }
2012}
2013
2014/// The memory ordering for atomic instructions.
2015///
2016/// For an in-depth explanation of memory orderings, see the C++ documentation
2017/// for [`memory_order`] or the Rust documentation for [`atomic::Ordering`].
2018///
2019/// [`memory_order`]: https://en.cppreference.com/w/cpp/atomic/memory_order
2020/// [`atomic::Ordering`]: https://doc.rust-lang.org/std/sync/atomic/enum.Ordering.html
2021#[derive(Clone, Debug)]
2022pub enum Ordering {
2023    /// Like `AcqRel` but all threads see all sequentially consistent operations
2024    /// in the same order.
2025    AcqRel,
2026    /// For a load, it acquires; this orders all operations before the last
2027    /// "releasing" store. For a store, it releases; this orders all operations
2028    /// before it at the next "acquiring" load.
2029    SeqCst,
2030}
2031
2032impl<'a> Parse<'a> for Ordering {
2033    fn parse(parser: Parser<'a>) -> Result<Self> {
2034        if parser.peek::<kw::seq_cst>()? {
2035            parser.parse::<kw::seq_cst>()?;
2036            Ok(Ordering::SeqCst)
2037        } else if parser.peek::<kw::acq_rel>()? {
2038            parser.parse::<kw::acq_rel>()?;
2039            Ok(Ordering::AcqRel)
2040        } else {
2041            Err(parser.error("expected a memory ordering: `seq_cst` or `acq_rel`"))
2042        }
2043    }
2044}
2045
2046/// Add a memory [`Ordering`] to the argument `T` of some instruction.
2047///
2048/// This is helpful for many kinds of `*.atomic.*` instructions introduced by
2049/// the shared-everything-threads proposal. Many of these instructions "build
2050/// on" existing instructions by simply adding a memory order to them.
2051#[derive(Clone, Debug)]
2052pub struct Ordered<T> {
2053    /// The memory ordering for this atomic instruction.
2054    pub ordering: Ordering,
2055    /// The original argument type.
2056    pub inner: T,
2057}
2058
2059impl<'a, T> Parse<'a> for Ordered<T>
2060where
2061    T: Parse<'a>,
2062{
2063    fn parse(parser: Parser<'a>) -> Result<Self> {
2064        let ordering = parser.parse()?;
2065        let inner = parser.parse()?;
2066        Ok(Ordered { ordering, inner })
2067    }
2068}
2069
2070/// Different ways to specify a `v128.const` instruction
2071#[derive(Clone, Debug)]
2072#[allow(missing_docs)]
2073pub enum V128Const {
2074    I8x16([i8; 16]),
2075    I16x8([i16; 8]),
2076    I32x4([i32; 4]),
2077    I64x2([i64; 2]),
2078    F32x4([F32; 4]),
2079    F64x2([F64; 2]),
2080}
2081
2082impl V128Const {
2083    /// Returns the raw little-ended byte sequence used to represent this
2084    /// `v128` constant`
2085    ///
2086    /// This is typically suitable for encoding as the payload of the
2087    /// `v128.const` instruction.
2088    #[rustfmt::skip]
2089    pub fn to_le_bytes(&self) -> [u8; 16] {
2090        match self {
2091            V128Const::I8x16(arr) => [
2092                arr[0] as u8,
2093                arr[1] as u8,
2094                arr[2] as u8,
2095                arr[3] as u8,
2096                arr[4] as u8,
2097                arr[5] as u8,
2098                arr[6] as u8,
2099                arr[7] as u8,
2100                arr[8] as u8,
2101                arr[9] as u8,
2102                arr[10] as u8,
2103                arr[11] as u8,
2104                arr[12] as u8,
2105                arr[13] as u8,
2106                arr[14] as u8,
2107                arr[15] as u8,
2108            ],
2109            V128Const::I16x8(arr) => {
2110                let a1 = arr[0].to_le_bytes();
2111                let a2 = arr[1].to_le_bytes();
2112                let a3 = arr[2].to_le_bytes();
2113                let a4 = arr[3].to_le_bytes();
2114                let a5 = arr[4].to_le_bytes();
2115                let a6 = arr[5].to_le_bytes();
2116                let a7 = arr[6].to_le_bytes();
2117                let a8 = arr[7].to_le_bytes();
2118                [
2119                    a1[0], a1[1],
2120                    a2[0], a2[1],
2121                    a3[0], a3[1],
2122                    a4[0], a4[1],
2123                    a5[0], a5[1],
2124                    a6[0], a6[1],
2125                    a7[0], a7[1],
2126                    a8[0], a8[1],
2127                ]
2128            }
2129            V128Const::I32x4(arr) => {
2130                let a1 = arr[0].to_le_bytes();
2131                let a2 = arr[1].to_le_bytes();
2132                let a3 = arr[2].to_le_bytes();
2133                let a4 = arr[3].to_le_bytes();
2134                [
2135                    a1[0], a1[1], a1[2], a1[3],
2136                    a2[0], a2[1], a2[2], a2[3],
2137                    a3[0], a3[1], a3[2], a3[3],
2138                    a4[0], a4[1], a4[2], a4[3],
2139                ]
2140            }
2141            V128Const::I64x2(arr) => {
2142                let a1 = arr[0].to_le_bytes();
2143                let a2 = arr[1].to_le_bytes();
2144                [
2145                    a1[0], a1[1], a1[2], a1[3], a1[4], a1[5], a1[6], a1[7],
2146                    a2[0], a2[1], a2[2], a2[3], a2[4], a2[5], a2[6], a2[7],
2147                ]
2148            }
2149            V128Const::F32x4(arr) => {
2150                let a1 = arr[0].bits.to_le_bytes();
2151                let a2 = arr[1].bits.to_le_bytes();
2152                let a3 = arr[2].bits.to_le_bytes();
2153                let a4 = arr[3].bits.to_le_bytes();
2154                [
2155                    a1[0], a1[1], a1[2], a1[3],
2156                    a2[0], a2[1], a2[2], a2[3],
2157                    a3[0], a3[1], a3[2], a3[3],
2158                    a4[0], a4[1], a4[2], a4[3],
2159                ]
2160            }
2161            V128Const::F64x2(arr) => {
2162                let a1 = arr[0].bits.to_le_bytes();
2163                let a2 = arr[1].bits.to_le_bytes();
2164                [
2165                    a1[0], a1[1], a1[2], a1[3], a1[4], a1[5], a1[6], a1[7],
2166                    a2[0], a2[1], a2[2], a2[3], a2[4], a2[5], a2[6], a2[7],
2167                ]
2168            }
2169        }
2170    }
2171}
2172
2173impl<'a> Parse<'a> for V128Const {
2174    fn parse(parser: Parser<'a>) -> Result<Self> {
2175        let mut l = parser.lookahead1();
2176        if l.peek::<kw::i8x16>()? {
2177            parser.parse::<kw::i8x16>()?;
2178            Ok(V128Const::I8x16([
2179                parser.parse()?,
2180                parser.parse()?,
2181                parser.parse()?,
2182                parser.parse()?,
2183                parser.parse()?,
2184                parser.parse()?,
2185                parser.parse()?,
2186                parser.parse()?,
2187                parser.parse()?,
2188                parser.parse()?,
2189                parser.parse()?,
2190                parser.parse()?,
2191                parser.parse()?,
2192                parser.parse()?,
2193                parser.parse()?,
2194                parser.parse()?,
2195            ]))
2196        } else if l.peek::<kw::i16x8>()? {
2197            parser.parse::<kw::i16x8>()?;
2198            Ok(V128Const::I16x8([
2199                parser.parse()?,
2200                parser.parse()?,
2201                parser.parse()?,
2202                parser.parse()?,
2203                parser.parse()?,
2204                parser.parse()?,
2205                parser.parse()?,
2206                parser.parse()?,
2207            ]))
2208        } else if l.peek::<kw::i32x4>()? {
2209            parser.parse::<kw::i32x4>()?;
2210            Ok(V128Const::I32x4([
2211                parser.parse()?,
2212                parser.parse()?,
2213                parser.parse()?,
2214                parser.parse()?,
2215            ]))
2216        } else if l.peek::<kw::i64x2>()? {
2217            parser.parse::<kw::i64x2>()?;
2218            Ok(V128Const::I64x2([parser.parse()?, parser.parse()?]))
2219        } else if l.peek::<kw::f32x4>()? {
2220            parser.parse::<kw::f32x4>()?;
2221            Ok(V128Const::F32x4([
2222                parser.parse()?,
2223                parser.parse()?,
2224                parser.parse()?,
2225                parser.parse()?,
2226            ]))
2227        } else if l.peek::<kw::f64x2>()? {
2228            parser.parse::<kw::f64x2>()?;
2229            Ok(V128Const::F64x2([parser.parse()?, parser.parse()?]))
2230        } else {
2231            Err(l.error())
2232        }
2233    }
2234}
2235
2236/// Lanes being shuffled in the `i8x16.shuffle` instruction
2237#[derive(Debug, Clone)]
2238pub struct I8x16Shuffle {
2239    #[allow(missing_docs)]
2240    pub lanes: [u8; 16],
2241}
2242
2243impl<'a> Parse<'a> for I8x16Shuffle {
2244    fn parse(parser: Parser<'a>) -> Result<Self> {
2245        Ok(I8x16Shuffle {
2246            lanes: [
2247                parser.parse()?,
2248                parser.parse()?,
2249                parser.parse()?,
2250                parser.parse()?,
2251                parser.parse()?,
2252                parser.parse()?,
2253                parser.parse()?,
2254                parser.parse()?,
2255                parser.parse()?,
2256                parser.parse()?,
2257                parser.parse()?,
2258                parser.parse()?,
2259                parser.parse()?,
2260                parser.parse()?,
2261                parser.parse()?,
2262                parser.parse()?,
2263            ],
2264        })
2265    }
2266}
2267
2268/// Payload of the `select` instructions
2269#[derive(Debug, Clone)]
2270pub struct SelectTypes<'a> {
2271    #[allow(missing_docs)]
2272    pub tys: Option<Vec<ValType<'a>>>,
2273}
2274
2275impl<'a> Parse<'a> for SelectTypes<'a> {
2276    fn parse(parser: Parser<'a>) -> Result<Self> {
2277        let mut found = false;
2278        let mut list = Vec::new();
2279        while parser.peek2::<kw::result>()? {
2280            found = true;
2281            parser.parens(|p| {
2282                p.parse::<kw::result>()?;
2283                while !p.is_empty() {
2284                    list.push(p.parse()?);
2285                }
2286                Ok(())
2287            })?;
2288        }
2289        Ok(SelectTypes {
2290            tys: if found { Some(list) } else { None },
2291        })
2292    }
2293}