Next Generation WASM Microkernel Operating System
at trap_handler 2232 lines 88 kB view raw
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}