Skip to main content

wast/core/
expr.rs

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