Skip to main content

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