use crate::annotation;
use crate::core::*;
use crate::kw;
use crate::lexer::{Lexer, Token, TokenKind};
use crate::parser::{Cursor, Parse, Parser, Peek, Result};
use crate::token::*;
use std::mem;
#[derive(Debug)]
#[allow(missing_docs)]
pub struct Expression<'a> {
pub instrs: Box<[Instruction<'a>]>,
pub branch_hints: Box<[BranchHint]>,
pub instr_spans: Option<Box<[Span]>>,
}
#[derive(Debug)]
pub struct BranchHint {
pub instr_index: usize,
pub value: u32,
}
impl<'a> Parse<'a> for Expression<'a> {
fn parse(parser: Parser<'a>) -> Result<Self> {
let mut exprs = ExpressionParser::new(parser);
exprs.parse(parser)?;
Ok(Expression {
instrs: exprs.raw_instrs.into(),
branch_hints: exprs.branch_hints.into(),
instr_spans: exprs.spans.map(|s| s.into()),
})
}
}
impl<'a> Expression<'a> {
pub fn one(instr: Instruction<'a>) -> Expression<'a> {
Expression {
instrs: [instr].into(),
branch_hints: Box::new([]),
instr_spans: None,
}
}
pub fn parse_folded_instruction(parser: Parser<'a>) -> Result<Self> {
let mut exprs = ExpressionParser::new(parser);
exprs.parse_folded_instruction(parser)?;
Ok(Expression {
instrs: exprs.raw_instrs.into(),
branch_hints: exprs.branch_hints.into(),
instr_spans: exprs.spans.map(|s| s.into()),
})
}
}
struct ExpressionParser<'a> {
raw_instrs: Vec<Instruction<'a>>,
stack: Vec<Level<'a>>,
branch_hints: Vec<BranchHint>,
pending_hint: Option<u32>,
spans: Option<Vec<Span>>,
}
enum Paren {
None,
Left,
Right(Span),
}
enum Level<'a> {
EndWith(Instruction<'a>, Option<Span>, Option<u32>),
If(If<'a>, Option<u32>),
IfArm,
BranchHint,
}
enum If<'a> {
Clause(Instruction<'a>, Span),
Then,
Else,
}
impl<'a> ExpressionParser<'a> {
fn new(parser: Parser<'a>) -> ExpressionParser<'a> {
ExpressionParser {
raw_instrs: Vec::new(),
stack: Vec::new(),
branch_hints: Vec::new(),
pending_hint: None,
spans: if parser.track_instr_spans() {
Some(Vec::new())
} else {
None
},
}
}
fn parse(&mut self, parser: Parser<'a>) -> Result<()> {
while !parser.is_empty() || !self.stack.is_empty() {
if let Some(Level::If(..)) = self.stack.last() {
if !parser.is_empty() && !parser.peek::<LParen>()? {
return Err(parser.error("expected `(`"));
}
}
match self.paren(parser)? {
Paren::None => {
let span = parser.cur_span();
let hint = self.pending_hint.take();
self.push_instr_with_hint(parser.parse()?, span, hint);
}
Paren::Left => {
if self.handle_if_lparen(parser)? {
continue;
}
if parser.peek::<annotation::metadata_code_branch_hint>()? {
self.parse_branch_hint(parser)?;
self.stack.push(Level::BranchHint);
continue;
}
let span = parser.cur_span();
let hint = self.pending_hint.take();
match parser.parse()? {
i @ Instruction::block(_)
| i @ Instruction::loop_(_)
| i @ Instruction::try_table(_) => {
self.push_instr_with_hint(i, span, hint);
self.stack
.push(Level::EndWith(Instruction::end(None), None, None));
}
i @ Instruction::if_(_) => {
self.stack.push(Level::If(If::Clause(i, span), hint));
}
other => self.stack.push(Level::EndWith(other, Some(span), hint)),
}
}
Paren::Right(span) => {
let level = self.stack.pop().unwrap();
if !matches!(level, Level::BranchHint) {
self.check_hint_consumed(parser)?;
}
match level {
Level::EndWith(i, s, hint) => {
self.push_instr_with_hint(i, s.unwrap_or(span), hint)
}
Level::IfArm => {}
Level::BranchHint => {}
Level::If(If::Clause(..), _) => {
return Err(parser.error("previous `if` had no `then`"));
}
Level::If(_, _) => {
self.push_instr(Instruction::end(None), span);
}
}
}
}
}
self.check_hint_consumed(parser)?;
Ok(())
}
fn parse_folded_instruction(&mut self, parser: Parser<'a>) -> Result<()> {
let mut done = false;
while !done {
match self.paren(parser)? {
Paren::Left => {
let span = parser.cur_span();
self.stack
.push(Level::EndWith(parser.parse()?, Some(span), None));
}
Paren::Right(span) => {
let (top_instr, span) = match self.stack.pop().unwrap() {
Level::EndWith(i, s, _) => (i, s.unwrap_or(span)),
_ => panic!("unknown level type"),
};
self.push_instr(top_instr, span);
if self.stack.is_empty() {
done = true;
}
}
Paren::None => {
return Err(parser.error("expected to continue a folded instruction"));
}
}
}
Ok(())
}
fn paren(&self, parser: Parser<'a>) -> Result<Paren> {
parser.step(|cursor| {
Ok(match cursor.lparen()? {
Some(rest) => (Paren::Left, rest),
None if self.stack.is_empty() => (Paren::None, cursor),
None => match cursor.rparen()? {
Some(rest) => (Paren::Right(cursor.cur_span()), rest),
None => (Paren::None, cursor),
},
})
})
}
fn handle_if_lparen(&mut self, parser: Parser<'a>) -> Result<bool> {
let (i, pending) = match self.stack.last_mut() {
Some(Level::If(i, pending)) => (i, pending),
_ => return Ok(false),
};
match i {
If::Clause(if_instr, if_instr_span) => {
if !parser.peek::<kw::then>()? {
return Ok(false);
}
if self.pending_hint.is_some() {
return Err(Self::hint_placement_error(parser));
}
parser.parse::<kw::then>()?;
let instr = mem::replace(if_instr, Instruction::end(None));
let span = *if_instr_span;
let hint = pending.take();
*i = If::Then;
self.push_instr_with_hint(instr, span, hint);
self.stack.push(Level::IfArm);
Ok(true)
}
If::Then => {
let span = parser.parse::<kw::r#else>()?.0;
*i = If::Else;
self.push_instr(Instruction::else_(None), span);
self.stack.push(Level::IfArm);
Ok(true)
}
If::Else => Err(parser.error("unexpected token: too many payloads inside of `(if)`")),
}
}
fn parse_branch_hint(&mut self, parser: Parser<'a>) -> Result<()> {
parser.parse::<annotation::metadata_code_branch_hint>()?;
let hint = parser.parse::<String>()?;
let value = match hint.as_bytes() {
[0] => 0,
[1] => 1,
_ => return Err(parser.error("invalid value for branch hint")),
};
if self.pending_hint.is_some() {
return Err(parser.error("@metadata.code.branch_hint annotation: duplicate annotation"));
}
self.pending_hint = Some(value);
Ok(())
}
fn push_instr(&mut self, instr: Instruction<'a>, span: Span) {
self.raw_instrs.push(instr);
if let Some(spans) = &mut self.spans {
spans.push(span);
}
}
fn check_hint_consumed(&self, parser: Parser<'a>) -> Result<()> {
if self.pending_hint.is_some() {
return Err(Self::hint_placement_error(parser));
}
Ok(())
}
fn hint_placement_error(parser: Parser<'a>) -> crate::Error {
parser.error("@metadata.code.branch_hint annotation: must precede an instruction")
}
fn push_instr_with_hint(&mut self, instr: Instruction<'a>, span: Span, hint: Option<u32>) {
if let Some(value) = hint {
self.branch_hints.push(BranchHint {
instr_index: self.raw_instrs.len(),
value,
});
}
self.push_instr(instr, span);
}
}
macro_rules! instructions {
(pub enum Instruction<'a> {
$(
$(#[$custom:ident])?
$name:ident $(($($arg:tt)*))? : $instr:tt $( | $deprecated:tt )?,
)*
}) => (
#[derive(Debug, Clone)]
#[allow(missing_docs, non_camel_case_types)]
pub enum Instruction<'a> {
$(
$name $(( instructions!(@ty $($arg)*) ))?,
)*
}
impl<'a> Parse<'a> for Instruction<'a> {
fn parse(parser: Parser<'a>) -> Result<Self> {
$(
fn $name<'a>(_parser: Parser<'a>) -> Result<Instruction<'a>> {
Ok(Instruction::$name $((
instructions!(@parse _parser $($arg)*)?
))?)
}
)*
let parse_remainder = parser.step(|c| {
let (kw, rest) = match c.keyword() ?{
Some(pair) => pair,
None => return Err(c.error("expected an instruction")),
};
match kw {
$($instr $( | $deprecated )?=> Ok(($name as fn(_) -> _, rest)),)*
_ => return Err(c.error("unknown operator or unexpected token")),
}
})?;
parse_remainder(parser)
}
}
impl<'a> Instruction<'a> {
pub(crate) fn encode(&self, sink: &mut wasm_encoder::InstructionSink<'_>) {
match self {
$(
Instruction::$name $((instructions!(@first x $($arg)*)))? => {
instructions!(@encode sink x $name $(($($arg)*))? $(#[$custom])?)
}
)*
}
}
#[allow(unused_variables)]
pub fn memarg_mut(&mut self) -> Option<&mut MemArg<'a>> {
match self {
$(
Instruction::$name $((instructions!(@memarg_binding a $($arg)*)))? => {
instructions!(@get_memarg a $($($arg)*)?)
}
)*
}
}
}
);
(@ty MemArg<$amt:tt>) => (MemArg<'a>);
(@ty AtomicMemArg<$amt:tt>) => (MemArg<'a>);
(@ty RmwMemArg<$amt:tt>) => (MemArg<'a>);
(@ty LoadOrStoreLane<$amt:tt>) => (LoadOrStoreLane<'a>);
(@ty $other:ty) => ($other);
(@first $first:ident $($t:tt)*) => ($first);
(@parse $parser:ident MemArg<$amt:tt>) => (MemArg::parse($parser, $amt));
(@parse $parser:ident MemArg) => (compile_error!("must specify `MemArg` default"));
(@parse $parser:ident AtomicMemArg<$amt:tt>) => (MemArg::parse_atomic($parser, $amt, false));
(@parse $parser:ident RmwMemArg<$amt:tt>) => (MemArg::parse_atomic($parser, $amt, true));
(@parse $parser:ident LoadOrStoreLane<$amt:tt>) => (LoadOrStoreLane::parse($parser, $amt));
(@parse $parser:ident LoadOrStoreLane) => (compile_error!("must specify `LoadOrStoreLane` default"));
(@parse $parser:ident $other:ty) => ($parser.parse::<$other>());
(@encode $sink:ident $x:ident $method:ident $(($($arg:tt)*))?) => ({
$sink.$method($(instructions!(@first $x $($arg)*).into())?);
});
(@encode $sink:ident $x:ident $method:ident ($($arg:tt)*) #[custom_encode]) => ({
crate::core::binary::custom_encoders::$method($sink, $x);
});
(@get_memarg $name:ident MemArg<$amt:tt>) => (Some($name));
(@get_memarg $name:ident AtomicMemArg<$amt:tt>) => (Some($name));
(@get_memarg $name:ident RmwMemArg<$amt:tt>) => (Some($name));
(@get_memarg $name:ident LoadOrStoreLane<$amt:tt>) => (Some(&mut $name.memarg));
(@get_memarg $($other:tt)*) => (None);
(@memarg_binding $name:ident MemArg<$amt:tt>) => ($name);
(@memarg_binding $name:ident AtomicMemArg<$amt:tt>) => ($name);
(@memarg_binding $name:ident RmwMemArg<$amt:tt>) => ($name);
(@memarg_binding $name:ident LoadOrStoreLane<$amt:tt>) => ($name);
(@memarg_binding $name:ident $other:ty) => (_);
}
instructions! {
pub enum Instruction<'a> {
block(Box<BlockType<'a>>) : "block",
if_(Box<BlockType<'a>>) : "if",
#[custom_encode]
else_(Option<Id<'a>>) : "else",
loop_(Box<BlockType<'a>>) : "loop",
#[custom_encode]
end(Option<Id<'a>>) : "end",
unreachable : "unreachable",
nop : "nop",
br(Index<'a>) : "br",
br_if(Index<'a>) : "br_if",
#[custom_encode]
br_table(BrTableIndices<'a>) : "br_table",
return_ : "return",
call(Index<'a>) : "call",
#[custom_encode]
call_indirect(Box<CallIndirect<'a>>) : "call_indirect",
return_call(Index<'a>) : "return_call",
#[custom_encode]
return_call_indirect(Box<CallIndirect<'a>>) : "return_call_indirect",
call_ref(Index<'a>) : "call_ref",
return_call_ref(Index<'a>) : "return_call_ref",
drop : "drop",
#[custom_encode]
select(SelectTypes<'a>) : "select",
local_get(Index<'a>) : "local.get",
local_set(Index<'a>) : "local.set",
local_tee(Index<'a>) : "local.tee",
global_get(Index<'a>) : "global.get",
global_set(Index<'a>) : "global.set",
table_get(TableArg<'a>) : "table.get",
table_set(TableArg<'a>) : "table.set",
i32_load(MemArg<4>) : "i32.load",
i64_load(MemArg<8>) : "i64.load",
f32_load(MemArg<4>) : "f32.load",
f64_load(MemArg<8>) : "f64.load",
i32_load8_s(MemArg<1>) : "i32.load8_s",
i32_load8_u(MemArg<1>) : "i32.load8_u",
i32_load16_s(MemArg<2>) : "i32.load16_s",
i32_load16_u(MemArg<2>) : "i32.load16_u",
i64_load8_s(MemArg<1>) : "i64.load8_s",
i64_load8_u(MemArg<1>) : "i64.load8_u",
i64_load16_s(MemArg<2>) : "i64.load16_s",
i64_load16_u(MemArg<2>) : "i64.load16_u",
i64_load32_s(MemArg<4>) : "i64.load32_s",
i64_load32_u(MemArg<4>) : "i64.load32_u",
i32_store(MemArg<4>) : "i32.store",
i64_store(MemArg<8>) : "i64.store",
f32_store(MemArg<4>) : "f32.store",
f64_store(MemArg<8>) : "f64.store",
i32_store8(MemArg<1>) : "i32.store8",
i32_store16(MemArg<2>) : "i32.store16",
i64_store8(MemArg<1>) : "i64.store8",
i64_store16(MemArg<2>) : "i64.store16",
i64_store32(MemArg<4>) : "i64.store32",
memory_size(MemoryArg<'a>) : "memory.size",
memory_grow(MemoryArg<'a>) : "memory.grow",
#[custom_encode]
memory_init(MemoryInit<'a>) : "memory.init",
#[custom_encode]
memory_copy(MemoryCopy<'a>) : "memory.copy",
memory_fill(MemoryArg<'a>) : "memory.fill",
memory_discard(MemoryArg<'a>) : "memory.discard",
data_drop(Index<'a>) : "data.drop",
elem_drop(Index<'a>) : "elem.drop",
#[custom_encode]
table_init(TableInit<'a>) : "table.init",
#[custom_encode]
table_copy(TableCopy<'a>) : "table.copy",
table_fill(TableArg<'a>) : "table.fill",
table_size(TableArg<'a>) : "table.size",
table_grow(TableArg<'a>) : "table.grow",
ref_null(HeapType<'a>) : "ref.null",
ref_is_null : "ref.is_null",
ref_func(Index<'a>) : "ref.func",
ref_as_non_null : "ref.as_non_null",
br_on_null(Index<'a>) : "br_on_null",
br_on_non_null(Index<'a>) : "br_on_non_null",
ref_eq : "ref.eq",
struct_new(Index<'a>) : "struct.new",
struct_new_default(Index<'a>) : "struct.new_default",
#[custom_encode]
struct_get(StructAccess<'a>) : "struct.get",
#[custom_encode]
struct_get_s(StructAccess<'a>) : "struct.get_s",
#[custom_encode]
struct_get_u(StructAccess<'a>) : "struct.get_u",
#[custom_encode]
struct_set(StructAccess<'a>) : "struct.set",
array_new(Index<'a>) : "array.new",
array_new_default(Index<'a>) : "array.new_default",
#[custom_encode]
array_new_fixed(ArrayNewFixed<'a>) : "array.new_fixed",
#[custom_encode]
array_new_data(ArrayNewData<'a>) : "array.new_data",
#[custom_encode]
array_new_elem(ArrayNewElem<'a>) : "array.new_elem",
array_get(Index<'a>) : "array.get",
array_get_s(Index<'a>) : "array.get_s",
array_get_u(Index<'a>) : "array.get_u",
array_set(Index<'a>) : "array.set",
array_len : "array.len",
array_fill(ArrayFill<'a>) : "array.fill",
#[custom_encode]
array_copy(ArrayCopy<'a>) : "array.copy",
#[custom_encode]
array_init_data(ArrayInit<'a>) : "array.init_data",
#[custom_encode]
array_init_elem(ArrayInit<'a>) : "array.init_elem",
ref_i31 : "ref.i31",
i31_get_s : "i31.get_s",
i31_get_u : "i31.get_u",
#[custom_encode]
ref_test(RefTest<'a>) : "ref.test",
#[custom_encode]
ref_cast(RefCast<'a>) : "ref.cast",
#[custom_encode]
br_on_cast(Box<BrOnCast<'a>>) : "br_on_cast",
#[custom_encode]
br_on_cast_fail(Box<BrOnCastFail<'a>>) : "br_on_cast_fail",
any_convert_extern : "any.convert_extern",
extern_convert_any : "extern.convert_any",
#[custom_encode]
i32_const(i32) : "i32.const",
#[custom_encode]
i64_const(i64) : "i64.const",
f32_const(F32) : "f32.const",
f64_const(F64) : "f64.const",
i32_clz : "i32.clz",
i32_ctz : "i32.ctz",
i32_popcnt : "i32.popcnt",
i32_add : "i32.add",
i32_sub : "i32.sub",
i32_mul : "i32.mul",
i32_div_s : "i32.div_s",
i32_div_u : "i32.div_u",
i32_rem_s : "i32.rem_s",
i32_rem_u : "i32.rem_u",
i32_and : "i32.and",
i32_or : "i32.or",
i32_xor : "i32.xor",
i32_shl : "i32.shl",
i32_shr_s : "i32.shr_s",
i32_shr_u : "i32.shr_u",
i32_rotl : "i32.rotl",
i32_rotr : "i32.rotr",
i64_clz : "i64.clz",
i64_ctz : "i64.ctz",
i64_popcnt : "i64.popcnt",
i64_add : "i64.add",
i64_sub : "i64.sub",
i64_mul : "i64.mul",
i64_div_s : "i64.div_s",
i64_div_u : "i64.div_u",
i64_rem_s : "i64.rem_s",
i64_rem_u : "i64.rem_u",
i64_and : "i64.and",
i64_or : "i64.or",
i64_xor : "i64.xor",
i64_shl : "i64.shl",
i64_shr_s : "i64.shr_s",
i64_shr_u : "i64.shr_u",
i64_rotl : "i64.rotl",
i64_rotr : "i64.rotr",
f32_abs : "f32.abs",
f32_neg : "f32.neg",
f32_ceil : "f32.ceil",
f32_floor : "f32.floor",
f32_trunc : "f32.trunc",
f32_nearest : "f32.nearest",
f32_sqrt : "f32.sqrt",
f32_add : "f32.add",
f32_sub : "f32.sub",
f32_mul : "f32.mul",
f32_div : "f32.div",
f32_min : "f32.min",
f32_max : "f32.max",
f32_copysign : "f32.copysign",
f64_abs : "f64.abs",
f64_neg : "f64.neg",
f64_ceil : "f64.ceil",
f64_floor : "f64.floor",
f64_trunc : "f64.trunc",
f64_nearest : "f64.nearest",
f64_sqrt : "f64.sqrt",
f64_add : "f64.add",
f64_sub : "f64.sub",
f64_mul : "f64.mul",
f64_div : "f64.div",
f64_min : "f64.min",
f64_max : "f64.max",
f64_copysign : "f64.copysign",
i32_eqz : "i32.eqz",
i32_eq : "i32.eq",
i32_ne : "i32.ne",
i32_lt_s : "i32.lt_s",
i32_lt_u : "i32.lt_u",
i32_gt_s : "i32.gt_s",
i32_gt_u : "i32.gt_u",
i32_le_s : "i32.le_s",
i32_le_u : "i32.le_u",
i32_ge_s : "i32.ge_s",
i32_ge_u : "i32.ge_u",
i64_eqz : "i64.eqz",
i64_eq : "i64.eq",
i64_ne : "i64.ne",
i64_lt_s : "i64.lt_s",
i64_lt_u : "i64.lt_u",
i64_gt_s : "i64.gt_s",
i64_gt_u : "i64.gt_u",
i64_le_s : "i64.le_s",
i64_le_u : "i64.le_u",
i64_ge_s : "i64.ge_s",
i64_ge_u : "i64.ge_u",
f32_eq : "f32.eq",
f32_ne : "f32.ne",
f32_lt : "f32.lt",
f32_gt : "f32.gt",
f32_le : "f32.le",
f32_ge : "f32.ge",
f64_eq : "f64.eq",
f64_ne : "f64.ne",
f64_lt : "f64.lt",
f64_gt : "f64.gt",
f64_le : "f64.le",
f64_ge : "f64.ge",
i32_wrap_i64 : "i32.wrap_i64",
i32_trunc_f32_s : "i32.trunc_f32_s",
i32_trunc_f32_u : "i32.trunc_f32_u",
i32_trunc_f64_s : "i32.trunc_f64_s",
i32_trunc_f64_u : "i32.trunc_f64_u",
i64_extend_i32_s : "i64.extend_i32_s",
i64_extend_i32_u : "i64.extend_i32_u",
i64_trunc_f32_s : "i64.trunc_f32_s",
i64_trunc_f32_u : "i64.trunc_f32_u",
i64_trunc_f64_s : "i64.trunc_f64_s",
i64_trunc_f64_u : "i64.trunc_f64_u",
f32_convert_i32_s : "f32.convert_i32_s",
f32_convert_i32_u : "f32.convert_i32_u",
f32_convert_i64_s : "f32.convert_i64_s",
f32_convert_i64_u : "f32.convert_i64_u",
f32_demote_f64 : "f32.demote_f64",
f64_convert_i32_s : "f64.convert_i32_s",
f64_convert_i32_u : "f64.convert_i32_u",
f64_convert_i64_s : "f64.convert_i64_s",
f64_convert_i64_u : "f64.convert_i64_u",
f64_promote_f32 : "f64.promote_f32",
i32_reinterpret_f32 : "i32.reinterpret_f32",
i64_reinterpret_f64 : "i64.reinterpret_f64",
f32_reinterpret_i32 : "f32.reinterpret_i32",
f64_reinterpret_i64 : "f64.reinterpret_i64",
i32_trunc_sat_f32_s : "i32.trunc_sat_f32_s",
i32_trunc_sat_f32_u : "i32.trunc_sat_f32_u",
i32_trunc_sat_f64_s : "i32.trunc_sat_f64_s",
i32_trunc_sat_f64_u : "i32.trunc_sat_f64_u",
i64_trunc_sat_f32_s : "i64.trunc_sat_f32_s",
i64_trunc_sat_f32_u : "i64.trunc_sat_f32_u",
i64_trunc_sat_f64_s : "i64.trunc_sat_f64_s",
i64_trunc_sat_f64_u : "i64.trunc_sat_f64_u",
i32_extend8_s : "i32.extend8_s",
i32_extend16_s : "i32.extend16_s",
i64_extend8_s : "i64.extend8_s",
i64_extend16_s : "i64.extend16_s",
i64_extend32_s : "i64.extend32_s",
memory_atomic_notify(MemArg<4>) : "memory.atomic.notify",
memory_atomic_wait32(MemArg<4>) : "memory.atomic.wait32",
memory_atomic_wait64(MemArg<8>) : "memory.atomic.wait64",
#[custom_encode]
atomic_fence(Option<Ordering>) : "atomic.fence",
pause : "pause",
i32_atomic_load(AtomicMemArg<4>) : "i32.atomic.load",
i64_atomic_load(AtomicMemArg<8>) : "i64.atomic.load",
i32_atomic_load8_u(AtomicMemArg<1>) : "i32.atomic.load8_u",
i32_atomic_load16_u(AtomicMemArg<2>) : "i32.atomic.load16_u",
i64_atomic_load8_u(AtomicMemArg<1>) : "i64.atomic.load8_u",
i64_atomic_load16_u(AtomicMemArg<2>) : "i64.atomic.load16_u",
i64_atomic_load32_u(AtomicMemArg<4>) : "i64.atomic.load32_u",
i32_atomic_store(AtomicMemArg<4>) : "i32.atomic.store",
i64_atomic_store(AtomicMemArg<8>) : "i64.atomic.store",
i32_atomic_store8(AtomicMemArg<1>) : "i32.atomic.store8",
i32_atomic_store16(AtomicMemArg<2>) : "i32.atomic.store16",
i64_atomic_store8(AtomicMemArg<1>) : "i64.atomic.store8",
i64_atomic_store16(AtomicMemArg<2>) : "i64.atomic.store16",
i64_atomic_store32(AtomicMemArg<4>) : "i64.atomic.store32",
i32_atomic_rmw_add(RmwMemArg<4>) : "i32.atomic.rmw.add",
i64_atomic_rmw_add(RmwMemArg<8>) : "i64.atomic.rmw.add",
i32_atomic_rmw8_add_u(RmwMemArg<1>) : "i32.atomic.rmw8.add_u",
i32_atomic_rmw16_add_u(RmwMemArg<2>) : "i32.atomic.rmw16.add_u",
i64_atomic_rmw8_add_u(RmwMemArg<1>) : "i64.atomic.rmw8.add_u",
i64_atomic_rmw16_add_u(RmwMemArg<2>) : "i64.atomic.rmw16.add_u",
i64_atomic_rmw32_add_u(RmwMemArg<4>) : "i64.atomic.rmw32.add_u",
i32_atomic_rmw_sub(RmwMemArg<4>) : "i32.atomic.rmw.sub",
i64_atomic_rmw_sub(RmwMemArg<8>) : "i64.atomic.rmw.sub",
i32_atomic_rmw8_sub_u(RmwMemArg<1>) : "i32.atomic.rmw8.sub_u",
i32_atomic_rmw16_sub_u(RmwMemArg<2>) : "i32.atomic.rmw16.sub_u",
i64_atomic_rmw8_sub_u(RmwMemArg<1>) : "i64.atomic.rmw8.sub_u",
i64_atomic_rmw16_sub_u(RmwMemArg<2>) : "i64.atomic.rmw16.sub_u",
i64_atomic_rmw32_sub_u(RmwMemArg<4>) : "i64.atomic.rmw32.sub_u",
i32_atomic_rmw_and(RmwMemArg<4>) : "i32.atomic.rmw.and",
i64_atomic_rmw_and(RmwMemArg<8>) : "i64.atomic.rmw.and",
i32_atomic_rmw8_and_u(RmwMemArg<1>) : "i32.atomic.rmw8.and_u",
i32_atomic_rmw16_and_u(RmwMemArg<2>) : "i32.atomic.rmw16.and_u",
i64_atomic_rmw8_and_u(RmwMemArg<1>) : "i64.atomic.rmw8.and_u",
i64_atomic_rmw16_and_u(RmwMemArg<2>) : "i64.atomic.rmw16.and_u",
i64_atomic_rmw32_and_u(RmwMemArg<4>) : "i64.atomic.rmw32.and_u",
i32_atomic_rmw_or(RmwMemArg<4>) : "i32.atomic.rmw.or",
i64_atomic_rmw_or(RmwMemArg<8>) : "i64.atomic.rmw.or",
i32_atomic_rmw8_or_u(RmwMemArg<1>) : "i32.atomic.rmw8.or_u",
i32_atomic_rmw16_or_u(RmwMemArg<2>) : "i32.atomic.rmw16.or_u",
i64_atomic_rmw8_or_u(RmwMemArg<1>) : "i64.atomic.rmw8.or_u",
i64_atomic_rmw16_or_u(RmwMemArg<2>) : "i64.atomic.rmw16.or_u",
i64_atomic_rmw32_or_u(RmwMemArg<4>) : "i64.atomic.rmw32.or_u",
i32_atomic_rmw_xor(RmwMemArg<4>) : "i32.atomic.rmw.xor",
i64_atomic_rmw_xor(RmwMemArg<8>) : "i64.atomic.rmw.xor",
i32_atomic_rmw8_xor_u(RmwMemArg<1>) : "i32.atomic.rmw8.xor_u",
i32_atomic_rmw16_xor_u(RmwMemArg<2>) : "i32.atomic.rmw16.xor_u",
i64_atomic_rmw8_xor_u(RmwMemArg<1>) : "i64.atomic.rmw8.xor_u",
i64_atomic_rmw16_xor_u(RmwMemArg<2>) : "i64.atomic.rmw16.xor_u",
i64_atomic_rmw32_xor_u(RmwMemArg<4>) : "i64.atomic.rmw32.xor_u",
i32_atomic_rmw_xchg(RmwMemArg<4>) : "i32.atomic.rmw.xchg",
i64_atomic_rmw_xchg(RmwMemArg<8>) : "i64.atomic.rmw.xchg",
i32_atomic_rmw8_xchg_u(RmwMemArg<1>) : "i32.atomic.rmw8.xchg_u",
i32_atomic_rmw16_xchg_u(RmwMemArg<2>) : "i32.atomic.rmw16.xchg_u",
i64_atomic_rmw8_xchg_u(RmwMemArg<1>) : "i64.atomic.rmw8.xchg_u",
i64_atomic_rmw16_xchg_u(RmwMemArg<2>) : "i64.atomic.rmw16.xchg_u",
i64_atomic_rmw32_xchg_u(RmwMemArg<4>) : "i64.atomic.rmw32.xchg_u",
i32_atomic_rmw_cmpxchg(RmwMemArg<4>) : "i32.atomic.rmw.cmpxchg",
i64_atomic_rmw_cmpxchg(RmwMemArg<8>) : "i64.atomic.rmw.cmpxchg",
i32_atomic_rmw8_cmpxchg_u(RmwMemArg<1>) : "i32.atomic.rmw8.cmpxchg_u",
i32_atomic_rmw16_cmpxchg_u(RmwMemArg<2>) : "i32.atomic.rmw16.cmpxchg_u",
i64_atomic_rmw8_cmpxchg_u(RmwMemArg<1>) : "i64.atomic.rmw8.cmpxchg_u",
i64_atomic_rmw16_cmpxchg_u(RmwMemArg<2>) : "i64.atomic.rmw16.cmpxchg_u",
i64_atomic_rmw32_cmpxchg_u(RmwMemArg<4>) : "i64.atomic.rmw32.cmpxchg_u",
#[custom_encode]
global_atomic_get(Ordered<Index<'a>>) : "global.atomic.get",
#[custom_encode]
global_atomic_set(Ordered<Index<'a>>) : "global.atomic.set",
#[custom_encode]
global_atomic_rmw_add(Ordered<Index<'a>>) : "global.atomic.rmw.add",
#[custom_encode]
global_atomic_rmw_sub(Ordered<Index<'a>>) : "global.atomic.rmw.sub",
#[custom_encode]
global_atomic_rmw_and(Ordered<Index<'a>>) : "global.atomic.rmw.and",
#[custom_encode]
global_atomic_rmw_or(Ordered<Index<'a>>) : "global.atomic.rmw.or",
#[custom_encode]
global_atomic_rmw_xor(Ordered<Index<'a>>) : "global.atomic.rmw.xor",
#[custom_encode]
global_atomic_rmw_xchg(Ordered<Index<'a>>) : "global.atomic.rmw.xchg",
#[custom_encode]
global_atomic_rmw_cmpxchg(Ordered<Index<'a>>) : "global.atomic.rmw.cmpxchg",
#[custom_encode]
table_atomic_get(Ordered<TableArg<'a>>) : "table.atomic.get",
#[custom_encode]
table_atomic_set(Ordered<TableArg<'a>>) : "table.atomic.set",
#[custom_encode]
table_atomic_rmw_xchg(Ordered<TableArg<'a>>) : "table.atomic.rmw.xchg",
#[custom_encode]
table_atomic_rmw_cmpxchg(Ordered<TableArg<'a>>) : "table.atomic.rmw.cmpxchg",
#[custom_encode]
struct_atomic_get(Ordered<StructAccess<'a>>) : "struct.atomic.get",
#[custom_encode]
struct_atomic_get_s(Ordered<StructAccess<'a>>) : "struct.atomic.get_s",
#[custom_encode]
struct_atomic_get_u(Ordered<StructAccess<'a>>) : "struct.atomic.get_u",
#[custom_encode]
struct_atomic_set(Ordered<StructAccess<'a>>) : "struct.atomic.set",
#[custom_encode]
struct_atomic_rmw_add(Ordered<StructAccess<'a>>) : "struct.atomic.rmw.add",
#[custom_encode]
struct_atomic_rmw_sub(Ordered<StructAccess<'a>>) : "struct.atomic.rmw.sub",
#[custom_encode]
struct_atomic_rmw_and(Ordered<StructAccess<'a>>) : "struct.atomic.rmw.and",
#[custom_encode]
struct_atomic_rmw_or(Ordered<StructAccess<'a>>) : "struct.atomic.rmw.or",
#[custom_encode]
struct_atomic_rmw_xor(Ordered<StructAccess<'a>>) : "struct.atomic.rmw.xor",
#[custom_encode]
struct_atomic_rmw_xchg(Ordered<StructAccess<'a>>) : "struct.atomic.rmw.xchg",
#[custom_encode]
struct_atomic_rmw_cmpxchg(Ordered<StructAccess<'a>>) : "struct.atomic.rmw.cmpxchg",
#[custom_encode]
array_atomic_get(Ordered<Index<'a>>) : "array.atomic.get",
#[custom_encode]
array_atomic_get_s(Ordered<Index<'a>>) : "array.atomic.get_s",
#[custom_encode]
array_atomic_get_u(Ordered<Index<'a>>) : "array.atomic.get_u",
#[custom_encode]
array_atomic_set(Ordered<Index<'a>>) : "array.atomic.set",
#[custom_encode]
array_atomic_rmw_add(Ordered<Index<'a>>) : "array.atomic.rmw.add",
#[custom_encode]
array_atomic_rmw_sub(Ordered<Index<'a>>) : "array.atomic.rmw.sub",
#[custom_encode]
array_atomic_rmw_and(Ordered<Index<'a>>) : "array.atomic.rmw.and",
#[custom_encode]
array_atomic_rmw_or(Ordered<Index<'a>>) : "array.atomic.rmw.or",
#[custom_encode]
array_atomic_rmw_xor(Ordered<Index<'a>>) : "array.atomic.rmw.xor",
#[custom_encode]
array_atomic_rmw_xchg(Ordered<Index<'a>>) : "array.atomic.rmw.xchg",
#[custom_encode]
array_atomic_rmw_cmpxchg(Ordered<Index<'a>>) : "array.atomic.rmw.cmpxchg",
ref_i31_shared : "ref.i31_shared",
v128_load(MemArg<16>) : "v128.load",
v128_load8x8_s(MemArg<8>) : "v128.load8x8_s",
v128_load8x8_u(MemArg<8>) : "v128.load8x8_u",
v128_load16x4_s(MemArg<8>) : "v128.load16x4_s",
v128_load16x4_u(MemArg<8>) : "v128.load16x4_u",
v128_load32x2_s(MemArg<8>) : "v128.load32x2_s",
v128_load32x2_u(MemArg<8>) : "v128.load32x2_u",
v128_load8_splat(MemArg<1>) : "v128.load8_splat",
v128_load16_splat(MemArg<2>) : "v128.load16_splat",
v128_load32_splat(MemArg<4>) : "v128.load32_splat",
v128_load64_splat(MemArg<8>) : "v128.load64_splat",
v128_load32_zero(MemArg<4>) : "v128.load32_zero",
v128_load64_zero(MemArg<8>) : "v128.load64_zero",
v128_store(MemArg<16>) : "v128.store",
#[custom_encode]
v128_load8_lane(LoadOrStoreLane<1>) : "v128.load8_lane",
#[custom_encode]
v128_load16_lane(LoadOrStoreLane<2>) : "v128.load16_lane",
#[custom_encode]
v128_load32_lane(LoadOrStoreLane<4>) : "v128.load32_lane",
#[custom_encode]
v128_load64_lane(LoadOrStoreLane<8>) : "v128.load64_lane",
#[custom_encode]
v128_store8_lane(LoadOrStoreLane<1>) : "v128.store8_lane",
#[custom_encode]
v128_store16_lane(LoadOrStoreLane<2>) : "v128.store16_lane",
#[custom_encode]
v128_store32_lane(LoadOrStoreLane<4>) : "v128.store32_lane",
#[custom_encode]
v128_store64_lane(LoadOrStoreLane<8>) : "v128.store64_lane",
v128_const(V128Const) : "v128.const",
i8x16_shuffle(I8x16Shuffle) : "i8x16.shuffle",
i8x16_extract_lane_s(LaneArg) : "i8x16.extract_lane_s",
i8x16_extract_lane_u(LaneArg) : "i8x16.extract_lane_u",
i8x16_replace_lane(LaneArg) : "i8x16.replace_lane",
i16x8_extract_lane_s(LaneArg) : "i16x8.extract_lane_s",
i16x8_extract_lane_u(LaneArg) : "i16x8.extract_lane_u",
i16x8_replace_lane(LaneArg) : "i16x8.replace_lane",
i32x4_extract_lane(LaneArg) : "i32x4.extract_lane",
i32x4_replace_lane(LaneArg) : "i32x4.replace_lane",
i64x2_extract_lane(LaneArg) : "i64x2.extract_lane",
i64x2_replace_lane(LaneArg) : "i64x2.replace_lane",
f32x4_extract_lane(LaneArg) : "f32x4.extract_lane",
f32x4_replace_lane(LaneArg) : "f32x4.replace_lane",
f64x2_extract_lane(LaneArg) : "f64x2.extract_lane",
f64x2_replace_lane(LaneArg) : "f64x2.replace_lane",
i8x16_swizzle : "i8x16.swizzle",
i8x16_splat : "i8x16.splat",
i16x8_splat : "i16x8.splat",
i32x4_splat : "i32x4.splat",
i64x2_splat : "i64x2.splat",
f32x4_splat : "f32x4.splat",
f64x2_splat : "f64x2.splat",
i8x16_eq : "i8x16.eq",
i8x16_ne : "i8x16.ne",
i8x16_lt_s : "i8x16.lt_s",
i8x16_lt_u : "i8x16.lt_u",
i8x16_gt_s : "i8x16.gt_s",
i8x16_gt_u : "i8x16.gt_u",
i8x16_le_s : "i8x16.le_s",
i8x16_le_u : "i8x16.le_u",
i8x16_ge_s : "i8x16.ge_s",
i8x16_ge_u : "i8x16.ge_u",
i16x8_eq : "i16x8.eq",
i16x8_ne : "i16x8.ne",
i16x8_lt_s : "i16x8.lt_s",
i16x8_lt_u : "i16x8.lt_u",
i16x8_gt_s : "i16x8.gt_s",
i16x8_gt_u : "i16x8.gt_u",
i16x8_le_s : "i16x8.le_s",
i16x8_le_u : "i16x8.le_u",
i16x8_ge_s : "i16x8.ge_s",
i16x8_ge_u : "i16x8.ge_u",
i32x4_eq : "i32x4.eq",
i32x4_ne : "i32x4.ne",
i32x4_lt_s : "i32x4.lt_s",
i32x4_lt_u : "i32x4.lt_u",
i32x4_gt_s : "i32x4.gt_s",
i32x4_gt_u : "i32x4.gt_u",
i32x4_le_s : "i32x4.le_s",
i32x4_le_u : "i32x4.le_u",
i32x4_ge_s : "i32x4.ge_s",
i32x4_ge_u : "i32x4.ge_u",
i64x2_eq : "i64x2.eq",
i64x2_ne : "i64x2.ne",
i64x2_lt_s : "i64x2.lt_s",
i64x2_gt_s : "i64x2.gt_s",
i64x2_le_s : "i64x2.le_s",
i64x2_ge_s : "i64x2.ge_s",
f32x4_eq : "f32x4.eq",
f32x4_ne : "f32x4.ne",
f32x4_lt : "f32x4.lt",
f32x4_gt : "f32x4.gt",
f32x4_le : "f32x4.le",
f32x4_ge : "f32x4.ge",
f64x2_eq : "f64x2.eq",
f64x2_ne : "f64x2.ne",
f64x2_lt : "f64x2.lt",
f64x2_gt : "f64x2.gt",
f64x2_le : "f64x2.le",
f64x2_ge : "f64x2.ge",
v128_not : "v128.not",
v128_and : "v128.and",
v128_andnot : "v128.andnot",
v128_or : "v128.or",
v128_xor : "v128.xor",
v128_bitselect : "v128.bitselect",
v128_any_true : "v128.any_true",
i8x16_abs : "i8x16.abs",
i8x16_neg : "i8x16.neg",
i8x16_popcnt : "i8x16.popcnt",
i8x16_all_true : "i8x16.all_true",
i8x16_bitmask : "i8x16.bitmask",
i8x16_narrow_i16x8_s : "i8x16.narrow_i16x8_s",
i8x16_narrow_i16x8_u : "i8x16.narrow_i16x8_u",
i8x16_shl : "i8x16.shl",
i8x16_shr_s : "i8x16.shr_s",
i8x16_shr_u : "i8x16.shr_u",
i8x16_add : "i8x16.add",
i8x16_add_sat_s : "i8x16.add_sat_s",
i8x16_add_sat_u : "i8x16.add_sat_u",
i8x16_sub : "i8x16.sub",
i8x16_sub_sat_s : "i8x16.sub_sat_s",
i8x16_sub_sat_u : "i8x16.sub_sat_u",
i8x16_min_s : "i8x16.min_s",
i8x16_min_u : "i8x16.min_u",
i8x16_max_s : "i8x16.max_s",
i8x16_max_u : "i8x16.max_u",
i8x16_avgr_u : "i8x16.avgr_u",
i16x8_extadd_pairwise_i8x16_s : "i16x8.extadd_pairwise_i8x16_s",
i16x8_extadd_pairwise_i8x16_u : "i16x8.extadd_pairwise_i8x16_u",
i16x8_abs : "i16x8.abs",
i16x8_neg : "i16x8.neg",
i16x8_q15mulr_sat_s : "i16x8.q15mulr_sat_s",
i16x8_all_true : "i16x8.all_true",
i16x8_bitmask : "i16x8.bitmask",
i16x8_narrow_i32x4_s : "i16x8.narrow_i32x4_s",
i16x8_narrow_i32x4_u : "i16x8.narrow_i32x4_u",
i16x8_extend_low_i8x16_s : "i16x8.extend_low_i8x16_s",
i16x8_extend_high_i8x16_s : "i16x8.extend_high_i8x16_s",
i16x8_extend_low_i8x16_u : "i16x8.extend_low_i8x16_u",
i16x8_extend_high_i8x16_u : "i16x8.extend_high_i8x16_u",
i16x8_shl : "i16x8.shl",
i16x8_shr_s : "i16x8.shr_s",
i16x8_shr_u : "i16x8.shr_u",
i16x8_add : "i16x8.add",
i16x8_add_sat_s : "i16x8.add_sat_s",
i16x8_add_sat_u : "i16x8.add_sat_u",
i16x8_sub : "i16x8.sub",
i16x8_sub_sat_s : "i16x8.sub_sat_s",
i16x8_sub_sat_u : "i16x8.sub_sat_u",
i16x8_mul : "i16x8.mul",
i16x8_min_s : "i16x8.min_s",
i16x8_min_u : "i16x8.min_u",
i16x8_max_s : "i16x8.max_s",
i16x8_max_u : "i16x8.max_u",
i16x8_avgr_u : "i16x8.avgr_u",
i16x8_extmul_low_i8x16_s : "i16x8.extmul_low_i8x16_s",
i16x8_extmul_high_i8x16_s : "i16x8.extmul_high_i8x16_s",
i16x8_extmul_low_i8x16_u : "i16x8.extmul_low_i8x16_u",
i16x8_extmul_high_i8x16_u : "i16x8.extmul_high_i8x16_u",
i32x4_extadd_pairwise_i16x8_s : "i32x4.extadd_pairwise_i16x8_s",
i32x4_extadd_pairwise_i16x8_u : "i32x4.extadd_pairwise_i16x8_u",
i32x4_abs : "i32x4.abs",
i32x4_neg : "i32x4.neg",
i32x4_all_true : "i32x4.all_true",
i32x4_bitmask : "i32x4.bitmask",
i32x4_extend_low_i16x8_s : "i32x4.extend_low_i16x8_s",
i32x4_extend_high_i16x8_s : "i32x4.extend_high_i16x8_s",
i32x4_extend_low_i16x8_u : "i32x4.extend_low_i16x8_u",
i32x4_extend_high_i16x8_u : "i32x4.extend_high_i16x8_u",
i32x4_shl : "i32x4.shl",
i32x4_shr_s : "i32x4.shr_s",
i32x4_shr_u : "i32x4.shr_u",
i32x4_add : "i32x4.add",
i32x4_sub : "i32x4.sub",
i32x4_mul : "i32x4.mul",
i32x4_min_s : "i32x4.min_s",
i32x4_min_u : "i32x4.min_u",
i32x4_max_s : "i32x4.max_s",
i32x4_max_u : "i32x4.max_u",
i32x4_dot_i16x8_s : "i32x4.dot_i16x8_s",
i32x4_extmul_low_i16x8_s : "i32x4.extmul_low_i16x8_s",
i32x4_extmul_high_i16x8_s : "i32x4.extmul_high_i16x8_s",
i32x4_extmul_low_i16x8_u : "i32x4.extmul_low_i16x8_u",
i32x4_extmul_high_i16x8_u : "i32x4.extmul_high_i16x8_u",
i64x2_abs : "i64x2.abs",
i64x2_neg : "i64x2.neg",
i64x2_all_true : "i64x2.all_true",
i64x2_bitmask : "i64x2.bitmask",
i64x2_extend_low_i32x4_s : "i64x2.extend_low_i32x4_s",
i64x2_extend_high_i32x4_s : "i64x2.extend_high_i32x4_s",
i64x2_extend_low_i32x4_u : "i64x2.extend_low_i32x4_u",
i64x2_extend_high_i32x4_u : "i64x2.extend_high_i32x4_u",
i64x2_shl : "i64x2.shl",
i64x2_shr_s : "i64x2.shr_s",
i64x2_shr_u : "i64x2.shr_u",
i64x2_add : "i64x2.add",
i64x2_sub : "i64x2.sub",
i64x2_mul : "i64x2.mul",
i64x2_extmul_low_i32x4_s : "i64x2.extmul_low_i32x4_s",
i64x2_extmul_high_i32x4_s : "i64x2.extmul_high_i32x4_s",
i64x2_extmul_low_i32x4_u : "i64x2.extmul_low_i32x4_u",
i64x2_extmul_high_i32x4_u : "i64x2.extmul_high_i32x4_u",
f32x4_ceil : "f32x4.ceil",
f32x4_floor : "f32x4.floor",
f32x4_trunc : "f32x4.trunc",
f32x4_nearest : "f32x4.nearest",
f32x4_abs : "f32x4.abs",
f32x4_neg : "f32x4.neg",
f32x4_sqrt : "f32x4.sqrt",
f32x4_add : "f32x4.add",
f32x4_sub : "f32x4.sub",
f32x4_mul : "f32x4.mul",
f32x4_div : "f32x4.div",
f32x4_min : "f32x4.min",
f32x4_max : "f32x4.max",
f32x4_pmin : "f32x4.pmin",
f32x4_pmax : "f32x4.pmax",
f64x2_ceil : "f64x2.ceil",
f64x2_floor : "f64x2.floor",
f64x2_trunc : "f64x2.trunc",
f64x2_nearest : "f64x2.nearest",
f64x2_abs : "f64x2.abs",
f64x2_neg : "f64x2.neg",
f64x2_sqrt : "f64x2.sqrt",
f64x2_add : "f64x2.add",
f64x2_sub : "f64x2.sub",
f64x2_mul : "f64x2.mul",
f64x2_div : "f64x2.div",
f64x2_min : "f64x2.min",
f64x2_max : "f64x2.max",
f64x2_pmin : "f64x2.pmin",
f64x2_pmax : "f64x2.pmax",
i32x4_trunc_sat_f32x4_s : "i32x4.trunc_sat_f32x4_s",
i32x4_trunc_sat_f32x4_u : "i32x4.trunc_sat_f32x4_u",
f32x4_convert_i32x4_s : "f32x4.convert_i32x4_s",
f32x4_convert_i32x4_u : "f32x4.convert_i32x4_u",
i32x4_trunc_sat_f64x2_s_zero : "i32x4.trunc_sat_f64x2_s_zero",
i32x4_trunc_sat_f64x2_u_zero : "i32x4.trunc_sat_f64x2_u_zero",
f64x2_convert_low_i32x4_s : "f64x2.convert_low_i32x4_s",
f64x2_convert_low_i32x4_u : "f64x2.convert_low_i32x4_u",
f32x4_demote_f64x2_zero : "f32x4.demote_f64x2_zero",
f64x2_promote_low_f32x4 : "f64x2.promote_low_f32x4",
throw_ref : "throw_ref",
#[custom_encode]
try_table(TryTable<'a>) : "try_table",
throw(Index<'a>) : "throw",
try_(Box<BlockType<'a>>) : "try",
catch(Index<'a>) : "catch",
rethrow(Index<'a>) : "rethrow",
delegate(Index<'a>) : "delegate",
catch_all : "catch_all",
i8x16_relaxed_swizzle : "i8x16.relaxed_swizzle",
i32x4_relaxed_trunc_f32x4_s : "i32x4.relaxed_trunc_f32x4_s",
i32x4_relaxed_trunc_f32x4_u : "i32x4.relaxed_trunc_f32x4_u",
i32x4_relaxed_trunc_f64x2_s_zero : "i32x4.relaxed_trunc_f64x2_s_zero",
i32x4_relaxed_trunc_f64x2_u_zero : "i32x4.relaxed_trunc_f64x2_u_zero",
f32x4_relaxed_madd : "f32x4.relaxed_madd",
f32x4_relaxed_nmadd : "f32x4.relaxed_nmadd",
f64x2_relaxed_madd : "f64x2.relaxed_madd",
f64x2_relaxed_nmadd : "f64x2.relaxed_nmadd",
i8x16_relaxed_laneselect : "i8x16.relaxed_laneselect",
i16x8_relaxed_laneselect : "i16x8.relaxed_laneselect",
i32x4_relaxed_laneselect : "i32x4.relaxed_laneselect",
i64x2_relaxed_laneselect : "i64x2.relaxed_laneselect",
f32x4_relaxed_min : "f32x4.relaxed_min",
f32x4_relaxed_max : "f32x4.relaxed_max",
f64x2_relaxed_min : "f64x2.relaxed_min",
f64x2_relaxed_max : "f64x2.relaxed_max",
i16x8_relaxed_q15mulr_s : "i16x8.relaxed_q15mulr_s",
i16x8_relaxed_dot_i8x16_i7x16_s : "i16x8.relaxed_dot_i8x16_i7x16_s",
i32x4_relaxed_dot_i8x16_i7x16_add_s : "i32x4.relaxed_dot_i8x16_i7x16_add_s",
cont_new(Index<'a>) : "cont.new",
#[custom_encode]
cont_bind(ContBind<'a>) : "cont.bind",
suspend(Index<'a>) : "suspend",
#[custom_encode]
resume(Resume<'a>) : "resume",
#[custom_encode]
resume_throw(ResumeThrow<'a>) : "resume_throw",
#[custom_encode]
resume_throw_ref(ResumeThrowRef<'a>) : "resume_throw_ref",
#[custom_encode]
switch(Switch<'a>) : "switch",
i64_add128 : "i64.add128",
i64_sub128 : "i64.sub128",
i64_mul_wide_s : "i64.mul_wide_s",
i64_mul_wide_u : "i64.mul_wide_u",
struct_new_desc(Index<'a>) : "struct.new_desc",
struct_new_default_desc(Index<'a>) : "struct.new_default_desc",
ref_get_desc(Index<'a>) : "ref.get_desc",
#[custom_encode]
ref_cast_desc_eq(RefCastDescEq<'a>) : "ref.cast_desc_eq",
#[custom_encode]
br_on_cast_desc_eq(Box<BrOnCastDescEq<'a>>) : "br_on_cast_desc_eq",
#[custom_encode]
br_on_cast_desc_eq_fail(Box<BrOnCastDescEqFail<'a>>) : "br_on_cast_desc_eq_fail",
}
}
#[test]
fn assert_instruction_not_too_large() {
let size = std::mem::size_of::<Instruction<'_>>();
let pointer = std::mem::size_of::<u64>();
assert!(size <= pointer * 11);
}
impl<'a> Instruction<'a> {
pub(crate) fn needs_data_count(&self) -> bool {
match self {
Instruction::memory_init(_)
| Instruction::data_drop(_)
| Instruction::array_new_data(_)
| Instruction::array_init_data(_) => true,
_ => false,
}
}
}
#[derive(Debug, Clone)]
#[allow(missing_docs)]
pub struct BlockType<'a> {
pub label: Option<Id<'a>>,
pub label_name: Option<NameAnnotation<'a>>,
pub ty: TypeUse<'a, FunctionType<'a>>,
}
impl<'a> Parse<'a> for BlockType<'a> {
fn parse(parser: Parser<'a>) -> Result<Self> {
Ok(BlockType {
label: parser.parse()?,
label_name: parser.parse()?,
ty: parser
.parse::<TypeUse<'a, FunctionTypeNoNames<'a>>>()?
.into(),
})
}
}
#[derive(Debug, Clone)]
#[allow(missing_docs)]
pub struct ContBind<'a> {
pub argument_index: Index<'a>,
pub result_index: Index<'a>,
}
impl<'a> Parse<'a> for ContBind<'a> {
fn parse(parser: Parser<'a>) -> Result<Self> {
Ok(ContBind {
argument_index: parser.parse()?,
result_index: parser.parse()?,
})
}
}
#[derive(Debug, Clone)]
#[allow(missing_docs)]
pub struct Resume<'a> {
pub type_index: Index<'a>,
pub table: ResumeTable<'a>,
}
impl<'a> Parse<'a> for Resume<'a> {
fn parse(parser: Parser<'a>) -> Result<Self> {
Ok(Resume {
type_index: parser.parse()?,
table: parser.parse()?,
})
}
}
#[derive(Debug, Clone)]
#[allow(missing_docs)]
pub struct ResumeThrow<'a> {
pub type_index: Index<'a>,
pub tag_index: Index<'a>,
pub table: ResumeTable<'a>,
}
impl<'a> Parse<'a> for ResumeThrow<'a> {
fn parse(parser: Parser<'a>) -> Result<Self> {
Ok(ResumeThrow {
type_index: parser.parse()?,
tag_index: parser.parse()?,
table: parser.parse()?,
})
}
}
#[derive(Debug, Clone)]
#[allow(missing_docs)]
pub struct ResumeThrowRef<'a> {
pub type_index: Index<'a>,
pub table: ResumeTable<'a>,
}
impl<'a> Parse<'a> for ResumeThrowRef<'a> {
fn parse(parser: Parser<'a>) -> Result<Self> {
Ok(ResumeThrowRef {
type_index: parser.parse()?,
table: parser.parse()?,
})
}
}
#[derive(Debug, Clone)]
#[allow(missing_docs)]
pub struct Switch<'a> {
pub type_index: Index<'a>,
pub tag_index: Index<'a>,
}
impl<'a> Parse<'a> for Switch<'a> {
fn parse(parser: Parser<'a>) -> Result<Self> {
Ok(Switch {
type_index: parser.parse()?,
tag_index: parser.parse()?,
})
}
}
#[derive(Debug, Clone)]
#[allow(missing_docs)]
pub struct ResumeTable<'a> {
pub handlers: Vec<Handle<'a>>,
}
#[derive(Debug, Clone)]
#[allow(missing_docs)]
pub enum Handle<'a> {
OnLabel { tag: Index<'a>, label: Index<'a> },
OnSwitch { tag: Index<'a> },
}
impl<'a> Parse<'a> for ResumeTable<'a> {
fn parse(parser: Parser<'a>) -> Result<Self> {
let mut handlers = Vec::new();
while parser.peek::<LParen>()? && parser.peek2::<kw::on>()? {
handlers.push(parser.parens(|p| {
p.parse::<kw::on>()?;
let tag: Index<'a> = p.parse()?;
if p.peek::<kw::switch>()? {
p.parse::<kw::switch>()?;
Ok(Handle::OnSwitch { tag })
} else {
Ok(Handle::OnLabel {
tag,
label: p.parse()?,
})
}
})?);
}
Ok(ResumeTable { handlers })
}
}
#[derive(Debug, Clone)]
#[allow(missing_docs)]
pub struct TryTable<'a> {
pub block: Box<BlockType<'a>>,
pub catches: Vec<TryTableCatch<'a>>,
}
impl<'a> Parse<'a> for TryTable<'a> {
fn parse(parser: Parser<'a>) -> Result<Self> {
let block = parser.parse()?;
let mut catches = Vec::new();
while parser.peek::<LParen>()?
&& (parser.peek2::<kw::catch>()?
|| parser.peek2::<kw::catch_ref>()?
|| parser.peek2::<kw::catch_all>()?
|| parser.peek2::<kw::catch_all_ref>()?)
{
catches.push(parser.parens(|p| {
let kind = if parser.peek::<kw::catch_ref>()? {
p.parse::<kw::catch_ref>()?;
TryTableCatchKind::CatchRef(p.parse()?)
} else if parser.peek::<kw::catch>()? {
p.parse::<kw::catch>()?;
TryTableCatchKind::Catch(p.parse()?)
} else if parser.peek::<kw::catch_all>()? {
p.parse::<kw::catch_all>()?;
TryTableCatchKind::CatchAll
} else {
p.parse::<kw::catch_all_ref>()?;
TryTableCatchKind::CatchAllRef
};
Ok(TryTableCatch {
kind,
label: p.parse()?,
})
})?);
}
Ok(TryTable { block, catches })
}
}
#[derive(Debug, Clone)]
#[allow(missing_docs)]
pub enum TryTableCatchKind<'a> {
Catch(Index<'a>),
CatchRef(Index<'a>),
CatchAll,
CatchAllRef,
}
impl<'a> TryTableCatchKind<'a> {
#[allow(missing_docs)]
pub fn tag_index_mut(&mut self) -> Option<&mut Index<'a>> {
match self {
TryTableCatchKind::Catch(tag) | TryTableCatchKind::CatchRef(tag) => Some(tag),
TryTableCatchKind::CatchAll | TryTableCatchKind::CatchAllRef => None,
}
}
}
#[derive(Debug, Clone)]
#[allow(missing_docs)]
pub struct TryTableCatch<'a> {
pub kind: TryTableCatchKind<'a>,
pub label: Index<'a>,
}
#[allow(missing_docs)]
#[derive(Debug, Clone)]
pub struct BrTableIndices<'a> {
pub labels: Vec<Index<'a>>,
pub default: Index<'a>,
}
impl<'a> Parse<'a> for BrTableIndices<'a> {
fn parse(parser: Parser<'a>) -> Result<Self> {
let mut labels = vec![parser.parse()?];
while parser.peek::<Index>()? {
labels.push(parser.parse()?);
}
let default = labels.pop().unwrap();
Ok(BrTableIndices { labels, default })
}
}
#[derive(Debug, Clone)]
pub struct LaneArg {
pub lane: u8,
}
impl<'a> Parse<'a> for LaneArg {
fn parse(parser: Parser<'a>) -> Result<Self> {
let lane = parser.step(|c| {
if let Some((i, rest)) = c.integer()? {
if i.sign() == None {
let (src, radix) = i.val();
let val = u8::from_str_radix(src, radix)
.map_err(|_| c.error("malformed lane index"))?;
Ok((val, rest))
} else {
Err(c.error("unexpected token"))
}
} else {
Err(c.error("expected a lane index"))
}
})?;
Ok(LaneArg { lane })
}
}
#[derive(Debug, Clone)]
pub struct MemArg<'a> {
pub align: u64,
pub offset: u64,
pub target: MemArgTarget<'a>,
pub ordering: Option<MemArgOrdering>,
}
#[derive(Debug, Clone)]
pub enum MemArgTarget<'a> {
Memory(Index<'a>),
Array(Index<'a>),
}
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
pub enum MemArgOrdering {
Op(Ordering),
Rmw(Ordering),
}
impl<'a> MemArg<'a> {
fn parse(parser: Parser<'a>, default_align: u64) -> Result<Self> {
fn parse_field(name: &str, parser: Parser<'_>) -> Result<Option<u64>> {
parser.step(|c| {
let (kw, rest) = match c.keyword()? {
Some(p) => p,
None => return Ok((None, c)),
};
if !kw.starts_with(name) {
return Ok((None, c));
}
let kw = &kw[name.len()..];
if !kw.starts_with('=') {
return Ok((None, c));
}
let num = &kw[1..];
let lexer = Lexer::new(num);
let mut pos = 0;
if let Ok(Some(
token @ Token {
kind: TokenKind::Integer(integer_kind),
..
},
)) = lexer.parse(&mut pos)
{
let int = token.integer(lexer.input(), integer_kind);
let (s, base) = int.val();
let value = u64::from_str_radix(s, base);
return match value {
Ok(n) => Ok((Some(n), rest)),
Err(_) => Err(c.error("u64 constant out of range")),
};
}
Err(c.error("expected u64 integer constant"))
})
}
let target = if parser.peek2::<kw::r#type>()? {
MemArgTarget::Array(parser.parens(|p| {
p.parse::<kw::r#type>()?;
p.parse()
})?)
} else {
MemArgTarget::Memory(
parser
.parse::<Option<_>>()?
.unwrap_or_else(|| Index::Num(0, parser.prev_span())),
)
};
let offset = parse_field("offset", parser)?.unwrap_or(0);
let align = match parse_field("align", parser)? {
Some(n) if !n.is_power_of_two() => {
return Err(parser.error("alignment must be a power of two"));
}
n => n.unwrap_or(default_align),
};
Ok(MemArg {
offset,
align,
target,
ordering: None,
})
}
fn parse_atomic(parser: Parser<'a>, default_align: u64, rmw: bool) -> Result<Self> {
let mut memarg = MemArg::parse(parser, default_align)?;
let ordering = parser.parse::<Option<_>>()?;
memarg.ordering = if rmw {
ordering.map(MemArgOrdering::Rmw)
} else {
ordering.map(MemArgOrdering::Op)
};
Ok(memarg)
}
}
#[derive(Debug, Clone)]
pub struct LoadOrStoreLane<'a> {
pub memarg: MemArg<'a>,
pub lane: LaneArg,
}
impl<'a> LoadOrStoreLane<'a> {
fn parse(parser: Parser<'a>, default_align: u64) -> Result<Self> {
let has_memarg = parser.step(|c| match c.integer()? {
Some((_, after_int)) => {
if after_int.integer()?.is_some() {
return Ok((true, c));
}
if let Some((kw, _)) = after_int.keyword()? {
if kw.starts_with("offset=") || kw.starts_with("align=") {
return Ok((true, c));
}
}
Ok((false, c))
}
None => Ok((true, c)),
})?;
Ok(LoadOrStoreLane {
memarg: if has_memarg {
MemArg::parse(parser, default_align)?
} else {
MemArg {
align: default_align,
offset: 0,
target: MemArgTarget::Memory(Index::Num(0, parser.prev_span())),
ordering: None,
}
},
lane: LaneArg::parse(parser)?,
})
}
}
#[derive(Debug, Clone)]
pub struct CallIndirect<'a> {
pub table: Index<'a>,
pub ty: TypeUse<'a, FunctionType<'a>>,
}
impl<'a> Parse<'a> for CallIndirect<'a> {
fn parse(parser: Parser<'a>) -> Result<Self> {
let prev_span = parser.prev_span();
let table: Option<_> = parser.parse()?;
let ty = parser.parse::<TypeUse<'a, FunctionTypeNoNames<'a>>>()?;
Ok(CallIndirect {
table: table.unwrap_or(Index::Num(0, prev_span)),
ty: ty.into(),
})
}
}
#[derive(Debug, Clone)]
pub struct TableInit<'a> {
pub table: Index<'a>,
pub elem: Index<'a>,
}
impl<'a> Parse<'a> for TableInit<'a> {
fn parse(parser: Parser<'a>) -> Result<Self> {
let prev_span = parser.prev_span();
let (elem, table) = if parser.peek2::<Index>()? {
let table = parser.parse()?;
(parser.parse()?, table)
} else {
(parser.parse()?, Index::Num(0, prev_span))
};
Ok(TableInit { table, elem })
}
}
#[derive(Debug, Clone)]
pub struct TableCopy<'a> {
pub dst: Index<'a>,
pub src: Index<'a>,
}
impl<'a> Parse<'a> for TableCopy<'a> {
fn parse(parser: Parser<'a>) -> Result<Self> {
let (dst, src) = match parser.parse::<Option<_>>()? {
Some(dst) => (dst, parser.parse()?),
None => (
Index::Num(0, parser.prev_span()),
Index::Num(0, parser.prev_span()),
),
};
Ok(TableCopy { dst, src })
}
}
#[derive(Debug, Clone)]
pub struct TableArg<'a> {
pub dst: Index<'a>,
}
impl<'a> Parse<'a> for TableArg<'a> {
fn parse(parser: Parser<'a>) -> Result<Self> {
let dst = if let Some(dst) = parser.parse()? {
dst
} else {
Index::Num(0, parser.prev_span())
};
Ok(TableArg { dst })
}
}
#[derive(Debug, Clone)]
pub struct MemoryArg<'a> {
pub mem: Index<'a>,
}
impl<'a> Parse<'a> for MemoryArg<'a> {
fn parse(parser: Parser<'a>) -> Result<Self> {
let mem = if let Some(mem) = parser.parse()? {
mem
} else {
Index::Num(0, parser.prev_span())
};
Ok(MemoryArg { mem })
}
}
#[derive(Debug, Clone)]
pub struct MemoryInit<'a> {
pub data: Index<'a>,
pub mem: Index<'a>,
}
impl<'a> Parse<'a> for MemoryInit<'a> {
fn parse(parser: Parser<'a>) -> Result<Self> {
let prev_span = parser.prev_span();
let (data, mem) = if parser.peek2::<Index>()? {
let memory = parser.parse()?;
(parser.parse()?, memory)
} else {
(parser.parse()?, Index::Num(0, prev_span))
};
Ok(MemoryInit { data, mem })
}
}
#[derive(Debug, Clone)]
pub struct MemoryCopy<'a> {
pub src: Index<'a>,
pub dst: Index<'a>,
}
impl<'a> Parse<'a> for MemoryCopy<'a> {
fn parse(parser: Parser<'a>) -> Result<Self> {
let (src, dst) = match parser.parse()? {
Some(dst) => (parser.parse()?, dst),
None => (
Index::Num(0, parser.prev_span()),
Index::Num(0, parser.prev_span()),
),
};
Ok(MemoryCopy { src, dst })
}
}
#[derive(Debug, Clone)]
pub struct StructAccess<'a> {
pub r#struct: Index<'a>,
pub field: Index<'a>,
}
impl<'a> Parse<'a> for StructAccess<'a> {
fn parse(parser: Parser<'a>) -> Result<Self> {
Ok(StructAccess {
r#struct: parser.parse()?,
field: parser.parse()?,
})
}
}
#[derive(Debug, Clone)]
pub struct ArrayFill<'a> {
pub array: Index<'a>,
}
impl<'a> Parse<'a> for ArrayFill<'a> {
fn parse(parser: Parser<'a>) -> Result<Self> {
Ok(ArrayFill {
array: parser.parse()?,
})
}
}
#[derive(Debug, Clone)]
pub struct ArrayCopy<'a> {
pub dest_array: Index<'a>,
pub src_array: Index<'a>,
}
impl<'a> Parse<'a> for ArrayCopy<'a> {
fn parse(parser: Parser<'a>) -> Result<Self> {
Ok(ArrayCopy {
dest_array: parser.parse()?,
src_array: parser.parse()?,
})
}
}
#[derive(Debug, Clone)]
pub struct ArrayInit<'a> {
pub array: Index<'a>,
pub segment: Index<'a>,
}
impl<'a> Parse<'a> for ArrayInit<'a> {
fn parse(parser: Parser<'a>) -> Result<Self> {
Ok(ArrayInit {
array: parser.parse()?,
segment: parser.parse()?,
})
}
}
#[derive(Debug, Clone)]
pub struct ArrayNewFixed<'a> {
pub array: Index<'a>,
pub length: u32,
}
impl<'a> Parse<'a> for ArrayNewFixed<'a> {
fn parse(parser: Parser<'a>) -> Result<Self> {
Ok(ArrayNewFixed {
array: parser.parse()?,
length: parser.parse()?,
})
}
}
#[derive(Debug, Clone)]
pub struct ArrayNewData<'a> {
pub array: Index<'a>,
pub data_idx: Index<'a>,
}
impl<'a> Parse<'a> for ArrayNewData<'a> {
fn parse(parser: Parser<'a>) -> Result<Self> {
Ok(ArrayNewData {
array: parser.parse()?,
data_idx: parser.parse()?,
})
}
}
#[derive(Debug, Clone)]
pub struct ArrayNewElem<'a> {
pub array: Index<'a>,
pub elem_idx: Index<'a>,
}
impl<'a> Parse<'a> for ArrayNewElem<'a> {
fn parse(parser: Parser<'a>) -> Result<Self> {
Ok(ArrayNewElem {
array: parser.parse()?,
elem_idx: parser.parse()?,
})
}
}
#[derive(Debug, Clone)]
pub struct RefCast<'a> {
pub r#type: RefType<'a>,
}
impl<'a> Parse<'a> for RefCast<'a> {
fn parse(parser: Parser<'a>) -> Result<Self> {
Ok(RefCast {
r#type: parser.parse()?,
})
}
}
#[derive(Debug, Clone)]
pub struct RefTest<'a> {
pub r#type: RefType<'a>,
}
impl<'a> Parse<'a> for RefTest<'a> {
fn parse(parser: Parser<'a>) -> Result<Self> {
Ok(RefTest {
r#type: parser.parse()?,
})
}
}
#[derive(Debug, Clone)]
pub struct BrOnCast<'a> {
pub label: Index<'a>,
pub from_type: RefType<'a>,
pub to_type: RefType<'a>,
}
impl<'a> Parse<'a> for BrOnCast<'a> {
fn parse(parser: Parser<'a>) -> Result<Self> {
Ok(BrOnCast {
label: parser.parse()?,
from_type: parser.parse()?,
to_type: parser.parse()?,
})
}
}
#[derive(Debug, Clone)]
pub struct BrOnCastFail<'a> {
pub label: Index<'a>,
pub from_type: RefType<'a>,
pub to_type: RefType<'a>,
}
impl<'a> Parse<'a> for BrOnCastFail<'a> {
fn parse(parser: Parser<'a>) -> Result<Self> {
Ok(BrOnCastFail {
label: parser.parse()?,
from_type: parser.parse()?,
to_type: parser.parse()?,
})
}
}
#[derive(Debug, Clone)]
pub struct RefCastDescEq<'a> {
pub r#type: RefType<'a>,
}
impl<'a> Parse<'a> for RefCastDescEq<'a> {
fn parse(parser: Parser<'a>) -> Result<Self> {
Ok(RefCastDescEq {
r#type: parser.parse()?,
})
}
}
#[derive(Debug, Clone)]
pub struct BrOnCastDescEq<'a> {
pub label: Index<'a>,
pub from_type: RefType<'a>,
pub to_type: RefType<'a>,
}
impl<'a> Parse<'a> for BrOnCastDescEq<'a> {
fn parse(parser: Parser<'a>) -> Result<Self> {
Ok(BrOnCastDescEq {
label: parser.parse()?,
from_type: parser.parse()?,
to_type: parser.parse()?,
})
}
}
#[derive(Debug, Clone)]
pub struct BrOnCastDescEqFail<'a> {
pub label: Index<'a>,
pub from_type: RefType<'a>,
pub to_type: RefType<'a>,
}
impl<'a> Parse<'a> for BrOnCastDescEqFail<'a> {
fn parse(parser: Parser<'a>) -> Result<Self> {
Ok(BrOnCastDescEqFail {
label: parser.parse()?,
from_type: parser.parse()?,
to_type: parser.parse()?,
})
}
}
#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
pub enum Ordering {
AcqRel,
SeqCst,
}
impl<'a> Parse<'a> for Ordering {
fn parse(parser: Parser<'a>) -> Result<Self> {
if parser.peek::<kw::seqcst>()? {
parser.parse::<kw::seqcst>()?;
Ok(Ordering::SeqCst)
} else if parser.peek::<kw::acqrel>()? {
parser.parse::<kw::acqrel>()?;
Ok(Ordering::AcqRel)
} else {
Err(parser.error("expected a memory ordering: `seqcst` or `acqrel`"))
}
}
}
impl Peek for Ordering {
fn peek(cursor: Cursor<'_>) -> Result<bool> {
Ok(kw::seqcst::peek(cursor)? || kw::acqrel::peek(cursor)?)
}
fn display() -> &'static str {
"ordering"
}
}
#[derive(Clone, Debug)]
pub struct Ordered<T> {
pub ordering: Ordering,
pub inner: T,
}
impl<'a, T> Parse<'a> for Ordered<T>
where
T: Parse<'a>,
{
fn parse(parser: Parser<'a>) -> Result<Self> {
let ordering = parser.parse()?;
let inner = parser.parse()?;
Ok(Ordered { ordering, inner })
}
}
#[derive(Clone, Debug)]
#[allow(missing_docs)]
pub enum V128Const {
I8x16([i8; 16]),
I16x8([i16; 8]),
I32x4([i32; 4]),
I64x2([i64; 2]),
F32x4([F32; 4]),
F64x2([F64; 2]),
}
impl V128Const {
#[rustfmt::skip]
pub fn to_le_bytes(&self) -> [u8; 16] {
match self {
V128Const::I8x16(arr) => [
arr[0] as u8,
arr[1] as u8,
arr[2] as u8,
arr[3] as u8,
arr[4] as u8,
arr[5] as u8,
arr[6] as u8,
arr[7] as u8,
arr[8] as u8,
arr[9] as u8,
arr[10] as u8,
arr[11] as u8,
arr[12] as u8,
arr[13] as u8,
arr[14] as u8,
arr[15] as u8,
],
V128Const::I16x8(arr) => {
let a1 = arr[0].to_le_bytes();
let a2 = arr[1].to_le_bytes();
let a3 = arr[2].to_le_bytes();
let a4 = arr[3].to_le_bytes();
let a5 = arr[4].to_le_bytes();
let a6 = arr[5].to_le_bytes();
let a7 = arr[6].to_le_bytes();
let a8 = arr[7].to_le_bytes();
[
a1[0], a1[1],
a2[0], a2[1],
a3[0], a3[1],
a4[0], a4[1],
a5[0], a5[1],
a6[0], a6[1],
a7[0], a7[1],
a8[0], a8[1],
]
}
V128Const::I32x4(arr) => {
let a1 = arr[0].to_le_bytes();
let a2 = arr[1].to_le_bytes();
let a3 = arr[2].to_le_bytes();
let a4 = arr[3].to_le_bytes();
[
a1[0], a1[1], a1[2], a1[3],
a2[0], a2[1], a2[2], a2[3],
a3[0], a3[1], a3[2], a3[3],
a4[0], a4[1], a4[2], a4[3],
]
}
V128Const::I64x2(arr) => {
let a1 = arr[0].to_le_bytes();
let a2 = arr[1].to_le_bytes();
[
a1[0], a1[1], a1[2], a1[3], a1[4], a1[5], a1[6], a1[7],
a2[0], a2[1], a2[2], a2[3], a2[4], a2[5], a2[6], a2[7],
]
}
V128Const::F32x4(arr) => {
let a1 = arr[0].bits.to_le_bytes();
let a2 = arr[1].bits.to_le_bytes();
let a3 = arr[2].bits.to_le_bytes();
let a4 = arr[3].bits.to_le_bytes();
[
a1[0], a1[1], a1[2], a1[3],
a2[0], a2[1], a2[2], a2[3],
a3[0], a3[1], a3[2], a3[3],
a4[0], a4[1], a4[2], a4[3],
]
}
V128Const::F64x2(arr) => {
let a1 = arr[0].bits.to_le_bytes();
let a2 = arr[1].bits.to_le_bytes();
[
a1[0], a1[1], a1[2], a1[3], a1[4], a1[5], a1[6], a1[7],
a2[0], a2[1], a2[2], a2[3], a2[4], a2[5], a2[6], a2[7],
]
}
}
}
}
impl<'a> Parse<'a> for V128Const {
fn parse(parser: Parser<'a>) -> Result<Self> {
let mut l = parser.lookahead1();
if l.peek::<kw::i8x16>()? {
parser.parse::<kw::i8x16>()?;
Ok(V128Const::I8x16([
parser.parse()?,
parser.parse()?,
parser.parse()?,
parser.parse()?,
parser.parse()?,
parser.parse()?,
parser.parse()?,
parser.parse()?,
parser.parse()?,
parser.parse()?,
parser.parse()?,
parser.parse()?,
parser.parse()?,
parser.parse()?,
parser.parse()?,
parser.parse()?,
]))
} else if l.peek::<kw::i16x8>()? {
parser.parse::<kw::i16x8>()?;
Ok(V128Const::I16x8([
parser.parse()?,
parser.parse()?,
parser.parse()?,
parser.parse()?,
parser.parse()?,
parser.parse()?,
parser.parse()?,
parser.parse()?,
]))
} else if l.peek::<kw::i32x4>()? {
parser.parse::<kw::i32x4>()?;
Ok(V128Const::I32x4([
parser.parse()?,
parser.parse()?,
parser.parse()?,
parser.parse()?,
]))
} else if l.peek::<kw::i64x2>()? {
parser.parse::<kw::i64x2>()?;
Ok(V128Const::I64x2([parser.parse()?, parser.parse()?]))
} else if l.peek::<kw::f32x4>()? {
parser.parse::<kw::f32x4>()?;
Ok(V128Const::F32x4([
parser.parse()?,
parser.parse()?,
parser.parse()?,
parser.parse()?,
]))
} else if l.peek::<kw::f64x2>()? {
parser.parse::<kw::f64x2>()?;
Ok(V128Const::F64x2([parser.parse()?, parser.parse()?]))
} else {
Err(l.error())
}
}
}
#[derive(Debug, Clone)]
pub struct I8x16Shuffle {
#[allow(missing_docs)]
pub lanes: [u8; 16],
}
impl<'a> Parse<'a> for I8x16Shuffle {
fn parse(parser: Parser<'a>) -> Result<Self> {
Ok(I8x16Shuffle {
lanes: [
parser.parse()?,
parser.parse()?,
parser.parse()?,
parser.parse()?,
parser.parse()?,
parser.parse()?,
parser.parse()?,
parser.parse()?,
parser.parse()?,
parser.parse()?,
parser.parse()?,
parser.parse()?,
parser.parse()?,
parser.parse()?,
parser.parse()?,
parser.parse()?,
],
})
}
}
#[derive(Debug, Clone)]
pub struct SelectTypes<'a> {
#[allow(missing_docs)]
pub tys: Option<Vec<ValType<'a>>>,
}
impl<'a> Parse<'a> for SelectTypes<'a> {
fn parse(parser: Parser<'a>) -> Result<Self> {
let mut found = false;
let mut list = Vec::new();
while parser.peek2::<kw::result>()? {
found = true;
parser.parens(|p| {
p.parse::<kw::result>()?;
while !p.is_empty() {
list.push(p.parse()?);
}
Ok(())
})?;
}
Ok(SelectTypes {
tys: if found { Some(list) } else { None },
})
}
}