Source code
Revision control
Copy as Markdown
Other Tools
use crate::{encode_section, Encode, HeapType, RefType, Section, SectionId, ValType};
use std::borrow::Cow;
/// An encoder for the code section.
///
/// Code sections are only supported for modules.
///
/// # Example
///
/// ```
/// use wasm_encoder::{
/// CodeSection, Function, FunctionSection, Instruction, Module,
/// TypeSection, ValType
/// };
///
/// let mut types = TypeSection::new();
/// types.ty().function(vec![], vec![ValType::I32]);
///
/// let mut functions = FunctionSection::new();
/// let type_index = 0;
/// functions.function(type_index);
///
/// let locals = vec![];
/// let mut func = Function::new(locals);
/// func.instruction(&Instruction::I32Const(42));
/// let mut code = CodeSection::new();
/// code.function(&func);
///
/// let mut module = Module::new();
/// module
/// .section(&types)
/// .section(&functions)
/// .section(&code);
///
/// let wasm_bytes = module.finish();
/// ```
#[derive(Clone, Default, Debug)]
pub struct CodeSection {
bytes: Vec<u8>,
num_added: u32,
}
impl CodeSection {
/// Create a new code section encoder.
pub fn new() -> Self {
Self::default()
}
/// The number of functions in the section.
pub fn len(&self) -> u32 {
self.num_added
}
/// The number of bytes already added to this section.
///
/// This number doesn't include the vector length that precedes the
/// code entries, since it has a variable size that isn't known until all
/// functions are added.
pub fn byte_len(&self) -> usize {
self.bytes.len()
}
/// Determines if the section is empty.
pub fn is_empty(&self) -> bool {
self.num_added == 0
}
/// Write a function body into this code section.
pub fn function(&mut self, func: &Function) -> &mut Self {
func.encode(&mut self.bytes);
self.num_added += 1;
self
}
/// Add a raw byte slice into this code section as a function body.
///
/// The length prefix of the function body will be automatically prepended,
/// and should not be included in the raw byte slice.
///
/// # Example
///
/// You can use the `raw` method to copy an already-encoded function body
/// into a new code section encoder:
///
/// ```
/// # use wasmparser::{BinaryReader, CodeSectionReader};
/// // id, size, # entries, entry
/// let code_section = [10, 6, 1, 4, 0, 65, 0, 11];
///
/// // Parse the code section.
/// let reader = BinaryReader::new(&code_section, 0);
/// let reader = CodeSectionReader::new(reader).unwrap();
/// let body = reader.into_iter().next().unwrap().unwrap();
/// let body_range = body.range();
///
/// // Add the body to a new code section encoder by copying bytes rather
/// // than re-parsing and re-encoding it.
/// let mut encoder = wasm_encoder::CodeSection::new();
/// encoder.raw(&code_section[body_range.start..body_range.end]);
/// ```
pub fn raw(&mut self, data: &[u8]) -> &mut Self {
data.encode(&mut self.bytes);
self.num_added += 1;
self
}
}
impl Encode for CodeSection {
fn encode(&self, sink: &mut Vec<u8>) {
encode_section(sink, self.num_added, &self.bytes);
}
}
impl Section for CodeSection {
fn id(&self) -> u8 {
SectionId::Code.into()
}
}
/// An encoder for a function body within the code section.
///
/// # Example
///
/// ```
/// use wasm_encoder::{CodeSection, Function, Instruction};
///
/// // Define the function body for:
/// //
/// // (func (param i32 i32) (result i32)
/// // local.get 0
/// // local.get 1
/// // i32.add)
/// let locals = vec![];
/// let mut func = Function::new(locals);
/// func.instruction(&Instruction::LocalGet(0));
/// func.instruction(&Instruction::LocalGet(1));
/// func.instruction(&Instruction::I32Add);
///
/// // Add our function to the code section.
/// let mut code = CodeSection::new();
/// code.function(&func);
/// ```
#[derive(Clone, Debug, Eq, PartialEq)]
pub struct Function {
bytes: Vec<u8>,
}
impl Function {
/// Create a new function body with the given locals.
///
/// The argument is an iterator over `(N, Ty)`, which defines
/// that the next `N` locals will be of type `Ty`.
///
/// For example, a function with locals 0 and 1 of type I32 and
/// local 2 of type F32 would be created as:
///
/// ```
/// # use wasm_encoder::{Function, ValType};
/// let f = Function::new([(2, ValType::I32), (1, ValType::F32)]);
/// ```
///
/// For more information about the code section (and function definition) in the WASM binary format
/// see the [WebAssembly spec](https://webassembly.github.io/spec/core/binary/modules.html#binary-func)
pub fn new<L>(locals: L) -> Self
where
L: IntoIterator<Item = (u32, ValType)>,
L::IntoIter: ExactSizeIterator,
{
let locals = locals.into_iter();
let mut bytes = vec![];
locals.len().encode(&mut bytes);
for (count, ty) in locals {
count.encode(&mut bytes);
ty.encode(&mut bytes);
}
Function { bytes }
}
/// Create a function from a list of locals' types.
///
/// Unlike [`Function::new`], this constructor simply takes a list of types
/// which are in order associated with locals.
///
/// For example:
///
/// ```
/// # use wasm_encoder::{Function, ValType};
/// let f = Function::new([(2, ValType::I32), (1, ValType::F32)]);
/// let g = Function::new_with_locals_types([
/// ValType::I32, ValType::I32, ValType::F32
/// ]);
///
/// assert_eq!(f, g)
/// ```
pub fn new_with_locals_types<L>(locals: L) -> Self
where
L: IntoIterator<Item = ValType>,
{
let locals = locals.into_iter();
let mut locals_collected: Vec<(u32, ValType)> = vec![];
for l in locals {
if let Some((last_count, last_type)) = locals_collected.last_mut() {
if l == *last_type {
// Increment the count of consecutive locals of this type
*last_count += 1;
continue;
}
}
// If we didn't increment, a new type of local appeared
locals_collected.push((1, l));
}
Function::new(locals_collected)
}
/// Write an instruction into this function body.
pub fn instruction(&mut self, instruction: &Instruction) -> &mut Self {
instruction.encode(&mut self.bytes);
self
}
/// Add raw bytes to this function's body.
pub fn raw<B>(&mut self, bytes: B) -> &mut Self
where
B: IntoIterator<Item = u8>,
{
self.bytes.extend(bytes);
self
}
/// The number of bytes already added to this function.
///
/// This number doesn't include the variable-width size field that `encode`
/// will write before the added bytes, since the size of that field isn't
/// known until all the instructions are added to this function.
pub fn byte_len(&self) -> usize {
self.bytes.len()
}
/// Unwraps and returns the raw byte encoding of this function.
///
/// This encoding doesn't include the variable-width size field
/// that `encode` will write before the added bytes. As such, its
/// length will match the return value of [`byte_len`].
///
/// # Use Case
///
/// This raw byte form is suitable for later using with
/// [`CodeSection::raw`]. Note that it *differs* from what results
/// from [`Function::encode`] precisely due to the *lack* of the
/// length prefix; [`CodeSection::raw`] will use this. Using
/// [`Function::encode`] instead produces bytes that cannot be fed
/// into other wasm-encoder types without stripping off the length
/// prefix, which is awkward and error-prone.
///
/// This method combined with [`CodeSection::raw`] may be useful
/// together if one wants to save the result of function encoding
/// and use it later: for example, caching the result of some code
/// generation process.
///
/// For example:
///
/// ```
/// # use wasm_encoder::{CodeSection, Function, Instruction};
/// let mut f = Function::new([]);
/// f.instruction(&Instruction::End);
/// let bytes = f.into_raw_body();
/// // (save `bytes` somewhere for later use)
/// let mut code = CodeSection::new();
/// code.raw(&bytes[..]);
///
/// assert_eq!(2, bytes.len()); // Locals count, then `end`
/// assert_eq!(3, code.byte_len()); // Function length byte, function body
/// ```
pub fn into_raw_body(self) -> Vec<u8> {
self.bytes
}
}
impl Encode for Function {
fn encode(&self, sink: &mut Vec<u8>) {
self.bytes.encode(sink);
}
}
/// The immediate for a memory instruction.
#[derive(Clone, Copy, Debug)]
pub struct MemArg {
/// A static offset to add to the instruction's dynamic address operand.
///
/// This is a `u64` field for the memory64 proposal, but 32-bit memories
/// limit offsets to at most `u32::MAX` bytes. This will be encoded as a LEB
/// but it won't generate a valid module if an offset is specified which is
/// larger than the maximum size of the index space for the memory indicated
/// by `memory_index`.
pub offset: u64,
/// The expected alignment of the instruction's dynamic address operand
/// (expressed the exponent of a power of two).
pub align: u32,
/// The index of the memory this instruction is operating upon.
pub memory_index: u32,
}
impl Encode for MemArg {
fn encode(&self, sink: &mut Vec<u8>) {
if self.memory_index == 0 {
self.align.encode(sink);
self.offset.encode(sink);
} else {
(self.align | (1 << 6)).encode(sink);
self.memory_index.encode(sink);
self.offset.encode(sink);
}
}
}
/// The memory ordering for atomic instructions.
///
/// For an in-depth explanation of memory orderings, see the C++ documentation
/// for [`memory_order`] or the Rust documentation for [`atomic::Ordering`].
///
#[derive(Clone, Copy, Debug)]
pub enum Ordering {
/// For a load, it acquires; this orders all operations before the last
/// "releasing" store. For a store, it releases; this orders all operations
/// before it at the next "acquiring" load.
AcqRel,
/// Like `AcqRel` but all threads see all sequentially consistent operations
/// in the same order.
SeqCst,
}
impl Encode for Ordering {
fn encode(&self, sink: &mut Vec<u8>) {
let flag: u8 = match self {
Ordering::SeqCst => 0,
Ordering::AcqRel => 1,
};
sink.push(flag);
}
}
/// Describe an unchecked SIMD lane index.
pub type Lane = u8;
/// The type for a `block`/`if`/`loop`.
#[derive(Clone, Copy, Debug)]
pub enum BlockType {
/// `[] -> []`
Empty,
/// `[] -> [t]`
Result(ValType),
/// The `n`th function type.
FunctionType(u32),
}
impl Encode for BlockType {
fn encode(&self, sink: &mut Vec<u8>) {
match *self {
Self::Empty => sink.push(0x40),
Self::Result(ty) => ty.encode(sink),
Self::FunctionType(f) => (f as i64).encode(sink),
}
}
}
/// WebAssembly instructions.
#[derive(Clone, Debug)]
#[non_exhaustive]
#[allow(missing_docs, non_camel_case_types)]
pub enum Instruction<'a> {
// Control instructions.
Unreachable,
Nop,
Block(BlockType),
Loop(BlockType),
If(BlockType),
Else,
End,
Br(u32),
BrIf(u32),
BrTable(Cow<'a, [u32]>, u32),
BrOnNull(u32),
BrOnNonNull(u32),
Return,
Call(u32),
CallRef(u32),
CallIndirect {
type_index: u32,
table_index: u32,
},
ReturnCallRef(u32),
ReturnCall(u32),
ReturnCallIndirect {
type_index: u32,
table_index: u32,
},
TryTable(BlockType, Cow<'a, [Catch]>),
Throw(u32),
ThrowRef,
// Deprecated exception-handling instructions
Try(BlockType),
Delegate(u32),
Catch(u32),
CatchAll,
Rethrow(u32),
// Parametric instructions.
Drop,
Select,
// Variable instructions.
LocalGet(u32),
LocalSet(u32),
LocalTee(u32),
GlobalGet(u32),
GlobalSet(u32),
// Memory instructions.
I32Load(MemArg),
I64Load(MemArg),
F32Load(MemArg),
F64Load(MemArg),
I32Load8S(MemArg),
I32Load8U(MemArg),
I32Load16S(MemArg),
I32Load16U(MemArg),
I64Load8S(MemArg),
I64Load8U(MemArg),
I64Load16S(MemArg),
I64Load16U(MemArg),
I64Load32S(MemArg),
I64Load32U(MemArg),
I32Store(MemArg),
I64Store(MemArg),
F32Store(MemArg),
F64Store(MemArg),
I32Store8(MemArg),
I32Store16(MemArg),
I64Store8(MemArg),
I64Store16(MemArg),
I64Store32(MemArg),
MemorySize(u32),
MemoryGrow(u32),
MemoryInit {
mem: u32,
data_index: u32,
},
DataDrop(u32),
MemoryCopy {
src_mem: u32,
dst_mem: u32,
},
MemoryFill(u32),
MemoryDiscard(u32),
// Numeric instructions.
I32Const(i32),
I64Const(i64),
F32Const(f32),
F64Const(f64),
I32Eqz,
I32Eq,
I32Ne,
I32LtS,
I32LtU,
I32GtS,
I32GtU,
I32LeS,
I32LeU,
I32GeS,
I32GeU,
I64Eqz,
I64Eq,
I64Ne,
I64LtS,
I64LtU,
I64GtS,
I64GtU,
I64LeS,
I64LeU,
I64GeS,
I64GeU,
F32Eq,
F32Ne,
F32Lt,
F32Gt,
F32Le,
F32Ge,
F64Eq,
F64Ne,
F64Lt,
F64Gt,
F64Le,
F64Ge,
I32Clz,
I32Ctz,
I32Popcnt,
I32Add,
I32Sub,
I32Mul,
I32DivS,
I32DivU,
I32RemS,
I32RemU,
I32And,
I32Or,
I32Xor,
I32Shl,
I32ShrS,
I32ShrU,
I32Rotl,
I32Rotr,
I64Clz,
I64Ctz,
I64Popcnt,
I64Add,
I64Sub,
I64Mul,
I64DivS,
I64DivU,
I64RemS,
I64RemU,
I64And,
I64Or,
I64Xor,
I64Shl,
I64ShrS,
I64ShrU,
I64Rotl,
I64Rotr,
F32Abs,
F32Neg,
F32Ceil,
F32Floor,
F32Trunc,
F32Nearest,
F32Sqrt,
F32Add,
F32Sub,
F32Mul,
F32Div,
F32Min,
F32Max,
F32Copysign,
F64Abs,
F64Neg,
F64Ceil,
F64Floor,
F64Trunc,
F64Nearest,
F64Sqrt,
F64Add,
F64Sub,
F64Mul,
F64Div,
F64Min,
F64Max,
F64Copysign,
I32WrapI64,
I32TruncF32S,
I32TruncF32U,
I32TruncF64S,
I32TruncF64U,
I64ExtendI32S,
I64ExtendI32U,
I64TruncF32S,
I64TruncF32U,
I64TruncF64S,
I64TruncF64U,
F32ConvertI32S,
F32ConvertI32U,
F32ConvertI64S,
F32ConvertI64U,
F32DemoteF64,
F64ConvertI32S,
F64ConvertI32U,
F64ConvertI64S,
F64ConvertI64U,
F64PromoteF32,
I32ReinterpretF32,
I64ReinterpretF64,
F32ReinterpretI32,
F64ReinterpretI64,
I32Extend8S,
I32Extend16S,
I64Extend8S,
I64Extend16S,
I64Extend32S,
I32TruncSatF32S,
I32TruncSatF32U,
I32TruncSatF64S,
I32TruncSatF64U,
I64TruncSatF32S,
I64TruncSatF32U,
I64TruncSatF64S,
I64TruncSatF64U,
// Reference types instructions.
TypedSelect(ValType),
RefNull(HeapType),
RefIsNull,
RefFunc(u32),
RefEq,
RefAsNonNull,
// GC types instructions.
StructNew(u32),
StructNewDefault(u32),
StructGet {
struct_type_index: u32,
field_index: u32,
},
StructGetS {
struct_type_index: u32,
field_index: u32,
},
StructGetU {
struct_type_index: u32,
field_index: u32,
},
StructSet {
struct_type_index: u32,
field_index: u32,
},
ArrayNew(u32),
ArrayNewDefault(u32),
ArrayNewFixed {
array_type_index: u32,
array_size: u32,
},
ArrayNewData {
array_type_index: u32,
array_data_index: u32,
},
ArrayNewElem {
array_type_index: u32,
array_elem_index: u32,
},
ArrayGet(u32),
ArrayGetS(u32),
ArrayGetU(u32),
ArraySet(u32),
ArrayLen,
ArrayFill(u32),
ArrayCopy {
array_type_index_dst: u32,
array_type_index_src: u32,
},
ArrayInitData {
array_type_index: u32,
array_data_index: u32,
},
ArrayInitElem {
array_type_index: u32,
array_elem_index: u32,
},
RefTestNonNull(HeapType),
RefTestNullable(HeapType),
RefCastNonNull(HeapType),
RefCastNullable(HeapType),
BrOnCast {
relative_depth: u32,
from_ref_type: RefType,
to_ref_type: RefType,
},
BrOnCastFail {
relative_depth: u32,
from_ref_type: RefType,
to_ref_type: RefType,
},
AnyConvertExtern,
ExternConvertAny,
RefI31,
I31GetS,
I31GetU,
// Bulk memory instructions.
TableInit {
elem_index: u32,
table: u32,
},
ElemDrop(u32),
TableFill(u32),
TableSet(u32),
TableGet(u32),
TableGrow(u32),
TableSize(u32),
TableCopy {
src_table: u32,
dst_table: u32,
},
// SIMD instructions.
V128Load(MemArg),
V128Load8x8S(MemArg),
V128Load8x8U(MemArg),
V128Load16x4S(MemArg),
V128Load16x4U(MemArg),
V128Load32x2S(MemArg),
V128Load32x2U(MemArg),
V128Load8Splat(MemArg),
V128Load16Splat(MemArg),
V128Load32Splat(MemArg),
V128Load64Splat(MemArg),
V128Load32Zero(MemArg),
V128Load64Zero(MemArg),
V128Store(MemArg),
V128Load8Lane {
memarg: MemArg,
lane: Lane,
},
V128Load16Lane {
memarg: MemArg,
lane: Lane,
},
V128Load32Lane {
memarg: MemArg,
lane: Lane,
},
V128Load64Lane {
memarg: MemArg,
lane: Lane,
},
V128Store8Lane {
memarg: MemArg,
lane: Lane,
},
V128Store16Lane {
memarg: MemArg,
lane: Lane,
},
V128Store32Lane {
memarg: MemArg,
lane: Lane,
},
V128Store64Lane {
memarg: MemArg,
lane: Lane,
},
V128Const(i128),
I8x16Shuffle([Lane; 16]),
I8x16ExtractLaneS(Lane),
I8x16ExtractLaneU(Lane),
I8x16ReplaceLane(Lane),
I16x8ExtractLaneS(Lane),
I16x8ExtractLaneU(Lane),
I16x8ReplaceLane(Lane),
I32x4ExtractLane(Lane),
I32x4ReplaceLane(Lane),
I64x2ExtractLane(Lane),
I64x2ReplaceLane(Lane),
F32x4ExtractLane(Lane),
F32x4ReplaceLane(Lane),
F64x2ExtractLane(Lane),
F64x2ReplaceLane(Lane),
I8x16Swizzle,
I8x16Splat,
I16x8Splat,
I32x4Splat,
I64x2Splat,
F32x4Splat,
F64x2Splat,
I8x16Eq,
I8x16Ne,
I8x16LtS,
I8x16LtU,
I8x16GtS,
I8x16GtU,
I8x16LeS,
I8x16LeU,
I8x16GeS,
I8x16GeU,
I16x8Eq,
I16x8Ne,
I16x8LtS,
I16x8LtU,
I16x8GtS,
I16x8GtU,
I16x8LeS,
I16x8LeU,
I16x8GeS,
I16x8GeU,
I32x4Eq,
I32x4Ne,
I32x4LtS,
I32x4LtU,
I32x4GtS,
I32x4GtU,
I32x4LeS,
I32x4LeU,
I32x4GeS,
I32x4GeU,
I64x2Eq,
I64x2Ne,
I64x2LtS,
I64x2GtS,
I64x2LeS,
I64x2GeS,
F32x4Eq,
F32x4Ne,
F32x4Lt,
F32x4Gt,
F32x4Le,
F32x4Ge,
F64x2Eq,
F64x2Ne,
F64x2Lt,
F64x2Gt,
F64x2Le,
F64x2Ge,
V128Not,
V128And,
V128AndNot,
V128Or,
V128Xor,
V128Bitselect,
V128AnyTrue,
I8x16Abs,
I8x16Neg,
I8x16Popcnt,
I8x16AllTrue,
I8x16Bitmask,
I8x16NarrowI16x8S,
I8x16NarrowI16x8U,
I8x16Shl,
I8x16ShrS,
I8x16ShrU,
I8x16Add,
I8x16AddSatS,
I8x16AddSatU,
I8x16Sub,
I8x16SubSatS,
I8x16SubSatU,
I8x16MinS,
I8x16MinU,
I8x16MaxS,
I8x16MaxU,
I8x16AvgrU,
I16x8ExtAddPairwiseI8x16S,
I16x8ExtAddPairwiseI8x16U,
I16x8Abs,
I16x8Neg,
I16x8Q15MulrSatS,
I16x8AllTrue,
I16x8Bitmask,
I16x8NarrowI32x4S,
I16x8NarrowI32x4U,
I16x8ExtendLowI8x16S,
I16x8ExtendHighI8x16S,
I16x8ExtendLowI8x16U,
I16x8ExtendHighI8x16U,
I16x8Shl,
I16x8ShrS,
I16x8ShrU,
I16x8Add,
I16x8AddSatS,
I16x8AddSatU,
I16x8Sub,
I16x8SubSatS,
I16x8SubSatU,
I16x8Mul,
I16x8MinS,
I16x8MinU,
I16x8MaxS,
I16x8MaxU,
I16x8AvgrU,
I16x8ExtMulLowI8x16S,
I16x8ExtMulHighI8x16S,
I16x8ExtMulLowI8x16U,
I16x8ExtMulHighI8x16U,
I32x4ExtAddPairwiseI16x8S,
I32x4ExtAddPairwiseI16x8U,
I32x4Abs,
I32x4Neg,
I32x4AllTrue,
I32x4Bitmask,
I32x4ExtendLowI16x8S,
I32x4ExtendHighI16x8S,
I32x4ExtendLowI16x8U,
I32x4ExtendHighI16x8U,
I32x4Shl,
I32x4ShrS,
I32x4ShrU,
I32x4Add,
I32x4Sub,
I32x4Mul,
I32x4MinS,
I32x4MinU,
I32x4MaxS,
I32x4MaxU,
I32x4DotI16x8S,
I32x4ExtMulLowI16x8S,
I32x4ExtMulHighI16x8S,
I32x4ExtMulLowI16x8U,
I32x4ExtMulHighI16x8U,
I64x2Abs,
I64x2Neg,
I64x2AllTrue,
I64x2Bitmask,
I64x2ExtendLowI32x4S,
I64x2ExtendHighI32x4S,
I64x2ExtendLowI32x4U,
I64x2ExtendHighI32x4U,
I64x2Shl,
I64x2ShrS,
I64x2ShrU,
I64x2Add,
I64x2Sub,
I64x2Mul,
I64x2ExtMulLowI32x4S,
I64x2ExtMulHighI32x4S,
I64x2ExtMulLowI32x4U,
I64x2ExtMulHighI32x4U,
F32x4Ceil,
F32x4Floor,
F32x4Trunc,
F32x4Nearest,
F32x4Abs,
F32x4Neg,
F32x4Sqrt,
F32x4Add,
F32x4Sub,
F32x4Mul,
F32x4Div,
F32x4Min,
F32x4Max,
F32x4PMin,
F32x4PMax,
F64x2Ceil,
F64x2Floor,
F64x2Trunc,
F64x2Nearest,
F64x2Abs,
F64x2Neg,
F64x2Sqrt,
F64x2Add,
F64x2Sub,
F64x2Mul,
F64x2Div,
F64x2Min,
F64x2Max,
F64x2PMin,
F64x2PMax,
I32x4TruncSatF32x4S,
I32x4TruncSatF32x4U,
F32x4ConvertI32x4S,
F32x4ConvertI32x4U,
I32x4TruncSatF64x2SZero,
I32x4TruncSatF64x2UZero,
F64x2ConvertLowI32x4S,
F64x2ConvertLowI32x4U,
F32x4DemoteF64x2Zero,
F64x2PromoteLowF32x4,
// Relaxed simd proposal
I8x16RelaxedSwizzle,
I32x4RelaxedTruncF32x4S,
I32x4RelaxedTruncF32x4U,
I32x4RelaxedTruncF64x2SZero,
I32x4RelaxedTruncF64x2UZero,
F32x4RelaxedMadd,
F32x4RelaxedNmadd,
F64x2RelaxedMadd,
F64x2RelaxedNmadd,
I8x16RelaxedLaneselect,
I16x8RelaxedLaneselect,
I32x4RelaxedLaneselect,
I64x2RelaxedLaneselect,
F32x4RelaxedMin,
F32x4RelaxedMax,
F64x2RelaxedMin,
F64x2RelaxedMax,
I16x8RelaxedQ15mulrS,
I16x8RelaxedDotI8x16I7x16S,
I32x4RelaxedDotI8x16I7x16AddS,
// Atomic instructions (the threads proposal)
MemoryAtomicNotify(MemArg),
MemoryAtomicWait32(MemArg),
MemoryAtomicWait64(MemArg),
AtomicFence,
I32AtomicLoad(MemArg),
I64AtomicLoad(MemArg),
I32AtomicLoad8U(MemArg),
I32AtomicLoad16U(MemArg),
I64AtomicLoad8U(MemArg),
I64AtomicLoad16U(MemArg),
I64AtomicLoad32U(MemArg),
I32AtomicStore(MemArg),
I64AtomicStore(MemArg),
I32AtomicStore8(MemArg),
I32AtomicStore16(MemArg),
I64AtomicStore8(MemArg),
I64AtomicStore16(MemArg),
I64AtomicStore32(MemArg),
I32AtomicRmwAdd(MemArg),
I64AtomicRmwAdd(MemArg),
I32AtomicRmw8AddU(MemArg),
I32AtomicRmw16AddU(MemArg),
I64AtomicRmw8AddU(MemArg),
I64AtomicRmw16AddU(MemArg),
I64AtomicRmw32AddU(MemArg),
I32AtomicRmwSub(MemArg),
I64AtomicRmwSub(MemArg),
I32AtomicRmw8SubU(MemArg),
I32AtomicRmw16SubU(MemArg),
I64AtomicRmw8SubU(MemArg),
I64AtomicRmw16SubU(MemArg),
I64AtomicRmw32SubU(MemArg),
I32AtomicRmwAnd(MemArg),
I64AtomicRmwAnd(MemArg),
I32AtomicRmw8AndU(MemArg),
I32AtomicRmw16AndU(MemArg),
I64AtomicRmw8AndU(MemArg),
I64AtomicRmw16AndU(MemArg),
I64AtomicRmw32AndU(MemArg),
I32AtomicRmwOr(MemArg),
I64AtomicRmwOr(MemArg),
I32AtomicRmw8OrU(MemArg),
I32AtomicRmw16OrU(MemArg),
I64AtomicRmw8OrU(MemArg),
I64AtomicRmw16OrU(MemArg),
I64AtomicRmw32OrU(MemArg),
I32AtomicRmwXor(MemArg),
I64AtomicRmwXor(MemArg),
I32AtomicRmw8XorU(MemArg),
I32AtomicRmw16XorU(MemArg),
I64AtomicRmw8XorU(MemArg),
I64AtomicRmw16XorU(MemArg),
I64AtomicRmw32XorU(MemArg),
I32AtomicRmwXchg(MemArg),
I64AtomicRmwXchg(MemArg),
I32AtomicRmw8XchgU(MemArg),
I32AtomicRmw16XchgU(MemArg),
I64AtomicRmw8XchgU(MemArg),
I64AtomicRmw16XchgU(MemArg),
I64AtomicRmw32XchgU(MemArg),
I32AtomicRmwCmpxchg(MemArg),
I64AtomicRmwCmpxchg(MemArg),
I32AtomicRmw8CmpxchgU(MemArg),
I32AtomicRmw16CmpxchgU(MemArg),
I64AtomicRmw8CmpxchgU(MemArg),
I64AtomicRmw16CmpxchgU(MemArg),
I64AtomicRmw32CmpxchgU(MemArg),
// More atomic instructions (the shared-everything-threads proposal)
GlobalAtomicGet {
ordering: Ordering,
global_index: u32,
},
GlobalAtomicSet {
ordering: Ordering,
global_index: u32,
},
GlobalAtomicRmwAdd {
ordering: Ordering,
global_index: u32,
},
GlobalAtomicRmwSub {
ordering: Ordering,
global_index: u32,
},
GlobalAtomicRmwAnd {
ordering: Ordering,
global_index: u32,
},
GlobalAtomicRmwOr {
ordering: Ordering,
global_index: u32,
},
GlobalAtomicRmwXor {
ordering: Ordering,
global_index: u32,
},
GlobalAtomicRmwXchg {
ordering: Ordering,
global_index: u32,
},
GlobalAtomicRmwCmpxchg {
ordering: Ordering,
global_index: u32,
},
TableAtomicGet {
ordering: Ordering,
table_index: u32,
},
TableAtomicSet {
ordering: Ordering,
table_index: u32,
},
TableAtomicRmwXchg {
ordering: Ordering,
table_index: u32,
},
TableAtomicRmwCmpxchg {
ordering: Ordering,
table_index: u32,
},
StructAtomicGet {
ordering: Ordering,
struct_type_index: u32,
field_index: u32,
},
StructAtomicGetS {
ordering: Ordering,
struct_type_index: u32,
field_index: u32,
},
StructAtomicGetU {
ordering: Ordering,
struct_type_index: u32,
field_index: u32,
},
StructAtomicSet {
ordering: Ordering,
struct_type_index: u32,
field_index: u32,
},
StructAtomicRmwAdd {
ordering: Ordering,
struct_type_index: u32,
field_index: u32,
},
StructAtomicRmwSub {
ordering: Ordering,
struct_type_index: u32,
field_index: u32,
},
StructAtomicRmwAnd {
ordering: Ordering,
struct_type_index: u32,
field_index: u32,
},
StructAtomicRmwOr {
ordering: Ordering,
struct_type_index: u32,
field_index: u32,
},
StructAtomicRmwXor {
ordering: Ordering,
struct_type_index: u32,
field_index: u32,
},
StructAtomicRmwXchg {
ordering: Ordering,
struct_type_index: u32,
field_index: u32,
},
StructAtomicRmwCmpxchg {
ordering: Ordering,
struct_type_index: u32,
field_index: u32,
},
ArrayAtomicGet {
ordering: Ordering,
array_type_index: u32,
},
ArrayAtomicGetS {
ordering: Ordering,
array_type_index: u32,
},
ArrayAtomicGetU {
ordering: Ordering,
array_type_index: u32,
},
ArrayAtomicSet {
ordering: Ordering,
array_type_index: u32,
},
ArrayAtomicRmwAdd {
ordering: Ordering,
array_type_index: u32,
},
ArrayAtomicRmwSub {
ordering: Ordering,
array_type_index: u32,
},
ArrayAtomicRmwAnd {
ordering: Ordering,
array_type_index: u32,
},
ArrayAtomicRmwOr {
ordering: Ordering,
array_type_index: u32,
},
ArrayAtomicRmwXor {
ordering: Ordering,
array_type_index: u32,
},
ArrayAtomicRmwXchg {
ordering: Ordering,
array_type_index: u32,
},
ArrayAtomicRmwCmpxchg {
ordering: Ordering,
array_type_index: u32,
},
RefI31Shared,
// Stack switching
ContNew(u32),
ContBind {
argument_index: u32,
result_index: u32,
},
Suspend(u32),
Resume {
cont_type_index: u32,
resume_table: Cow<'a, [Handle]>,
},
ResumeThrow {
cont_type_index: u32,
tag_index: u32,
resume_table: Cow<'a, [Handle]>,
},
Switch {
cont_type_index: u32,
tag_index: u32,
},
// Wide Arithmetic
I64Add128,
I64Sub128,
I64MulWideS,
I64MulWideU,
}
impl Encode for Instruction<'_> {
fn encode(&self, sink: &mut Vec<u8>) {
match *self {
// Control instructions.
Instruction::Unreachable => sink.push(0x00),
Instruction::Nop => sink.push(0x01),
Instruction::Block(bt) => {
sink.push(0x02);
bt.encode(sink);
}
Instruction::Loop(bt) => {
sink.push(0x03);
bt.encode(sink);
}
Instruction::If(bt) => {
sink.push(0x04);
bt.encode(sink);
}
Instruction::Else => sink.push(0x05),
Instruction::Try(bt) => {
sink.push(0x06);
bt.encode(sink);
}
Instruction::Catch(t) => {
sink.push(0x07);
t.encode(sink);
}
Instruction::Throw(t) => {
sink.push(0x08);
t.encode(sink);
}
Instruction::Rethrow(l) => {
sink.push(0x09);
l.encode(sink);
}
Instruction::ThrowRef => {
sink.push(0x0A);
}
Instruction::End => sink.push(0x0B),
Instruction::Br(l) => {
sink.push(0x0C);
l.encode(sink);
}
Instruction::BrIf(l) => {
sink.push(0x0D);
l.encode(sink);
}
Instruction::BrTable(ref ls, l) => {
sink.push(0x0E);
ls.encode(sink);
l.encode(sink);
}
Instruction::BrOnNull(l) => {
sink.push(0xD5);
l.encode(sink);
}
Instruction::BrOnNonNull(l) => {
sink.push(0xD6);
l.encode(sink);
}
Instruction::Return => sink.push(0x0F),
Instruction::Call(f) => {
sink.push(0x10);
f.encode(sink);
}
Instruction::CallRef(ty) => {
sink.push(0x14);
ty.encode(sink);
}
Instruction::CallIndirect {
type_index,
table_index,
} => {
sink.push(0x11);
type_index.encode(sink);
table_index.encode(sink);
}
Instruction::ReturnCallRef(ty) => {
sink.push(0x15);
ty.encode(sink);
}
Instruction::ReturnCall(f) => {
sink.push(0x12);
f.encode(sink);
}
Instruction::ReturnCallIndirect {
type_index,
table_index,
} => {
sink.push(0x13);
type_index.encode(sink);
table_index.encode(sink);
}
Instruction::Delegate(l) => {
sink.push(0x18);
l.encode(sink);
}
Instruction::CatchAll => {
sink.push(0x19);
}
// Parametric instructions.
Instruction::Drop => sink.push(0x1A),
Instruction::Select => sink.push(0x1B),
Instruction::TypedSelect(ty) => {
sink.push(0x1c);
[ty].encode(sink);
}
Instruction::TryTable(ty, ref catches) => {
sink.push(0x1f);
ty.encode(sink);
catches.encode(sink);
}
// Variable instructions.
Instruction::LocalGet(l) => {
sink.push(0x20);
l.encode(sink);
}
Instruction::LocalSet(l) => {
sink.push(0x21);
l.encode(sink);
}
Instruction::LocalTee(l) => {
sink.push(0x22);
l.encode(sink);
}
Instruction::GlobalGet(g) => {
sink.push(0x23);
g.encode(sink);
}
Instruction::GlobalSet(g) => {
sink.push(0x24);
g.encode(sink);
}
Instruction::TableGet(table) => {
sink.push(0x25);
table.encode(sink);
}
Instruction::TableSet(table) => {
sink.push(0x26);
table.encode(sink);
}
// Memory instructions.
Instruction::I32Load(m) => {
sink.push(0x28);
m.encode(sink);
}
Instruction::I64Load(m) => {
sink.push(0x29);
m.encode(sink);
}
Instruction::F32Load(m) => {
sink.push(0x2A);
m.encode(sink);
}
Instruction::F64Load(m) => {
sink.push(0x2B);
m.encode(sink);
}
Instruction::I32Load8S(m) => {
sink.push(0x2C);
m.encode(sink);
}
Instruction::I32Load8U(m) => {
sink.push(0x2D);
m.encode(sink);
}
Instruction::I32Load16S(m) => {
sink.push(0x2E);
m.encode(sink);
}
Instruction::I32Load16U(m) => {
sink.push(0x2F);
m.encode(sink);
}
Instruction::I64Load8S(m) => {
sink.push(0x30);
m.encode(sink);
}
Instruction::I64Load8U(m) => {
sink.push(0x31);
m.encode(sink);
}
Instruction::I64Load16S(m) => {
sink.push(0x32);
m.encode(sink);
}
Instruction::I64Load16U(m) => {
sink.push(0x33);
m.encode(sink);
}
Instruction::I64Load32S(m) => {
sink.push(0x34);
m.encode(sink);
}
Instruction::I64Load32U(m) => {
sink.push(0x35);
m.encode(sink);
}
Instruction::I32Store(m) => {
sink.push(0x36);
m.encode(sink);
}
Instruction::I64Store(m) => {
sink.push(0x37);
m.encode(sink);
}
Instruction::F32Store(m) => {
sink.push(0x38);
m.encode(sink);
}
Instruction::F64Store(m) => {
sink.push(0x39);
m.encode(sink);
}
Instruction::I32Store8(m) => {
sink.push(0x3A);
m.encode(sink);
}
Instruction::I32Store16(m) => {
sink.push(0x3B);
m.encode(sink);
}
Instruction::I64Store8(m) => {
sink.push(0x3C);
m.encode(sink);
}
Instruction::I64Store16(m) => {
sink.push(0x3D);
m.encode(sink);
}
Instruction::I64Store32(m) => {
sink.push(0x3E);
m.encode(sink);
}
Instruction::MemorySize(i) => {
sink.push(0x3F);
i.encode(sink);
}
Instruction::MemoryGrow(i) => {
sink.push(0x40);
i.encode(sink);
}
Instruction::MemoryInit { mem, data_index } => {
sink.push(0xfc);
sink.push(0x08);
data_index.encode(sink);
mem.encode(sink);
}
Instruction::DataDrop(data) => {
sink.push(0xfc);
sink.push(0x09);
data.encode(sink);
}
Instruction::MemoryCopy { src_mem, dst_mem } => {
sink.push(0xfc);
sink.push(0x0a);
dst_mem.encode(sink);
src_mem.encode(sink);
}
Instruction::MemoryFill(mem) => {
sink.push(0xfc);
sink.push(0x0b);
mem.encode(sink);
}
Instruction::MemoryDiscard(mem) => {
sink.push(0xfc);
sink.push(0x12);
mem.encode(sink);
}
// Numeric instructions.
Instruction::I32Const(x) => {
sink.push(0x41);
x.encode(sink);
}
Instruction::I64Const(x) => {
sink.push(0x42);
x.encode(sink);
}
Instruction::F32Const(x) => {
sink.push(0x43);
let x = x.to_bits();
sink.extend(x.to_le_bytes().iter().copied());
}
Instruction::F64Const(x) => {
sink.push(0x44);
let x = x.to_bits();
sink.extend(x.to_le_bytes().iter().copied());
}
Instruction::I32Eqz => sink.push(0x45),
Instruction::I32Eq => sink.push(0x46),
Instruction::I32Ne => sink.push(0x47),
Instruction::I32LtS => sink.push(0x48),
Instruction::I32LtU => sink.push(0x49),
Instruction::I32GtS => sink.push(0x4A),
Instruction::I32GtU => sink.push(0x4B),
Instruction::I32LeS => sink.push(0x4C),
Instruction::I32LeU => sink.push(0x4D),
Instruction::I32GeS => sink.push(0x4E),
Instruction::I32GeU => sink.push(0x4F),
Instruction::I64Eqz => sink.push(0x50),
Instruction::I64Eq => sink.push(0x51),
Instruction::I64Ne => sink.push(0x52),
Instruction::I64LtS => sink.push(0x53),
Instruction::I64LtU => sink.push(0x54),
Instruction::I64GtS => sink.push(0x55),
Instruction::I64GtU => sink.push(0x56),
Instruction::I64LeS => sink.push(0x57),
Instruction::I64LeU => sink.push(0x58),
Instruction::I64GeS => sink.push(0x59),
Instruction::I64GeU => sink.push(0x5A),
Instruction::F32Eq => sink.push(0x5B),
Instruction::F32Ne => sink.push(0x5C),
Instruction::F32Lt => sink.push(0x5D),
Instruction::F32Gt => sink.push(0x5E),
Instruction::F32Le => sink.push(0x5F),
Instruction::F32Ge => sink.push(0x60),
Instruction::F64Eq => sink.push(0x61),
Instruction::F64Ne => sink.push(0x62),
Instruction::F64Lt => sink.push(0x63),
Instruction::F64Gt => sink.push(0x64),
Instruction::F64Le => sink.push(0x65),
Instruction::F64Ge => sink.push(0x66),
Instruction::I32Clz => sink.push(0x67),
Instruction::I32Ctz => sink.push(0x68),
Instruction::I32Popcnt => sink.push(0x69),
Instruction::I32Add => sink.push(0x6A),
Instruction::I32Sub => sink.push(0x6B),
Instruction::I32Mul => sink.push(0x6C),
Instruction::I32DivS => sink.push(0x6D),
Instruction::I32DivU => sink.push(0x6E),
Instruction::I32RemS => sink.push(0x6F),
Instruction::I32RemU => sink.push(0x70),
Instruction::I32And => sink.push(0x71),
Instruction::I32Or => sink.push(0x72),
Instruction::I32Xor => sink.push(0x73),
Instruction::I32Shl => sink.push(0x74),
Instruction::I32ShrS => sink.push(0x75),
Instruction::I32ShrU => sink.push(0x76),
Instruction::I32Rotl => sink.push(0x77),
Instruction::I32Rotr => sink.push(0x78),
Instruction::I64Clz => sink.push(0x79),
Instruction::I64Ctz => sink.push(0x7A),
Instruction::I64Popcnt => sink.push(0x7B),
Instruction::I64Add => sink.push(0x7C),
Instruction::I64Sub => sink.push(0x7D),
Instruction::I64Mul => sink.push(0x7E),
Instruction::I64DivS => sink.push(0x7F),
Instruction::I64DivU => sink.push(0x80),
Instruction::I64RemS => sink.push(0x81),
Instruction::I64RemU => sink.push(0x82),
Instruction::I64And => sink.push(0x83),
Instruction::I64Or => sink.push(0x84),
Instruction::I64Xor => sink.push(0x85),
Instruction::I64Shl => sink.push(0x86),
Instruction::I64ShrS => sink.push(0x87),
Instruction::I64ShrU => sink.push(0x88),
Instruction::I64Rotl => sink.push(0x89),
Instruction::I64Rotr => sink.push(0x8A),
Instruction::F32Abs => sink.push(0x8B),
Instruction::F32Neg => sink.push(0x8C),
Instruction::F32Ceil => sink.push(0x8D),
Instruction::F32Floor => sink.push(0x8E),
Instruction::F32Trunc => sink.push(0x8F),
Instruction::F32Nearest => sink.push(0x90),
Instruction::F32Sqrt => sink.push(0x91),
Instruction::F32Add => sink.push(0x92),
Instruction::F32Sub => sink.push(0x93),
Instruction::F32Mul => sink.push(0x94),
Instruction::F32Div => sink.push(0x95),
Instruction::F32Min => sink.push(0x96),
Instruction::F32Max => sink.push(0x97),
Instruction::F32Copysign => sink.push(0x98),
Instruction::F64Abs => sink.push(0x99),
Instruction::F64Neg => sink.push(0x9A),
Instruction::F64Ceil => sink.push(0x9B),
Instruction::F64Floor => sink.push(0x9C),
Instruction::F64Trunc => sink.push(0x9D),
Instruction::F64Nearest => sink.push(0x9E),
Instruction::F64Sqrt => sink.push(0x9F),
Instruction::F64Add => sink.push(0xA0),
Instruction::F64Sub => sink.push(0xA1),
Instruction::F64Mul => sink.push(0xA2),
Instruction::F64Div => sink.push(0xA3),
Instruction::F64Min => sink.push(0xA4),
Instruction::F64Max => sink.push(0xA5),
Instruction::F64Copysign => sink.push(0xA6),
Instruction::I32WrapI64 => sink.push(0xA7),
Instruction::I32TruncF32S => sink.push(0xA8),
Instruction::I32TruncF32U => sink.push(0xA9),
Instruction::I32TruncF64S => sink.push(0xAA),
Instruction::I32TruncF64U => sink.push(0xAB),
Instruction::I64ExtendI32S => sink.push(0xAC),
Instruction::I64ExtendI32U => sink.push(0xAD),
Instruction::I64TruncF32S => sink.push(0xAE),
Instruction::I64TruncF32U => sink.push(0xAF),
Instruction::I64TruncF64S => sink.push(0xB0),
Instruction::I64TruncF64U => sink.push(0xB1),
Instruction::F32ConvertI32S => sink.push(0xB2),
Instruction::F32ConvertI32U => sink.push(0xB3),
Instruction::F32ConvertI64S => sink.push(0xB4),
Instruction::F32ConvertI64U => sink.push(0xB5),
Instruction::F32DemoteF64 => sink.push(0xB6),
Instruction::F64ConvertI32S => sink.push(0xB7),
Instruction::F64ConvertI32U => sink.push(0xB8),
Instruction::F64ConvertI64S => sink.push(0xB9),
Instruction::F64ConvertI64U => sink.push(0xBA),
Instruction::F64PromoteF32 => sink.push(0xBB),
Instruction::I32ReinterpretF32 => sink.push(0xBC),
Instruction::I64ReinterpretF64 => sink.push(0xBD),
Instruction::F32ReinterpretI32 => sink.push(0xBE),
Instruction::F64ReinterpretI64 => sink.push(0xBF),
Instruction::I32Extend8S => sink.push(0xC0),
Instruction::I32Extend16S => sink.push(0xC1),
Instruction::I64Extend8S => sink.push(0xC2),
Instruction::I64Extend16S => sink.push(0xC3),
Instruction::I64Extend32S => sink.push(0xC4),
Instruction::I32TruncSatF32S => {
sink.push(0xFC);
sink.push(0x00);
}
Instruction::I32TruncSatF32U => {
sink.push(0xFC);
sink.push(0x01);
}
Instruction::I32TruncSatF64S => {
sink.push(0xFC);
sink.push(0x02);
}
Instruction::I32TruncSatF64U => {
sink.push(0xFC);
sink.push(0x03);
}
Instruction::I64TruncSatF32S => {
sink.push(0xFC);
sink.push(0x04);
}
Instruction::I64TruncSatF32U => {
sink.push(0xFC);
sink.push(0x05);
}
Instruction::I64TruncSatF64S => {
sink.push(0xFC);
sink.push(0x06);
}
Instruction::I64TruncSatF64U => {
sink.push(0xFC);
sink.push(0x07);
}
// Reference types instructions.
Instruction::RefNull(ty) => {
sink.push(0xd0);
ty.encode(sink);
}
Instruction::RefIsNull => sink.push(0xd1),
Instruction::RefFunc(f) => {
sink.push(0xd2);
f.encode(sink);
}
Instruction::RefEq => sink.push(0xd3),
Instruction::RefAsNonNull => sink.push(0xd4),
// GC instructions.
Instruction::StructNew(type_index) => {
sink.push(0xfb);
sink.push(0x00);
type_index.encode(sink);
}
Instruction::StructNewDefault(type_index) => {
sink.push(0xfb);
sink.push(0x01);
type_index.encode(sink);
}
Instruction::StructGet {
struct_type_index,
field_index,
} => {
sink.push(0xfb);
sink.push(0x02);
struct_type_index.encode(sink);
field_index.encode(sink);
}
Instruction::StructGetS {
struct_type_index,
field_index,
} => {
sink.push(0xfb);
sink.push(0x03);
struct_type_index.encode(sink);
field_index.encode(sink);
}
Instruction::StructGetU {
struct_type_index,
field_index,
} => {
sink.push(0xfb);
sink.push(0x04);
struct_type_index.encode(sink);
field_index.encode(sink);
}
Instruction::StructSet {
struct_type_index,
field_index,
} => {
sink.push(0xfb);
sink.push(0x05);
struct_type_index.encode(sink);
field_index.encode(sink);
}
Instruction::ArrayNew(type_index) => {
sink.push(0xfb);
sink.push(0x06);
type_index.encode(sink);
}
Instruction::ArrayNewDefault(type_index) => {
sink.push(0xfb);
sink.push(0x07);
type_index.encode(sink);
}
Instruction::ArrayNewFixed {
array_type_index,
array_size,
} => {
sink.push(0xfb);
sink.push(0x08);
array_type_index.encode(sink);
array_size.encode(sink);
}
Instruction::ArrayNewData {
array_type_index,
array_data_index,
} => {
sink.push(0xfb);
sink.push(0x09);
array_type_index.encode(sink);
array_data_index.encode(sink);
}
Instruction::ArrayNewElem {
array_type_index,
array_elem_index,
} => {
sink.push(0xfb);
sink.push(0x0a);
array_type_index.encode(sink);
array_elem_index.encode(sink);
}
Instruction::ArrayGet(type_index) => {
sink.push(0xfb);
sink.push(0x0b);
type_index.encode(sink);
}
Instruction::ArrayGetS(type_index) => {
sink.push(0xfb);
sink.push(0x0c);
type_index.encode(sink);
}
Instruction::ArrayGetU(type_index) => {
sink.push(0xfb);
sink.push(0x0d);
type_index.encode(sink);
}
Instruction::ArraySet(type_index) => {
sink.push(0xfb);
sink.push(0x0e);
type_index.encode(sink);
}
Instruction::ArrayLen => {
sink.push(0xfb);
sink.push(0x0f);
}
Instruction::ArrayFill(type_index) => {
sink.push(0xfb);
sink.push(0x10);
type_index.encode(sink);
}
Instruction::ArrayCopy {
array_type_index_dst,
array_type_index_src,
} => {
sink.push(0xfb);
sink.push(0x11);
array_type_index_dst.encode(sink);
array_type_index_src.encode(sink);
}
Instruction::ArrayInitData {
array_type_index,
array_data_index,
} => {
sink.push(0xfb);
sink.push(0x12);
array_type_index.encode(sink);
array_data_index.encode(sink);
}
Instruction::ArrayInitElem {
array_type_index,
array_elem_index,
} => {
sink.push(0xfb);
sink.push(0x13);
array_type_index.encode(sink);
array_elem_index.encode(sink);
}
Instruction::RefTestNonNull(heap_type) => {
sink.push(0xfb);
sink.push(0x14);
heap_type.encode(sink);
}
Instruction::RefTestNullable(heap_type) => {
sink.push(0xfb);
sink.push(0x15);
heap_type.encode(sink);
}
Instruction::RefCastNonNull(heap_type) => {
sink.push(0xfb);
sink.push(0x16);
heap_type.encode(sink);
}
Instruction::RefCastNullable(heap_type) => {
sink.push(0xfb);
sink.push(0x17);
heap_type.encode(sink);
}
Instruction::BrOnCast {
relative_depth,
from_ref_type,
to_ref_type,
} => {
sink.push(0xfb);
sink.push(0x18);
let cast_flags =
(from_ref_type.nullable as u8) | ((to_ref_type.nullable as u8) << 1);
sink.push(cast_flags);
relative_depth.encode(sink);
from_ref_type.heap_type.encode(sink);
to_ref_type.heap_type.encode(sink);
}
Instruction::BrOnCastFail {
relative_depth,
from_ref_type,
to_ref_type,
} => {
sink.push(0xfb);
sink.push(0x19);
let cast_flags =
(from_ref_type.nullable as u8) | ((to_ref_type.nullable as u8) << 1);
sink.push(cast_flags);
relative_depth.encode(sink);
from_ref_type.heap_type.encode(sink);
to_ref_type.heap_type.encode(sink);
}
Instruction::AnyConvertExtern => {
sink.push(0xfb);
sink.push(0x1a);
}
Instruction::ExternConvertAny => {
sink.push(0xfb);
sink.push(0x1b);
}
Instruction::RefI31 => {
sink.push(0xfb);
sink.push(0x1c);
}
Instruction::I31GetS => {
sink.push(0xfb);
sink.push(0x1d);
}
Instruction::I31GetU => {
sink.push(0xfb);
sink.push(0x1e);
}
// Bulk memory instructions.
Instruction::TableInit { elem_index, table } => {
sink.push(0xfc);
sink.push(0x0c);
elem_index.encode(sink);
table.encode(sink);
}
Instruction::ElemDrop(segment) => {
sink.push(0xfc);
sink.push(0x0d);
segment.encode(sink);
}
Instruction::TableCopy {
src_table,
dst_table,
} => {
sink.push(0xfc);
sink.push(0x0e);
dst_table.encode(sink);
src_table.encode(sink);
}
Instruction::TableGrow(table) => {
sink.push(0xfc);
sink.push(0x0f);
table.encode(sink);
}
Instruction::TableSize(table) => {
sink.push(0xfc);
sink.push(0x10);
table.encode(sink);
}
Instruction::TableFill(table) => {
sink.push(0xfc);
sink.push(0x11);
table.encode(sink);
}
// SIMD instructions.
Instruction::V128Load(memarg) => {
sink.push(0xFD);
0x00u32.encode(sink);
memarg.encode(sink);
}
Instruction::V128Load8x8S(memarg) => {
sink.push(0xFD);
0x01u32.encode(sink);
memarg.encode(sink);
}
Instruction::V128Load8x8U(memarg) => {
sink.push(0xFD);
0x02u32.encode(sink);
memarg.encode(sink);
}
Instruction::V128Load16x4S(memarg) => {
sink.push(0xFD);
0x03u32.encode(sink);
memarg.encode(sink);
}
Instruction::V128Load16x4U(memarg) => {
sink.push(0xFD);
0x04u32.encode(sink);
memarg.encode(sink);
}
Instruction::V128Load32x2S(memarg) => {
sink.push(0xFD);
0x05u32.encode(sink);
memarg.encode(sink);
}
Instruction::V128Load32x2U(memarg) => {
sink.push(0xFD);
0x06u32.encode(sink);
memarg.encode(sink);
}
Instruction::V128Load8Splat(memarg) => {
sink.push(0xFD);
0x07u32.encode(sink);
memarg.encode(sink);
}
Instruction::V128Load16Splat(memarg) => {
sink.push(0xFD);
0x08u32.encode(sink);
memarg.encode(sink);
}
Instruction::V128Load32Splat(memarg) => {
sink.push(0xFD);
0x09u32.encode(sink);
memarg.encode(sink);
}
Instruction::V128Load64Splat(memarg) => {
sink.push(0xFD);
0x0Au32.encode(sink);
memarg.encode(sink);
}
Instruction::V128Store(memarg) => {
sink.push(0xFD);
0x0Bu32.encode(sink);
memarg.encode(sink);
}
Instruction::V128Const(x) => {
sink.push(0xFD);
0x0Cu32.encode(sink);
sink.extend(x.to_le_bytes().iter().copied());
}
Instruction::I8x16Shuffle(lanes) => {
sink.push(0xFD);
0x0Du32.encode(sink);
assert!(lanes.iter().all(|l: &u8| *l < 32));
sink.extend(lanes.iter().copied());
}
Instruction::I8x16Swizzle => {
sink.push(0xFD);
0x0Eu32.encode(sink);
}
Instruction::I8x16Splat => {
sink.push(0xFD);
0x0Fu32.encode(sink);
}
Instruction::I16x8Splat => {
sink.push(0xFD);
0x10u32.encode(sink);
}
Instruction::I32x4Splat => {
sink.push(0xFD);
0x11u32.encode(sink);
}
Instruction::I64x2Splat => {
sink.push(0xFD);
0x12u32.encode(sink);
}
Instruction::F32x4Splat => {
sink.push(0xFD);
0x13u32.encode(sink);
}
Instruction::F64x2Splat => {
sink.push(0xFD);
0x14u32.encode(sink);
}
Instruction::I8x16ExtractLaneS(lane) => {
sink.push(0xFD);
0x15u32.encode(sink);
assert!(lane < 16);
sink.push(lane);
}
Instruction::I8x16ExtractLaneU(lane) => {
sink.push(0xFD);
0x16u32.encode(sink);
assert!(lane < 16);
sink.push(lane);
}
Instruction::I8x16ReplaceLane(lane) => {
sink.push(0xFD);
0x17u32.encode(sink);
assert!(lane < 16);
sink.push(lane);
}
Instruction::I16x8ExtractLaneS(lane) => {
sink.push(0xFD);
0x18u32.encode(sink);
assert!(lane < 8);
sink.push(lane);
}
Instruction::I16x8ExtractLaneU(lane) => {
sink.push(0xFD);
0x19u32.encode(sink);
assert!(lane < 8);
sink.push(lane);
}
Instruction::I16x8ReplaceLane(lane) => {
sink.push(0xFD);
0x1Au32.encode(sink);
assert!(lane < 8);
sink.push(lane);
}
Instruction::I32x4ExtractLane(lane) => {
sink.push(0xFD);
0x1Bu32.encode(sink);
assert!(lane < 4);
sink.push(lane);
}
Instruction::I32x4ReplaceLane(lane) => {
sink.push(0xFD);
0x1Cu32.encode(sink);
assert!(lane < 4);
sink.push(lane);
}
Instruction::I64x2ExtractLane(lane) => {
sink.push(0xFD);
0x1Du32.encode(sink);
assert!(lane < 2);
sink.push(lane);
}
Instruction::I64x2ReplaceLane(lane) => {
sink.push(0xFD);
0x1Eu32.encode(sink);
assert!(lane < 2);
sink.push(lane);
}
Instruction::F32x4ExtractLane(lane) => {
sink.push(0xFD);
0x1Fu32.encode(sink);
assert!(lane < 4);
sink.push(lane);
}
Instruction::F32x4ReplaceLane(lane) => {
sink.push(0xFD);
0x20u32.encode(sink);
assert!(lane < 4);
sink.push(lane);
}
Instruction::F64x2ExtractLane(lane) => {
sink.push(0xFD);
0x21u32.encode(sink);
assert!(lane < 2);
sink.push(lane);
}
Instruction::F64x2ReplaceLane(lane) => {
sink.push(0xFD);
0x22u32.encode(sink);
assert!(lane < 2);
sink.push(lane);
}
Instruction::I8x16Eq => {
sink.push(0xFD);
0x23u32.encode(sink);
}
Instruction::I8x16Ne => {
sink.push(0xFD);
0x24u32.encode(sink);
}
Instruction::I8x16LtS => {
sink.push(0xFD);
0x25u32.encode(sink);
}
Instruction::I8x16LtU => {
sink.push(0xFD);
0x26u32.encode(sink);
}
Instruction::I8x16GtS => {
sink.push(0xFD);
0x27u32.encode(sink);
}
Instruction::I8x16GtU => {
sink.push(0xFD);
0x28u32.encode(sink);
}
Instruction::I8x16LeS => {
sink.push(0xFD);
0x29u32.encode(sink);
}
Instruction::I8x16LeU => {
sink.push(0xFD);
0x2Au32.encode(sink);
}
Instruction::I8x16GeS => {
sink.push(0xFD);
0x2Bu32.encode(sink);
}
Instruction::I8x16GeU => {
sink.push(0xFD);
0x2Cu32.encode(sink);
}
Instruction::I16x8Eq => {
sink.push(0xFD);
0x2Du32.encode(sink);
}
Instruction::I16x8Ne => {
sink.push(0xFD);
0x2Eu32.encode(sink);
}
Instruction::I16x8LtS => {
sink.push(0xFD);
0x2Fu32.encode(sink);
}
Instruction::I16x8LtU => {
sink.push(0xFD);
0x30u32.encode(sink);
}
Instruction::I16x8GtS => {
sink.push(0xFD);
0x31u32.encode(sink);
}
Instruction::I16x8GtU => {
sink.push(0xFD);
0x32u32.encode(sink);
}
Instruction::I16x8LeS => {
sink.push(0xFD);
0x33u32.encode(sink);
}
Instruction::I16x8LeU => {
sink.push(0xFD);
0x34u32.encode(sink);
}
Instruction::I16x8GeS => {
sink.push(0xFD);
0x35u32.encode(sink);
}
Instruction::I16x8GeU => {
sink.push(0xFD);
0x36u32.encode(sink);
}
Instruction::I32x4Eq => {
sink.push(0xFD);
0x37u32.encode(sink);
}
Instruction::I32x4Ne => {
sink.push(0xFD);
0x38u32.encode(sink);
}
Instruction::I32x4LtS => {
sink.push(0xFD);
0x39u32.encode(sink);
}
Instruction::I32x4LtU => {
sink.push(0xFD);
0x3Au32.encode(sink);
}
Instruction::I32x4GtS => {
sink.push(0xFD);
0x3Bu32.encode(sink);
}
Instruction::I32x4GtU => {
sink.push(0xFD);
0x3Cu32.encode(sink);
}
Instruction::I32x4LeS => {
sink.push(0xFD);
0x3Du32.encode(sink);
}
Instruction::I32x4LeU => {
sink.push(0xFD);
0x3Eu32.encode(sink);
}
Instruction::I32x4GeS => {
sink.push(0xFD);
0x3Fu32.encode(sink);
}
Instruction::I32x4GeU => {
sink.push(0xFD);
0x40u32.encode(sink);
}
Instruction::F32x4Eq => {
sink.push(0xFD);
0x41u32.encode(sink);
}
Instruction::F32x4Ne => {
sink.push(0xFD);
0x42u32.encode(sink);
}
Instruction::F32x4Lt => {
sink.push(0xFD);
0x43u32.encode(sink);
}
Instruction::F32x4Gt => {
sink.push(0xFD);
0x44u32.encode(sink);
}
Instruction::F32x4Le => {
sink.push(0xFD);
0x45u32.encode(sink);
}
Instruction::F32x4Ge => {
sink.push(0xFD);
0x46u32.encode(sink);
}
Instruction::F64x2Eq => {
sink.push(0xFD);
0x47u32.encode(sink);
}
Instruction::F64x2Ne => {
sink.push(0xFD);
0x48u32.encode(sink);
}
Instruction::F64x2Lt => {
sink.push(0xFD);
0x49u32.encode(sink);
}
Instruction::F64x2Gt => {
sink.push(0xFD);
0x4Au32.encode(sink);
}
Instruction::F64x2Le => {
sink.push(0xFD);
0x4Bu32.encode(sink);
}
Instruction::F64x2Ge => {
sink.push(0xFD);
0x4Cu32.encode(sink);
}
Instruction::V128Not => {
sink.push(0xFD);
0x4Du32.encode(sink);
}
Instruction::V128And => {
sink.push(0xFD);
0x4Eu32.encode(sink);
}
Instruction::V128AndNot => {
sink.push(0xFD);
0x4Fu32.encode(sink);
}
Instruction::V128Or => {
sink.push(0xFD);
0x50u32.encode(sink);
}
Instruction::V128Xor => {
sink.push(0xFD);
0x51u32.encode(sink);
}
Instruction::V128Bitselect => {
sink.push(0xFD);
0x52u32.encode(sink);
}
Instruction::V128AnyTrue => {
sink.push(0xFD);
0x53u32.encode(sink);
}
Instruction::I8x16Abs => {
sink.push(0xFD);
0x60u32.encode(sink);
}
Instruction::I8x16Neg => {
sink.push(0xFD);
0x61u32.encode(sink);
}
Instruction::I8x16Popcnt => {
sink.push(0xFD);
0x62u32.encode(sink);
}
Instruction::I8x16AllTrue => {
sink.push(0xFD);
0x63u32.encode(sink);
}
Instruction::I8x16Bitmask => {
sink.push(0xFD);
0x64u32.encode(sink);
}
Instruction::I8x16NarrowI16x8S => {
sink.push(0xFD);
0x65u32.encode(sink);
}
Instruction::I8x16NarrowI16x8U => {
sink.push(0xFD);
0x66u32.encode(sink);
}
Instruction::I8x16Shl => {
sink.push(0xFD);
0x6bu32.encode(sink);
}
Instruction::I8x16ShrS => {
sink.push(0xFD);
0x6cu32.encode(sink);
}
Instruction::I8x16ShrU => {
sink.push(0xFD);
0x6du32.encode(sink);
}
Instruction::I8x16Add => {
sink.push(0xFD);
0x6eu32.encode(sink);
}
Instruction::I8x16AddSatS => {
sink.push(0xFD);
0x6fu32.encode(sink);
}
Instruction::I8x16AddSatU => {
sink.push(0xFD);
0x70u32.encode(sink);
}
Instruction::I8x16Sub => {
sink.push(0xFD);
0x71u32.encode(sink);
}
Instruction::I8x16SubSatS => {
sink.push(0xFD);
0x72u32.encode(sink);
}
Instruction::I8x16SubSatU => {
sink.push(0xFD);
0x73u32.encode(sink);
}
Instruction::I8x16MinS => {
sink.push(0xFD);
0x76u32.encode(sink);
}
Instruction::I8x16MinU => {
sink.push(0xFD);
0x77u32.encode(sink);
}
Instruction::I8x16MaxS => {
sink.push(0xFD);
0x78u32.encode(sink);
}
Instruction::I8x16MaxU => {
sink.push(0xFD);
0x79u32.encode(sink);
}
Instruction::I8x16AvgrU => {
sink.push(0xFD);
0x7Bu32.encode(sink);
}
Instruction::I16x8ExtAddPairwiseI8x16S => {
sink.push(0xFD);
0x7Cu32.encode(sink);
}
Instruction::I16x8ExtAddPairwiseI8x16U => {
sink.push(0xFD);
0x7Du32.encode(sink);
}
Instruction::I32x4ExtAddPairwiseI16x8S => {
sink.push(0xFD);
0x7Eu32.encode(sink);
}
Instruction::I32x4ExtAddPairwiseI16x8U => {
sink.push(0xFD);
0x7Fu32.encode(sink);
}
Instruction::I16x8Abs => {
sink.push(0xFD);
0x80u32.encode(sink);
}
Instruction::I16x8Neg => {
sink.push(0xFD);
0x81u32.encode(sink);
}
Instruction::I16x8Q15MulrSatS => {
sink.push(0xFD);
0x82u32.encode(sink);
}
Instruction::I16x8AllTrue => {
sink.push(0xFD);
0x83u32.encode(sink);
}
Instruction::I16x8Bitmask => {
sink.push(0xFD);
0x84u32.encode(sink);
}
Instruction::I16x8NarrowI32x4S => {
sink.push(0xFD);
0x85u32.encode(sink);
}
Instruction::I16x8NarrowI32x4U => {
sink.push(0xFD);
0x86u32.encode(sink);
}
Instruction::I16x8ExtendLowI8x16S => {
sink.push(0xFD);
0x87u32.encode(sink);
}
Instruction::I16x8ExtendHighI8x16S => {
sink.push(0xFD);
0x88u32.encode(sink);
}
Instruction::I16x8ExtendLowI8x16U => {
sink.push(0xFD);
0x89u32.encode(sink);
}
Instruction::I16x8ExtendHighI8x16U => {
sink.push(0xFD);
0x8Au32.encode(sink);
}
Instruction::I16x8Shl => {
sink.push(0xFD);
0x8Bu32.encode(sink);
}
Instruction::I16x8ShrS => {
sink.push(0xFD);
0x8Cu32.encode(sink);
}
Instruction::I16x8ShrU => {
sink.push(0xFD);
0x8Du32.encode(sink);
}
Instruction::I16x8Add => {
sink.push(0xFD);
0x8Eu32.encode(sink);
}
Instruction::I16x8AddSatS => {
sink.push(0xFD);
0x8Fu32.encode(sink);
}
Instruction::I16x8AddSatU => {
sink.push(0xFD);
0x90u32.encode(sink);
}
Instruction::I16x8Sub => {
sink.push(0xFD);
0x91u32.encode(sink);
}
Instruction::I16x8SubSatS => {
sink.push(0xFD);
0x92u32.encode(sink);
}
Instruction::I16x8SubSatU => {
sink.push(0xFD);
0x93u32.encode(sink);
}
Instruction::I16x8Mul => {
sink.push(0xFD);
0x95u32.encode(sink);
}
Instruction::I16x8MinS => {
sink.push(0xFD);
0x96u32.encode(sink);
}
Instruction::I16x8MinU => {
sink.push(0xFD);
0x97u32.encode(sink);
}
Instruction::I16x8MaxS => {
sink.push(0xFD);
0x98u32.encode(sink);
}
Instruction::I16x8MaxU => {
sink.push(0xFD);
0x99u32.encode(sink);
}
Instruction::I16x8AvgrU => {
sink.push(0xFD);
0x9Bu32.encode(sink);
}
Instruction::I16x8ExtMulLowI8x16S => {
sink.push(0xFD);
0x9Cu32.encode(sink);
}
Instruction::I16x8ExtMulHighI8x16S => {
sink.push(0xFD);
0x9Du32.encode(sink);
}
Instruction::I16x8ExtMulLowI8x16U => {
sink.push(0xFD);
0x9Eu32.encode(sink);
}
Instruction::I16x8ExtMulHighI8x16U => {
sink.push(0xFD);
0x9Fu32.encode(sink);
}
Instruction::I32x4Abs => {
sink.push(0xFD);
0xA0u32.encode(sink);
}
Instruction::I32x4Neg => {
sink.push(0xFD);
0xA1u32.encode(sink);
}
Instruction::I32x4AllTrue => {
sink.push(0xFD);
0xA3u32.encode(sink);
}
Instruction::I32x4Bitmask => {
sink.push(0xFD);
0xA4u32.encode(sink);
}
Instruction::I32x4ExtendLowI16x8S => {
sink.push(0xFD);
0xA7u32.encode(sink);
}
Instruction::I32x4ExtendHighI16x8S => {
sink.push(0xFD);
0xA8u32.encode(sink);
}
Instruction::I32x4ExtendLowI16x8U => {
sink.push(0xFD);
0xA9u32.encode(sink);
}
Instruction::I32x4ExtendHighI16x8U => {
sink.push(0xFD);
0xAAu32.encode(sink);
}
Instruction::I32x4Shl => {
sink.push(0xFD);
0xABu32.encode(sink);
}
Instruction::I32x4ShrS => {
sink.push(0xFD);
0xACu32.encode(sink);
}
Instruction::I32x4ShrU => {
sink.push(0xFD);
0xADu32.encode(sink);
}
Instruction::I32x4Add => {
sink.push(0xFD);
0xAEu32.encode(sink);
}
Instruction::I32x4Sub => {
sink.push(0xFD);
0xB1u32.encode(sink);
}
Instruction::I32x4Mul => {
sink.push(0xFD);
0xB5u32.encode(sink);
}
Instruction::I32x4MinS => {
sink.push(0xFD);
0xB6u32.encode(sink);
}
Instruction::I32x4MinU => {
sink.push(0xFD);
0xB7u32.encode(sink);
}
Instruction::I32x4MaxS => {
sink.push(0xFD);
0xB8u32.encode(sink);
}
Instruction::I32x4MaxU => {
sink.push(0xFD);
0xB9u32.encode(sink);
}
Instruction::I32x4DotI16x8S => {
sink.push(0xFD);
0xBAu32.encode(sink);
}
Instruction::I32x4ExtMulLowI16x8S => {
sink.push(0xFD);
0xBCu32.encode(sink);
}
Instruction::I32x4ExtMulHighI16x8S => {
sink.push(0xFD);
0xBDu32.encode(sink);
}
Instruction::I32x4ExtMulLowI16x8U => {
sink.push(0xFD);
0xBEu32.encode(sink);
}
Instruction::I32x4ExtMulHighI16x8U => {
sink.push(0xFD);
0xBFu32.encode(sink);
}
Instruction::I64x2Abs => {
sink.push(0xFD);
0xC0u32.encode(sink);
}
Instruction::I64x2Neg => {
sink.push(0xFD);
0xC1u32.encode(sink);
}
Instruction::I64x2AllTrue => {
sink.push(0xFD);
0xC3u32.encode(sink);
}
Instruction::I64x2Bitmask => {
sink.push(0xFD);
0xC4u32.encode(sink);
}
Instruction::I64x2ExtendLowI32x4S => {
sink.push(0xFD);
0xC7u32.encode(sink);
}
Instruction::I64x2ExtendHighI32x4S => {
sink.push(0xFD);
0xC8u32.encode(sink);
}
Instruction::I64x2ExtendLowI32x4U => {
sink.push(0xFD);
0xC9u32.encode(sink);
}
Instruction::I64x2ExtendHighI32x4U => {
sink.push(0xFD);
0xCAu32.encode(sink);
}
Instruction::I64x2Shl => {
sink.push(0xFD);
0xCBu32.encode(sink);
}
Instruction::I64x2ShrS => {
sink.push(0xFD);
0xCCu32.encode(sink);
}
Instruction::I64x2ShrU => {
sink.push(0xFD);
0xCDu32.encode(sink);
}
Instruction::I64x2Add => {
sink.push(0xFD);
0xCEu32.encode(sink);
}
Instruction::I64x2Sub => {
sink.push(0xFD);
0xD1u32.encode(sink);
}
Instruction::I64x2Mul => {
sink.push(0xFD);
0xD5u32.encode(sink);
}
Instruction::I64x2ExtMulLowI32x4S => {
sink.push(0xFD);
0xDCu32.encode(sink);
}
Instruction::I64x2ExtMulHighI32x4S => {
sink.push(0xFD);
0xDDu32.encode(sink);
}
Instruction::I64x2ExtMulLowI32x4U => {
sink.push(0xFD);
0xDEu32.encode(sink);
}
Instruction::I64x2ExtMulHighI32x4U => {
sink.push(0xFD);
0xDFu32.encode(sink);
}
Instruction::F32x4Ceil => {
sink.push(0xFD);
0x67u32.encode(sink);
}
Instruction::F32x4Floor => {
sink.push(0xFD);
0x68u32.encode(sink);
}
Instruction::F32x4Trunc => {
sink.push(0xFD);
0x69u32.encode(sink);
}
Instruction::F32x4Nearest => {
sink.push(0xFD);
0x6Au32.encode(sink);
}
Instruction::F32x4Abs => {
sink.push(0xFD);
0xE0u32.encode(sink);
}
Instruction::F32x4Neg => {
sink.push(0xFD);
0xE1u32.encode(sink);
}
Instruction::F32x4Sqrt => {
sink.push(0xFD);
0xE3u32.encode(sink);
}
Instruction::F32x4Add => {
sink.push(0xFD);
0xE4u32.encode(sink);
}
Instruction::F32x4Sub => {
sink.push(0xFD);
0xE5u32.encode(sink);
}
Instruction::F32x4Mul => {
sink.push(0xFD);
0xE6u32.encode(sink);
}
Instruction::F32x4Div => {
sink.push(0xFD);
0xE7u32.encode(sink);
}
Instruction::F32x4Min => {
sink.push(0xFD);
0xE8u32.encode(sink);
}
Instruction::F32x4Max => {
sink.push(0xFD);
0xE9u32.encode(sink);
}
Instruction::F32x4PMin => {
sink.push(0xFD);
0xEAu32.encode(sink);
}
Instruction::F32x4PMax => {
sink.push(0xFD);
0xEBu32.encode(sink);
}
Instruction::F64x2Ceil => {
sink.push(0xFD);
0x74u32.encode(sink);
}
Instruction::F64x2Floor => {
sink.push(0xFD);
0x75u32.encode(sink);
}
Instruction::F64x2Trunc => {
sink.push(0xFD);
0x7Au32.encode(sink);
}
Instruction::F64x2Nearest => {
sink.push(0xFD);
0x94u32.encode(sink);
}
Instruction::F64x2Abs => {
sink.push(0xFD);
0xECu32.encode(sink);
}
Instruction::F64x2Neg => {
sink.push(0xFD);
0xEDu32.encode(sink);
}
Instruction::F64x2Sqrt => {
sink.push(0xFD);
0xEFu32.encode(sink);
}
Instruction::F64x2Add => {
sink.push(0xFD);
0xF0u32.encode(sink);
}
Instruction::F64x2Sub => {
sink.push(0xFD);
0xF1u32.encode(sink);
}
Instruction::F64x2Mul => {
sink.push(0xFD);
0xF2u32.encode(sink);
}
Instruction::F64x2Div => {
sink.push(0xFD);
0xF3u32.encode(sink);
}
Instruction::F64x2Min => {
sink.push(0xFD);
0xF4u32.encode(sink);
}
Instruction::F64x2Max => {
sink.push(0xFD);
0xF5u32.encode(sink);
}
Instruction::F64x2PMin => {
sink.push(0xFD);
0xF6u32.encode(sink);
}
Instruction::F64x2PMax => {
sink.push(0xFD);
0xF7u32.encode(sink);
}
Instruction::I32x4TruncSatF32x4S => {
sink.push(0xFD);
0xF8u32.encode(sink);
}
Instruction::I32x4TruncSatF32x4U => {
sink.push(0xFD);
0xF9u32.encode(sink);
}
Instruction::F32x4ConvertI32x4S => {
sink.push(0xFD);
0xFAu32.encode(sink);
}
Instruction::F32x4ConvertI32x4U => {
sink.push(0xFD);
0xFBu32.encode(sink);
}
Instruction::I32x4TruncSatF64x2SZero => {
sink.push(0xFD);
0xFCu32.encode(sink);
}
Instruction::I32x4TruncSatF64x2UZero => {
sink.push(0xFD);
0xFDu32.encode(sink);
}
Instruction::F64x2ConvertLowI32x4S => {
sink.push(0xFD);
0xFEu32.encode(sink);
}
Instruction::F64x2ConvertLowI32x4U => {
sink.push(0xFD);
0xFFu32.encode(sink);
}
Instruction::F32x4DemoteF64x2Zero => {
sink.push(0xFD);
0x5Eu32.encode(sink);
}
Instruction::F64x2PromoteLowF32x4 => {
sink.push(0xFD);
0x5Fu32.encode(sink);
}
Instruction::V128Load32Zero(memarg) => {
sink.push(0xFD);
0x5Cu32.encode(sink);
memarg.encode(sink);
}
Instruction::V128Load64Zero(memarg) => {
sink.push(0xFD);
0x5Du32.encode(sink);
memarg.encode(sink);
}
Instruction::V128Load8Lane { memarg, lane } => {
sink.push(0xFD);
0x54u32.encode(sink);
memarg.encode(sink);
assert!(lane < 16);
sink.push(lane);
}
Instruction::V128Load16Lane { memarg, lane } => {
sink.push(0xFD);
0x55u32.encode(sink);
memarg.encode(sink);
assert!(lane < 8);
sink.push(lane);
}
Instruction::V128Load32Lane { memarg, lane } => {
sink.push(0xFD);
0x56u32.encode(sink);
memarg.encode(sink);
assert!(lane < 4);
sink.push(lane);
}
Instruction::V128Load64Lane { memarg, lane } => {
sink.push(0xFD);
0x57u32.encode(sink);
memarg.encode(sink);
assert!(lane < 2);
sink.push(lane);
}
Instruction::V128Store8Lane { memarg, lane } => {
sink.push(0xFD);
0x58u32.encode(sink);
memarg.encode(sink);
assert!(lane < 16);
sink.push(lane);
}
Instruction::V128Store16Lane { memarg, lane } => {
sink.push(0xFD);
0x59u32.encode(sink);
memarg.encode(sink);
assert!(lane < 8);
sink.push(lane);
}
Instruction::V128Store32Lane { memarg, lane } => {
sink.push(0xFD);
0x5Au32.encode(sink);
memarg.encode(sink);
assert!(lane < 4);
sink.push(lane);
}
Instruction::V128Store64Lane { memarg, lane } => {
sink.push(0xFD);
0x5Bu32.encode(sink);
memarg.encode(sink);
assert!(lane < 2);
sink.push(lane);
}
Instruction::I64x2Eq => {
sink.push(0xFD);
0xD6u32.encode(sink);
}
Instruction::I64x2Ne => {
sink.push(0xFD);
0xD7u32.encode(sink);
}
Instruction::I64x2LtS => {
sink.push(0xFD);
0xD8u32.encode(sink);
}
Instruction::I64x2GtS => {
sink.push(0xFD);
0xD9u32.encode(sink);
}
Instruction::I64x2LeS => {
sink.push(0xFD);
0xDAu32.encode(sink);
}
Instruction::I64x2GeS => {
sink.push(0xFD);
0xDBu32.encode(sink);
}
Instruction::I8x16RelaxedSwizzle => {
sink.push(0xFD);
0x100u32.encode(sink);
}
Instruction::I32x4RelaxedTruncF32x4S => {
sink.push(0xFD);
0x101u32.encode(sink);
}
Instruction::I32x4RelaxedTruncF32x4U => {
sink.push(0xFD);
0x102u32.encode(sink);
}
Instruction::I32x4RelaxedTruncF64x2SZero => {
sink.push(0xFD);
0x103u32.encode(sink);
}
Instruction::I32x4RelaxedTruncF64x2UZero => {
sink.push(0xFD);
0x104u32.encode(sink);
}
Instruction::F32x4RelaxedMadd => {
sink.push(0xFD);
0x105u32.encode(sink);
}
Instruction::F32x4RelaxedNmadd => {
sink.push(0xFD);
0x106u32.encode(sink);
}
Instruction::F64x2RelaxedMadd => {
sink.push(0xFD);
0x107u32.encode(sink);
}
Instruction::F64x2RelaxedNmadd => {
sink.push(0xFD);
0x108u32.encode(sink);
}
Instruction::I8x16RelaxedLaneselect => {
sink.push(0xFD);
0x109u32.encode(sink);
}
Instruction::I16x8RelaxedLaneselect => {
sink.push(0xFD);
0x10Au32.encode(sink);
}
Instruction::I32x4RelaxedLaneselect => {
sink.push(0xFD);
0x10Bu32.encode(sink);
}
Instruction::I64x2RelaxedLaneselect => {
sink.push(0xFD);
0x10Cu32.encode(sink);
}
Instruction::F32x4RelaxedMin => {
sink.push(0xFD);
0x10Du32.encode(sink);
}
Instruction::F32x4RelaxedMax => {
sink.push(0xFD);
0x10Eu32.encode(sink);
}
Instruction::F64x2RelaxedMin => {
sink.push(0xFD);
0x10Fu32.encode(sink);
}
Instruction::F64x2RelaxedMax => {
sink.push(0xFD);
0x110u32.encode(sink);
}
Instruction::I16x8RelaxedQ15mulrS => {
sink.push(0xFD);
0x111u32.encode(sink);
}
Instruction::I16x8RelaxedDotI8x16I7x16S => {
sink.push(0xFD);
0x112u32.encode(sink);
}
Instruction::I32x4RelaxedDotI8x16I7x16AddS => {
sink.push(0xFD);
0x113u32.encode(sink);
}
// Atomic instructions from the thread proposal
Instruction::MemoryAtomicNotify(memarg) => {
sink.push(0xFE);
sink.push(0x00);
memarg.encode(sink);
}
Instruction::MemoryAtomicWait32(memarg) => {
sink.push(0xFE);
sink.push(0x01);
memarg.encode(sink);
}
Instruction::MemoryAtomicWait64(memarg) => {
sink.push(0xFE);
sink.push(0x02);
memarg.encode(sink);
}
Instruction::AtomicFence => {
sink.push(0xFE);
sink.push(0x03);
sink.push(0x00);
}
Instruction::I32AtomicLoad(memarg) => {
sink.push(0xFE);
sink.push(0x10);
memarg.encode(sink);
}
Instruction::I64AtomicLoad(memarg) => {
sink.push(0xFE);
sink.push(0x11);
memarg.encode(sink);
}
Instruction::I32AtomicLoad8U(memarg) => {
sink.push(0xFE);
sink.push(0x12);
memarg.encode(sink);
}
Instruction::I32AtomicLoad16U(memarg) => {
sink.push(0xFE);
sink.push(0x13);
memarg.encode(sink);
}
Instruction::I64AtomicLoad8U(memarg) => {
sink.push(0xFE);
sink.push(0x14);
memarg.encode(sink);
}
Instruction::I64AtomicLoad16U(memarg) => {
sink.push(0xFE);
sink.push(0x15);
memarg.encode(sink);
}
Instruction::I64AtomicLoad32U(memarg) => {
sink.push(0xFE);
sink.push(0x16);
memarg.encode(sink);
}
Instruction::I32AtomicStore(memarg) => {
sink.push(0xFE);
sink.push(0x17);
memarg.encode(sink);
}
Instruction::I64AtomicStore(memarg) => {
sink.push(0xFE);
sink.push(0x18);
memarg.encode(sink);
}
Instruction::I32AtomicStore8(memarg) => {
sink.push(0xFE);
sink.push(0x19);
memarg.encode(sink);
}
Instruction::I32AtomicStore16(memarg) => {
sink.push(0xFE);
sink.push(0x1A);
memarg.encode(sink);
}
Instruction::I64AtomicStore8(memarg) => {
sink.push(0xFE);
sink.push(0x1B);
memarg.encode(sink);
}
Instruction::I64AtomicStore16(memarg) => {
sink.push(0xFE);
sink.push(0x1C);
memarg.encode(sink);
}
Instruction::I64AtomicStore32(memarg) => {
sink.push(0xFE);
sink.push(0x1D);
memarg.encode(sink);
}
Instruction::I32AtomicRmwAdd(memarg) => {
sink.push(0xFE);
sink.push(0x1E);
memarg.encode(sink);
}
Instruction::I64AtomicRmwAdd(memarg) => {
sink.push(0xFE);
sink.push(0x1F);
memarg.encode(sink);
}
Instruction::I32AtomicRmw8AddU(memarg) => {
sink.push(0xFE);
sink.push(0x20);
memarg.encode(sink);
}
Instruction::I32AtomicRmw16AddU(memarg) => {
sink.push(0xFE);
sink.push(0x21);
memarg.encode(sink);
}
Instruction::I64AtomicRmw8AddU(memarg) => {
sink.push(0xFE);
sink.push(0x22);
memarg.encode(sink);
}
Instruction::I64AtomicRmw16AddU(memarg) => {
sink.push(0xFE);
sink.push(0x23);
memarg.encode(sink);
}
Instruction::I64AtomicRmw32AddU(memarg) => {
sink.push(0xFE);
sink.push(0x24);
memarg.encode(sink);
}
Instruction::I32AtomicRmwSub(memarg) => {
sink.push(0xFE);
sink.push(0x25);
memarg.encode(sink);
}
Instruction::I64AtomicRmwSub(memarg) => {
sink.push(0xFE);
sink.push(0x26);
memarg.encode(sink);
}
Instruction::I32AtomicRmw8SubU(memarg) => {
sink.push(0xFE);
sink.push(0x27);
memarg.encode(sink);
}
Instruction::I32AtomicRmw16SubU(memarg) => {
sink.push(0xFE);
sink.push(0x28);
memarg.encode(sink);
}
Instruction::I64AtomicRmw8SubU(memarg) => {
sink.push(0xFE);
sink.push(0x29);
memarg.encode(sink);
}
Instruction::I64AtomicRmw16SubU(memarg) => {
sink.push(0xFE);
sink.push(0x2A);
memarg.encode(sink);
}
Instruction::I64AtomicRmw32SubU(memarg) => {
sink.push(0xFE);
sink.push(0x2B);
memarg.encode(sink);
}
Instruction::I32AtomicRmwAnd(memarg) => {
sink.push(0xFE);
sink.push(0x2C);
memarg.encode(sink);
}
Instruction::I64AtomicRmwAnd(memarg) => {
sink.push(0xFE);
sink.push(0x2D);
memarg.encode(sink);
}
Instruction::I32AtomicRmw8AndU(memarg) => {
sink.push(0xFE);
sink.push(0x2E);
memarg.encode(sink);
}
Instruction::I32AtomicRmw16AndU(memarg) => {
sink.push(0xFE);
sink.push(0x2F);
memarg.encode(sink);
}
Instruction::I64AtomicRmw8AndU(memarg) => {
sink.push(0xFE);
sink.push(0x30);
memarg.encode(sink);
}
Instruction::I64AtomicRmw16AndU(memarg) => {
sink.push(0xFE);
sink.push(0x31);
memarg.encode(sink);
}
Instruction::I64AtomicRmw32AndU(memarg) => {
sink.push(0xFE);
sink.push(0x32);
memarg.encode(sink);
}
Instruction::I32AtomicRmwOr(memarg) => {
sink.push(0xFE);
sink.push(0x33);
memarg.encode(sink);
}
Instruction::I64AtomicRmwOr(memarg) => {
sink.push(0xFE);
sink.push(0x34);
memarg.encode(sink);
}
Instruction::I32AtomicRmw8OrU(memarg) => {
sink.push(0xFE);
sink.push(0x35);
memarg.encode(sink);
}
Instruction::I32AtomicRmw16OrU(memarg) => {
sink.push(0xFE);
sink.push(0x36);
memarg.encode(sink);
}
Instruction::I64AtomicRmw8OrU(memarg) => {
sink.push(0xFE);
sink.push(0x37);
memarg.encode(sink);
}
Instruction::I64AtomicRmw16OrU(memarg) => {
sink.push(0xFE);
sink.push(0x38);
memarg.encode(sink);
}
Instruction::I64AtomicRmw32OrU(memarg) => {
sink.push(0xFE);
sink.push(0x39);
memarg.encode(sink);
}
Instruction::I32AtomicRmwXor(memarg) => {
sink.push(0xFE);
sink.push(0x3A);
memarg.encode(sink);
}
Instruction::I64AtomicRmwXor(memarg) => {
sink.push(0xFE);
sink.push(0x3B);
memarg.encode(sink);
}
Instruction::I32AtomicRmw8XorU(memarg) => {
sink.push(0xFE);
sink.push(0x3C);
memarg.encode(sink);
}
Instruction::I32AtomicRmw16XorU(memarg) => {
sink.push(0xFE);
sink.push(0x3D);
memarg.encode(sink);
}
Instruction::I64AtomicRmw8XorU(memarg) => {
sink.push(0xFE);
sink.push(0x3E);
memarg.encode(sink);
}
Instruction::I64AtomicRmw16XorU(memarg) => {
sink.push(0xFE);
sink.push(0x3F);
memarg.encode(sink);
}
Instruction::I64AtomicRmw32XorU(memarg) => {
sink.push(0xFE);
sink.push(0x40);
memarg.encode(sink);
}
Instruction::I32AtomicRmwXchg(memarg) => {
sink.push(0xFE);
sink.push(0x41);
memarg.encode(sink);
}
Instruction::I64AtomicRmwXchg(memarg) => {
sink.push(0xFE);
sink.push(0x42);
memarg.encode(sink);
}
Instruction::I32AtomicRmw8XchgU(memarg) => {
sink.push(0xFE);
sink.push(0x43);
memarg.encode(sink);
}
Instruction::I32AtomicRmw16XchgU(memarg) => {
sink.push(0xFE);
sink.push(0x44);
memarg.encode(sink);
}
Instruction::I64AtomicRmw8XchgU(memarg) => {
sink.push(0xFE);
sink.push(0x45);
memarg.encode(sink);
}
Instruction::I64AtomicRmw16XchgU(memarg) => {
sink.push(0xFE);
sink.push(0x46);
memarg.encode(sink);
}
Instruction::I64AtomicRmw32XchgU(memarg) => {
sink.push(0xFE);
sink.push(0x47);
memarg.encode(sink);
}
Instruction::I32AtomicRmwCmpxchg(memarg) => {
sink.push(0xFE);
sink.push(0x48);
memarg.encode(sink);
}
Instruction::I64AtomicRmwCmpxchg(memarg) => {
sink.push(0xFE);
sink.push(0x49);
memarg.encode(sink);
}
Instruction::I32AtomicRmw8CmpxchgU(memarg) => {
sink.push(0xFE);
sink.push(0x4A);
memarg.encode(sink);
}
Instruction::I32AtomicRmw16CmpxchgU(memarg) => {
sink.push(0xFE);
sink.push(0x4B);
memarg.encode(sink);
}
Instruction::I64AtomicRmw8CmpxchgU(memarg) => {
sink.push(0xFE);
sink.push(0x4C);
memarg.encode(sink);
}
Instruction::I64AtomicRmw16CmpxchgU(memarg) => {
sink.push(0xFE);
sink.push(0x4D);
memarg.encode(sink);
}
Instruction::I64AtomicRmw32CmpxchgU(memarg) => {
sink.push(0xFE);
sink.push(0x4E);
memarg.encode(sink);
}
// Atomic instructions from the shared-everything-threads proposal
Instruction::GlobalAtomicGet {
ordering,
global_index,
} => {
sink.push(0xFE);
sink.push(0x4F);
ordering.encode(sink);
global_index.encode(sink);
}
Instruction::GlobalAtomicSet {
ordering,
global_index,
} => {
sink.push(0xFE);
sink.push(0x50);
ordering.encode(sink);
global_index.encode(sink);
}
Instruction::GlobalAtomicRmwAdd {
ordering,
global_index,
} => {
sink.push(0xFE);
sink.push(0x51);
ordering.encode(sink);
global_index.encode(sink);
}
Instruction::GlobalAtomicRmwSub {
ordering,
global_index,
} => {
sink.push(0xFE);
sink.push(0x52);
ordering.encode(sink);
global_index.encode(sink);
}
Instruction::GlobalAtomicRmwAnd {
ordering,
global_index,
} => {
sink.push(0xFE);
sink.push(0x53);
ordering.encode(sink);
global_index.encode(sink);
}
Instruction::GlobalAtomicRmwOr {
ordering,
global_index,
} => {
sink.push(0xFE);
sink.push(0x54);
ordering.encode(sink);
global_index.encode(sink);
}
Instruction::GlobalAtomicRmwXor {
ordering,
global_index,
} => {
sink.push(0xFE);
sink.push(0x55);
ordering.encode(sink);
global_index.encode(sink);
}
Instruction::GlobalAtomicRmwXchg {
ordering,
global_index,
} => {
sink.push(0xFE);
sink.push(0x56);
ordering.encode(sink);
global_index.encode(sink);
}
Instruction::GlobalAtomicRmwCmpxchg {
ordering,
global_index,
} => {
sink.push(0xFE);
sink.push(0x57);
ordering.encode(sink);
global_index.encode(sink);
}
Instruction::TableAtomicGet {
ordering,
table_index,
} => {
sink.push(0xFE);
sink.push(0x58);
ordering.encode(sink);
table_index.encode(sink);
}
Instruction::TableAtomicSet {
ordering,
table_index,
} => {
sink.push(0xFE);
sink.push(0x59);
ordering.encode(sink);
table_index.encode(sink);
}
Instruction::TableAtomicRmwXchg {
ordering,
table_index,
} => {
sink.push(0xFE);
sink.push(0x5A);
ordering.encode(sink);
table_index.encode(sink);
}
Instruction::TableAtomicRmwCmpxchg {
ordering,
table_index,
} => {
sink.push(0xFE);
sink.push(0x5B);
ordering.encode(sink);
table_index.encode(sink);
}
Instruction::StructAtomicGet {
ordering,
struct_type_index,
field_index,
} => {
sink.push(0xFE);
sink.push(0x5C);
ordering.encode(sink);
struct_type_index.encode(sink);
field_index.encode(sink);
}
Instruction::StructAtomicGetS {
ordering,
struct_type_index,
field_index,
} => {
sink.push(0xFE);
sink.push(0x5D);
ordering.encode(sink);
struct_type_index.encode(sink);
field_index.encode(sink);
}
Instruction::StructAtomicGetU {
ordering,
struct_type_index,
field_index,
} => {
sink.push(0xFE);
sink.push(0x5E);
ordering.encode(sink);
struct_type_index.encode(sink);
field_index.encode(sink);
}
Instruction::StructAtomicSet {
ordering,
struct_type_index,
field_index,
} => {
sink.push(0xFE);
sink.push(0x5F);
ordering.encode(sink);
struct_type_index.encode(sink);
field_index.encode(sink);
}
Instruction::StructAtomicRmwAdd {
ordering,
struct_type_index,
field_index,
} => {
sink.push(0xFE);
sink.push(0x60);
ordering.encode(sink);
struct_type_index.encode(sink);
field_index.encode(sink);
}
Instruction::StructAtomicRmwSub {
ordering,
struct_type_index,
field_index,
} => {
sink.push(0xFE);
sink.push(0x61);
ordering.encode(sink);
struct_type_index.encode(sink);
field_index.encode(sink);
}
Instruction::StructAtomicRmwAnd {
ordering,
struct_type_index,
field_index,
} => {
sink.push(0xFE);
sink.push(0x62);
ordering.encode(sink);
struct_type_index.encode(sink);
field_index.encode(sink);
}
Instruction::StructAtomicRmwOr {
ordering,
struct_type_index,
field_index,
} => {
sink.push(0xFE);
sink.push(0x63);
ordering.encode(sink);
struct_type_index.encode(sink);
field_index.encode(sink);
}
Instruction::StructAtomicRmwXor {
ordering,
struct_type_index,
field_index,
} => {
sink.push(0xFE);
sink.push(0x64);
ordering.encode(sink);
struct_type_index.encode(sink);
field_index.encode(sink);
}
Instruction::StructAtomicRmwXchg {
ordering,
struct_type_index,
field_index,
} => {
sink.push(0xFE);
sink.push(0x65);
ordering.encode(sink);
struct_type_index.encode(sink);
field_index.encode(sink);
}
Instruction::StructAtomicRmwCmpxchg {
ordering,
struct_type_index,
field_index,
} => {
sink.push(0xFE);
sink.push(0x66);
ordering.encode(sink);
struct_type_index.encode(sink);
field_index.encode(sink);
}
Instruction::ArrayAtomicGet {
ordering,
array_type_index,
} => {
sink.push(0xFE);
sink.push(0x67);
ordering.encode(sink);
array_type_index.encode(sink);
}
Instruction::ArrayAtomicGetS {
ordering,
array_type_index,
} => {
sink.push(0xFE);
sink.push(0x68);
ordering.encode(sink);
array_type_index.encode(sink);
}
Instruction::ArrayAtomicGetU {
ordering,
array_type_index,
} => {
sink.push(0xFE);
sink.push(0x69);
ordering.encode(sink);
array_type_index.encode(sink);
}
Instruction::ArrayAtomicSet {
ordering,
array_type_index,
} => {
sink.push(0xFE);
sink.push(0x6A);
ordering.encode(sink);
array_type_index.encode(sink);
}
Instruction::ArrayAtomicRmwAdd {
ordering,
array_type_index,
} => {
sink.push(0xFE);
sink.push(0x6B);
ordering.encode(sink);
array_type_index.encode(sink);
}
Instruction::ArrayAtomicRmwSub {
ordering,
array_type_index,
} => {
sink.push(0xFE);
sink.push(0x6C);
ordering.encode(sink);
array_type_index.encode(sink);
}
Instruction::ArrayAtomicRmwAnd {
ordering,
array_type_index,
} => {
sink.push(0xFE);
sink.push(0x6D);
ordering.encode(sink);
array_type_index.encode(sink);
}
Instruction::ArrayAtomicRmwOr {
ordering,
array_type_index,
} => {
sink.push(0xFE);
sink.push(0x6E);
ordering.encode(sink);
array_type_index.encode(sink);
}
Instruction::ArrayAtomicRmwXor {
ordering,
array_type_index,
} => {
sink.push(0xFE);
sink.push(0x6F);
ordering.encode(sink);
array_type_index.encode(sink);
}
Instruction::ArrayAtomicRmwXchg {
ordering,
array_type_index,
} => {
sink.push(0xFE);
sink.push(0x70);
ordering.encode(sink);
array_type_index.encode(sink);
}
Instruction::ArrayAtomicRmwCmpxchg {
ordering,
array_type_index,
} => {
sink.push(0xFE);
sink.push(0x71);
ordering.encode(sink);
array_type_index.encode(sink);
}
Instruction::RefI31Shared => {
sink.push(0xFE);
sink.push(0x72);
}
Instruction::ContNew(type_index) => {
sink.push(0xE0);
type_index.encode(sink);
}
Instruction::ContBind {
argument_index,
result_index,
} => {
sink.push(0xE1);
argument_index.encode(sink);
result_index.encode(sink);
}
Instruction::Suspend(tag_index) => {
sink.push(0xE2);
tag_index.encode(sink);
}
Instruction::Resume {
cont_type_index,
ref resume_table,
} => {
sink.push(0xE3);
cont_type_index.encode(sink);
resume_table.encode(sink);
}
Instruction::ResumeThrow {
cont_type_index,
tag_index,
ref resume_table,
} => {
sink.push(0xE4);
cont_type_index.encode(sink);
tag_index.encode(sink);
resume_table.encode(sink);
}
Instruction::Switch {
cont_type_index,
tag_index,
} => {
sink.push(0xE5);
cont_type_index.encode(sink);
tag_index.encode(sink);
}
Instruction::I64Add128 => {
sink.push(0xFC);
19u32.encode(sink);
}
Instruction::I64Sub128 => {
sink.push(0xFC);
20u32.encode(sink);
}
Instruction::I64MulWideS => {
sink.push(0xFC);
21u32.encode(sink);
}
Instruction::I64MulWideU => {
sink.push(0xFC);
22u32.encode(sink);
}
}
}
}
#[derive(Clone, Debug)]
#[allow(missing_docs)]
pub enum Catch {
One { tag: u32, label: u32 },
OneRef { tag: u32, label: u32 },
All { label: u32 },
AllRef { label: u32 },
}
impl Encode for Catch {
fn encode(&self, sink: &mut Vec<u8>) {
match self {
Catch::One { tag, label } => {
sink.push(0x00);
tag.encode(sink);
label.encode(sink);
}
Catch::OneRef { tag, label } => {
sink.push(0x01);
tag.encode(sink);
label.encode(sink);
}
Catch::All { label } => {
sink.push(0x02);
label.encode(sink);
}
Catch::AllRef { label } => {
sink.push(0x03);
label.encode(sink);
}
}
}
}
#[derive(Clone, Debug)]
#[allow(missing_docs)]
pub enum Handle {
OnLabel { tag: u32, label: u32 },
OnSwitch { tag: u32 },
}
impl Encode for Handle {
fn encode(&self, sink: &mut Vec<u8>) {
match self {
Handle::OnLabel { tag, label } => {
sink.push(0x00);
tag.encode(sink);
label.encode(sink);
}
Handle::OnSwitch { tag } => {
sink.push(0x01);
tag.encode(sink);
}
}
}
}
/// A constant expression.
///
/// Usable in contexts such as offsets or initializers.
#[derive(Clone, Debug)]
pub struct ConstExpr {
bytes: Vec<u8>,
}
impl ConstExpr {
/// Create a new empty constant expression builder.
pub fn empty() -> Self {
Self { bytes: Vec::new() }
}
/// Create a constant expression with the specified raw encoding of instructions.
pub fn raw(bytes: impl IntoIterator<Item = u8>) -> Self {
Self {
bytes: bytes.into_iter().collect(),
}
}
fn new_insn(insn: Instruction) -> Self {
let mut bytes = vec![];
insn.encode(&mut bytes);
Self { bytes }
}
fn with_insn(mut self, insn: Instruction) -> Self {
insn.encode(&mut self.bytes);
self
}
/// Create a constant expression containing a single `global.get` instruction.
pub fn global_get(index: u32) -> Self {
Self::new_insn(Instruction::GlobalGet(index))
}
/// Create a constant expression containing a single `ref.null` instruction.
pub fn ref_null(ty: HeapType) -> Self {
Self::new_insn(Instruction::RefNull(ty))
}
/// Create a constant expression containing a single `ref.func` instruction.
pub fn ref_func(func: u32) -> Self {
Self::new_insn(Instruction::RefFunc(func))
}
/// Create a constant expression containing a single `i32.const` instruction.
pub fn i32_const(value: i32) -> Self {
Self::new_insn(Instruction::I32Const(value))
}
/// Create a constant expression containing a single `i64.const` instruction.
pub fn i64_const(value: i64) -> Self {
Self::new_insn(Instruction::I64Const(value))
}
/// Create a constant expression containing a single `f32.const` instruction.
pub fn f32_const(value: f32) -> Self {
Self::new_insn(Instruction::F32Const(value))
}
/// Create a constant expression containing a single `f64.const` instruction.
pub fn f64_const(value: f64) -> Self {
Self::new_insn(Instruction::F64Const(value))
}
/// Create a constant expression containing a single `v128.const` instruction.
pub fn v128_const(value: i128) -> Self {
Self::new_insn(Instruction::V128Const(value))
}
/// Add a `global.get` instruction to this constant expression.
pub fn with_global_get(self, index: u32) -> Self {
self.with_insn(Instruction::GlobalGet(index))
}
/// Add a `ref.null` instruction to this constant expression.
pub fn with_ref_null(self, ty: HeapType) -> Self {
self.with_insn(Instruction::RefNull(ty))
}
/// Add a `ref.func` instruction to this constant expression.
pub fn with_ref_func(self, func: u32) -> Self {
self.with_insn(Instruction::RefFunc(func))
}
/// Add an `i32.const` instruction to this constant expression.
pub fn with_i32_const(self, value: i32) -> Self {
self.with_insn(Instruction::I32Const(value))
}
/// Add an `i64.const` instruction to this constant expression.
pub fn with_i64_const(self, value: i64) -> Self {
self.with_insn(Instruction::I64Const(value))
}
/// Add a `f32.const` instruction to this constant expression.
pub fn with_f32_const(self, value: f32) -> Self {
self.with_insn(Instruction::F32Const(value))
}
/// Add a `f64.const` instruction to this constant expression.
pub fn with_f64_const(self, value: f64) -> Self {
self.with_insn(Instruction::F64Const(value))
}
/// Add a `v128.const` instruction to this constant expression.
pub fn with_v128_const(self, value: i128) -> Self {
self.with_insn(Instruction::V128Const(value))
}
/// Add an `i32.add` instruction to this constant expression.
pub fn with_i32_add(self) -> Self {
self.with_insn(Instruction::I32Add)
}
/// Add an `i32.sub` instruction to this constant expression.
pub fn with_i32_sub(self) -> Self {
self.with_insn(Instruction::I32Sub)
}
/// Add an `i32.mul` instruction to this constant expression.
pub fn with_i32_mul(self) -> Self {
self.with_insn(Instruction::I32Mul)
}
/// Add an `i64.add` instruction to this constant expression.
pub fn with_i64_add(self) -> Self {
self.with_insn(Instruction::I64Add)
}
/// Add an `i64.sub` instruction to this constant expression.
pub fn with_i64_sub(self) -> Self {
self.with_insn(Instruction::I64Sub)
}
/// Add an `i64.mul` instruction to this constant expression.
pub fn with_i64_mul(self) -> Self {
self.with_insn(Instruction::I64Mul)
}
/// Returns the function, if any, referenced by this global.
pub fn get_ref_func(&self) -> Option<u32> {
let prefix = *self.bytes.get(0)?;
// 0xd2 == `ref.func` opcode, and if that's found then load the leb
// corresponding to the function index.
if prefix != 0xd2 {
return None;
}
leb128::read::unsigned(&mut &self.bytes[1..])
.ok()?
.try_into()
.ok()
}
}
impl Encode for ConstExpr {
fn encode(&self, sink: &mut Vec<u8>) {
sink.extend(&self.bytes);
Instruction::End.encode(sink);
}
}
#[cfg(test)]
mod tests {
#[test]
fn function_new_with_locals_test() {
use super::*;
// Test the algorithm for conversion is correct
let f1 = Function::new_with_locals_types([
ValType::I32,
ValType::I32,
ValType::I64,
ValType::F32,
ValType::F32,
ValType::F32,
ValType::I32,
ValType::I64,
ValType::I64,
]);
let f2 = Function::new([
(2, ValType::I32),
(1, ValType::I64),
(3, ValType::F32),
(1, ValType::I32),
(2, ValType::I64),
]);
assert_eq!(f1.bytes, f2.bytes)
}
#[test]
fn func_raw_bytes() {
use super::*;
let mut f = Function::new([(1, ValType::I32), (1, ValType::F32)]);
f.instruction(&Instruction::End);
let mut code_from_func = CodeSection::new();
code_from_func.function(&f);
let bytes = f.into_raw_body();
let mut code_from_raw = CodeSection::new();
code_from_raw.raw(&bytes[..]);
let mut c1 = vec![];
code_from_func.encode(&mut c1);
let mut c2 = vec![];
code_from_raw.encode(&mut c2);
assert_eq!(c1, c2);
}
}