wasm_encoder/core/
code.rs

1use crate::{
2    encode_section, Encode, HeapType, InstructionSink, RefType, Section, SectionId, ValType,
3};
4use alloc::borrow::Cow;
5use alloc::vec;
6use alloc::vec::Vec;
7
8/// An encoder for the code section.
9///
10/// Code sections are only supported for modules.
11///
12/// # Example
13///
14/// ```
15/// use wasm_encoder::{
16///     CodeSection, Function, FunctionSection, Module,
17///     TypeSection, ValType
18/// };
19///
20/// let mut types = TypeSection::new();
21/// types.ty().function(vec![], vec![ValType::I32]);
22///
23/// let mut functions = FunctionSection::new();
24/// let type_index = 0;
25/// functions.function(type_index);
26///
27/// let locals = vec![];
28/// let mut func = Function::new(locals);
29/// func.instructions().i32_const(42);
30/// let mut code = CodeSection::new();
31/// code.function(&func);
32///
33/// let mut module = Module::new();
34/// module
35///     .section(&types)
36///     .section(&functions)
37///     .section(&code);
38///
39/// let wasm_bytes = module.finish();
40/// ```
41#[derive(Clone, Default, Debug)]
42pub struct CodeSection {
43    bytes: Vec<u8>,
44    num_added: u32,
45}
46
47impl CodeSection {
48    /// Create a new code section encoder.
49    pub fn new() -> Self {
50        Self::default()
51    }
52
53    /// The number of functions in the section.
54    pub fn len(&self) -> u32 {
55        self.num_added
56    }
57
58    /// The number of bytes already added to this section.
59    ///
60    /// This number doesn't include the vector length that precedes the
61    /// code entries, since it has a variable size that isn't known until all
62    /// functions are added.
63    pub fn byte_len(&self) -> usize {
64        self.bytes.len()
65    }
66
67    /// Determines if the section is empty.
68    pub fn is_empty(&self) -> bool {
69        self.num_added == 0
70    }
71
72    /// Write a function body into this code section.
73    pub fn function(&mut self, func: &Function) -> &mut Self {
74        func.encode(&mut self.bytes);
75        self.num_added += 1;
76        self
77    }
78
79    /// Add a raw byte slice into this code section as a function body.
80    ///
81    /// The length prefix of the function body will be automatically prepended,
82    /// and should not be included in the raw byte slice.
83    ///
84    /// # Example
85    ///
86    /// You can use the `raw` method to copy an already-encoded function body
87    /// into a new code section encoder:
88    ///
89    /// ```
90    /// # use wasmparser::{BinaryReader, CodeSectionReader};
91    /// //                  id, size, # entries, entry
92    /// let code_section = [10, 6,    1,         4, 0, 65, 0, 11];
93    ///
94    /// // Parse the code section.
95    /// let reader = BinaryReader::new(&code_section, 0);
96    /// let reader = CodeSectionReader::new(reader).unwrap();
97    /// let body = reader.into_iter().next().unwrap().unwrap();
98    /// let body_range = body.range();
99    ///
100    /// // Add the body to a new code section encoder by copying bytes rather
101    /// // than re-parsing and re-encoding it.
102    /// let mut encoder = wasm_encoder::CodeSection::new();
103    /// encoder.raw(&code_section[body_range.start..body_range.end]);
104    /// ```
105    pub fn raw(&mut self, data: &[u8]) -> &mut Self {
106        data.encode(&mut self.bytes);
107        self.num_added += 1;
108        self
109    }
110}
111
112impl Encode for CodeSection {
113    fn encode(&self, sink: &mut Vec<u8>) {
114        encode_section(sink, self.num_added, &self.bytes);
115    }
116}
117
118impl Section for CodeSection {
119    fn id(&self) -> u8 {
120        SectionId::Code.into()
121    }
122}
123
124/// An encoder for a function body within the code section.
125///
126/// # Example
127///
128/// ```
129/// use wasm_encoder::{CodeSection, Function};
130///
131/// // Define the function body for:
132/// //
133/// //     (func (param i32 i32) (result i32)
134/// //       local.get 0
135/// //       local.get 1
136/// //       i32.add)
137/// let locals = vec![];
138/// let mut func = Function::new(locals);
139/// func.instructions()
140///     .local_get(0)
141///     .local_get(1)
142///     .i32_add();
143///
144/// // Add our function to the code section.
145/// let mut code = CodeSection::new();
146/// code.function(&func);
147/// ```
148#[derive(Clone, Debug, Eq, PartialEq)]
149pub struct Function {
150    bytes: Vec<u8>,
151}
152
153impl Function {
154    /// Create a new function body with the given locals.
155    ///
156    /// The argument is an iterator over `(N, Ty)`, which defines
157    /// that the next `N` locals will be of type `Ty`.
158    ///
159    /// For example, a function with locals 0 and 1 of type I32 and
160    /// local 2 of type F32 would be created as:
161    ///
162    /// ```
163    /// # use wasm_encoder::{Function, ValType};
164    /// let f = Function::new([(2, ValType::I32), (1, ValType::F32)]);
165    /// ```
166    ///
167    /// For more information about the code section (and function definition) in the WASM binary format
168    /// see the [WebAssembly spec](https://webassembly.github.io/spec/core/binary/modules.html#binary-func)
169    pub fn new<L>(locals: L) -> Self
170    where
171        L: IntoIterator<Item = (u32, ValType)>,
172        L::IntoIter: ExactSizeIterator,
173    {
174        let locals = locals.into_iter();
175        let mut bytes = vec![];
176        locals.len().encode(&mut bytes);
177        for (count, ty) in locals {
178            count.encode(&mut bytes);
179            ty.encode(&mut bytes);
180        }
181        Function { bytes }
182    }
183
184    /// Create a function from a list of locals' types.
185    ///
186    /// Unlike [`Function::new`], this constructor simply takes a list of types
187    /// which are in order associated with locals.
188    ///
189    /// For example:
190    ///
191    ///  ```
192    /// # use wasm_encoder::{Function, ValType};
193    /// let f = Function::new([(2, ValType::I32), (1, ValType::F32)]);
194    /// let g = Function::new_with_locals_types([
195    ///     ValType::I32, ValType::I32, ValType::F32
196    /// ]);
197    ///
198    /// assert_eq!(f, g)
199    /// ```
200    pub fn new_with_locals_types<L>(locals: L) -> Self
201    where
202        L: IntoIterator<Item = ValType>,
203    {
204        let locals = locals.into_iter();
205
206        let mut locals_collected: Vec<(u32, ValType)> = vec![];
207        for l in locals {
208            if let Some((last_count, last_type)) = locals_collected.last_mut() {
209                if l == *last_type {
210                    // Increment the count of consecutive locals of this type
211                    *last_count += 1;
212                    continue;
213                }
214            }
215            // If we didn't increment, a new type of local appeared
216            locals_collected.push((1, l));
217        }
218
219        Function::new(locals_collected)
220    }
221
222    /// Get an instruction encoder for this function body.
223    pub fn instructions(&mut self) -> InstructionSink {
224        InstructionSink::new(&mut self.bytes)
225    }
226
227    /// Write an instruction into this function body.
228    pub fn instruction(&mut self, instruction: &Instruction) -> &mut Self {
229        instruction.encode(&mut self.bytes);
230        self
231    }
232
233    /// Add raw bytes to this function's body.
234    pub fn raw<B>(&mut self, bytes: B) -> &mut Self
235    where
236        B: IntoIterator<Item = u8>,
237    {
238        self.bytes.extend(bytes);
239        self
240    }
241
242    /// The number of bytes already added to this function.
243    ///
244    /// This number doesn't include the variable-width size field that `encode`
245    /// will write before the added bytes, since the size of that field isn't
246    /// known until all the instructions are added to this function.
247    pub fn byte_len(&self) -> usize {
248        self.bytes.len()
249    }
250
251    /// Unwraps and returns the raw byte encoding of this function.
252    ///
253    /// This encoding doesn't include the variable-width size field
254    /// that `encode` will write before the added bytes. As such, its
255    /// length will match the return value of [`Function::byte_len`].
256    ///
257    /// # Use Case
258    ///
259    /// This raw byte form is suitable for later using with
260    /// [`CodeSection::raw`]. Note that it *differs* from what results
261    /// from [`Function::encode`] precisely due to the *lack* of the
262    /// length prefix; [`CodeSection::raw`] will use this. Using
263    /// [`Function::encode`] instead produces bytes that cannot be fed
264    /// into other wasm-encoder types without stripping off the length
265    /// prefix, which is awkward and error-prone.
266    ///
267    /// This method combined with [`CodeSection::raw`] may be useful
268    /// together if one wants to save the result of function encoding
269    /// and use it later: for example, caching the result of some code
270    /// generation process.
271    ///
272    /// For example:
273    ///
274    /// ```
275    /// # use wasm_encoder::{CodeSection, Function};
276    /// let mut f = Function::new([]);
277    /// f.instructions().end();
278    /// let bytes = f.into_raw_body();
279    /// // (save `bytes` somewhere for later use)
280    /// let mut code = CodeSection::new();
281    /// code.raw(&bytes[..]);
282    ///
283    /// assert_eq!(2, bytes.len());  // Locals count, then `end`
284    /// assert_eq!(3, code.byte_len()); // Function length byte, function body
285    /// ```
286    pub fn into_raw_body(self) -> Vec<u8> {
287        self.bytes
288    }
289}
290
291impl Encode for Function {
292    fn encode(&self, sink: &mut Vec<u8>) {
293        self.bytes.encode(sink);
294    }
295}
296
297/// The immediate for a memory instruction.
298#[derive(Clone, Copy, Debug)]
299pub struct MemArg {
300    /// A static offset to add to the instruction's dynamic address operand.
301    ///
302    /// This is a `u64` field for the memory64 proposal, but 32-bit memories
303    /// limit offsets to at most `u32::MAX` bytes. This will be encoded as a LEB
304    /// but it won't generate a valid module if an offset is specified which is
305    /// larger than the maximum size of the index space for the memory indicated
306    /// by `memory_index`.
307    pub offset: u64,
308    /// The expected alignment of the instruction's dynamic address operand
309    /// (expressed the exponent of a power of two).
310    pub align: u32,
311    /// The index of the memory this instruction is operating upon.
312    pub memory_index: u32,
313}
314
315impl Encode for MemArg {
316    fn encode(&self, sink: &mut Vec<u8>) {
317        if self.memory_index == 0 {
318            self.align.encode(sink);
319            self.offset.encode(sink);
320        } else {
321            (self.align | (1 << 6)).encode(sink);
322            self.memory_index.encode(sink);
323            self.offset.encode(sink);
324        }
325    }
326}
327
328/// The memory ordering for atomic instructions.
329///
330/// For an in-depth explanation of memory orderings, see the C++ documentation
331/// for [`memory_order`] or the Rust documentation for [`atomic::Ordering`].
332///
333/// [`memory_order`]: https://en.cppreference.com/w/cpp/atomic/memory_order
334/// [`atomic::Ordering`]: https://doc.rust-lang.org/std/sync/atomic/enum.Ordering.html
335#[derive(Clone, Copy, Debug)]
336pub enum Ordering {
337    /// For a load, it acquires; this orders all operations before the last
338    /// "releasing" store. For a store, it releases; this orders all operations
339    /// before it at the next "acquiring" load.
340    AcqRel,
341    /// Like `AcqRel` but all threads see all sequentially consistent operations
342    /// in the same order.
343    SeqCst,
344}
345
346impl Encode for Ordering {
347    fn encode(&self, sink: &mut Vec<u8>) {
348        let flag: u8 = match self {
349            Ordering::SeqCst => 0,
350            Ordering::AcqRel => 1,
351        };
352        sink.push(flag);
353    }
354}
355
356/// Describe an unchecked SIMD lane index.
357pub type Lane = u8;
358
359/// The type for a `block`/`if`/`loop`.
360#[derive(Clone, Copy, Debug)]
361pub enum BlockType {
362    /// `[] -> []`
363    Empty,
364    /// `[] -> [t]`
365    Result(ValType),
366    /// The `n`th function type.
367    FunctionType(u32),
368}
369
370impl Encode for BlockType {
371    fn encode(&self, sink: &mut Vec<u8>) {
372        match *self {
373            Self::Empty => sink.push(0x40),
374            Self::Result(ty) => ty.encode(sink),
375            Self::FunctionType(f) => (f as i64).encode(sink),
376        }
377    }
378}
379
380/// WebAssembly instructions.
381#[derive(Clone, Debug)]
382#[non_exhaustive]
383#[allow(missing_docs, non_camel_case_types)]
384pub enum Instruction<'a> {
385    // Control instructions.
386    Unreachable,
387    Nop,
388    Block(BlockType),
389    Loop(BlockType),
390    If(BlockType),
391    Else,
392    End,
393    Br(u32),
394    BrIf(u32),
395    BrTable(Cow<'a, [u32]>, u32),
396    BrOnNull(u32),
397    BrOnNonNull(u32),
398    Return,
399    Call(u32),
400    CallRef(u32),
401    CallIndirect {
402        type_index: u32,
403        table_index: u32,
404    },
405    ReturnCallRef(u32),
406    ReturnCall(u32),
407    ReturnCallIndirect {
408        type_index: u32,
409        table_index: u32,
410    },
411    TryTable(BlockType, Cow<'a, [Catch]>),
412    Throw(u32),
413    ThrowRef,
414
415    // Deprecated exception-handling instructions
416    Try(BlockType),
417    Delegate(u32),
418    Catch(u32),
419    CatchAll,
420    Rethrow(u32),
421
422    // Parametric instructions.
423    Drop,
424    Select,
425
426    // Variable instructions.
427    LocalGet(u32),
428    LocalSet(u32),
429    LocalTee(u32),
430    GlobalGet(u32),
431    GlobalSet(u32),
432
433    // Memory instructions.
434    I32Load(MemArg),
435    I64Load(MemArg),
436    F32Load(MemArg),
437    F64Load(MemArg),
438    I32Load8S(MemArg),
439    I32Load8U(MemArg),
440    I32Load16S(MemArg),
441    I32Load16U(MemArg),
442    I64Load8S(MemArg),
443    I64Load8U(MemArg),
444    I64Load16S(MemArg),
445    I64Load16U(MemArg),
446    I64Load32S(MemArg),
447    I64Load32U(MemArg),
448    I32Store(MemArg),
449    I64Store(MemArg),
450    F32Store(MemArg),
451    F64Store(MemArg),
452    I32Store8(MemArg),
453    I32Store16(MemArg),
454    I64Store8(MemArg),
455    I64Store16(MemArg),
456    I64Store32(MemArg),
457    MemorySize(u32),
458    MemoryGrow(u32),
459    MemoryInit {
460        mem: u32,
461        data_index: u32,
462    },
463    DataDrop(u32),
464    MemoryCopy {
465        src_mem: u32,
466        dst_mem: u32,
467    },
468    MemoryFill(u32),
469    MemoryDiscard(u32),
470
471    // Numeric instructions.
472    I32Const(i32),
473    I64Const(i64),
474    F32Const(f32),
475    F64Const(f64),
476    I32Eqz,
477    I32Eq,
478    I32Ne,
479    I32LtS,
480    I32LtU,
481    I32GtS,
482    I32GtU,
483    I32LeS,
484    I32LeU,
485    I32GeS,
486    I32GeU,
487    I64Eqz,
488    I64Eq,
489    I64Ne,
490    I64LtS,
491    I64LtU,
492    I64GtS,
493    I64GtU,
494    I64LeS,
495    I64LeU,
496    I64GeS,
497    I64GeU,
498    F32Eq,
499    F32Ne,
500    F32Lt,
501    F32Gt,
502    F32Le,
503    F32Ge,
504    F64Eq,
505    F64Ne,
506    F64Lt,
507    F64Gt,
508    F64Le,
509    F64Ge,
510    I32Clz,
511    I32Ctz,
512    I32Popcnt,
513    I32Add,
514    I32Sub,
515    I32Mul,
516    I32DivS,
517    I32DivU,
518    I32RemS,
519    I32RemU,
520    I32And,
521    I32Or,
522    I32Xor,
523    I32Shl,
524    I32ShrS,
525    I32ShrU,
526    I32Rotl,
527    I32Rotr,
528    I64Clz,
529    I64Ctz,
530    I64Popcnt,
531    I64Add,
532    I64Sub,
533    I64Mul,
534    I64DivS,
535    I64DivU,
536    I64RemS,
537    I64RemU,
538    I64And,
539    I64Or,
540    I64Xor,
541    I64Shl,
542    I64ShrS,
543    I64ShrU,
544    I64Rotl,
545    I64Rotr,
546    F32Abs,
547    F32Neg,
548    F32Ceil,
549    F32Floor,
550    F32Trunc,
551    F32Nearest,
552    F32Sqrt,
553    F32Add,
554    F32Sub,
555    F32Mul,
556    F32Div,
557    F32Min,
558    F32Max,
559    F32Copysign,
560    F64Abs,
561    F64Neg,
562    F64Ceil,
563    F64Floor,
564    F64Trunc,
565    F64Nearest,
566    F64Sqrt,
567    F64Add,
568    F64Sub,
569    F64Mul,
570    F64Div,
571    F64Min,
572    F64Max,
573    F64Copysign,
574    I32WrapI64,
575    I32TruncF32S,
576    I32TruncF32U,
577    I32TruncF64S,
578    I32TruncF64U,
579    I64ExtendI32S,
580    I64ExtendI32U,
581    I64TruncF32S,
582    I64TruncF32U,
583    I64TruncF64S,
584    I64TruncF64U,
585    F32ConvertI32S,
586    F32ConvertI32U,
587    F32ConvertI64S,
588    F32ConvertI64U,
589    F32DemoteF64,
590    F64ConvertI32S,
591    F64ConvertI32U,
592    F64ConvertI64S,
593    F64ConvertI64U,
594    F64PromoteF32,
595    I32ReinterpretF32,
596    I64ReinterpretF64,
597    F32ReinterpretI32,
598    F64ReinterpretI64,
599    I32Extend8S,
600    I32Extend16S,
601    I64Extend8S,
602    I64Extend16S,
603    I64Extend32S,
604    I32TruncSatF32S,
605    I32TruncSatF32U,
606    I32TruncSatF64S,
607    I32TruncSatF64U,
608    I64TruncSatF32S,
609    I64TruncSatF32U,
610    I64TruncSatF64S,
611    I64TruncSatF64U,
612
613    // Reference types instructions.
614    TypedSelect(ValType),
615    RefNull(HeapType),
616    RefIsNull,
617    RefFunc(u32),
618    RefEq,
619    RefAsNonNull,
620
621    // GC types instructions.
622    StructNew(u32),
623    StructNewDefault(u32),
624    StructGet {
625        struct_type_index: u32,
626        field_index: u32,
627    },
628    StructGetS {
629        struct_type_index: u32,
630        field_index: u32,
631    },
632    StructGetU {
633        struct_type_index: u32,
634        field_index: u32,
635    },
636    StructSet {
637        struct_type_index: u32,
638        field_index: u32,
639    },
640
641    ArrayNew(u32),
642    ArrayNewDefault(u32),
643    ArrayNewFixed {
644        array_type_index: u32,
645        array_size: u32,
646    },
647    ArrayNewData {
648        array_type_index: u32,
649        array_data_index: u32,
650    },
651    ArrayNewElem {
652        array_type_index: u32,
653        array_elem_index: u32,
654    },
655    ArrayGet(u32),
656    ArrayGetS(u32),
657    ArrayGetU(u32),
658    ArraySet(u32),
659    ArrayLen,
660    ArrayFill(u32),
661    ArrayCopy {
662        array_type_index_dst: u32,
663        array_type_index_src: u32,
664    },
665    ArrayInitData {
666        array_type_index: u32,
667        array_data_index: u32,
668    },
669    ArrayInitElem {
670        array_type_index: u32,
671        array_elem_index: u32,
672    },
673    RefTestNonNull(HeapType),
674    RefTestNullable(HeapType),
675    RefCastNonNull(HeapType),
676    RefCastNullable(HeapType),
677    BrOnCast {
678        relative_depth: u32,
679        from_ref_type: RefType,
680        to_ref_type: RefType,
681    },
682    BrOnCastFail {
683        relative_depth: u32,
684        from_ref_type: RefType,
685        to_ref_type: RefType,
686    },
687    AnyConvertExtern,
688    ExternConvertAny,
689
690    RefI31,
691    I31GetS,
692    I31GetU,
693
694    // Bulk memory instructions.
695    TableInit {
696        elem_index: u32,
697        table: u32,
698    },
699    ElemDrop(u32),
700    TableFill(u32),
701    TableSet(u32),
702    TableGet(u32),
703    TableGrow(u32),
704    TableSize(u32),
705    TableCopy {
706        src_table: u32,
707        dst_table: u32,
708    },
709
710    // SIMD instructions.
711    V128Load(MemArg),
712    V128Load8x8S(MemArg),
713    V128Load8x8U(MemArg),
714    V128Load16x4S(MemArg),
715    V128Load16x4U(MemArg),
716    V128Load32x2S(MemArg),
717    V128Load32x2U(MemArg),
718    V128Load8Splat(MemArg),
719    V128Load16Splat(MemArg),
720    V128Load32Splat(MemArg),
721    V128Load64Splat(MemArg),
722    V128Load32Zero(MemArg),
723    V128Load64Zero(MemArg),
724    V128Store(MemArg),
725    V128Load8Lane {
726        memarg: MemArg,
727        lane: Lane,
728    },
729    V128Load16Lane {
730        memarg: MemArg,
731        lane: Lane,
732    },
733    V128Load32Lane {
734        memarg: MemArg,
735        lane: Lane,
736    },
737    V128Load64Lane {
738        memarg: MemArg,
739        lane: Lane,
740    },
741    V128Store8Lane {
742        memarg: MemArg,
743        lane: Lane,
744    },
745    V128Store16Lane {
746        memarg: MemArg,
747        lane: Lane,
748    },
749    V128Store32Lane {
750        memarg: MemArg,
751        lane: Lane,
752    },
753    V128Store64Lane {
754        memarg: MemArg,
755        lane: Lane,
756    },
757    V128Const(i128),
758    I8x16Shuffle([Lane; 16]),
759    I8x16ExtractLaneS(Lane),
760    I8x16ExtractLaneU(Lane),
761    I8x16ReplaceLane(Lane),
762    I16x8ExtractLaneS(Lane),
763    I16x8ExtractLaneU(Lane),
764    I16x8ReplaceLane(Lane),
765    I32x4ExtractLane(Lane),
766    I32x4ReplaceLane(Lane),
767    I64x2ExtractLane(Lane),
768    I64x2ReplaceLane(Lane),
769    F32x4ExtractLane(Lane),
770    F32x4ReplaceLane(Lane),
771    F64x2ExtractLane(Lane),
772    F64x2ReplaceLane(Lane),
773    I8x16Swizzle,
774    I8x16Splat,
775    I16x8Splat,
776    I32x4Splat,
777    I64x2Splat,
778    F32x4Splat,
779    F64x2Splat,
780    I8x16Eq,
781    I8x16Ne,
782    I8x16LtS,
783    I8x16LtU,
784    I8x16GtS,
785    I8x16GtU,
786    I8x16LeS,
787    I8x16LeU,
788    I8x16GeS,
789    I8x16GeU,
790    I16x8Eq,
791    I16x8Ne,
792    I16x8LtS,
793    I16x8LtU,
794    I16x8GtS,
795    I16x8GtU,
796    I16x8LeS,
797    I16x8LeU,
798    I16x8GeS,
799    I16x8GeU,
800    I32x4Eq,
801    I32x4Ne,
802    I32x4LtS,
803    I32x4LtU,
804    I32x4GtS,
805    I32x4GtU,
806    I32x4LeS,
807    I32x4LeU,
808    I32x4GeS,
809    I32x4GeU,
810    I64x2Eq,
811    I64x2Ne,
812    I64x2LtS,
813    I64x2GtS,
814    I64x2LeS,
815    I64x2GeS,
816    F32x4Eq,
817    F32x4Ne,
818    F32x4Lt,
819    F32x4Gt,
820    F32x4Le,
821    F32x4Ge,
822    F64x2Eq,
823    F64x2Ne,
824    F64x2Lt,
825    F64x2Gt,
826    F64x2Le,
827    F64x2Ge,
828    V128Not,
829    V128And,
830    V128AndNot,
831    V128Or,
832    V128Xor,
833    V128Bitselect,
834    V128AnyTrue,
835    I8x16Abs,
836    I8x16Neg,
837    I8x16Popcnt,
838    I8x16AllTrue,
839    I8x16Bitmask,
840    I8x16NarrowI16x8S,
841    I8x16NarrowI16x8U,
842    I8x16Shl,
843    I8x16ShrS,
844    I8x16ShrU,
845    I8x16Add,
846    I8x16AddSatS,
847    I8x16AddSatU,
848    I8x16Sub,
849    I8x16SubSatS,
850    I8x16SubSatU,
851    I8x16MinS,
852    I8x16MinU,
853    I8x16MaxS,
854    I8x16MaxU,
855    I8x16AvgrU,
856    I16x8ExtAddPairwiseI8x16S,
857    I16x8ExtAddPairwiseI8x16U,
858    I16x8Abs,
859    I16x8Neg,
860    I16x8Q15MulrSatS,
861    I16x8AllTrue,
862    I16x8Bitmask,
863    I16x8NarrowI32x4S,
864    I16x8NarrowI32x4U,
865    I16x8ExtendLowI8x16S,
866    I16x8ExtendHighI8x16S,
867    I16x8ExtendLowI8x16U,
868    I16x8ExtendHighI8x16U,
869    I16x8Shl,
870    I16x8ShrS,
871    I16x8ShrU,
872    I16x8Add,
873    I16x8AddSatS,
874    I16x8AddSatU,
875    I16x8Sub,
876    I16x8SubSatS,
877    I16x8SubSatU,
878    I16x8Mul,
879    I16x8MinS,
880    I16x8MinU,
881    I16x8MaxS,
882    I16x8MaxU,
883    I16x8AvgrU,
884    I16x8ExtMulLowI8x16S,
885    I16x8ExtMulHighI8x16S,
886    I16x8ExtMulLowI8x16U,
887    I16x8ExtMulHighI8x16U,
888    I32x4ExtAddPairwiseI16x8S,
889    I32x4ExtAddPairwiseI16x8U,
890    I32x4Abs,
891    I32x4Neg,
892    I32x4AllTrue,
893    I32x4Bitmask,
894    I32x4ExtendLowI16x8S,
895    I32x4ExtendHighI16x8S,
896    I32x4ExtendLowI16x8U,
897    I32x4ExtendHighI16x8U,
898    I32x4Shl,
899    I32x4ShrS,
900    I32x4ShrU,
901    I32x4Add,
902    I32x4Sub,
903    I32x4Mul,
904    I32x4MinS,
905    I32x4MinU,
906    I32x4MaxS,
907    I32x4MaxU,
908    I32x4DotI16x8S,
909    I32x4ExtMulLowI16x8S,
910    I32x4ExtMulHighI16x8S,
911    I32x4ExtMulLowI16x8U,
912    I32x4ExtMulHighI16x8U,
913    I64x2Abs,
914    I64x2Neg,
915    I64x2AllTrue,
916    I64x2Bitmask,
917    I64x2ExtendLowI32x4S,
918    I64x2ExtendHighI32x4S,
919    I64x2ExtendLowI32x4U,
920    I64x2ExtendHighI32x4U,
921    I64x2Shl,
922    I64x2ShrS,
923    I64x2ShrU,
924    I64x2Add,
925    I64x2Sub,
926    I64x2Mul,
927    I64x2ExtMulLowI32x4S,
928    I64x2ExtMulHighI32x4S,
929    I64x2ExtMulLowI32x4U,
930    I64x2ExtMulHighI32x4U,
931    F32x4Ceil,
932    F32x4Floor,
933    F32x4Trunc,
934    F32x4Nearest,
935    F32x4Abs,
936    F32x4Neg,
937    F32x4Sqrt,
938    F32x4Add,
939    F32x4Sub,
940    F32x4Mul,
941    F32x4Div,
942    F32x4Min,
943    F32x4Max,
944    F32x4PMin,
945    F32x4PMax,
946    F64x2Ceil,
947    F64x2Floor,
948    F64x2Trunc,
949    F64x2Nearest,
950    F64x2Abs,
951    F64x2Neg,
952    F64x2Sqrt,
953    F64x2Add,
954    F64x2Sub,
955    F64x2Mul,
956    F64x2Div,
957    F64x2Min,
958    F64x2Max,
959    F64x2PMin,
960    F64x2PMax,
961    I32x4TruncSatF32x4S,
962    I32x4TruncSatF32x4U,
963    F32x4ConvertI32x4S,
964    F32x4ConvertI32x4U,
965    I32x4TruncSatF64x2SZero,
966    I32x4TruncSatF64x2UZero,
967    F64x2ConvertLowI32x4S,
968    F64x2ConvertLowI32x4U,
969    F32x4DemoteF64x2Zero,
970    F64x2PromoteLowF32x4,
971
972    // Relaxed simd proposal
973    I8x16RelaxedSwizzle,
974    I32x4RelaxedTruncF32x4S,
975    I32x4RelaxedTruncF32x4U,
976    I32x4RelaxedTruncF64x2SZero,
977    I32x4RelaxedTruncF64x2UZero,
978    F32x4RelaxedMadd,
979    F32x4RelaxedNmadd,
980    F64x2RelaxedMadd,
981    F64x2RelaxedNmadd,
982    I8x16RelaxedLaneselect,
983    I16x8RelaxedLaneselect,
984    I32x4RelaxedLaneselect,
985    I64x2RelaxedLaneselect,
986    F32x4RelaxedMin,
987    F32x4RelaxedMax,
988    F64x2RelaxedMin,
989    F64x2RelaxedMax,
990    I16x8RelaxedQ15mulrS,
991    I16x8RelaxedDotI8x16I7x16S,
992    I32x4RelaxedDotI8x16I7x16AddS,
993
994    // Atomic instructions (the threads proposal)
995    MemoryAtomicNotify(MemArg),
996    MemoryAtomicWait32(MemArg),
997    MemoryAtomicWait64(MemArg),
998    AtomicFence,
999    I32AtomicLoad(MemArg),
1000    I64AtomicLoad(MemArg),
1001    I32AtomicLoad8U(MemArg),
1002    I32AtomicLoad16U(MemArg),
1003    I64AtomicLoad8U(MemArg),
1004    I64AtomicLoad16U(MemArg),
1005    I64AtomicLoad32U(MemArg),
1006    I32AtomicStore(MemArg),
1007    I64AtomicStore(MemArg),
1008    I32AtomicStore8(MemArg),
1009    I32AtomicStore16(MemArg),
1010    I64AtomicStore8(MemArg),
1011    I64AtomicStore16(MemArg),
1012    I64AtomicStore32(MemArg),
1013    I32AtomicRmwAdd(MemArg),
1014    I64AtomicRmwAdd(MemArg),
1015    I32AtomicRmw8AddU(MemArg),
1016    I32AtomicRmw16AddU(MemArg),
1017    I64AtomicRmw8AddU(MemArg),
1018    I64AtomicRmw16AddU(MemArg),
1019    I64AtomicRmw32AddU(MemArg),
1020    I32AtomicRmwSub(MemArg),
1021    I64AtomicRmwSub(MemArg),
1022    I32AtomicRmw8SubU(MemArg),
1023    I32AtomicRmw16SubU(MemArg),
1024    I64AtomicRmw8SubU(MemArg),
1025    I64AtomicRmw16SubU(MemArg),
1026    I64AtomicRmw32SubU(MemArg),
1027    I32AtomicRmwAnd(MemArg),
1028    I64AtomicRmwAnd(MemArg),
1029    I32AtomicRmw8AndU(MemArg),
1030    I32AtomicRmw16AndU(MemArg),
1031    I64AtomicRmw8AndU(MemArg),
1032    I64AtomicRmw16AndU(MemArg),
1033    I64AtomicRmw32AndU(MemArg),
1034    I32AtomicRmwOr(MemArg),
1035    I64AtomicRmwOr(MemArg),
1036    I32AtomicRmw8OrU(MemArg),
1037    I32AtomicRmw16OrU(MemArg),
1038    I64AtomicRmw8OrU(MemArg),
1039    I64AtomicRmw16OrU(MemArg),
1040    I64AtomicRmw32OrU(MemArg),
1041    I32AtomicRmwXor(MemArg),
1042    I64AtomicRmwXor(MemArg),
1043    I32AtomicRmw8XorU(MemArg),
1044    I32AtomicRmw16XorU(MemArg),
1045    I64AtomicRmw8XorU(MemArg),
1046    I64AtomicRmw16XorU(MemArg),
1047    I64AtomicRmw32XorU(MemArg),
1048    I32AtomicRmwXchg(MemArg),
1049    I64AtomicRmwXchg(MemArg),
1050    I32AtomicRmw8XchgU(MemArg),
1051    I32AtomicRmw16XchgU(MemArg),
1052    I64AtomicRmw8XchgU(MemArg),
1053    I64AtomicRmw16XchgU(MemArg),
1054    I64AtomicRmw32XchgU(MemArg),
1055    I32AtomicRmwCmpxchg(MemArg),
1056    I64AtomicRmwCmpxchg(MemArg),
1057    I32AtomicRmw8CmpxchgU(MemArg),
1058    I32AtomicRmw16CmpxchgU(MemArg),
1059    I64AtomicRmw8CmpxchgU(MemArg),
1060    I64AtomicRmw16CmpxchgU(MemArg),
1061    I64AtomicRmw32CmpxchgU(MemArg),
1062
1063    // More atomic instructions (the shared-everything-threads proposal)
1064    GlobalAtomicGet {
1065        ordering: Ordering,
1066        global_index: u32,
1067    },
1068    GlobalAtomicSet {
1069        ordering: Ordering,
1070        global_index: u32,
1071    },
1072    GlobalAtomicRmwAdd {
1073        ordering: Ordering,
1074        global_index: u32,
1075    },
1076    GlobalAtomicRmwSub {
1077        ordering: Ordering,
1078        global_index: u32,
1079    },
1080    GlobalAtomicRmwAnd {
1081        ordering: Ordering,
1082        global_index: u32,
1083    },
1084    GlobalAtomicRmwOr {
1085        ordering: Ordering,
1086        global_index: u32,
1087    },
1088    GlobalAtomicRmwXor {
1089        ordering: Ordering,
1090        global_index: u32,
1091    },
1092    GlobalAtomicRmwXchg {
1093        ordering: Ordering,
1094        global_index: u32,
1095    },
1096    GlobalAtomicRmwCmpxchg {
1097        ordering: Ordering,
1098        global_index: u32,
1099    },
1100    TableAtomicGet {
1101        ordering: Ordering,
1102        table_index: u32,
1103    },
1104    TableAtomicSet {
1105        ordering: Ordering,
1106        table_index: u32,
1107    },
1108    TableAtomicRmwXchg {
1109        ordering: Ordering,
1110        table_index: u32,
1111    },
1112    TableAtomicRmwCmpxchg {
1113        ordering: Ordering,
1114        table_index: u32,
1115    },
1116    StructAtomicGet {
1117        ordering: Ordering,
1118        struct_type_index: u32,
1119        field_index: u32,
1120    },
1121    StructAtomicGetS {
1122        ordering: Ordering,
1123        struct_type_index: u32,
1124        field_index: u32,
1125    },
1126    StructAtomicGetU {
1127        ordering: Ordering,
1128        struct_type_index: u32,
1129        field_index: u32,
1130    },
1131    StructAtomicSet {
1132        ordering: Ordering,
1133        struct_type_index: u32,
1134        field_index: u32,
1135    },
1136    StructAtomicRmwAdd {
1137        ordering: Ordering,
1138        struct_type_index: u32,
1139        field_index: u32,
1140    },
1141    StructAtomicRmwSub {
1142        ordering: Ordering,
1143        struct_type_index: u32,
1144        field_index: u32,
1145    },
1146    StructAtomicRmwAnd {
1147        ordering: Ordering,
1148        struct_type_index: u32,
1149        field_index: u32,
1150    },
1151    StructAtomicRmwOr {
1152        ordering: Ordering,
1153        struct_type_index: u32,
1154        field_index: u32,
1155    },
1156    StructAtomicRmwXor {
1157        ordering: Ordering,
1158        struct_type_index: u32,
1159        field_index: u32,
1160    },
1161    StructAtomicRmwXchg {
1162        ordering: Ordering,
1163        struct_type_index: u32,
1164        field_index: u32,
1165    },
1166    StructAtomicRmwCmpxchg {
1167        ordering: Ordering,
1168        struct_type_index: u32,
1169        field_index: u32,
1170    },
1171    ArrayAtomicGet {
1172        ordering: Ordering,
1173        array_type_index: u32,
1174    },
1175    ArrayAtomicGetS {
1176        ordering: Ordering,
1177        array_type_index: u32,
1178    },
1179    ArrayAtomicGetU {
1180        ordering: Ordering,
1181        array_type_index: u32,
1182    },
1183    ArrayAtomicSet {
1184        ordering: Ordering,
1185        array_type_index: u32,
1186    },
1187    ArrayAtomicRmwAdd {
1188        ordering: Ordering,
1189        array_type_index: u32,
1190    },
1191    ArrayAtomicRmwSub {
1192        ordering: Ordering,
1193        array_type_index: u32,
1194    },
1195    ArrayAtomicRmwAnd {
1196        ordering: Ordering,
1197        array_type_index: u32,
1198    },
1199    ArrayAtomicRmwOr {
1200        ordering: Ordering,
1201        array_type_index: u32,
1202    },
1203    ArrayAtomicRmwXor {
1204        ordering: Ordering,
1205        array_type_index: u32,
1206    },
1207    ArrayAtomicRmwXchg {
1208        ordering: Ordering,
1209        array_type_index: u32,
1210    },
1211    ArrayAtomicRmwCmpxchg {
1212        ordering: Ordering,
1213        array_type_index: u32,
1214    },
1215    RefI31Shared,
1216    // Stack switching
1217    ContNew(u32),
1218    ContBind {
1219        argument_index: u32,
1220        result_index: u32,
1221    },
1222    Suspend(u32),
1223    Resume {
1224        cont_type_index: u32,
1225        resume_table: Cow<'a, [Handle]>,
1226    },
1227    ResumeThrow {
1228        cont_type_index: u32,
1229        tag_index: u32,
1230        resume_table: Cow<'a, [Handle]>,
1231    },
1232    Switch {
1233        cont_type_index: u32,
1234        tag_index: u32,
1235    },
1236
1237    // Wide Arithmetic
1238    I64Add128,
1239    I64Sub128,
1240    I64MulWideS,
1241    I64MulWideU,
1242}
1243
1244impl Encode for Instruction<'_> {
1245    fn encode(&self, bytes: &mut Vec<u8>) {
1246        let mut sink = InstructionSink::new(bytes);
1247        match *self {
1248            // Control instructions.
1249            Instruction::Unreachable => sink.unreachable(),
1250            Instruction::Nop => sink.nop(),
1251            Instruction::Block(bt) => sink.block(bt),
1252            Instruction::Loop(bt) => sink.loop_(bt),
1253            Instruction::If(bt) => sink.if_(bt),
1254            Instruction::Else => sink.else_(),
1255            Instruction::Try(bt) => sink.try_(bt),
1256            Instruction::Catch(t) => sink.catch(t),
1257            Instruction::Throw(t) => sink.throw(t),
1258            Instruction::Rethrow(l) => sink.rethrow(l),
1259            Instruction::ThrowRef => sink.throw_ref(),
1260            Instruction::End => sink.end(),
1261            Instruction::Br(l) => sink.br(l),
1262            Instruction::BrIf(l) => sink.br_if(l),
1263            Instruction::BrTable(ref ls, l) => sink.br_table(ls.iter().copied(), l),
1264            Instruction::BrOnNull(l) => sink.br_on_null(l),
1265            Instruction::BrOnNonNull(l) => sink.br_on_non_null(l),
1266            Instruction::Return => sink.return_(),
1267            Instruction::Call(f) => sink.call(f),
1268            Instruction::CallRef(ty) => sink.call_ref(ty),
1269            Instruction::CallIndirect {
1270                type_index,
1271                table_index,
1272            } => sink.call_indirect(table_index, type_index),
1273            Instruction::ReturnCallRef(ty) => sink.return_call_ref(ty),
1274
1275            Instruction::ReturnCall(f) => sink.return_call(f),
1276            Instruction::ReturnCallIndirect {
1277                type_index,
1278                table_index,
1279            } => sink.return_call_indirect(table_index, type_index),
1280            Instruction::Delegate(l) => sink.delegate(l),
1281            Instruction::CatchAll => sink.catch_all(),
1282
1283            // Parametric instructions.
1284            Instruction::Drop => sink.drop(),
1285            Instruction::Select => sink.select(),
1286            Instruction::TypedSelect(ty) => sink.typed_select(ty),
1287
1288            Instruction::TryTable(ty, ref catches) => sink.try_table(ty, catches.iter().cloned()),
1289
1290            // Variable instructions.
1291            Instruction::LocalGet(l) => sink.local_get(l),
1292            Instruction::LocalSet(l) => sink.local_set(l),
1293            Instruction::LocalTee(l) => sink.local_tee(l),
1294            Instruction::GlobalGet(g) => sink.global_get(g),
1295            Instruction::GlobalSet(g) => sink.global_set(g),
1296            Instruction::TableGet(table) => sink.table_get(table),
1297            Instruction::TableSet(table) => sink.table_set(table),
1298
1299            // Memory instructions.
1300            Instruction::I32Load(m) => sink.i32_load(m),
1301            Instruction::I64Load(m) => sink.i64_load(m),
1302            Instruction::F32Load(m) => sink.f32_load(m),
1303            Instruction::F64Load(m) => sink.f64_load(m),
1304            Instruction::I32Load8S(m) => sink.i32_load8_s(m),
1305            Instruction::I32Load8U(m) => sink.i32_load8_u(m),
1306            Instruction::I32Load16S(m) => sink.i32_load16_s(m),
1307            Instruction::I32Load16U(m) => sink.i32_load16_u(m),
1308            Instruction::I64Load8S(m) => sink.i64_load8_s(m),
1309            Instruction::I64Load8U(m) => sink.i64_load8_u(m),
1310            Instruction::I64Load16S(m) => sink.i64_load16_s(m),
1311            Instruction::I64Load16U(m) => sink.i64_load16_u(m),
1312            Instruction::I64Load32S(m) => sink.i64_load32_s(m),
1313            Instruction::I64Load32U(m) => sink.i64_load32_u(m),
1314            Instruction::I32Store(m) => sink.i32_store(m),
1315            Instruction::I64Store(m) => sink.i64_store(m),
1316            Instruction::F32Store(m) => sink.f32_store(m),
1317            Instruction::F64Store(m) => sink.f64_store(m),
1318            Instruction::I32Store8(m) => sink.i32_store8(m),
1319            Instruction::I32Store16(m) => sink.i32_store16(m),
1320            Instruction::I64Store8(m) => sink.i64_store8(m),
1321            Instruction::I64Store16(m) => sink.i64_store16(m),
1322            Instruction::I64Store32(m) => sink.i64_store32(m),
1323            Instruction::MemorySize(i) => sink.memory_size(i),
1324            Instruction::MemoryGrow(i) => sink.memory_grow(i),
1325            Instruction::MemoryInit { mem, data_index } => sink.memory_init(mem, data_index),
1326            Instruction::DataDrop(data) => sink.data_drop(data),
1327            Instruction::MemoryCopy { src_mem, dst_mem } => sink.memory_copy(dst_mem, src_mem),
1328            Instruction::MemoryFill(mem) => sink.memory_fill(mem),
1329            Instruction::MemoryDiscard(mem) => sink.memory_discard(mem),
1330
1331            // Numeric instructions.
1332            Instruction::I32Const(x) => sink.i32_const(x),
1333            Instruction::I64Const(x) => sink.i64_const(x),
1334            Instruction::F32Const(x) => sink.f32_const(x),
1335            Instruction::F64Const(x) => sink.f64_const(x),
1336            Instruction::I32Eqz => sink.i32_eqz(),
1337            Instruction::I32Eq => sink.i32_eq(),
1338            Instruction::I32Ne => sink.i32_ne(),
1339            Instruction::I32LtS => sink.i32_lt_s(),
1340            Instruction::I32LtU => sink.i32_lt_u(),
1341            Instruction::I32GtS => sink.i32_gt_s(),
1342            Instruction::I32GtU => sink.i32_gt_u(),
1343            Instruction::I32LeS => sink.i32_le_s(),
1344            Instruction::I32LeU => sink.i32_le_u(),
1345            Instruction::I32GeS => sink.i32_ge_s(),
1346            Instruction::I32GeU => sink.i32_ge_u(),
1347            Instruction::I64Eqz => sink.i64_eqz(),
1348            Instruction::I64Eq => sink.i64_eq(),
1349            Instruction::I64Ne => sink.i64_ne(),
1350            Instruction::I64LtS => sink.i64_lt_s(),
1351            Instruction::I64LtU => sink.i64_lt_u(),
1352            Instruction::I64GtS => sink.i64_gt_s(),
1353            Instruction::I64GtU => sink.i64_gt_u(),
1354            Instruction::I64LeS => sink.i64_le_s(),
1355            Instruction::I64LeU => sink.i64_le_u(),
1356            Instruction::I64GeS => sink.i64_ge_s(),
1357            Instruction::I64GeU => sink.i64_ge_u(),
1358            Instruction::F32Eq => sink.f32_eq(),
1359            Instruction::F32Ne => sink.f32_ne(),
1360            Instruction::F32Lt => sink.f32_lt(),
1361            Instruction::F32Gt => sink.f32_gt(),
1362            Instruction::F32Le => sink.f32_le(),
1363            Instruction::F32Ge => sink.f32_ge(),
1364            Instruction::F64Eq => sink.f64_eq(),
1365            Instruction::F64Ne => sink.f64_ne(),
1366            Instruction::F64Lt => sink.f64_lt(),
1367            Instruction::F64Gt => sink.f64_gt(),
1368            Instruction::F64Le => sink.f64_le(),
1369            Instruction::F64Ge => sink.f64_ge(),
1370            Instruction::I32Clz => sink.i32_clz(),
1371            Instruction::I32Ctz => sink.i32_ctz(),
1372            Instruction::I32Popcnt => sink.i32_popcnt(),
1373            Instruction::I32Add => sink.i32_add(),
1374            Instruction::I32Sub => sink.i32_sub(),
1375            Instruction::I32Mul => sink.i32_mul(),
1376            Instruction::I32DivS => sink.i32_div_s(),
1377            Instruction::I32DivU => sink.i32_div_u(),
1378            Instruction::I32RemS => sink.i32_rem_s(),
1379            Instruction::I32RemU => sink.i32_rem_u(),
1380            Instruction::I32And => sink.i32_and(),
1381            Instruction::I32Or => sink.i32_or(),
1382            Instruction::I32Xor => sink.i32_xor(),
1383            Instruction::I32Shl => sink.i32_shl(),
1384            Instruction::I32ShrS => sink.i32_shr_s(),
1385            Instruction::I32ShrU => sink.i32_shr_u(),
1386            Instruction::I32Rotl => sink.i32_rotl(),
1387            Instruction::I32Rotr => sink.i32_rotr(),
1388            Instruction::I64Clz => sink.i64_clz(),
1389            Instruction::I64Ctz => sink.i64_ctz(),
1390            Instruction::I64Popcnt => sink.i64_popcnt(),
1391            Instruction::I64Add => sink.i64_add(),
1392            Instruction::I64Sub => sink.i64_sub(),
1393            Instruction::I64Mul => sink.i64_mul(),
1394            Instruction::I64DivS => sink.i64_div_s(),
1395            Instruction::I64DivU => sink.i64_div_u(),
1396            Instruction::I64RemS => sink.i64_rem_s(),
1397            Instruction::I64RemU => sink.i64_rem_u(),
1398            Instruction::I64And => sink.i64_and(),
1399            Instruction::I64Or => sink.i64_or(),
1400            Instruction::I64Xor => sink.i64_xor(),
1401            Instruction::I64Shl => sink.i64_shl(),
1402            Instruction::I64ShrS => sink.i64_shr_s(),
1403            Instruction::I64ShrU => sink.i64_shr_u(),
1404            Instruction::I64Rotl => sink.i64_rotl(),
1405            Instruction::I64Rotr => sink.i64_rotr(),
1406            Instruction::F32Abs => sink.f32_abs(),
1407            Instruction::F32Neg => sink.f32_neg(),
1408            Instruction::F32Ceil => sink.f32_ceil(),
1409            Instruction::F32Floor => sink.f32_floor(),
1410            Instruction::F32Trunc => sink.f32_trunc(),
1411            Instruction::F32Nearest => sink.f32_nearest(),
1412            Instruction::F32Sqrt => sink.f32_sqrt(),
1413            Instruction::F32Add => sink.f32_add(),
1414            Instruction::F32Sub => sink.f32_sub(),
1415            Instruction::F32Mul => sink.f32_mul(),
1416            Instruction::F32Div => sink.f32_div(),
1417            Instruction::F32Min => sink.f32_min(),
1418            Instruction::F32Max => sink.f32_max(),
1419            Instruction::F32Copysign => sink.f32_copysign(),
1420            Instruction::F64Abs => sink.f64_abs(),
1421            Instruction::F64Neg => sink.f64_neg(),
1422            Instruction::F64Ceil => sink.f64_ceil(),
1423            Instruction::F64Floor => sink.f64_floor(),
1424            Instruction::F64Trunc => sink.f64_trunc(),
1425            Instruction::F64Nearest => sink.f64_nearest(),
1426            Instruction::F64Sqrt => sink.f64_sqrt(),
1427            Instruction::F64Add => sink.f64_add(),
1428            Instruction::F64Sub => sink.f64_sub(),
1429            Instruction::F64Mul => sink.f64_mul(),
1430            Instruction::F64Div => sink.f64_div(),
1431            Instruction::F64Min => sink.f64_min(),
1432            Instruction::F64Max => sink.f64_max(),
1433            Instruction::F64Copysign => sink.f64_copysign(),
1434            Instruction::I32WrapI64 => sink.i32_wrap_i64(),
1435            Instruction::I32TruncF32S => sink.i32_trunc_f32_s(),
1436            Instruction::I32TruncF32U => sink.i32_trunc_f32_u(),
1437            Instruction::I32TruncF64S => sink.i32_trunc_f64_s(),
1438            Instruction::I32TruncF64U => sink.i32_trunc_f64_u(),
1439            Instruction::I64ExtendI32S => sink.i64_extend_i32_s(),
1440            Instruction::I64ExtendI32U => sink.i64_extend_i32_u(),
1441            Instruction::I64TruncF32S => sink.i64_trunc_f32_s(),
1442            Instruction::I64TruncF32U => sink.i64_trunc_f32_u(),
1443            Instruction::I64TruncF64S => sink.i64_trunc_f64_s(),
1444            Instruction::I64TruncF64U => sink.i64_trunc_f64_u(),
1445            Instruction::F32ConvertI32S => sink.f32_convert_i32_s(),
1446            Instruction::F32ConvertI32U => sink.f32_convert_i32_u(),
1447            Instruction::F32ConvertI64S => sink.f32_convert_i64_s(),
1448            Instruction::F32ConvertI64U => sink.f32_convert_i64_u(),
1449            Instruction::F32DemoteF64 => sink.f32_demote_f64(),
1450            Instruction::F64ConvertI32S => sink.f64_convert_i32_s(),
1451            Instruction::F64ConvertI32U => sink.f64_convert_i32_u(),
1452            Instruction::F64ConvertI64S => sink.f64_convert_i64_s(),
1453            Instruction::F64ConvertI64U => sink.f64_convert_i64_u(),
1454            Instruction::F64PromoteF32 => sink.f64_promote_f32(),
1455            Instruction::I32ReinterpretF32 => sink.i32_reinterpret_f32(),
1456            Instruction::I64ReinterpretF64 => sink.i64_reinterpret_f64(),
1457            Instruction::F32ReinterpretI32 => sink.f32_reinterpret_i32(),
1458            Instruction::F64ReinterpretI64 => sink.f64_reinterpret_i64(),
1459            Instruction::I32Extend8S => sink.i32_extend8_s(),
1460            Instruction::I32Extend16S => sink.i32_extend16_s(),
1461            Instruction::I64Extend8S => sink.i64_extend8_s(),
1462            Instruction::I64Extend16S => sink.i64_extend16_s(),
1463            Instruction::I64Extend32S => sink.i64_extend32_s(),
1464
1465            Instruction::I32TruncSatF32S => sink.i32_trunc_sat_f32_s(),
1466            Instruction::I32TruncSatF32U => sink.i32_trunc_sat_f32_u(),
1467            Instruction::I32TruncSatF64S => sink.i32_trunc_sat_f64_s(),
1468            Instruction::I32TruncSatF64U => sink.i32_trunc_sat_f64_u(),
1469            Instruction::I64TruncSatF32S => sink.i64_trunc_sat_f32_s(),
1470            Instruction::I64TruncSatF32U => sink.i64_trunc_sat_f32_u(),
1471            Instruction::I64TruncSatF64S => sink.i64_trunc_sat_f64_s(),
1472            Instruction::I64TruncSatF64U => sink.i64_trunc_sat_f64_u(),
1473
1474            // Reference types instructions.
1475            Instruction::RefNull(ty) => sink.ref_null(ty),
1476            Instruction::RefIsNull => sink.ref_is_null(),
1477            Instruction::RefFunc(f) => sink.ref_func(f),
1478            Instruction::RefEq => sink.ref_eq(),
1479            Instruction::RefAsNonNull => sink.ref_as_non_null(),
1480
1481            // GC instructions.
1482            Instruction::StructNew(type_index) => sink.struct_new(type_index),
1483            Instruction::StructNewDefault(type_index) => sink.struct_new_default(type_index),
1484            Instruction::StructGet {
1485                struct_type_index,
1486                field_index,
1487            } => sink.struct_get(struct_type_index, field_index),
1488            Instruction::StructGetS {
1489                struct_type_index,
1490                field_index,
1491            } => sink.struct_get_s(struct_type_index, field_index),
1492            Instruction::StructGetU {
1493                struct_type_index,
1494                field_index,
1495            } => sink.struct_get_u(struct_type_index, field_index),
1496            Instruction::StructSet {
1497                struct_type_index,
1498                field_index,
1499            } => sink.struct_set(struct_type_index, field_index),
1500            Instruction::ArrayNew(type_index) => sink.array_new(type_index),
1501            Instruction::ArrayNewDefault(type_index) => sink.array_new_default(type_index),
1502            Instruction::ArrayNewFixed {
1503                array_type_index,
1504                array_size,
1505            } => sink.array_new_fixed(array_type_index, array_size),
1506            Instruction::ArrayNewData {
1507                array_type_index,
1508                array_data_index,
1509            } => sink.array_new_data(array_type_index, array_data_index),
1510            Instruction::ArrayNewElem {
1511                array_type_index,
1512                array_elem_index,
1513            } => sink.array_new_elem(array_type_index, array_elem_index),
1514            Instruction::ArrayGet(type_index) => sink.array_get(type_index),
1515            Instruction::ArrayGetS(type_index) => sink.array_get_s(type_index),
1516            Instruction::ArrayGetU(type_index) => sink.array_get_u(type_index),
1517            Instruction::ArraySet(type_index) => sink.array_set(type_index),
1518            Instruction::ArrayLen => sink.array_len(),
1519            Instruction::ArrayFill(type_index) => sink.array_fill(type_index),
1520            Instruction::ArrayCopy {
1521                array_type_index_dst,
1522                array_type_index_src,
1523            } => sink.array_copy(array_type_index_dst, array_type_index_src),
1524            Instruction::ArrayInitData {
1525                array_type_index,
1526                array_data_index,
1527            } => sink.array_init_data(array_type_index, array_data_index),
1528            Instruction::ArrayInitElem {
1529                array_type_index,
1530                array_elem_index,
1531            } => sink.array_init_elem(array_type_index, array_elem_index),
1532            Instruction::RefTestNonNull(heap_type) => sink.ref_test_non_null(heap_type),
1533            Instruction::RefTestNullable(heap_type) => sink.ref_test_nullable(heap_type),
1534            Instruction::RefCastNonNull(heap_type) => sink.ref_cast_non_null(heap_type),
1535            Instruction::RefCastNullable(heap_type) => sink.ref_cast_nullable(heap_type),
1536            Instruction::BrOnCast {
1537                relative_depth,
1538                from_ref_type,
1539                to_ref_type,
1540            } => sink.br_on_cast(relative_depth, from_ref_type, to_ref_type),
1541            Instruction::BrOnCastFail {
1542                relative_depth,
1543                from_ref_type,
1544                to_ref_type,
1545            } => sink.br_on_cast_fail(relative_depth, from_ref_type, to_ref_type),
1546            Instruction::AnyConvertExtern => sink.any_convert_extern(),
1547            Instruction::ExternConvertAny => sink.extern_convert_any(),
1548            Instruction::RefI31 => sink.ref_i31(),
1549            Instruction::I31GetS => sink.i31_get_s(),
1550            Instruction::I31GetU => sink.i31_get_u(),
1551
1552            // Bulk memory instructions.
1553            Instruction::TableInit { elem_index, table } => sink.table_init(table, elem_index),
1554            Instruction::ElemDrop(segment) => sink.elem_drop(segment),
1555            Instruction::TableCopy {
1556                src_table,
1557                dst_table,
1558            } => sink.table_copy(dst_table, src_table),
1559            Instruction::TableGrow(table) => sink.table_grow(table),
1560            Instruction::TableSize(table) => sink.table_size(table),
1561            Instruction::TableFill(table) => sink.table_fill(table),
1562
1563            // SIMD instructions.
1564            Instruction::V128Load(memarg) => sink.v128_load(memarg),
1565            Instruction::V128Load8x8S(memarg) => sink.v128_load8x8_s(memarg),
1566            Instruction::V128Load8x8U(memarg) => sink.v128_load8x8_u(memarg),
1567            Instruction::V128Load16x4S(memarg) => sink.v128_load16x4_s(memarg),
1568            Instruction::V128Load16x4U(memarg) => sink.v128_load16x4_u(memarg),
1569            Instruction::V128Load32x2S(memarg) => sink.v128_load32x2_s(memarg),
1570            Instruction::V128Load32x2U(memarg) => sink.v128_load32x2_u(memarg),
1571            Instruction::V128Load8Splat(memarg) => sink.v128_load8_splat(memarg),
1572            Instruction::V128Load16Splat(memarg) => sink.v128_load16_splat(memarg),
1573            Instruction::V128Load32Splat(memarg) => sink.v128_load32_splat(memarg),
1574            Instruction::V128Load64Splat(memarg) => sink.v128_load64_splat(memarg),
1575            Instruction::V128Store(memarg) => sink.v128_store(memarg),
1576            Instruction::V128Const(x) => sink.v128_const(x),
1577            Instruction::I8x16Shuffle(lanes) => sink.i8x16_shuffle(lanes),
1578            Instruction::I8x16Swizzle => sink.i8x16_swizzle(),
1579            Instruction::I8x16Splat => sink.i8x16_splat(),
1580            Instruction::I16x8Splat => sink.i16x8_splat(),
1581            Instruction::I32x4Splat => sink.i32x4_splat(),
1582            Instruction::I64x2Splat => sink.i64x2_splat(),
1583            Instruction::F32x4Splat => sink.f32x4_splat(),
1584            Instruction::F64x2Splat => sink.f64x2_splat(),
1585            Instruction::I8x16ExtractLaneS(lane) => sink.i8x16_extract_lane_s(lane),
1586            Instruction::I8x16ExtractLaneU(lane) => sink.i8x16_extract_lane_u(lane),
1587            Instruction::I8x16ReplaceLane(lane) => sink.i8x16_replace_lane(lane),
1588            Instruction::I16x8ExtractLaneS(lane) => sink.i16x8_extract_lane_s(lane),
1589            Instruction::I16x8ExtractLaneU(lane) => sink.i16x8_extract_lane_u(lane),
1590            Instruction::I16x8ReplaceLane(lane) => sink.i16x8_replace_lane(lane),
1591            Instruction::I32x4ExtractLane(lane) => sink.i32x4_extract_lane(lane),
1592            Instruction::I32x4ReplaceLane(lane) => sink.i32x4_replace_lane(lane),
1593            Instruction::I64x2ExtractLane(lane) => sink.i64x2_extract_lane(lane),
1594            Instruction::I64x2ReplaceLane(lane) => sink.i64x2_replace_lane(lane),
1595            Instruction::F32x4ExtractLane(lane) => sink.f32x4_extract_lane(lane),
1596            Instruction::F32x4ReplaceLane(lane) => sink.f32x4_replace_lane(lane),
1597            Instruction::F64x2ExtractLane(lane) => sink.f64x2_extract_lane(lane),
1598            Instruction::F64x2ReplaceLane(lane) => sink.f64x2_replace_lane(lane),
1599
1600            Instruction::I8x16Eq => sink.i8x16_eq(),
1601            Instruction::I8x16Ne => sink.i8x16_ne(),
1602            Instruction::I8x16LtS => sink.i8x16_lt_s(),
1603            Instruction::I8x16LtU => sink.i8x16_lt_u(),
1604            Instruction::I8x16GtS => sink.i8x16_gt_s(),
1605            Instruction::I8x16GtU => sink.i8x16_gt_u(),
1606            Instruction::I8x16LeS => sink.i8x16_le_s(),
1607            Instruction::I8x16LeU => sink.i8x16_le_u(),
1608            Instruction::I8x16GeS => sink.i8x16_ge_s(),
1609            Instruction::I8x16GeU => sink.i8x16_ge_u(),
1610            Instruction::I16x8Eq => sink.i16x8_eq(),
1611            Instruction::I16x8Ne => sink.i16x8_ne(),
1612            Instruction::I16x8LtS => sink.i16x8_lt_s(),
1613            Instruction::I16x8LtU => sink.i16x8_lt_u(),
1614            Instruction::I16x8GtS => sink.i16x8_gt_s(),
1615            Instruction::I16x8GtU => sink.i16x8_gt_u(),
1616            Instruction::I16x8LeS => sink.i16x8_le_s(),
1617            Instruction::I16x8LeU => sink.i16x8_le_u(),
1618            Instruction::I16x8GeS => sink.i16x8_ge_s(),
1619            Instruction::I16x8GeU => sink.i16x8_ge_u(),
1620            Instruction::I32x4Eq => sink.i32x4_eq(),
1621            Instruction::I32x4Ne => sink.i32x4_ne(),
1622            Instruction::I32x4LtS => sink.i32x4_lt_s(),
1623            Instruction::I32x4LtU => sink.i32x4_lt_u(),
1624            Instruction::I32x4GtS => sink.i32x4_gt_s(),
1625            Instruction::I32x4GtU => sink.i32x4_gt_u(),
1626            Instruction::I32x4LeS => sink.i32x4_le_s(),
1627            Instruction::I32x4LeU => sink.i32x4_le_u(),
1628            Instruction::I32x4GeS => sink.i32x4_ge_s(),
1629            Instruction::I32x4GeU => sink.i32x4_ge_u(),
1630            Instruction::F32x4Eq => sink.f32x4_eq(),
1631            Instruction::F32x4Ne => sink.f32x4_ne(),
1632            Instruction::F32x4Lt => sink.f32x4_lt(),
1633            Instruction::F32x4Gt => sink.f32x4_gt(),
1634            Instruction::F32x4Le => sink.f32x4_le(),
1635            Instruction::F32x4Ge => sink.f32x4_ge(),
1636            Instruction::F64x2Eq => sink.f64x2_eq(),
1637            Instruction::F64x2Ne => sink.f64x2_ne(),
1638            Instruction::F64x2Lt => sink.f64x2_lt(),
1639            Instruction::F64x2Gt => sink.f64x2_gt(),
1640            Instruction::F64x2Le => sink.f64x2_le(),
1641            Instruction::F64x2Ge => sink.f64x2_ge(),
1642            Instruction::V128Not => sink.v128_not(),
1643            Instruction::V128And => sink.v128_and(),
1644            Instruction::V128AndNot => sink.v128_andnot(),
1645            Instruction::V128Or => sink.v128_or(),
1646            Instruction::V128Xor => sink.v128_xor(),
1647            Instruction::V128Bitselect => sink.v128_bitselect(),
1648            Instruction::V128AnyTrue => sink.v128_any_true(),
1649            Instruction::I8x16Abs => sink.i8x16_abs(),
1650            Instruction::I8x16Neg => sink.i8x16_neg(),
1651            Instruction::I8x16Popcnt => sink.i8x16_popcnt(),
1652            Instruction::I8x16AllTrue => sink.i8x16_all_true(),
1653            Instruction::I8x16Bitmask => sink.i8x16_bitmask(),
1654            Instruction::I8x16NarrowI16x8S => sink.i8x16_narrow_i16x8_s(),
1655            Instruction::I8x16NarrowI16x8U => sink.i8x16_narrow_i16x8_u(),
1656            Instruction::I8x16Shl => sink.i8x16_shl(),
1657            Instruction::I8x16ShrS => sink.i8x16_shr_s(),
1658            Instruction::I8x16ShrU => sink.i8x16_shr_u(),
1659            Instruction::I8x16Add => sink.i8x16_add(),
1660            Instruction::I8x16AddSatS => sink.i8x16_add_sat_s(),
1661            Instruction::I8x16AddSatU => sink.i8x16_add_sat_u(),
1662            Instruction::I8x16Sub => sink.i8x16_sub(),
1663            Instruction::I8x16SubSatS => sink.i8x16_sub_sat_s(),
1664            Instruction::I8x16SubSatU => sink.i8x16_sub_sat_u(),
1665            Instruction::I8x16MinS => sink.i8x16_min_s(),
1666            Instruction::I8x16MinU => sink.i8x16_min_u(),
1667            Instruction::I8x16MaxS => sink.i8x16_max_s(),
1668            Instruction::I8x16MaxU => sink.i8x16_max_u(),
1669            Instruction::I8x16AvgrU => sink.i8x16_avgr_u(),
1670            Instruction::I16x8ExtAddPairwiseI8x16S => sink.i16x8_extadd_pairwise_i8x16_s(),
1671            Instruction::I16x8ExtAddPairwiseI8x16U => sink.i16x8_extadd_pairwise_i8x16_u(),
1672            Instruction::I32x4ExtAddPairwiseI16x8S => sink.i32x4_extadd_pairwise_i16x8_s(),
1673            Instruction::I32x4ExtAddPairwiseI16x8U => sink.i32x4_extadd_pairwise_i16x8_u(),
1674            Instruction::I16x8Abs => sink.i16x8_abs(),
1675            Instruction::I16x8Neg => sink.i16x8_neg(),
1676            Instruction::I16x8Q15MulrSatS => sink.i16x8_q15mulr_sat_s(),
1677            Instruction::I16x8AllTrue => sink.i16x8_all_true(),
1678            Instruction::I16x8Bitmask => sink.i16x8_bitmask(),
1679            Instruction::I16x8NarrowI32x4S => sink.i16x8_narrow_i32x4_s(),
1680            Instruction::I16x8NarrowI32x4U => sink.i16x8_narrow_i32x4_u(),
1681            Instruction::I16x8ExtendLowI8x16S => sink.i16x8_extend_low_i8x16_s(),
1682            Instruction::I16x8ExtendHighI8x16S => sink.i16x8_extend_high_i8x16_s(),
1683            Instruction::I16x8ExtendLowI8x16U => sink.i16x8_extend_low_i8x16_u(),
1684            Instruction::I16x8ExtendHighI8x16U => sink.i16x8_extend_high_i8x16_u(),
1685            Instruction::I16x8Shl => sink.i16x8_shl(),
1686            Instruction::I16x8ShrS => sink.i16x8_shr_s(),
1687            Instruction::I16x8ShrU => sink.i16x8_shr_u(),
1688            Instruction::I16x8Add => sink.i16x8_add(),
1689            Instruction::I16x8AddSatS => sink.i16x8_add_sat_s(),
1690            Instruction::I16x8AddSatU => sink.i16x8_add_sat_u(),
1691            Instruction::I16x8Sub => sink.i16x8_sub(),
1692            Instruction::I16x8SubSatS => sink.i16x8_sub_sat_s(),
1693            Instruction::I16x8SubSatU => sink.i16x8_sub_sat_u(),
1694            Instruction::I16x8Mul => sink.i16x8_mul(),
1695            Instruction::I16x8MinS => sink.i16x8_min_s(),
1696            Instruction::I16x8MinU => sink.i16x8_min_u(),
1697            Instruction::I16x8MaxS => sink.i16x8_max_s(),
1698            Instruction::I16x8MaxU => sink.i16x8_max_u(),
1699            Instruction::I16x8AvgrU => sink.i16x8_avgr_u(),
1700            Instruction::I16x8ExtMulLowI8x16S => sink.i16x8_extmul_low_i8x16_s(),
1701            Instruction::I16x8ExtMulHighI8x16S => sink.i16x8_extmul_high_i8x16_s(),
1702            Instruction::I16x8ExtMulLowI8x16U => sink.i16x8_extmul_low_i8x16_u(),
1703            Instruction::I16x8ExtMulHighI8x16U => sink.i16x8_extmul_high_i8x16_u(),
1704            Instruction::I32x4Abs => sink.i32x4_abs(),
1705            Instruction::I32x4Neg => sink.i32x4_neg(),
1706            Instruction::I32x4AllTrue => sink.i32x4_all_true(),
1707            Instruction::I32x4Bitmask => sink.i32x4_bitmask(),
1708            Instruction::I32x4ExtendLowI16x8S => sink.i32x4_extend_low_i16x8_s(),
1709            Instruction::I32x4ExtendHighI16x8S => sink.i32x4_extend_high_i16x8_s(),
1710            Instruction::I32x4ExtendLowI16x8U => sink.i32x4_extend_low_i16x8_u(),
1711            Instruction::I32x4ExtendHighI16x8U => sink.i32x4_extend_high_i16x8_u(),
1712            Instruction::I32x4Shl => sink.i32x4_shl(),
1713            Instruction::I32x4ShrS => sink.i32x4_shr_s(),
1714            Instruction::I32x4ShrU => sink.i32x4_shr_u(),
1715            Instruction::I32x4Add => sink.i32x4_add(),
1716            Instruction::I32x4Sub => sink.i32x4_sub(),
1717            Instruction::I32x4Mul => sink.i32x4_mul(),
1718            Instruction::I32x4MinS => sink.i32x4_min_s(),
1719            Instruction::I32x4MinU => sink.i32x4_min_u(),
1720            Instruction::I32x4MaxS => sink.i32x4_max_s(),
1721            Instruction::I32x4MaxU => sink.i32x4_max_u(),
1722            Instruction::I32x4DotI16x8S => sink.i32x4_dot_i16x8_s(),
1723            Instruction::I32x4ExtMulLowI16x8S => sink.i32x4_extmul_low_i16x8_s(),
1724            Instruction::I32x4ExtMulHighI16x8S => sink.i32x4_extmul_high_i16x8_s(),
1725            Instruction::I32x4ExtMulLowI16x8U => sink.i32x4_extmul_low_i16x8_u(),
1726            Instruction::I32x4ExtMulHighI16x8U => sink.i32x4_extmul_high_i16x8_u(),
1727            Instruction::I64x2Abs => sink.i64x2_abs(),
1728            Instruction::I64x2Neg => sink.i64x2_neg(),
1729            Instruction::I64x2AllTrue => sink.i64x2_all_true(),
1730            Instruction::I64x2Bitmask => sink.i64x2_bitmask(),
1731            Instruction::I64x2ExtendLowI32x4S => sink.i64x2_extend_low_i32x4_s(),
1732            Instruction::I64x2ExtendHighI32x4S => sink.i64x2_extend_high_i32x4_s(),
1733            Instruction::I64x2ExtendLowI32x4U => sink.i64x2_extend_low_i32x4_u(),
1734            Instruction::I64x2ExtendHighI32x4U => sink.i64x2_extend_high_i32x4_u(),
1735            Instruction::I64x2Shl => sink.i64x2_shl(),
1736            Instruction::I64x2ShrS => sink.i64x2_shr_s(),
1737            Instruction::I64x2ShrU => sink.i64x2_shr_u(),
1738            Instruction::I64x2Add => sink.i64x2_add(),
1739            Instruction::I64x2Sub => sink.i64x2_sub(),
1740            Instruction::I64x2Mul => sink.i64x2_mul(),
1741            Instruction::I64x2ExtMulLowI32x4S => sink.i64x2_extmul_low_i32x4_s(),
1742            Instruction::I64x2ExtMulHighI32x4S => sink.i64x2_extmul_high_i32x4_s(),
1743            Instruction::I64x2ExtMulLowI32x4U => sink.i64x2_extmul_low_i32x4_u(),
1744            Instruction::I64x2ExtMulHighI32x4U => sink.i64x2_extmul_high_i32x4_u(),
1745            Instruction::F32x4Ceil => sink.f32x4_ceil(),
1746            Instruction::F32x4Floor => sink.f32x4_floor(),
1747            Instruction::F32x4Trunc => sink.f32x4_trunc(),
1748            Instruction::F32x4Nearest => sink.f32x4_nearest(),
1749            Instruction::F32x4Abs => sink.f32x4_abs(),
1750            Instruction::F32x4Neg => sink.f32x4_neg(),
1751            Instruction::F32x4Sqrt => sink.f32x4_sqrt(),
1752            Instruction::F32x4Add => sink.f32x4_add(),
1753            Instruction::F32x4Sub => sink.f32x4_sub(),
1754            Instruction::F32x4Mul => sink.f32x4_mul(),
1755            Instruction::F32x4Div => sink.f32x4_div(),
1756            Instruction::F32x4Min => sink.f32x4_min(),
1757            Instruction::F32x4Max => sink.f32x4_max(),
1758            Instruction::F32x4PMin => sink.f32x4_pmin(),
1759            Instruction::F32x4PMax => sink.f32x4_pmax(),
1760            Instruction::F64x2Ceil => sink.f64x2_ceil(),
1761            Instruction::F64x2Floor => sink.f64x2_floor(),
1762            Instruction::F64x2Trunc => sink.f64x2_trunc(),
1763            Instruction::F64x2Nearest => sink.f64x2_nearest(),
1764            Instruction::F64x2Abs => sink.f64x2_abs(),
1765            Instruction::F64x2Neg => sink.f64x2_neg(),
1766            Instruction::F64x2Sqrt => sink.f64x2_sqrt(),
1767            Instruction::F64x2Add => sink.f64x2_add(),
1768            Instruction::F64x2Sub => sink.f64x2_sub(),
1769            Instruction::F64x2Mul => sink.f64x2_mul(),
1770            Instruction::F64x2Div => sink.f64x2_div(),
1771            Instruction::F64x2Min => sink.f64x2_min(),
1772            Instruction::F64x2Max => sink.f64x2_max(),
1773            Instruction::F64x2PMin => sink.f64x2_pmin(),
1774            Instruction::F64x2PMax => sink.f64x2_pmax(),
1775            Instruction::I32x4TruncSatF32x4S => sink.i32x4_trunc_sat_f32x4_s(),
1776            Instruction::I32x4TruncSatF32x4U => sink.i32x4_trunc_sat_f32x4_u(),
1777            Instruction::F32x4ConvertI32x4S => sink.f32x4_convert_i32x4_s(),
1778            Instruction::F32x4ConvertI32x4U => sink.f32x4_convert_i32x4_u(),
1779            Instruction::I32x4TruncSatF64x2SZero => sink.i32x4_trunc_sat_f64x2_s_zero(),
1780            Instruction::I32x4TruncSatF64x2UZero => sink.i32x4_trunc_sat_f64x2_u_zero(),
1781            Instruction::F64x2ConvertLowI32x4S => sink.f64x2_convert_low_i32x4_s(),
1782            Instruction::F64x2ConvertLowI32x4U => sink.f64x2_convert_low_i32x4_u(),
1783            Instruction::F32x4DemoteF64x2Zero => sink.f32x4_demote_f64x2_zero(),
1784            Instruction::F64x2PromoteLowF32x4 => sink.f64x2_promote_low_f32x4(),
1785            Instruction::V128Load32Zero(memarg) => sink.v128_load32_zero(memarg),
1786            Instruction::V128Load64Zero(memarg) => sink.v128_load64_zero(memarg),
1787            Instruction::V128Load8Lane { memarg, lane } => sink.v128_load8_lane(memarg, lane),
1788            Instruction::V128Load16Lane { memarg, lane } => sink.v128_load16_lane(memarg, lane),
1789            Instruction::V128Load32Lane { memarg, lane } => sink.v128_load32_lane(memarg, lane),
1790            Instruction::V128Load64Lane { memarg, lane } => sink.v128_load64_lane(memarg, lane),
1791            Instruction::V128Store8Lane { memarg, lane } => sink.v128_store8_lane(memarg, lane),
1792            Instruction::V128Store16Lane { memarg, lane } => sink.v128_store16_lane(memarg, lane),
1793            Instruction::V128Store32Lane { memarg, lane } => sink.v128_store32_lane(memarg, lane),
1794            Instruction::V128Store64Lane { memarg, lane } => sink.v128_store64_lane(memarg, lane),
1795            Instruction::I64x2Eq => sink.i64x2_eq(),
1796            Instruction::I64x2Ne => sink.i64x2_ne(),
1797            Instruction::I64x2LtS => sink.i64x2_lt_s(),
1798            Instruction::I64x2GtS => sink.i64x2_gt_s(),
1799            Instruction::I64x2LeS => sink.i64x2_le_s(),
1800            Instruction::I64x2GeS => sink.i64x2_ge_s(),
1801            Instruction::I8x16RelaxedSwizzle => sink.i8x16_relaxed_swizzle(),
1802            Instruction::I32x4RelaxedTruncF32x4S => sink.i32x4_relaxed_trunc_f32x4_s(),
1803            Instruction::I32x4RelaxedTruncF32x4U => sink.i32x4_relaxed_trunc_f32x4_u(),
1804            Instruction::I32x4RelaxedTruncF64x2SZero => sink.i32x4_relaxed_trunc_f64x2_s_zero(),
1805            Instruction::I32x4RelaxedTruncF64x2UZero => sink.i32x4_relaxed_trunc_f64x2_u_zero(),
1806            Instruction::F32x4RelaxedMadd => sink.f32x4_relaxed_madd(),
1807            Instruction::F32x4RelaxedNmadd => sink.f32x4_relaxed_nmadd(),
1808            Instruction::F64x2RelaxedMadd => sink.f64x2_relaxed_madd(),
1809            Instruction::F64x2RelaxedNmadd => sink.f64x2_relaxed_nmadd(),
1810            Instruction::I8x16RelaxedLaneselect => sink.i8x16_relaxed_laneselect(),
1811            Instruction::I16x8RelaxedLaneselect => sink.i16x8_relaxed_laneselect(),
1812            Instruction::I32x4RelaxedLaneselect => sink.i32x4_relaxed_laneselect(),
1813            Instruction::I64x2RelaxedLaneselect => sink.i64x2_relaxed_laneselect(),
1814            Instruction::F32x4RelaxedMin => sink.f32x4_relaxed_min(),
1815            Instruction::F32x4RelaxedMax => sink.f32x4_relaxed_max(),
1816            Instruction::F64x2RelaxedMin => sink.f64x2_relaxed_min(),
1817            Instruction::F64x2RelaxedMax => sink.f64x2_relaxed_max(),
1818            Instruction::I16x8RelaxedQ15mulrS => sink.i16x8_relaxed_q15mulr_s(),
1819            Instruction::I16x8RelaxedDotI8x16I7x16S => sink.i16x8_relaxed_dot_i8x16_i7x16_s(),
1820            Instruction::I32x4RelaxedDotI8x16I7x16AddS => {
1821                sink.i32x4_relaxed_dot_i8x16_i7x16_add_s()
1822            }
1823
1824            // Atomic instructions from the thread proposal
1825            Instruction::MemoryAtomicNotify(memarg) => sink.memory_atomic_notify(memarg),
1826            Instruction::MemoryAtomicWait32(memarg) => sink.memory_atomic_wait32(memarg),
1827            Instruction::MemoryAtomicWait64(memarg) => sink.memory_atomic_wait64(memarg),
1828            Instruction::AtomicFence => sink.atomic_fence(),
1829            Instruction::I32AtomicLoad(memarg) => sink.i32_atomic_load(memarg),
1830            Instruction::I64AtomicLoad(memarg) => sink.i64_atomic_load(memarg),
1831            Instruction::I32AtomicLoad8U(memarg) => sink.i32_atomic_load8_u(memarg),
1832            Instruction::I32AtomicLoad16U(memarg) => sink.i32_atomic_load16_u(memarg),
1833            Instruction::I64AtomicLoad8U(memarg) => sink.i64_atomic_load8_u(memarg),
1834            Instruction::I64AtomicLoad16U(memarg) => sink.i64_atomic_load16_u(memarg),
1835            Instruction::I64AtomicLoad32U(memarg) => sink.i64_atomic_load32_u(memarg),
1836            Instruction::I32AtomicStore(memarg) => sink.i32_atomic_store(memarg),
1837            Instruction::I64AtomicStore(memarg) => sink.i64_atomic_store(memarg),
1838            Instruction::I32AtomicStore8(memarg) => sink.i32_atomic_store8(memarg),
1839            Instruction::I32AtomicStore16(memarg) => sink.i32_atomic_store16(memarg),
1840            Instruction::I64AtomicStore8(memarg) => sink.i64_atomic_store8(memarg),
1841            Instruction::I64AtomicStore16(memarg) => sink.i64_atomic_store16(memarg),
1842            Instruction::I64AtomicStore32(memarg) => sink.i64_atomic_store32(memarg),
1843            Instruction::I32AtomicRmwAdd(memarg) => sink.i32_atomic_rmw_add(memarg),
1844            Instruction::I64AtomicRmwAdd(memarg) => sink.i64_atomic_rmw_add(memarg),
1845            Instruction::I32AtomicRmw8AddU(memarg) => sink.i32_atomic_rmw8_add_u(memarg),
1846            Instruction::I32AtomicRmw16AddU(memarg) => sink.i32_atomic_rmw16_add_u(memarg),
1847            Instruction::I64AtomicRmw8AddU(memarg) => sink.i64_atomic_rmw8_add_u(memarg),
1848            Instruction::I64AtomicRmw16AddU(memarg) => sink.i64_atomic_rmw16_add_u(memarg),
1849            Instruction::I64AtomicRmw32AddU(memarg) => sink.i64_atomic_rmw32_add_u(memarg),
1850            Instruction::I32AtomicRmwSub(memarg) => sink.i32_atomic_rmw_sub(memarg),
1851            Instruction::I64AtomicRmwSub(memarg) => sink.i64_atomic_rmw_sub(memarg),
1852            Instruction::I32AtomicRmw8SubU(memarg) => sink.i32_atomic_rmw8_sub_u(memarg),
1853            Instruction::I32AtomicRmw16SubU(memarg) => sink.i32_atomic_rmw16_sub_u(memarg),
1854            Instruction::I64AtomicRmw8SubU(memarg) => sink.i64_atomic_rmw8_sub_u(memarg),
1855            Instruction::I64AtomicRmw16SubU(memarg) => sink.i64_atomic_rmw16_sub_u(memarg),
1856            Instruction::I64AtomicRmw32SubU(memarg) => sink.i64_atomic_rmw32_sub_u(memarg),
1857            Instruction::I32AtomicRmwAnd(memarg) => sink.i32_atomic_rmw_and(memarg),
1858            Instruction::I64AtomicRmwAnd(memarg) => sink.i64_atomic_rmw_and(memarg),
1859            Instruction::I32AtomicRmw8AndU(memarg) => sink.i32_atomic_rmw8_and_u(memarg),
1860            Instruction::I32AtomicRmw16AndU(memarg) => sink.i32_atomic_rmw16_and_u(memarg),
1861            Instruction::I64AtomicRmw8AndU(memarg) => sink.i64_atomic_rmw8_and_u(memarg),
1862            Instruction::I64AtomicRmw16AndU(memarg) => sink.i64_atomic_rmw16_and_u(memarg),
1863            Instruction::I64AtomicRmw32AndU(memarg) => sink.i64_atomic_rmw32_and_u(memarg),
1864            Instruction::I32AtomicRmwOr(memarg) => sink.i32_atomic_rmw_or(memarg),
1865            Instruction::I64AtomicRmwOr(memarg) => sink.i64_atomic_rmw_or(memarg),
1866            Instruction::I32AtomicRmw8OrU(memarg) => sink.i32_atomic_rmw8_or_u(memarg),
1867            Instruction::I32AtomicRmw16OrU(memarg) => sink.i32_atomic_rmw16_or_u(memarg),
1868            Instruction::I64AtomicRmw8OrU(memarg) => sink.i64_atomic_rmw8_or_u(memarg),
1869            Instruction::I64AtomicRmw16OrU(memarg) => sink.i64_atomic_rmw16_or_u(memarg),
1870            Instruction::I64AtomicRmw32OrU(memarg) => sink.i64_atomic_rmw32_or_u(memarg),
1871            Instruction::I32AtomicRmwXor(memarg) => sink.i32_atomic_rmw_xor(memarg),
1872            Instruction::I64AtomicRmwXor(memarg) => sink.i64_atomic_rmw_xor(memarg),
1873            Instruction::I32AtomicRmw8XorU(memarg) => sink.i32_atomic_rmw8_xor_u(memarg),
1874            Instruction::I32AtomicRmw16XorU(memarg) => sink.i32_atomic_rmw16_xor_u(memarg),
1875            Instruction::I64AtomicRmw8XorU(memarg) => sink.i64_atomic_rmw8_xor_u(memarg),
1876            Instruction::I64AtomicRmw16XorU(memarg) => sink.i64_atomic_rmw16_xor_u(memarg),
1877            Instruction::I64AtomicRmw32XorU(memarg) => sink.i64_atomic_rmw32_xor_u(memarg),
1878            Instruction::I32AtomicRmwXchg(memarg) => sink.i32_atomic_rmw_xchg(memarg),
1879            Instruction::I64AtomicRmwXchg(memarg) => sink.i64_atomic_rmw_xchg(memarg),
1880            Instruction::I32AtomicRmw8XchgU(memarg) => sink.i32_atomic_rmw8_xchg_u(memarg),
1881            Instruction::I32AtomicRmw16XchgU(memarg) => sink.i32_atomic_rmw16_xchg_u(memarg),
1882            Instruction::I64AtomicRmw8XchgU(memarg) => sink.i64_atomic_rmw8_xchg_u(memarg),
1883            Instruction::I64AtomicRmw16XchgU(memarg) => sink.i64_atomic_rmw16_xchg_u(memarg),
1884            Instruction::I64AtomicRmw32XchgU(memarg) => sink.i64_atomic_rmw32_xchg_u(memarg),
1885            Instruction::I32AtomicRmwCmpxchg(memarg) => sink.i32_atomic_rmw_cmpxchg(memarg),
1886            Instruction::I64AtomicRmwCmpxchg(memarg) => sink.i64_atomic_rmw_cmpxchg(memarg),
1887            Instruction::I32AtomicRmw8CmpxchgU(memarg) => sink.i32_atomic_rmw8_cmpxchg_u(memarg),
1888            Instruction::I32AtomicRmw16CmpxchgU(memarg) => sink.i32_atomic_rmw16_cmpxchg_u(memarg),
1889            Instruction::I64AtomicRmw8CmpxchgU(memarg) => sink.i64_atomic_rmw8_cmpxchg_u(memarg),
1890            Instruction::I64AtomicRmw16CmpxchgU(memarg) => sink.i64_atomic_rmw16_cmpxchg_u(memarg),
1891            Instruction::I64AtomicRmw32CmpxchgU(memarg) => sink.i64_atomic_rmw32_cmpxchg_u(memarg),
1892
1893            // Atomic instructions from the shared-everything-threads proposal
1894            Instruction::GlobalAtomicGet {
1895                ordering,
1896                global_index,
1897            } => sink.global_atomic_get(ordering, global_index),
1898            Instruction::GlobalAtomicSet {
1899                ordering,
1900                global_index,
1901            } => sink.global_atomic_set(ordering, global_index),
1902            Instruction::GlobalAtomicRmwAdd {
1903                ordering,
1904                global_index,
1905            } => sink.global_atomic_rmw_add(ordering, global_index),
1906            Instruction::GlobalAtomicRmwSub {
1907                ordering,
1908                global_index,
1909            } => sink.global_atomic_rmw_sub(ordering, global_index),
1910            Instruction::GlobalAtomicRmwAnd {
1911                ordering,
1912                global_index,
1913            } => sink.global_atomic_rmw_and(ordering, global_index),
1914            Instruction::GlobalAtomicRmwOr {
1915                ordering,
1916                global_index,
1917            } => sink.global_atomic_rmw_or(ordering, global_index),
1918            Instruction::GlobalAtomicRmwXor {
1919                ordering,
1920                global_index,
1921            } => sink.global_atomic_rmw_xor(ordering, global_index),
1922            Instruction::GlobalAtomicRmwXchg {
1923                ordering,
1924                global_index,
1925            } => sink.global_atomic_rmw_xchg(ordering, global_index),
1926            Instruction::GlobalAtomicRmwCmpxchg {
1927                ordering,
1928                global_index,
1929            } => sink.global_atomic_rmw_cmpxchg(ordering, global_index),
1930            Instruction::TableAtomicGet {
1931                ordering,
1932                table_index,
1933            } => sink.table_atomic_get(ordering, table_index),
1934            Instruction::TableAtomicSet {
1935                ordering,
1936                table_index,
1937            } => sink.table_atomic_set(ordering, table_index),
1938            Instruction::TableAtomicRmwXchg {
1939                ordering,
1940                table_index,
1941            } => sink.table_atomic_rmw_xchg(ordering, table_index),
1942            Instruction::TableAtomicRmwCmpxchg {
1943                ordering,
1944                table_index,
1945            } => sink.table_atomic_rmw_cmpxchg(ordering, table_index),
1946            Instruction::StructAtomicGet {
1947                ordering,
1948                struct_type_index,
1949                field_index,
1950            } => sink.struct_atomic_get(ordering, struct_type_index, field_index),
1951            Instruction::StructAtomicGetS {
1952                ordering,
1953                struct_type_index,
1954                field_index,
1955            } => sink.struct_atomic_get_s(ordering, struct_type_index, field_index),
1956            Instruction::StructAtomicGetU {
1957                ordering,
1958                struct_type_index,
1959                field_index,
1960            } => sink.struct_atomic_get_u(ordering, struct_type_index, field_index),
1961            Instruction::StructAtomicSet {
1962                ordering,
1963                struct_type_index,
1964                field_index,
1965            } => sink.struct_atomic_set(ordering, struct_type_index, field_index),
1966            Instruction::StructAtomicRmwAdd {
1967                ordering,
1968                struct_type_index,
1969                field_index,
1970            } => sink.struct_atomic_rmw_add(ordering, struct_type_index, field_index),
1971            Instruction::StructAtomicRmwSub {
1972                ordering,
1973                struct_type_index,
1974                field_index,
1975            } => sink.struct_atomic_rmw_sub(ordering, struct_type_index, field_index),
1976            Instruction::StructAtomicRmwAnd {
1977                ordering,
1978                struct_type_index,
1979                field_index,
1980            } => sink.struct_atomic_rmw_and(ordering, struct_type_index, field_index),
1981            Instruction::StructAtomicRmwOr {
1982                ordering,
1983                struct_type_index,
1984                field_index,
1985            } => sink.struct_atomic_rmw_or(ordering, struct_type_index, field_index),
1986            Instruction::StructAtomicRmwXor {
1987                ordering,
1988                struct_type_index,
1989                field_index,
1990            } => sink.struct_atomic_rmw_xor(ordering, struct_type_index, field_index),
1991            Instruction::StructAtomicRmwXchg {
1992                ordering,
1993                struct_type_index,
1994                field_index,
1995            } => sink.struct_atomic_rmw_xchg(ordering, struct_type_index, field_index),
1996            Instruction::StructAtomicRmwCmpxchg {
1997                ordering,
1998                struct_type_index,
1999                field_index,
2000            } => sink.struct_atomic_rmw_cmpxchg(ordering, struct_type_index, field_index),
2001            Instruction::ArrayAtomicGet {
2002                ordering,
2003                array_type_index,
2004            } => sink.array_atomic_get(ordering, array_type_index),
2005            Instruction::ArrayAtomicGetS {
2006                ordering,
2007                array_type_index,
2008            } => sink.array_atomic_get_s(ordering, array_type_index),
2009            Instruction::ArrayAtomicGetU {
2010                ordering,
2011                array_type_index,
2012            } => sink.array_atomic_get_u(ordering, array_type_index),
2013            Instruction::ArrayAtomicSet {
2014                ordering,
2015                array_type_index,
2016            } => sink.array_atomic_set(ordering, array_type_index),
2017            Instruction::ArrayAtomicRmwAdd {
2018                ordering,
2019                array_type_index,
2020            } => sink.array_atomic_rmw_add(ordering, array_type_index),
2021            Instruction::ArrayAtomicRmwSub {
2022                ordering,
2023                array_type_index,
2024            } => sink.array_atomic_rmw_sub(ordering, array_type_index),
2025            Instruction::ArrayAtomicRmwAnd {
2026                ordering,
2027                array_type_index,
2028            } => sink.array_atomic_rmw_and(ordering, array_type_index),
2029            Instruction::ArrayAtomicRmwOr {
2030                ordering,
2031                array_type_index,
2032            } => sink.array_atomic_rmw_or(ordering, array_type_index),
2033            Instruction::ArrayAtomicRmwXor {
2034                ordering,
2035                array_type_index,
2036            } => sink.array_atomic_rmw_xor(ordering, array_type_index),
2037            Instruction::ArrayAtomicRmwXchg {
2038                ordering,
2039                array_type_index,
2040            } => sink.array_atomic_rmw_xchg(ordering, array_type_index),
2041            Instruction::ArrayAtomicRmwCmpxchg {
2042                ordering,
2043                array_type_index,
2044            } => sink.array_atomic_rmw_cmpxchg(ordering, array_type_index),
2045            Instruction::RefI31Shared => sink.ref_i31_shared(),
2046            Instruction::ContNew(type_index) => sink.cont_new(type_index),
2047            Instruction::ContBind {
2048                argument_index,
2049                result_index,
2050            } => sink.cont_bind(argument_index, result_index),
2051            Instruction::Suspend(tag_index) => sink.suspend(tag_index),
2052            Instruction::Resume {
2053                cont_type_index,
2054                ref resume_table,
2055            } => sink.resume(cont_type_index, resume_table.iter().cloned()),
2056            Instruction::ResumeThrow {
2057                cont_type_index,
2058                tag_index,
2059                ref resume_table,
2060            } => sink.resume_throw(cont_type_index, tag_index, resume_table.iter().cloned()),
2061            Instruction::Switch {
2062                cont_type_index,
2063                tag_index,
2064            } => sink.switch(cont_type_index, tag_index),
2065            Instruction::I64Add128 => sink.i64_add128(),
2066            Instruction::I64Sub128 => sink.i64_sub128(),
2067            Instruction::I64MulWideS => sink.i64_mul_wide_s(),
2068            Instruction::I64MulWideU => sink.i64_mul_wide_u(),
2069        };
2070    }
2071}
2072
2073#[derive(Clone, Debug)]
2074#[allow(missing_docs)]
2075pub enum Catch {
2076    One { tag: u32, label: u32 },
2077    OneRef { tag: u32, label: u32 },
2078    All { label: u32 },
2079    AllRef { label: u32 },
2080}
2081
2082impl Encode for Catch {
2083    fn encode(&self, sink: &mut Vec<u8>) {
2084        match self {
2085            Catch::One { tag, label } => {
2086                sink.push(0x00);
2087                tag.encode(sink);
2088                label.encode(sink);
2089            }
2090            Catch::OneRef { tag, label } => {
2091                sink.push(0x01);
2092                tag.encode(sink);
2093                label.encode(sink);
2094            }
2095            Catch::All { label } => {
2096                sink.push(0x02);
2097                label.encode(sink);
2098            }
2099            Catch::AllRef { label } => {
2100                sink.push(0x03);
2101                label.encode(sink);
2102            }
2103        }
2104    }
2105}
2106
2107#[derive(Clone, Debug)]
2108#[allow(missing_docs)]
2109pub enum Handle {
2110    OnLabel { tag: u32, label: u32 },
2111    OnSwitch { tag: u32 },
2112}
2113
2114impl Encode for Handle {
2115    fn encode(&self, sink: &mut Vec<u8>) {
2116        match self {
2117            Handle::OnLabel { tag, label } => {
2118                sink.push(0x00);
2119                tag.encode(sink);
2120                label.encode(sink);
2121            }
2122            Handle::OnSwitch { tag } => {
2123                sink.push(0x01);
2124                tag.encode(sink);
2125            }
2126        }
2127    }
2128}
2129
2130/// A constant expression.
2131///
2132/// Usable in contexts such as offsets or initializers.
2133#[derive(Clone, Debug)]
2134pub struct ConstExpr {
2135    bytes: Vec<u8>,
2136}
2137
2138impl ConstExpr {
2139    /// Create a new empty constant expression builder.
2140    pub fn empty() -> Self {
2141        Self { bytes: Vec::new() }
2142    }
2143
2144    /// Create a constant expression with the specified raw encoding of instructions.
2145    pub fn raw(bytes: impl IntoIterator<Item = u8>) -> Self {
2146        Self {
2147            bytes: bytes.into_iter().collect(),
2148        }
2149    }
2150
2151    /// Create a constant expression with the sequence of instructions
2152    pub fn extended<'a>(insns: impl IntoIterator<Item = Instruction<'a>>) -> Self {
2153        let mut bytes = vec![];
2154        for insn in insns {
2155            insn.encode(&mut bytes);
2156        }
2157        Self { bytes }
2158    }
2159
2160    fn new(f: impl FnOnce(&mut InstructionSink)) -> Self {
2161        let mut bytes = vec![];
2162        f(&mut InstructionSink::new(&mut bytes));
2163        Self { bytes }
2164    }
2165
2166    fn with(mut self, f: impl FnOnce(&mut InstructionSink)) -> Self {
2167        f(&mut InstructionSink::new(&mut self.bytes));
2168        self
2169    }
2170
2171    /// Create a constant expression containing a single `global.get` instruction.
2172    pub fn global_get(index: u32) -> Self {
2173        Self::new(|insn| {
2174            insn.global_get(index);
2175        })
2176    }
2177
2178    /// Create a constant expression containing a single `ref.null` instruction.
2179    pub fn ref_null(ty: HeapType) -> Self {
2180        Self::new(|insn| {
2181            insn.ref_null(ty);
2182        })
2183    }
2184
2185    /// Create a constant expression containing a single `ref.func` instruction.
2186    pub fn ref_func(func: u32) -> Self {
2187        Self::new(|insn| {
2188            insn.ref_func(func);
2189        })
2190    }
2191
2192    /// Create a constant expression containing a single `i32.const` instruction.
2193    pub fn i32_const(value: i32) -> Self {
2194        Self::new(|insn| {
2195            insn.i32_const(value);
2196        })
2197    }
2198
2199    /// Create a constant expression containing a single `i64.const` instruction.
2200    pub fn i64_const(value: i64) -> Self {
2201        Self::new(|insn| {
2202            insn.i64_const(value);
2203        })
2204    }
2205
2206    /// Create a constant expression containing a single `f32.const` instruction.
2207    pub fn f32_const(value: f32) -> Self {
2208        Self::new(|insn| {
2209            insn.f32_const(value);
2210        })
2211    }
2212
2213    /// Create a constant expression containing a single `f64.const` instruction.
2214    pub fn f64_const(value: f64) -> Self {
2215        Self::new(|insn| {
2216            insn.f64_const(value);
2217        })
2218    }
2219
2220    /// Create a constant expression containing a single `v128.const` instruction.
2221    pub fn v128_const(value: i128) -> Self {
2222        Self::new(|insn| {
2223            insn.v128_const(value);
2224        })
2225    }
2226
2227    /// Add a `global.get` instruction to this constant expression.
2228    pub fn with_global_get(self, index: u32) -> Self {
2229        self.with(|insn| {
2230            insn.global_get(index);
2231        })
2232    }
2233
2234    /// Add a `ref.null` instruction to this constant expression.
2235    pub fn with_ref_null(self, ty: HeapType) -> Self {
2236        self.with(|insn| {
2237            insn.ref_null(ty);
2238        })
2239    }
2240
2241    /// Add a `ref.func` instruction to this constant expression.
2242    pub fn with_ref_func(self, func: u32) -> Self {
2243        self.with(|insn| {
2244            insn.ref_func(func);
2245        })
2246    }
2247
2248    /// Add an `i32.const` instruction to this constant expression.
2249    pub fn with_i32_const(self, value: i32) -> Self {
2250        self.with(|insn| {
2251            insn.i32_const(value);
2252        })
2253    }
2254
2255    /// Add an `i64.const` instruction to this constant expression.
2256    pub fn with_i64_const(self, value: i64) -> Self {
2257        self.with(|insn| {
2258            insn.i64_const(value);
2259        })
2260    }
2261
2262    /// Add a `f32.const` instruction to this constant expression.
2263    pub fn with_f32_const(self, value: f32) -> Self {
2264        self.with(|insn| {
2265            insn.f32_const(value);
2266        })
2267    }
2268
2269    /// Add a `f64.const` instruction to this constant expression.
2270    pub fn with_f64_const(self, value: f64) -> Self {
2271        self.with(|insn| {
2272            insn.f64_const(value);
2273        })
2274    }
2275
2276    /// Add a `v128.const` instruction to this constant expression.
2277    pub fn with_v128_const(self, value: i128) -> Self {
2278        self.with(|insn| {
2279            insn.v128_const(value);
2280        })
2281    }
2282
2283    /// Add an `i32.add` instruction to this constant expression.
2284    pub fn with_i32_add(self) -> Self {
2285        self.with(|insn| {
2286            insn.i32_add();
2287        })
2288    }
2289
2290    /// Add an `i32.sub` instruction to this constant expression.
2291    pub fn with_i32_sub(self) -> Self {
2292        self.with(|insn| {
2293            insn.i32_sub();
2294        })
2295    }
2296
2297    /// Add an `i32.mul` instruction to this constant expression.
2298    pub fn with_i32_mul(self) -> Self {
2299        self.with(|insn| {
2300            insn.i32_mul();
2301        })
2302    }
2303
2304    /// Add an `i64.add` instruction to this constant expression.
2305    pub fn with_i64_add(self) -> Self {
2306        self.with(|insn| {
2307            insn.i64_add();
2308        })
2309    }
2310
2311    /// Add an `i64.sub` instruction to this constant expression.
2312    pub fn with_i64_sub(self) -> Self {
2313        self.with(|insn| {
2314            insn.i64_sub();
2315        })
2316    }
2317
2318    /// Add an `i64.mul` instruction to this constant expression.
2319    pub fn with_i64_mul(self) -> Self {
2320        self.with(|insn| {
2321            insn.i64_mul();
2322        })
2323    }
2324
2325    /// Returns the function, if any, referenced by this global.
2326    pub fn get_ref_func(&self) -> Option<u32> {
2327        let prefix = *self.bytes.get(0)?;
2328        // 0xd2 == `ref.func` opcode, and if that's found then load the leb
2329        // corresponding to the function index.
2330        if prefix != 0xd2 {
2331            return None;
2332        }
2333        leb128fmt::decode_uint_slice::<u32, 32>(&self.bytes[1..], &mut 0).ok()
2334    }
2335}
2336
2337impl Encode for ConstExpr {
2338    fn encode(&self, sink: &mut Vec<u8>) {
2339        sink.extend(&self.bytes);
2340        InstructionSink::new(sink).end();
2341    }
2342}
2343
2344#[cfg(test)]
2345mod tests {
2346    #[test]
2347    fn function_new_with_locals_test() {
2348        use super::*;
2349
2350        // Test the algorithm for conversion is correct
2351        let f1 = Function::new_with_locals_types([
2352            ValType::I32,
2353            ValType::I32,
2354            ValType::I64,
2355            ValType::F32,
2356            ValType::F32,
2357            ValType::F32,
2358            ValType::I32,
2359            ValType::I64,
2360            ValType::I64,
2361        ]);
2362        let f2 = Function::new([
2363            (2, ValType::I32),
2364            (1, ValType::I64),
2365            (3, ValType::F32),
2366            (1, ValType::I32),
2367            (2, ValType::I64),
2368        ]);
2369
2370        assert_eq!(f1.bytes, f2.bytes)
2371    }
2372
2373    #[test]
2374    fn func_raw_bytes() {
2375        use super::*;
2376
2377        let mut f = Function::new([(1, ValType::I32), (1, ValType::F32)]);
2378        f.instructions().end();
2379        let mut code_from_func = CodeSection::new();
2380        code_from_func.function(&f);
2381        let bytes = f.into_raw_body();
2382        let mut code_from_raw = CodeSection::new();
2383        code_from_raw.raw(&bytes[..]);
2384
2385        let mut c1 = vec![];
2386        code_from_func.encode(&mut c1);
2387        let mut c2 = vec![];
2388        code_from_raw.encode(&mut c2);
2389        assert_eq!(c1, c2);
2390    }
2391}