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