wast/core/
expr.rs

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