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