susywasmi/
isa.rs

1//! An instruction set used by susywasmi.
2//!
3//! The instruction set is mostly derived from Wasm. However,
4//! there is a substantial difference.
5//!
6//! # Structured Stack Machine vs Plain One
7//!
8//! Wasm is a structured stack machine. Wasm encodes control flow in structures
9//! similar to that commonly found in a programming languages
10//! such as if, while. That contrasts to a plain stack machine which
11//!  encodes all control flow with goto-like instructions.
12//!
13//! Structured stack machine code aligns well with goals of Wasm,
14//! namely providing fast validation of Wasm code and compilation to native code.
15//!
16//! Unfortunately, the downside of structured stack machine code is
17//! that it is less convenient to interpret. For example, let's look at
18//! the following example in hypothetical structured stack machine:
19//!
20//! ```plain
21//! loop
22//!   ...
23//!   if_true_jump_to_end
24//!   ...
25//! end
26//! ```
27//!
28//! To execute `if_true_jump_to_end` , the interpreter needs to skip all instructions
29//! until it reaches the *matching* `end`. That's quite inefficient compared
30//! to a plain goto to the specific position.
31//!
32//! Because of this, the translation from the Wasm structured stack machine into a
33//! plain one is taking place.
34//!
35//! # Locals
36//!
37//! In a plain stack machine local variables and arguments live on the stack. Instead of
38//! accessing predefined locals slots in a plain stack machine locals are addressed relative
39//! to the current stack pointer. Because of this instead of taking an index of a local
40//! in {get,set,tee}_local operations, they take a relative depth as immediate. This works
41//! because at each instruction we always know the current stack height.
42//!
43//! Roughly, the stack layout looks like this
44//!
45//! | caller arguments |
46//! |  - arg 1         |
47//! |  - arg 2         |
48//! +------------------+
49//! | callee locals    |
50//! |  - var 1         |
51//! |  - var 2         |
52//! +------------------+
53//! | operands         |
54//! |  - op 1          |
55//! |  - op 2          |
56//! |                  |  <-- current stack pointer
57//! +------------------+
58//!
59//! # Differences from Wasm
60//!
61//! - There is no `nop` instruction.
62//! - All control flow structures are flattened to plain gotos.
63//! - Implicit returns via reaching function scope `End` are replaced with an explicit `return` instruction.
64//! - Locals live on the value stack now.
65//! - Load/store instructions doesn't take `align` parameter.
66//! - *.const store value in straight encoding.
67//! - Reserved immediates are ignored for `call_indirect`, `current_memory`, `grow_memory`.
68//!
69
70#[allow(unused_imports)]
71use alloc::prelude::v1::*;
72
73/// Should we keep a value before "discarding" a stack frame?
74///
75/// Note that this is a `enum` since Wasm doesn't support multiple return
76/// values at the moment.
77#[derive(Copy, Clone, Debug, PartialEq, Eq)]
78pub enum Keep {
79    None,
80    /// Pop one value from the yet-to-be-discarded stack frame to the
81    /// current stack frame.
82    Single,
83}
84
85impl Keep {
86    /// Reutrns a number of items that should be kept on the stack.
87    pub fn count(&self) -> u32 {
88        match *self {
89            Keep::None => 0,
90            Keep::Single => 1,
91        }
92    }
93}
94
95/// Specifies how many values we should keep and how many we should drop.
96#[derive(Copy, Clone, Debug, PartialEq, Eq)]
97pub struct DropKeep {
98    pub drop: u32,
99    pub keep: Keep,
100}
101
102#[derive(Copy, Clone, Debug, PartialEq, Eq)]
103pub struct Target {
104    pub dst_pc: u32,
105    pub drop_keep: DropKeep,
106}
107
108/// A relocation entry that specifies.
109#[derive(Copy, Clone, Debug, PartialEq, Eq)]
110pub enum Reloc {
111    /// Patch the destination of the branch instruction (br, br_eqz, br_nez)
112    /// at the specified pc.
113    Br { pc: u32 },
114    /// Patch the specified destination index inside of br_table instruction at
115    /// the specified pc.
116    BrTable { pc: u32, idx: usize },
117}
118
119#[derive(Copy, Clone, Debug, PartialEq, Eq)]
120pub struct BrTargets<'a> {
121    stream: &'a [InstructionInternal],
122}
123
124impl<'a> BrTargets<'a> {
125    pub(crate) fn from_internal(targets: &'a [InstructionInternal]) -> Self {
126        BrTargets { stream: targets }
127    }
128
129    #[inline]
130    pub fn get(&self, index: u32) -> Target {
131        match self.stream[index.min(self.stream.len() as u32 - 1) as usize] {
132            InstructionInternal::BrTableTarget(target) => target,
133            _ => panic!("BrTable has incorrect target count"),
134        }
135    }
136}
137
138/// The main interpreted instruction type. This is what is returned by `InstructionIter`, but
139/// it is not what is stored internally. For that, see `InstructionInternal`.
140#[derive(Debug, Clone, PartialEq)]
141pub enum Instruction<'a> {
142    /// Push a local variable or an argument from the specified depth.
143    GetLocal(u32),
144
145    /// Pop a value and put it in at the specified depth.
146    SetLocal(u32),
147
148    /// Copy a value to the specified depth.
149    TeeLocal(u32),
150
151    /// Similar to the Wasm ones, but instead of a label depth
152    /// they specify direct PC.
153    Br(Target),
154    BrIfEqz(Target),
155    BrIfNez(Target),
156
157    /// br_table [t1 t2 t3 .. tn] tdefault
158    ///
159    /// Pops the value from the stack. Then this value is used as an index
160    /// to the branch table.
161    ///
162    /// However, the last target represents the default target. So if the index
163    /// is greater than length of the branch table, then the last index will be used.
164    ///
165    /// Validation ensures that there should be at least one target.
166    BrTable(BrTargets<'a>),
167
168    Unreachable,
169    Return(DropKeep),
170
171    Call(u32),
172    CallIndirect(u32),
173
174    Drop,
175    Select,
176
177    GetGlobal(u32),
178    SetGlobal(u32),
179
180    I32Load(u32),
181    I64Load(u32),
182    F32Load(u32),
183    F64Load(u32),
184    I32Load8S(u32),
185    I32Load8U(u32),
186    I32Load16S(u32),
187    I32Load16U(u32),
188    I64Load8S(u32),
189    I64Load8U(u32),
190    I64Load16S(u32),
191    I64Load16U(u32),
192    I64Load32S(u32),
193    I64Load32U(u32),
194    I32Store(u32),
195    I64Store(u32),
196    F32Store(u32),
197    F64Store(u32),
198    I32Store8(u32),
199    I32Store16(u32),
200    I64Store8(u32),
201    I64Store16(u32),
202    I64Store32(u32),
203
204    CurrentMemory,
205    GrowMemory,
206
207    I32Const(i32),
208    I64Const(i64),
209    F32Const(u32),
210    F64Const(u64),
211
212    I32Eqz,
213    I32Eq,
214    I32Ne,
215    I32LtS,
216    I32LtU,
217    I32GtS,
218    I32GtU,
219    I32LeS,
220    I32LeU,
221    I32GeS,
222    I32GeU,
223
224    I64Eqz,
225    I64Eq,
226    I64Ne,
227    I64LtS,
228    I64LtU,
229    I64GtS,
230    I64GtU,
231    I64LeS,
232    I64LeU,
233    I64GeS,
234    I64GeU,
235
236    F32Eq,
237    F32Ne,
238    F32Lt,
239    F32Gt,
240    F32Le,
241    F32Ge,
242
243    F64Eq,
244    F64Ne,
245    F64Lt,
246    F64Gt,
247    F64Le,
248    F64Ge,
249
250    I32Clz,
251    I32Ctz,
252    I32Popcnt,
253    I32Add,
254    I32Sub,
255    I32Mul,
256    I32DivS,
257    I32DivU,
258    I32RemS,
259    I32RemU,
260    I32And,
261    I32Or,
262    I32Xor,
263    I32Shl,
264    I32ShrS,
265    I32ShrU,
266    I32Rotl,
267    I32Rotr,
268
269    I64Clz,
270    I64Ctz,
271    I64Popcnt,
272    I64Add,
273    I64Sub,
274    I64Mul,
275    I64DivS,
276    I64DivU,
277    I64RemS,
278    I64RemU,
279    I64And,
280    I64Or,
281    I64Xor,
282    I64Shl,
283    I64ShrS,
284    I64ShrU,
285    I64Rotl,
286    I64Rotr,
287    F32Abs,
288    F32Neg,
289    F32Ceil,
290    F32Floor,
291    F32Trunc,
292    F32Nearest,
293    F32Sqrt,
294    F32Add,
295    F32Sub,
296    F32Mul,
297    F32Div,
298    F32Min,
299    F32Max,
300    F32Copysign,
301    F64Abs,
302    F64Neg,
303    F64Ceil,
304    F64Floor,
305    F64Trunc,
306    F64Nearest,
307    F64Sqrt,
308    F64Add,
309    F64Sub,
310    F64Mul,
311    F64Div,
312    F64Min,
313    F64Max,
314    F64Copysign,
315
316    I32WrapI64,
317    I32TruncSF32,
318    I32TruncUF32,
319    I32TruncSF64,
320    I32TruncUF64,
321    I64ExtendSI32,
322    I64ExtendUI32,
323    I64TruncSF32,
324    I64TruncUF32,
325    I64TruncSF64,
326    I64TruncUF64,
327    F32ConvertSI32,
328    F32ConvertUI32,
329    F32ConvertSI64,
330    F32ConvertUI64,
331    F32DemoteF64,
332    F64ConvertSI32,
333    F64ConvertUI32,
334    F64ConvertSI64,
335    F64ConvertUI64,
336    F64PromoteF32,
337
338    I32ReinterpretF32,
339    I64ReinterpretF64,
340    F32ReinterpretI32,
341    F64ReinterpretI64,
342}
343
344/// The internally-stored instruction type. This differs from `Instruction` in that the `BrTable`
345/// target list is "unrolled" into seperate instructions in order to be able to A) improve cache
346/// usage and B) allow this struct to be `Copy` and therefore allow `Instructions::clone` to be
347/// a `memcpy`. It also means that `Instructions::drop` is trivial. The overall speedup on some
348/// benchmarks is as high as 13%.
349///
350/// When returning instructions we convert to `Instruction`, whose `BrTable` variant internally
351/// borrows the list of instructions and returns targets by reading it.
352#[derive(Copy, Debug, Clone, PartialEq, Eq)]
353pub(crate) enum InstructionInternal {
354    GetLocal(u32),
355    SetLocal(u32),
356    TeeLocal(u32),
357    Br(Target),
358    BrIfEqz(Target),
359    BrIfNez(Target),
360    BrTable { count: u32 },
361    BrTableTarget(Target),
362
363    Unreachable,
364    Return(DropKeep),
365
366    Call(u32),
367    CallIndirect(u32),
368
369    Drop,
370    Select,
371
372    GetGlobal(u32),
373    SetGlobal(u32),
374
375    I32Load(u32),
376    I64Load(u32),
377    F32Load(u32),
378    F64Load(u32),
379    I32Load8S(u32),
380    I32Load8U(u32),
381    I32Load16S(u32),
382    I32Load16U(u32),
383    I64Load8S(u32),
384    I64Load8U(u32),
385    I64Load16S(u32),
386    I64Load16U(u32),
387    I64Load32S(u32),
388    I64Load32U(u32),
389    I32Store(u32),
390    I64Store(u32),
391    F32Store(u32),
392    F64Store(u32),
393    I32Store8(u32),
394    I32Store16(u32),
395    I64Store8(u32),
396    I64Store16(u32),
397    I64Store32(u32),
398
399    CurrentMemory,
400    GrowMemory,
401
402    I32Const(i32),
403    I64Const(i64),
404    F32Const(u32),
405    F64Const(u64),
406
407    I32Eqz,
408    I32Eq,
409    I32Ne,
410    I32LtS,
411    I32LtU,
412    I32GtS,
413    I32GtU,
414    I32LeS,
415    I32LeU,
416    I32GeS,
417    I32GeU,
418
419    I64Eqz,
420    I64Eq,
421    I64Ne,
422    I64LtS,
423    I64LtU,
424    I64GtS,
425    I64GtU,
426    I64LeS,
427    I64LeU,
428    I64GeS,
429    I64GeU,
430
431    F32Eq,
432    F32Ne,
433    F32Lt,
434    F32Gt,
435    F32Le,
436    F32Ge,
437
438    F64Eq,
439    F64Ne,
440    F64Lt,
441    F64Gt,
442    F64Le,
443    F64Ge,
444
445    I32Clz,
446    I32Ctz,
447    I32Popcnt,
448    I32Add,
449    I32Sub,
450    I32Mul,
451    I32DivS,
452    I32DivU,
453    I32RemS,
454    I32RemU,
455    I32And,
456    I32Or,
457    I32Xor,
458    I32Shl,
459    I32ShrS,
460    I32ShrU,
461    I32Rotl,
462    I32Rotr,
463
464    I64Clz,
465    I64Ctz,
466    I64Popcnt,
467    I64Add,
468    I64Sub,
469    I64Mul,
470    I64DivS,
471    I64DivU,
472    I64RemS,
473    I64RemU,
474    I64And,
475    I64Or,
476    I64Xor,
477    I64Shl,
478    I64ShrS,
479    I64ShrU,
480    I64Rotl,
481    I64Rotr,
482    F32Abs,
483    F32Neg,
484    F32Ceil,
485    F32Floor,
486    F32Trunc,
487    F32Nearest,
488    F32Sqrt,
489    F32Add,
490    F32Sub,
491    F32Mul,
492    F32Div,
493    F32Min,
494    F32Max,
495    F32Copysign,
496    F64Abs,
497    F64Neg,
498    F64Ceil,
499    F64Floor,
500    F64Trunc,
501    F64Nearest,
502    F64Sqrt,
503    F64Add,
504    F64Sub,
505    F64Mul,
506    F64Div,
507    F64Min,
508    F64Max,
509    F64Copysign,
510
511    I32WrapI64,
512    I32TruncSF32,
513    I32TruncUF32,
514    I32TruncSF64,
515    I32TruncUF64,
516    I64ExtendSI32,
517    I64ExtendUI32,
518    I64TruncSF32,
519    I64TruncUF32,
520    I64TruncSF64,
521    I64TruncUF64,
522    F32ConvertSI32,
523    F32ConvertUI32,
524    F32ConvertSI64,
525    F32ConvertUI64,
526    F32DemoteF64,
527    F64ConvertSI32,
528    F64ConvertUI32,
529    F64ConvertSI64,
530    F64ConvertUI64,
531    F64PromoteF32,
532
533    I32ReinterpretF32,
534    I64ReinterpretF64,
535    F32ReinterpretI32,
536    F64ReinterpretI64,
537}
538
539#[derive(Debug, Clone)]
540pub struct Instructions {
541    vec: Vec<InstructionInternal>,
542}
543
544impl Instructions {
545    pub fn with_capacity(capacity: usize) -> Self {
546        Instructions {
547            vec: Vec::with_capacity(capacity),
548        }
549    }
550
551    pub fn current_pc(&self) -> u32 {
552        self.vec.len() as u32
553    }
554
555    pub(crate) fn push(&mut self, instruction: InstructionInternal) {
556        self.vec.push(instruction);
557    }
558
559    pub fn patch_relocation(&mut self, reloc: Reloc, dst_pc: u32) {
560        match reloc {
561            Reloc::Br { pc } => match self.vec[pc as usize] {
562                InstructionInternal::Br(ref mut target)
563                | InstructionInternal::BrIfEqz(ref mut target)
564                | InstructionInternal::BrIfNez(ref mut target) => target.dst_pc = dst_pc,
565                _ => panic!("branch relocation points to a non-branch instruction"),
566            },
567            Reloc::BrTable { pc, idx } => match &mut self.vec[pc as usize + idx + 1] {
568                InstructionInternal::BrTableTarget(target) => target.dst_pc = dst_pc,
569                _ => panic!("brtable relocation points to not brtable instruction"),
570            },
571        }
572    }
573
574    pub fn iterate_from(&self, position: u32) -> InstructionIter {
575        InstructionIter {
576            instructions: &self.vec,
577            position,
578        }
579    }
580}
581
582pub struct InstructionIter<'a> {
583    instructions: &'a [InstructionInternal],
584    position: u32,
585}
586
587impl<'a> InstructionIter<'a> {
588    #[inline]
589    pub fn position(&self) -> u32 {
590        self.position
591    }
592}
593
594impl<'a> Iterator for InstructionIter<'a> {
595    type Item = Instruction<'a>;
596
597    #[inline]
598    fn next(&mut self) -> Option<Self::Item> {
599        let internal = if let Some(i) = self.instructions.get(self.position as usize) {
600            i
601        } else {
602            return None;
603        };
604
605        let out = match *internal {
606            InstructionInternal::GetLocal(x) => Instruction::GetLocal(x),
607            InstructionInternal::SetLocal(x) => Instruction::SetLocal(x),
608            InstructionInternal::TeeLocal(x) => Instruction::TeeLocal(x),
609            InstructionInternal::Br(x) => Instruction::Br(x),
610            InstructionInternal::BrIfEqz(x) => Instruction::BrIfEqz(x),
611            InstructionInternal::BrIfNez(x) => Instruction::BrIfNez(x),
612            InstructionInternal::BrTable { count } => {
613                let start = self.position as usize + 1;
614
615                self.position += count;
616
617                Instruction::BrTable(BrTargets::from_internal(
618                    &self.instructions[start..start + count as usize],
619                ))
620            }
621            InstructionInternal::BrTableTarget(_) => panic!("Executed BrTableTarget"),
622
623            InstructionInternal::Unreachable => Instruction::Unreachable,
624            InstructionInternal::Return(x) => Instruction::Return(x),
625
626            InstructionInternal::Call(x) => Instruction::Call(x),
627            InstructionInternal::CallIndirect(x) => Instruction::CallIndirect(x),
628
629            InstructionInternal::Drop => Instruction::Drop,
630            InstructionInternal::Select => Instruction::Select,
631
632            InstructionInternal::GetGlobal(x) => Instruction::GetGlobal(x),
633            InstructionInternal::SetGlobal(x) => Instruction::SetGlobal(x),
634
635            InstructionInternal::I32Load(x) => Instruction::I32Load(x),
636            InstructionInternal::I64Load(x) => Instruction::I64Load(x),
637            InstructionInternal::F32Load(x) => Instruction::F32Load(x),
638            InstructionInternal::F64Load(x) => Instruction::F64Load(x),
639            InstructionInternal::I32Load8S(x) => Instruction::I32Load8S(x),
640            InstructionInternal::I32Load8U(x) => Instruction::I32Load8U(x),
641            InstructionInternal::I32Load16S(x) => Instruction::I32Load16S(x),
642            InstructionInternal::I32Load16U(x) => Instruction::I32Load16U(x),
643            InstructionInternal::I64Load8S(x) => Instruction::I64Load8S(x),
644            InstructionInternal::I64Load8U(x) => Instruction::I64Load8U(x),
645            InstructionInternal::I64Load16S(x) => Instruction::I64Load16S(x),
646            InstructionInternal::I64Load16U(x) => Instruction::I64Load16U(x),
647            InstructionInternal::I64Load32S(x) => Instruction::I64Load32S(x),
648            InstructionInternal::I64Load32U(x) => Instruction::I64Load32U(x),
649            InstructionInternal::I32Store(x) => Instruction::I32Store(x),
650            InstructionInternal::I64Store(x) => Instruction::I64Store(x),
651            InstructionInternal::F32Store(x) => Instruction::F32Store(x),
652            InstructionInternal::F64Store(x) => Instruction::F64Store(x),
653            InstructionInternal::I32Store8(x) => Instruction::I32Store8(x),
654            InstructionInternal::I32Store16(x) => Instruction::I32Store16(x),
655            InstructionInternal::I64Store8(x) => Instruction::I64Store8(x),
656            InstructionInternal::I64Store16(x) => Instruction::I64Store16(x),
657            InstructionInternal::I64Store32(x) => Instruction::I64Store32(x),
658
659            InstructionInternal::CurrentMemory => Instruction::CurrentMemory,
660            InstructionInternal::GrowMemory => Instruction::GrowMemory,
661
662            InstructionInternal::I32Const(x) => Instruction::I32Const(x),
663            InstructionInternal::I64Const(x) => Instruction::I64Const(x),
664            InstructionInternal::F32Const(x) => Instruction::F32Const(x),
665            InstructionInternal::F64Const(x) => Instruction::F64Const(x),
666
667            InstructionInternal::I32Eqz => Instruction::I32Eqz,
668            InstructionInternal::I32Eq => Instruction::I32Eq,
669            InstructionInternal::I32Ne => Instruction::I32Ne,
670            InstructionInternal::I32LtS => Instruction::I32LtS,
671            InstructionInternal::I32LtU => Instruction::I32LtU,
672            InstructionInternal::I32GtS => Instruction::I32GtS,
673            InstructionInternal::I32GtU => Instruction::I32GtU,
674            InstructionInternal::I32LeS => Instruction::I32LeS,
675            InstructionInternal::I32LeU => Instruction::I32LeU,
676            InstructionInternal::I32GeS => Instruction::I32GeS,
677            InstructionInternal::I32GeU => Instruction::I32GeU,
678
679            InstructionInternal::I64Eqz => Instruction::I64Eqz,
680            InstructionInternal::I64Eq => Instruction::I64Eq,
681            InstructionInternal::I64Ne => Instruction::I64Ne,
682            InstructionInternal::I64LtS => Instruction::I64LtS,
683            InstructionInternal::I64LtU => Instruction::I64LtU,
684            InstructionInternal::I64GtS => Instruction::I64GtS,
685            InstructionInternal::I64GtU => Instruction::I64GtU,
686            InstructionInternal::I64LeS => Instruction::I64LeS,
687            InstructionInternal::I64LeU => Instruction::I64LeU,
688            InstructionInternal::I64GeS => Instruction::I64GeS,
689            InstructionInternal::I64GeU => Instruction::I64GeU,
690
691            InstructionInternal::F32Eq => Instruction::F32Eq,
692            InstructionInternal::F32Ne => Instruction::F32Ne,
693            InstructionInternal::F32Lt => Instruction::F32Lt,
694            InstructionInternal::F32Gt => Instruction::F32Gt,
695            InstructionInternal::F32Le => Instruction::F32Le,
696            InstructionInternal::F32Ge => Instruction::F32Ge,
697
698            InstructionInternal::F64Eq => Instruction::F64Eq,
699            InstructionInternal::F64Ne => Instruction::F64Ne,
700            InstructionInternal::F64Lt => Instruction::F64Lt,
701            InstructionInternal::F64Gt => Instruction::F64Gt,
702            InstructionInternal::F64Le => Instruction::F64Le,
703            InstructionInternal::F64Ge => Instruction::F64Ge,
704
705            InstructionInternal::I32Clz => Instruction::I32Clz,
706            InstructionInternal::I32Ctz => Instruction::I32Ctz,
707            InstructionInternal::I32Popcnt => Instruction::I32Popcnt,
708            InstructionInternal::I32Add => Instruction::I32Add,
709            InstructionInternal::I32Sub => Instruction::I32Sub,
710            InstructionInternal::I32Mul => Instruction::I32Mul,
711            InstructionInternal::I32DivS => Instruction::I32DivS,
712            InstructionInternal::I32DivU => Instruction::I32DivU,
713            InstructionInternal::I32RemS => Instruction::I32RemS,
714            InstructionInternal::I32RemU => Instruction::I32RemU,
715            InstructionInternal::I32And => Instruction::I32And,
716            InstructionInternal::I32Or => Instruction::I32Or,
717            InstructionInternal::I32Xor => Instruction::I32Xor,
718            InstructionInternal::I32Shl => Instruction::I32Shl,
719            InstructionInternal::I32ShrS => Instruction::I32ShrS,
720            InstructionInternal::I32ShrU => Instruction::I32ShrU,
721            InstructionInternal::I32Rotl => Instruction::I32Rotl,
722            InstructionInternal::I32Rotr => Instruction::I32Rotr,
723
724            InstructionInternal::I64Clz => Instruction::I64Clz,
725            InstructionInternal::I64Ctz => Instruction::I64Ctz,
726            InstructionInternal::I64Popcnt => Instruction::I64Popcnt,
727            InstructionInternal::I64Add => Instruction::I64Add,
728            InstructionInternal::I64Sub => Instruction::I64Sub,
729            InstructionInternal::I64Mul => Instruction::I64Mul,
730            InstructionInternal::I64DivS => Instruction::I64DivS,
731            InstructionInternal::I64DivU => Instruction::I64DivU,
732            InstructionInternal::I64RemS => Instruction::I64RemS,
733            InstructionInternal::I64RemU => Instruction::I64RemU,
734            InstructionInternal::I64And => Instruction::I64And,
735            InstructionInternal::I64Or => Instruction::I64Or,
736            InstructionInternal::I64Xor => Instruction::I64Xor,
737            InstructionInternal::I64Shl => Instruction::I64Shl,
738            InstructionInternal::I64ShrS => Instruction::I64ShrS,
739            InstructionInternal::I64ShrU => Instruction::I64ShrU,
740            InstructionInternal::I64Rotl => Instruction::I64Rotl,
741            InstructionInternal::I64Rotr => Instruction::I64Rotr,
742            InstructionInternal::F32Abs => Instruction::F32Abs,
743            InstructionInternal::F32Neg => Instruction::F32Neg,
744            InstructionInternal::F32Ceil => Instruction::F32Ceil,
745            InstructionInternal::F32Floor => Instruction::F32Floor,
746            InstructionInternal::F32Trunc => Instruction::F32Trunc,
747            InstructionInternal::F32Nearest => Instruction::F32Nearest,
748            InstructionInternal::F32Sqrt => Instruction::F32Sqrt,
749            InstructionInternal::F32Add => Instruction::F32Add,
750            InstructionInternal::F32Sub => Instruction::F32Sub,
751            InstructionInternal::F32Mul => Instruction::F32Mul,
752            InstructionInternal::F32Div => Instruction::F32Div,
753            InstructionInternal::F32Min => Instruction::F32Min,
754            InstructionInternal::F32Max => Instruction::F32Max,
755            InstructionInternal::F32Copysign => Instruction::F32Copysign,
756            InstructionInternal::F64Abs => Instruction::F64Abs,
757            InstructionInternal::F64Neg => Instruction::F64Neg,
758            InstructionInternal::F64Ceil => Instruction::F64Ceil,
759            InstructionInternal::F64Floor => Instruction::F64Floor,
760            InstructionInternal::F64Trunc => Instruction::F64Trunc,
761            InstructionInternal::F64Nearest => Instruction::F64Nearest,
762            InstructionInternal::F64Sqrt => Instruction::F64Sqrt,
763            InstructionInternal::F64Add => Instruction::F64Add,
764            InstructionInternal::F64Sub => Instruction::F64Sub,
765            InstructionInternal::F64Mul => Instruction::F64Mul,
766            InstructionInternal::F64Div => Instruction::F64Div,
767            InstructionInternal::F64Min => Instruction::F64Min,
768            InstructionInternal::F64Max => Instruction::F64Max,
769            InstructionInternal::F64Copysign => Instruction::F64Copysign,
770
771            InstructionInternal::I32WrapI64 => Instruction::I32WrapI64,
772            InstructionInternal::I32TruncSF32 => Instruction::I32TruncSF32,
773            InstructionInternal::I32TruncUF32 => Instruction::I32TruncUF32,
774            InstructionInternal::I32TruncSF64 => Instruction::I32TruncSF64,
775            InstructionInternal::I32TruncUF64 => Instruction::I32TruncUF64,
776            InstructionInternal::I64ExtendSI32 => Instruction::I64ExtendSI32,
777            InstructionInternal::I64ExtendUI32 => Instruction::I64ExtendUI32,
778            InstructionInternal::I64TruncSF32 => Instruction::I64TruncSF32,
779            InstructionInternal::I64TruncUF32 => Instruction::I64TruncUF32,
780            InstructionInternal::I64TruncSF64 => Instruction::I64TruncSF64,
781            InstructionInternal::I64TruncUF64 => Instruction::I64TruncUF64,
782            InstructionInternal::F32ConvertSI32 => Instruction::F32ConvertSI32,
783            InstructionInternal::F32ConvertUI32 => Instruction::F32ConvertUI32,
784            InstructionInternal::F32ConvertSI64 => Instruction::F32ConvertSI64,
785            InstructionInternal::F32ConvertUI64 => Instruction::F32ConvertUI64,
786            InstructionInternal::F32DemoteF64 => Instruction::F32DemoteF64,
787            InstructionInternal::F64ConvertSI32 => Instruction::F64ConvertSI32,
788            InstructionInternal::F64ConvertUI32 => Instruction::F64ConvertUI32,
789            InstructionInternal::F64ConvertSI64 => Instruction::F64ConvertSI64,
790            InstructionInternal::F64ConvertUI64 => Instruction::F64ConvertUI64,
791            InstructionInternal::F64PromoteF32 => Instruction::F64PromoteF32,
792
793            InstructionInternal::I32ReinterpretF32 => Instruction::I32ReinterpretF32,
794            InstructionInternal::I64ReinterpretF64 => Instruction::I64ReinterpretF64,
795            InstructionInternal::F32ReinterpretI32 => Instruction::F32ReinterpretI32,
796            InstructionInternal::F64ReinterpretI64 => Instruction::F64ReinterpretI64,
797        };
798
799        self.position += 1;
800
801        Some(out)
802    }
803}