1 use crate::{
2     error::Error,
3     module::{ModuleContext, SigType, Signature},
4 };
5 use itertools::Either;
6 use smallvec::SmallVec;
7 use std::{
8     convert::TryInto,
9     fmt,
10     iter::{self, FromIterator},
11     ops::RangeInclusive,
12 };
13 use wasmparser::{
14     FunctionBody, Ieee32 as WasmIeee32, Ieee64 as WasmIeee64,
15     MemoryImmediate as WasmMemoryImmediate, Operator as WasmOperator, OperatorsReader,
16 };
17 
dis<L>( mut out: impl std::io::Write, function_name: impl fmt::Display, microwasm: impl IntoIterator<Item = Operator<L>>, ) -> std::io::Result<()> where BrTarget<L>: fmt::Display, L: Clone,18 pub fn dis<L>(
19     mut out: impl std::io::Write,
20     function_name: impl fmt::Display,
21     microwasm: impl IntoIterator<Item = Operator<L>>,
22 ) -> std::io::Result<()>
23 where
24     BrTarget<L>: fmt::Display,
25     L: Clone,
26 {
27     writeln!(out, ".fn_{}:", function_name)?;
28 
29     let p = "      ";
30     for op in microwasm {
31         if op.is_label() || op.is_block() {
32             writeln!(out, "{}", op)?;
33         } else {
34             writeln!(out, "{}{}", p, op)?;
35         }
36     }
37 
38     Ok(())
39 }
40 
41 #[derive(Copy, Clone, Debug, Hash, PartialEq, Eq)]
42 pub struct Ieee32(u32);
43 #[derive(Copy, Clone, Debug, Hash, PartialEq, Eq)]
44 pub struct Ieee64(u64);
45 
46 impl Ieee32 {
to_bits(self) -> u3247     pub fn to_bits(self) -> u32 {
48         self.0
49     }
50 
from_bits(other: u32) -> Self51     pub fn from_bits(other: u32) -> Self {
52         Ieee32(other)
53     }
54 }
55 
56 impl From<WasmIeee32> for Ieee32 {
from(other: WasmIeee32) -> Self57     fn from(other: WasmIeee32) -> Self {
58         Self::from_bits(other.bits())
59     }
60 }
61 
62 impl Ieee64 {
to_bits(self) -> u6463     pub fn to_bits(self) -> u64 {
64         self.0
65     }
66 
from_bits(other: u64) -> Self67     pub fn from_bits(other: u64) -> Self {
68         Ieee64(other)
69     }
70 }
71 
72 impl From<WasmIeee64> for Ieee64 {
from(other: WasmIeee64) -> Self73     fn from(other: WasmIeee64) -> Self {
74         Self::from_bits(other.bits())
75     }
76 }
77 
78 /// A constant value embedded in the instructions
79 #[derive(Debug, Copy, Clone, PartialEq, Eq)]
80 pub enum Value {
81     I32(i32),
82     I64(i64),
83     F32(Ieee32),
84     F64(Ieee64),
85 }
86 
87 impl fmt::Display for Value {
fmt(&self, f: &mut fmt::Formatter) -> fmt::Result88     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
89         match self {
90             Value::I32(v) => write!(f, "{}i32", v),
91             Value::I64(v) => write!(f, "{}i64", v),
92             Value::F32(v) => write!(f, "{}f32", f32::from_bits(v.0)),
93             Value::F64(v) => write!(f, "{}f64", f64::from_bits(v.0)),
94         }
95     }
96 }
97 
98 impl Value {
as_int(self) -> Option<i64>99     pub fn as_int(self) -> Option<i64> {
100         self.as_i64().or_else(|| self.as_i32().map(|i| i as _))
101     }
102 
as_bytes(self) -> i64103     pub fn as_bytes(self) -> i64 {
104         match self {
105             Value::I32(val) => val as _,
106             Value::I64(val) => val,
107             Value::F32(val) => val.0 as _,
108             Value::F64(val) => val.0 as _,
109         }
110     }
111 
as_i32(self) -> Option<i32>112     pub fn as_i32(self) -> Option<i32> {
113         match self {
114             Value::I32(val) => Some(val),
115             _ => None,
116         }
117     }
118 
as_i64(self) -> Option<i64>119     pub fn as_i64(self) -> Option<i64> {
120         match self {
121             Value::I64(val) => Some(val),
122             _ => None,
123         }
124     }
125 
as_f32(self) -> Option<Ieee32>126     pub fn as_f32(self) -> Option<Ieee32> {
127         match self {
128             Value::F32(val) => Some(val),
129             _ => None,
130         }
131     }
132 
as_f64(self) -> Option<Ieee64>133     pub fn as_f64(self) -> Option<Ieee64> {
134         match self {
135             Value::F64(val) => Some(val),
136             _ => None,
137         }
138     }
139 
type_(&self) -> SignlessType140     pub fn type_(&self) -> SignlessType {
141         match self {
142             Value::I32(_) => Type::Int(Size::_32),
143             Value::I64(_) => Type::Int(Size::_64),
144             Value::F32(Ieee32(_)) => Type::Float(Size::_32),
145             Value::F64(Ieee64(_)) => Type::Float(Size::_64),
146         }
147     }
148 
default_for_type(ty: SignlessType) -> Self149     fn default_for_type(ty: SignlessType) -> Self {
150         match ty {
151             Type::Int(Size::_32) => Value::I32(0),
152             Type::Int(Size::_64) => Value::I64(0),
153             Type::Float(Size::_32) => Value::F32(Ieee32(0)),
154             Type::Float(Size::_64) => Value::F64(Ieee64(0)),
155         }
156     }
157 }
158 
159 impl From<i32> for Value {
from(other: i32) -> Self160     fn from(other: i32) -> Self {
161         Value::I32(other)
162     }
163 }
164 impl From<i64> for Value {
from(other: i64) -> Self165     fn from(other: i64) -> Self {
166         Value::I64(other)
167     }
168 }
169 impl From<u32> for Value {
from(other: u32) -> Self170     fn from(other: u32) -> Self {
171         Value::I32(other as _)
172     }
173 }
174 impl From<u64> for Value {
from(other: u64) -> Self175     fn from(other: u64) -> Self {
176         Value::I64(other as _)
177     }
178 }
179 impl From<Ieee32> for Value {
from(other: Ieee32) -> Self180     fn from(other: Ieee32) -> Self {
181         Value::F32(other)
182     }
183 }
184 impl From<Ieee64> for Value {
from(other: Ieee64) -> Self185     fn from(other: Ieee64) -> Self {
186         Value::F64(other)
187     }
188 }
189 
190 /// Whether to interpret an integer as signed or unsigned
191 #[derive(Debug, Copy, Clone, PartialEq, Eq)]
192 pub enum Signedness {
193     Signed,
194     Unsigned,
195 }
196 
197 #[derive(Debug, Copy, Clone, PartialEq, Eq)]
198 pub enum Size {
199     _32,
200     _64,
201 }
202 
203 type Int = Size;
204 type Float = Size;
205 
206 #[derive(Debug, Copy, Clone, PartialEq, Eq)]
207 pub struct SignfulInt(pub Signedness, pub Size);
208 
209 #[derive(Debug, Copy, Clone, PartialEq, Eq)]
210 pub enum Type<I> {
211     Int(I),
212     Float(Size),
213 }
214 
215 pub trait IntoType<T> {
into_type() -> T216     fn into_type() -> T;
217 }
218 
219 impl IntoType<SignlessType> for i32 {
into_type() -> SignlessType220     fn into_type() -> SignlessType {
221         I32
222     }
223 }
224 
225 impl IntoType<SignlessType> for i64 {
into_type() -> SignlessType226     fn into_type() -> SignlessType {
227         I64
228     }
229 }
230 
231 impl IntoType<SignlessType> for u32 {
into_type() -> SignlessType232     fn into_type() -> SignlessType {
233         I32
234     }
235 }
236 
237 impl IntoType<SignlessType> for u64 {
into_type() -> SignlessType238     fn into_type() -> SignlessType {
239         I64
240     }
241 }
242 
243 impl IntoType<SignlessType> for f32 {
into_type() -> SignlessType244     fn into_type() -> SignlessType {
245         F32
246     }
247 }
248 
249 impl IntoType<SignlessType> for f64 {
into_type() -> SignlessType250     fn into_type() -> SignlessType {
251         F64
252     }
253 }
254 
255 impl<I> Type<I> {
for_<T: IntoType<Self>>() -> Self256     pub fn for_<T: IntoType<Self>>() -> Self {
257         T::into_type()
258     }
259 }
260 
261 impl fmt::Display for SignfulType {
fmt(&self, f: &mut fmt::Formatter) -> fmt::Result262     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
263         match self {
264             Type::Int(i) => write!(f, "{}", i),
265             Type::Float(Size::_32) => write!(f, "f32"),
266             Type::Float(Size::_64) => write!(f, "f64"),
267         }
268     }
269 }
270 
271 impl fmt::Display for SignlessType {
fmt(&self, f: &mut fmt::Formatter) -> fmt::Result272     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
273         match self {
274             Type::Int(Size::_32) => write!(f, "i32"),
275             Type::Int(Size::_64) => write!(f, "i64"),
276             Type::Float(Size::_32) => write!(f, "f32"),
277             Type::Float(Size::_64) => write!(f, "f64"),
278         }
279     }
280 }
281 
282 impl fmt::Display for SignfulInt {
fmt(&self, f: &mut fmt::Formatter) -> fmt::Result283     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
284         match self {
285             SignfulInt(Signedness::Signed, Size::_32) => write!(f, "i32"),
286             SignfulInt(Signedness::Unsigned, Size::_32) => write!(f, "u32"),
287             SignfulInt(Signedness::Signed, Size::_64) => write!(f, "i64"),
288             SignfulInt(Signedness::Unsigned, Size::_64) => write!(f, "u64"),
289         }
290     }
291 }
292 
293 pub type SignlessType = Type<Size>;
294 pub type SignfulType = Type<SignfulInt>;
295 
296 pub const I32: SignlessType = Type::Int(Size::_32);
297 pub const I64: SignlessType = Type::Int(Size::_64);
298 pub const F32: SignlessType = Type::Float(Size::_32);
299 pub const F64: SignlessType = Type::Float(Size::_64);
300 
301 pub mod sint {
302     use super::{Signedness, SignfulInt, Size};
303 
304     pub const I32: SignfulInt = SignfulInt(Signedness::Signed, Size::_32);
305     pub const I64: SignfulInt = SignfulInt(Signedness::Signed, Size::_64);
306     pub const U32: SignfulInt = SignfulInt(Signedness::Unsigned, Size::_32);
307     pub const U64: SignfulInt = SignfulInt(Signedness::Unsigned, Size::_64);
308 }
309 
310 pub const SI32: SignfulType = Type::Int(sint::I32);
311 pub const SI64: SignfulType = Type::Int(sint::I64);
312 pub const SU32: SignfulType = Type::Int(sint::U32);
313 pub const SU64: SignfulType = Type::Int(sint::U64);
314 pub const SF32: SignfulType = Type::Float(Size::_32);
315 pub const SF64: SignfulType = Type::Float(Size::_64);
316 
317 impl SignlessType {
from_wasm_block(other: wasmparser::Type) -> Result<Option<Self>, Error>318     pub fn from_wasm_block(other: wasmparser::Type) -> Result<Option<Self>, Error> {
319         use wasmparser::Type;
320 
321         match other {
322             Type::I32 => Ok(Some(I32)),
323             Type::I64 => Ok(Some(I64)),
324             Type::F32 => Ok(Some(F32)),
325             Type::F64 => Ok(Some(F64)),
326             Type::EmptyBlockType => Ok(None),
327             _ => Err(Error::Input("Invalid type".into())),
328         }
329     }
330 
from_wasm(other: wasmparser::Type) -> Result<Self, Error>331     pub fn from_wasm(other: wasmparser::Type) -> Result<Self, Error> {
332         match Self::from_wasm_block(other) {
333             Ok(Some(v)) => Ok(v),
334             Ok(None) => Err(Error::Input("Invalid type".into())),
335             Err(e) => Err(e),
336         }
337     }
338 }
339 
340 #[derive(Debug, Clone)]
341 pub struct BrTable<L> {
342     pub targets: Vec<BrTargetDrop<L>>,
343     pub default: BrTargetDrop<L>,
344 }
345 
346 #[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)]
347 pub enum NameTag {
348     Header,
349     Else,
350     End,
351 }
352 
353 pub type WasmLabel = (u32, NameTag);
354 
355 pub type OperatorFromWasm = Operator<WasmLabel>;
356 
357 #[derive(Debug, Clone, Copy, Hash, PartialEq, Eq)]
358 pub enum BrTarget<L> {
359     Return,
360     Label(L),
361 }
362 
363 impl<L> BrTarget<L> {
label(&self) -> Option<&L>364     pub fn label(&self) -> Option<&L> {
365         match self {
366             BrTarget::Return => None,
367             BrTarget::Label(l) => Some(l),
368         }
369     }
370 }
371 
372 impl<L> From<L> for BrTarget<L> {
from(other: L) -> Self373     fn from(other: L) -> Self {
374         BrTarget::Label(other)
375     }
376 }
377 
378 impl fmt::Display for BrTarget<WasmLabel> {
fmt(&self, f: &mut fmt::Formatter) -> fmt::Result379     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
380         match self {
381             BrTarget::Return => write!(f, ".return"),
382             BrTarget::Label((i, NameTag::Header)) => write!(f, ".L{}", i),
383             BrTarget::Label((i, NameTag::Else)) => write!(f, ".L{}_else", i),
384             BrTarget::Label((i, NameTag::End)) => write!(f, ".L{}_end", i),
385         }
386     }
387 }
388 
389 impl fmt::Display for BrTarget<&str> {
fmt(&self, f: &mut fmt::Formatter) -> fmt::Result390     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
391         match self {
392             BrTarget::Return => write!(f, ".return"),
393             BrTarget::Label(l) => write!(f, ".L{}", l),
394         }
395     }
396 }
397 
398 #[derive(Debug, Clone, Hash, PartialEq, Eq)]
399 pub struct BrTargetDrop<L> {
400     pub target: BrTarget<L>,
401     pub to_drop: Option<RangeInclusive<u32>>,
402 }
403 
404 impl<L> From<BrTarget<L>> for BrTargetDrop<L> {
from(other: BrTarget<L>) -> Self405     fn from(other: BrTarget<L>) -> Self {
406         BrTargetDrop {
407             target: other,
408             to_drop: None,
409         }
410     }
411 }
412 
413 impl<L> fmt::Display for BrTargetDrop<L>
414 where
415     BrTarget<L>: fmt::Display,
416 {
fmt(&self, f: &mut fmt::Formatter) -> fmt::Result417     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
418         if let Some(drop) = &self.to_drop {
419             write!(
420                 f,
421                 "({}, drop {}..={})",
422                 self.target,
423                 drop.start(),
424                 drop.end()
425             )
426         } else {
427             write!(f, "{}", self.target)
428         }
429     }
430 }
431 
432 #[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)]
433 pub struct MemoryImmediate {
434     pub flags: u32,
435     pub offset: u32,
436 }
437 
438 impl From<WasmMemoryImmediate> for MemoryImmediate {
from(other: WasmMemoryImmediate) -> Self439     fn from(other: WasmMemoryImmediate) -> Self {
440         MemoryImmediate {
441             flags: other.flags,
442             offset: other.offset,
443         }
444     }
445 }
446 
447 // TODO: Explicit VmCtx?
448 #[derive(Debug, Clone)]
449 pub enum Operator<Label> {
450     /// Explicit trap instruction
451     Unreachable,
452     /// Define metadata for a block - its label, its signature, whether it has backwards callers etc. It
453     /// is an error to branch to a block that has yet to be defined.
454     Block {
455         label: Label,
456         // TODO: Do we need this?
457         params: Vec<SignlessType>,
458         // TODO: Ideally we'd have `num_backwards_callers` but we can't know that for WebAssembly
459         has_backwards_callers: bool,
460         num_callers: Option<u32>,
461     },
462     /// Start a new block. It is an error if the previous block has not been closed by emitting a `Br` or
463     /// `BrTable`.
464     Label(Label),
465     /// Unconditionally break to a new block. This the parameters off the stack and passes them into
466     /// the new block. Any remaining elements on the stack are discarded.
467     Br {
468         /// Returning from the function is just calling the "return" block
469         target: BrTarget<Label>,
470     },
471     /// Pop a value off the top of the stack, jump to the `else_` label if this value is `true`
472     /// and the `then` label otherwise. The `then` and `else_` blocks must have the same parameters.
473     BrIf {
474         /// Label to jump to if the value at the top of the stack is true
475         then: BrTargetDrop<Label>,
476         /// Label to jump to if the value at the top of the stack is false
477         else_: BrTargetDrop<Label>,
478     },
479     /// Pop a value off the top of the stack, jump to `table[value.min(table.len() - 1)]`. All elements
480     /// in the table must have the same parameters.
481     BrTable(
482         /// The table of labels to jump to - the index should be clamped to the length of the table
483         BrTable<Label>,
484     ),
485     /// Call a function
486     Call {
487         function_index: u32,
488     },
489     /// Pop an `i32` off the top of the stack, index into the table at `table_index` and call that function
490     CallIndirect {
491         type_index: u32,
492         table_index: u32,
493     },
494     /// Pop an element off of the stack and discard it.
495     Drop(RangeInclusive<u32>),
496     /// Pop an `i32` off of the stack and 2 elements off of the stack, call them `A` and `B` where `A` is the
497     /// first element popped and `B` is the second. If the `i32` is 0 then discard `B` and push `A` back onto
498     /// the stack, otherwise discard `A` and push `B` back onto the stack.
499     Select,
500     /// Duplicate the element at depth `depth` to the top of the stack. This can be used to implement
501     /// `LocalGet`.
502     Pick(u32),
503     /// Swap the top element of the stack with the element at depth `depth`. This can be used to implement
504     /// `LocalSet`.
505     // TODO: Is it better to have `Swap`, to have `Pull` (which moves the `nth` element instead of swapping)
506     //       or to have both?
507     Swap(u32),
508     GlobalGet(u32),
509     GlobalSet(u32),
510     Load {
511         ty: SignlessType,
512         memarg: MemoryImmediate,
513     },
514     Load8 {
515         ty: SignfulInt,
516         memarg: MemoryImmediate,
517     },
518     Load16 {
519         ty: SignfulInt,
520         memarg: MemoryImmediate,
521     },
522     // Only available for {I,U}64
523     // TODO: Roll this into `Load` somehow?
524     Load32 {
525         sign: Signedness,
526         memarg: MemoryImmediate,
527     },
528     Store {
529         ty: SignlessType,
530         memarg: MemoryImmediate,
531     },
532     Store8 {
533         /// `ty` on integers
534         ty: Int,
535         memarg: MemoryImmediate,
536     },
537     Store16 {
538         /// `ty` on integers
539         ty: Int,
540         memarg: MemoryImmediate,
541     },
542     // Only available for I64
543     // TODO: Roll this into `Store` somehow?
544     Store32 {
545         memarg: MemoryImmediate,
546     },
547     MemorySize {
548         reserved: u32,
549     },
550     MemoryGrow {
551         reserved: u32,
552     },
553     Const(Value),
554     Eq(SignlessType),
555     Ne(SignlessType),
556     /// `eqz` on integers
557     Eqz(Int),
558     Lt(SignfulType),
559     Gt(SignfulType),
560     Le(SignfulType),
561     Ge(SignfulType),
562     Add(SignlessType),
563     Sub(SignlessType),
564     Mul(SignlessType),
565     /// `clz` on integers
566     Clz(Int),
567     /// `ctz` on integers
568     Ctz(Int),
569     /// `popcnt` on integers
570     Popcnt(Int),
571     Div(SignfulType),
572     Rem(SignfulInt),
573     And(Int),
574     Or(Int),
575     Xor(Int),
576     Shl(Int),
577     Shr(SignfulInt),
578     Rotl(Int),
579     Rotr(Int),
580     Abs(Float),
581     Neg(Float),
582     Ceil(Float),
583     Floor(Float),
584     Trunc(Float),
585     Nearest(Float),
586     Sqrt(Float),
587     Min(Float),
588     Max(Float),
589     Copysign(Float),
590     I32WrapFromI64,
591     ITruncFromF {
592         input_ty: Float,
593         output_ty: SignfulInt,
594     },
595     FConvertFromI {
596         input_ty: SignfulInt,
597         output_ty: Float,
598     },
599     F32DemoteFromF64,
600     F64PromoteFromF32,
601     I32ReinterpretFromF32,
602     I64ReinterpretFromF64,
603     F32ReinterpretFromI32,
604     F64ReinterpretFromI64,
605     // Only available for input I32 and output I64
606     Extend {
607         sign: Signedness,
608     },
609 }
610 
611 impl<L> Operator<L> {
is_label(&self) -> bool612     pub fn is_label(&self) -> bool {
613         match self {
614             Operator::Label(..) => true,
615             _ => false,
616         }
617     }
618 
is_block(&self) -> bool619     pub fn is_block(&self) -> bool {
620         match self {
621             Operator::Block { .. } => true,
622             _ => false,
623         }
624     }
625 
end(params: Vec<SignlessType>, label: L) -> Self626     pub fn end(params: Vec<SignlessType>, label: L) -> Self {
627         Operator::Block {
628             params,
629             label,
630             has_backwards_callers: false,
631             // TODO
632             num_callers: None,
633         }
634     }
635 
block(params: Vec<SignlessType>, label: L) -> Self636     pub fn block(params: Vec<SignlessType>, label: L) -> Self {
637         Operator::Block {
638             params,
639             label,
640             has_backwards_callers: false,
641             num_callers: Some(1),
642         }
643     }
644 
loop_(params: Vec<SignlessType>, label: L) -> Self645     pub fn loop_(params: Vec<SignlessType>, label: L) -> Self {
646         Operator::Block {
647             params,
648             label,
649             has_backwards_callers: true,
650             num_callers: None,
651         }
652     }
653 }
654 
655 impl<L> fmt::Display for Operator<L>
656 where
657     BrTarget<L>: fmt::Display,
658     L: Clone,
659 {
fmt(&self, f: &mut fmt::Formatter) -> fmt::Result660     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
661         match self {
662             Operator::Unreachable => write!(f, "unreachable"),
663             Operator::Label(label) => write!(f, "{}:", BrTarget::Label(label.clone())),
664             Operator::Block {
665                 label,
666                 params,
667                 has_backwards_callers,
668                 num_callers,
669             } => {
670                 write!(f, "def {} :: [", BrTarget::Label(label.clone()))?;
671                 let mut iter = params.iter();
672                 if let Some(p) = iter.next() {
673                     write!(f, "{}", p)?;
674                     for p in iter {
675                         write!(f, ", {}", p)?;
676                     }
677                 }
678                 write!(f, "]")?;
679 
680                 if *has_backwards_callers {
681                     write!(f, " has_backwards_callers")?;
682                 }
683 
684                 if let Some(n) = num_callers {
685                     write!(f, " num_callers={}", n)?;
686                 }
687 
688                 Ok(())
689             }
690             Operator::Br { target } => write!(f, "br {}", target),
691             Operator::BrIf { then, else_ } => write!(f, "br_if {}, {}", then, else_),
692             Operator::BrTable(BrTable { targets, default }) => {
693                 write!(f, "br_table [")?;
694                 let mut iter = targets.iter();
695                 if let Some(p) = iter.next() {
696                     write!(f, "{}", p)?;
697                     for p in iter {
698                         write!(f, ", {}", p)?;
699                     }
700                 }
701 
702                 write!(f, "], {}", default)
703             }
704             Operator::Call { function_index } => write!(f, "call {}", function_index),
705             Operator::CallIndirect { .. } => write!(f, "call_indirect"),
706             Operator::Drop(range) => {
707                 write!(f, "drop")?;
708 
709                 match range.clone().into_inner() {
710                     (0, 0) => {}
711                     (start, end) if start == end => {
712                         write!(f, " {}", start)?;
713                     }
714                     (start, end) => {
715                         write!(f, " {}..={}", start, end)?;
716                     }
717                 }
718 
719                 Ok(())
720             }
721             Operator::Select => write!(f, "select"),
722             Operator::Pick(depth) => write!(f, "pick {}", depth),
723             Operator::Swap(depth) => write!(f, "swap {}", depth),
724             Operator::Load { ty, memarg } => {
725                 write!(f, "{}.load {}, {}", ty, memarg.flags, memarg.offset)
726             }
727             Operator::Load8 { ty, memarg } => {
728                 write!(f, "{}.load8 {}, {}", ty, memarg.flags, memarg.offset)
729             }
730             Operator::Load16 { ty, memarg } => {
731                 write!(f, "{}.load16 {}, {}", ty, memarg.flags, memarg.offset)
732             }
733             Operator::Load32 { sign, memarg } => write!(
734                 f,
735                 "{}.load32 {}, {}",
736                 SignfulInt(*sign, Size::_64),
737                 memarg.flags,
738                 memarg.offset
739             ),
740             Operator::Store { ty, memarg } => {
741                 write!(f, "{}.store {}, {}", ty, memarg.flags, memarg.offset)
742             }
743             Operator::Store8 { ty, memarg } => write!(
744                 f,
745                 "{}.store8 {}, {}",
746                 SignfulInt(Signedness::Unsigned, *ty),
747                 memarg.flags,
748                 memarg.offset
749             ),
750             Operator::Store16 { ty, memarg } => write!(
751                 f,
752                 "{}.store16 {}, {}",
753                 SignfulInt(Signedness::Unsigned, *ty),
754                 memarg.flags,
755                 memarg.offset
756             ),
757             Operator::Store32 { memarg } => {
758                 write!(f, "u64.store32 {}, {}", memarg.flags, memarg.offset)
759             }
760             Operator::MemorySize { .. } => write!(f, "memory.size"),
761             Operator::MemoryGrow { .. } => write!(f, "memory.grow"),
762             Operator::Const(val) => write!(f, "const {}", val),
763             Operator::Eq(ty) => write!(f, "{}.eq", ty),
764             Operator::Ne(ty) => write!(f, "{}.ne", ty),
765             Operator::Eqz(ty) => write!(f, "{}.eqz", SignfulInt(Signedness::Unsigned, *ty)),
766             Operator::Lt(ty) => write!(f, "{}.lt", ty),
767             Operator::Gt(ty) => write!(f, "{}.gt", ty),
768             Operator::Le(ty) => write!(f, "{}.le", ty),
769             Operator::Ge(ty) => write!(f, "{}.ge", ty),
770             Operator::Add(ty) => write!(f, "{}.add", ty),
771             Operator::Sub(ty) => write!(f, "{}.sub", ty),
772             Operator::Mul(ty) => write!(f, "{}.mul", ty),
773             Operator::Clz(ty) => write!(f, "{}.clz", SignfulInt(Signedness::Unsigned, *ty)),
774             Operator::Ctz(ty) => write!(f, "{}.ctz", SignfulInt(Signedness::Unsigned, *ty)),
775             Operator::Popcnt(ty) => write!(f, "{}.popcnt", SignfulInt(Signedness::Unsigned, *ty)),
776             Operator::Div(ty) => write!(f, "{}.div", ty),
777             Operator::Rem(ty) => write!(f, "{}.rem", ty),
778             Operator::And(ty) => write!(f, "{}.and", SignfulInt(Signedness::Unsigned, *ty)),
779             Operator::Or(ty) => write!(f, "{}.or", SignfulInt(Signedness::Unsigned, *ty)),
780             Operator::Xor(ty) => write!(f, "{}.xor", SignfulInt(Signedness::Unsigned, *ty)),
781             Operator::Shl(ty) => write!(f, "{}.shl", SignfulInt(Signedness::Unsigned, *ty)),
782             Operator::Shr(ty) => write!(f, "{}.shr", ty),
783             Operator::Rotl(ty) => write!(f, "{}.rotl", SignfulInt(Signedness::Unsigned, *ty)),
784             Operator::Rotr(ty) => write!(f, "{}.rotr", SignfulInt(Signedness::Unsigned, *ty)),
785             Operator::Abs(ty) => write!(f, "{}.abs", Type::<Int>::Float(*ty)),
786             Operator::Neg(ty) => write!(f, "{}.neg", Type::<Int>::Float(*ty)),
787             Operator::Ceil(ty) => write!(f, "{}.ceil", Type::<Int>::Float(*ty)),
788             Operator::Floor(ty) => write!(f, "{}.floor", Type::<Int>::Float(*ty)),
789             Operator::Trunc(ty) => write!(f, "{}.trunc", Type::<Int>::Float(*ty)),
790             Operator::Nearest(ty) => write!(f, "{}.nearest", Type::<Int>::Float(*ty)),
791             Operator::Sqrt(ty) => write!(f, "{}.sqrt", Type::<Int>::Float(*ty)),
792             Operator::Min(ty) => write!(f, "{}.min", Type::<Int>::Float(*ty)),
793             Operator::Max(ty) => write!(f, "{}.max", Type::<Int>::Float(*ty)),
794             Operator::Copysign(ty) => write!(f, "{}.copysign", Type::<Int>::Float(*ty)),
795             Operator::I32WrapFromI64 => write!(f, "i32.wrap_from.i64"),
796             Operator::F32DemoteFromF64 => write!(f, "f32.demote_from.f64"),
797             Operator::F64PromoteFromF32 => write!(f, "f64.promote_from.f32"),
798             Operator::I32ReinterpretFromF32 => write!(f, "i32.reinterpret_from.f32"),
799             Operator::I64ReinterpretFromF64 => write!(f, "i64.reinterpret_from.f64"),
800             Operator::F32ReinterpretFromI32 => write!(f, "f32.reinterpret_from.i32"),
801             Operator::F64ReinterpretFromI64 => write!(f, "f64.reinterpret_from.i64"),
802             Operator::FConvertFromI {
803                 input_ty,
804                 output_ty,
805             } => write!(
806                 f,
807                 "{}.convert_from.{}",
808                 Type::Float::<Int>(*output_ty),
809                 input_ty,
810             ),
811             Operator::GlobalGet(index) => write!(f, "global.get {}", index),
812             Operator::GlobalSet(index) => write!(f, "global.set {}", index),
813             Operator::ITruncFromF {
814                 input_ty,
815                 output_ty,
816             } => write!(
817                 f,
818                 "{}.truncate_from.{}",
819                 output_ty,
820                 Type::<Int>::Float(*input_ty)
821             ),
822             Operator::Extend { sign } => write!(
823                 f,
824                 "{}.extend_from.{}",
825                 SignfulInt(*sign, Size::_64),
826                 SignfulInt(*sign, Size::_32)
827             ),
828         }
829     }
830 }
831 
832 // TODO: If we return a `Vec<<T as MicrowasmReceiver>::Item>` will that convert to (essentially) a no-op
833 //       in the case that `Item` is a ZST? That is important for ensuring that we don't do unnecessary
834 //       work when we're directly generating asm.
835 /// WIP: Trait to abstract over either producing a stream of Microwasm or directly producing assembly
836 /// from the Wasm. This should give a significant speedup since we don't need to allocate any vectors
837 /// or pay the cost of branches - we can just use iterators and direct function calls.
838 pub trait MicrowasmReceiver<Label> {
839     type Item;
840 
unreachable(&mut self) -> Self::Item841     fn unreachable(&mut self) -> Self::Item;
block( &mut self, label: Label, params: impl Iterator<Item = SignlessType>, has_backwards_callers: bool, num_callers: Option<u32>, ) -> Self::Item842     fn block(
843         &mut self,
844         label: Label,
845         params: impl Iterator<Item = SignlessType>,
846         has_backwards_callers: bool,
847         num_callers: Option<u32>,
848     ) -> Self::Item;
label(&mut self, _: Label) -> Self::Item849     fn label(&mut self, _: Label) -> Self::Item;
br(&mut self, target: BrTarget<Label>) -> Self::Item850     fn br(&mut self, target: BrTarget<Label>) -> Self::Item;
br_if(&mut self, then: BrTargetDrop<Label>, else_: BrTargetDrop<Label>) -> Self::Item851     fn br_if(&mut self, then: BrTargetDrop<Label>, else_: BrTargetDrop<Label>) -> Self::Item;
br_table(&mut self, _: BrTable<Label>) -> Self::Item852     fn br_table(&mut self, _: BrTable<Label>) -> Self::Item;
call(&mut self, function_index: u32) -> Self::Item853     fn call(&mut self, function_index: u32) -> Self::Item;
call_indirect(&mut self, type_index: u32, table_index: u32) -> Self::Item854     fn call_indirect(&mut self, type_index: u32, table_index: u32) -> Self::Item;
drop(&mut self, _: RangeInclusive<u32>) -> Self::Item855     fn drop(&mut self, _: RangeInclusive<u32>) -> Self::Item;
select(&mut self) -> Self::Item856     fn select(&mut self) -> Self::Item;
pick(&mut self, _: u32) -> Self::Item857     fn pick(&mut self, _: u32) -> Self::Item;
swap(&mut self, _: u32) -> Self::Item858     fn swap(&mut self, _: u32) -> Self::Item;
get_global(&mut self, index: u32) -> Self::Item859     fn get_global(&mut self, index: u32) -> Self::Item;
set_global(&mut self, index: u32) -> Self::Item860     fn set_global(&mut self, index: u32) -> Self::Item;
load(&mut self, ty: SignlessType, memarg: MemoryImmediate) -> Self::Item861     fn load(&mut self, ty: SignlessType, memarg: MemoryImmediate) -> Self::Item;
load8(&mut self, ty: SignfulInt, memarg: MemoryImmediate) -> Self::Item862     fn load8(&mut self, ty: SignfulInt, memarg: MemoryImmediate) -> Self::Item;
load16(&mut self, ty: SignfulInt, memarg: MemoryImmediate) -> Self::Item863     fn load16(&mut self, ty: SignfulInt, memarg: MemoryImmediate) -> Self::Item;
load32(&mut self, sign: Signedness, memarg: MemoryImmediate) -> Self::Item864     fn load32(&mut self, sign: Signedness, memarg: MemoryImmediate) -> Self::Item;
store(&mut self, ty: SignlessType, memarg: MemoryImmediate) -> Self::Item865     fn store(&mut self, ty: SignlessType, memarg: MemoryImmediate) -> Self::Item;
store8(&mut self, ty: Int, memarg: MemoryImmediate) -> Self::Item866     fn store8(&mut self, ty: Int, memarg: MemoryImmediate) -> Self::Item;
store16(&mut self, ty: Int, memarg: MemoryImmediate) -> Self::Item867     fn store16(&mut self, ty: Int, memarg: MemoryImmediate) -> Self::Item;
store32(&mut self, memarg: MemoryImmediate) -> Self::Item868     fn store32(&mut self, memarg: MemoryImmediate) -> Self::Item;
memory_size(&mut self, reserved: u32) -> Self::Item869     fn memory_size(&mut self, reserved: u32) -> Self::Item;
memory_grow(&mut self, reserved: u32) -> Self::Item870     fn memory_grow(&mut self, reserved: u32) -> Self::Item;
const_(&mut self, _: Value) -> Self::Item871     fn const_(&mut self, _: Value) -> Self::Item;
ref_null(&mut self) -> Self::Item872     fn ref_null(&mut self) -> Self::Item;
ref_is_null(&mut self) -> Self::Item873     fn ref_is_null(&mut self) -> Self::Item;
eq(&mut self, _: SignlessType) -> Self::Item874     fn eq(&mut self, _: SignlessType) -> Self::Item;
ne(&mut self, _: SignlessType) -> Self::Item875     fn ne(&mut self, _: SignlessType) -> Self::Item;
eqz(&mut self, _: Int) -> Self::Item876     fn eqz(&mut self, _: Int) -> Self::Item;
lt(&mut self, _: SignfulType) -> Self::Item877     fn lt(&mut self, _: SignfulType) -> Self::Item;
gt(&mut self, _: SignfulType) -> Self::Item878     fn gt(&mut self, _: SignfulType) -> Self::Item;
le(&mut self, _: SignfulType) -> Self::Item879     fn le(&mut self, _: SignfulType) -> Self::Item;
ge(&mut self, _: SignfulType) -> Self::Item880     fn ge(&mut self, _: SignfulType) -> Self::Item;
add(&mut self, _: SignlessType) -> Self::Item881     fn add(&mut self, _: SignlessType) -> Self::Item;
sub(&mut self, _: SignlessType) -> Self::Item882     fn sub(&mut self, _: SignlessType) -> Self::Item;
mul(&mut self, _: SignlessType) -> Self::Item883     fn mul(&mut self, _: SignlessType) -> Self::Item;
clz(&mut self, _: Int) -> Self::Item884     fn clz(&mut self, _: Int) -> Self::Item;
ctz(&mut self, _: Int) -> Self::Item885     fn ctz(&mut self, _: Int) -> Self::Item;
popcnt(&mut self, _: Int) -> Self::Item886     fn popcnt(&mut self, _: Int) -> Self::Item;
div(&mut self, _: SignfulType) -> Self::Item887     fn div(&mut self, _: SignfulType) -> Self::Item;
rem(&mut self, _: SignfulInt) -> Self::Item888     fn rem(&mut self, _: SignfulInt) -> Self::Item;
and(&mut self, _: Int) -> Self::Item889     fn and(&mut self, _: Int) -> Self::Item;
or(&mut self, _: Int) -> Self::Item890     fn or(&mut self, _: Int) -> Self::Item;
xor(&mut self, _: Int) -> Self::Item891     fn xor(&mut self, _: Int) -> Self::Item;
shl(&mut self, _: Int) -> Self::Item892     fn shl(&mut self, _: Int) -> Self::Item;
shr(&mut self, _: SignfulInt) -> Self::Item893     fn shr(&mut self, _: SignfulInt) -> Self::Item;
rotl(&mut self, _: Int) -> Self::Item894     fn rotl(&mut self, _: Int) -> Self::Item;
rotr(&mut self, _: Int) -> Self::Item895     fn rotr(&mut self, _: Int) -> Self::Item;
abs(&mut self, _: Float) -> Self::Item896     fn abs(&mut self, _: Float) -> Self::Item;
neg(&mut self, _: Float) -> Self::Item897     fn neg(&mut self, _: Float) -> Self::Item;
ceil(&mut self, _: Float) -> Self::Item898     fn ceil(&mut self, _: Float) -> Self::Item;
floor(&mut self, _: Float) -> Self::Item899     fn floor(&mut self, _: Float) -> Self::Item;
trunc(&mut self, _: Float) -> Self::Item900     fn trunc(&mut self, _: Float) -> Self::Item;
nearest(&mut self, _: Float) -> Self::Item901     fn nearest(&mut self, _: Float) -> Self::Item;
sqrt(&mut self, _: Float) -> Self::Item902     fn sqrt(&mut self, _: Float) -> Self::Item;
min(&mut self, _: Float) -> Self::Item903     fn min(&mut self, _: Float) -> Self::Item;
max(&mut self, _: Float) -> Self::Item904     fn max(&mut self, _: Float) -> Self::Item;
copysign(&mut self, _: Float) -> Self::Item905     fn copysign(&mut self, _: Float) -> Self::Item;
i32_wrap_from_i64(&mut self) -> Self::Item906     fn i32_wrap_from_i64(&mut self) -> Self::Item;
i_trunc_from_f(&mut self, input_ty: Float, output_ty: SignfulInt) -> Self::Item907     fn i_trunc_from_f(&mut self, input_ty: Float, output_ty: SignfulInt) -> Self::Item;
f_convert_from_i(&mut self, input_ty: SignfulInt, output_ty: Float) -> Self::Item908     fn f_convert_from_i(&mut self, input_ty: SignfulInt, output_ty: Float) -> Self::Item;
f32_demote_from_f64(&mut self) -> Self::Item909     fn f32_demote_from_f64(&mut self) -> Self::Item;
f64_promote_from_f32(&mut self) -> Self::Item910     fn f64_promote_from_f32(&mut self) -> Self::Item;
i32_reinterpret_from_f32(&mut self) -> Self::Item911     fn i32_reinterpret_from_f32(&mut self) -> Self::Item;
i64_reinterpret_from_f64(&mut self) -> Self::Item912     fn i64_reinterpret_from_f64(&mut self) -> Self::Item;
f32_reinterpret_from_i32(&mut self) -> Self::Item913     fn f32_reinterpret_from_i32(&mut self) -> Self::Item;
f64_reinterpret_from_i64(&mut self) -> Self::Item914     fn f64_reinterpret_from_i64(&mut self) -> Self::Item;
extend(&mut self, sign: Signedness) -> Self::Item915     fn extend(&mut self, sign: Signedness) -> Self::Item;
i_sat_trunc_from_f(&mut self, input_ty: Float, output_ty: SignfulInt) -> Self::Item916     fn i_sat_trunc_from_f(&mut self, input_ty: Float, output_ty: SignfulInt) -> Self::Item;
memory_init(&mut self, segment: u32) -> Self::Item917     fn memory_init(&mut self, segment: u32) -> Self::Item;
data_drop(&mut self, segment: u32) -> Self::Item918     fn data_drop(&mut self, segment: u32) -> Self::Item;
memory_copy(&mut self) -> Self::Item919     fn memory_copy(&mut self) -> Self::Item;
memory_fill(&mut self) -> Self::Item920     fn memory_fill(&mut self) -> Self::Item;
table_init(&mut self, segment: u32) -> Self::Item921     fn table_init(&mut self, segment: u32) -> Self::Item;
elem_drop(&mut self, segment: u32) -> Self::Item922     fn elem_drop(&mut self, segment: u32) -> Self::Item;
table_copy(&mut self) -> Self::Item923     fn table_copy(&mut self) -> Self::Item;
924 }
925 
926 /// Type of a control frame.
927 #[derive(Debug, Clone, PartialEq)]
928 enum ControlFrameKind {
929     /// A regular block frame.
930     ///
931     /// Can be used for an implicit function block.
932     Block {
933         needs_end_label: bool,
934     },
935     Function,
936     /// Loop frame (branching to the beginning of block).
937     Loop,
938     /// True-subblock of if expression.
939     If {
940         has_else: bool,
941     },
942 }
943 
944 #[derive(Debug, Clone, PartialEq)]
945 struct ControlFrame {
946     id: u32,
947     arguments: u32,
948     returns: Vec<SignlessType>,
949     kind: ControlFrameKind,
950 }
951 
952 impl ControlFrame {
needs_end_label(&self) -> bool953     fn needs_end_label(&self) -> bool {
954         match self.kind {
955             ControlFrameKind::Block { needs_end_label } => needs_end_label,
956             ControlFrameKind::If { .. } => true,
957             ControlFrameKind::Loop | ControlFrameKind::Function => false,
958         }
959     }
960 
mark_branched_to(&mut self)961     fn mark_branched_to(&mut self) {
962         if let ControlFrameKind::Block { needs_end_label } = &mut self.kind {
963             *needs_end_label = true
964         }
965     }
966 
br_target(&self) -> BrTarget<(u32, NameTag)>967     fn br_target(&self) -> BrTarget<(u32, NameTag)> {
968         match self.kind {
969             ControlFrameKind::Loop => BrTarget::Label((self.id, NameTag::Header)),
970             ControlFrameKind::Function => BrTarget::Return,
971             ControlFrameKind::Block { .. } | ControlFrameKind::If { .. } => {
972                 BrTarget::Label((self.id, NameTag::End))
973             }
974         }
975     }
976 }
977 
978 #[derive(Default)]
979 struct ControlFrames {
980     inner: Vec<ControlFrame>,
981 }
982 
983 impl ControlFrames {
function_block(&self) -> &ControlFrame984     fn function_block(&self) -> &ControlFrame {
985         self.inner.first().unwrap()
986     }
987 
get(&self, n: usize) -> Option<&ControlFrame>988     fn get(&self, n: usize) -> Option<&ControlFrame> {
989         self.inner.iter().rev().nth(n)
990     }
991 
get_mut(&mut self, n: usize) -> Option<&mut ControlFrame>992     fn get_mut(&mut self, n: usize) -> Option<&mut ControlFrame> {
993         self.inner.iter_mut().rev().nth(n)
994     }
995 
top(&self) -> Option<&ControlFrame>996     fn top(&self) -> Option<&ControlFrame> {
997         self.get(0)
998     }
999 
top_mut(&mut self) -> Option<&mut ControlFrame>1000     fn top_mut(&mut self) -> Option<&mut ControlFrame> {
1001         self.get_mut(0)
1002     }
1003 
is_empty(&self) -> bool1004     fn is_empty(&self) -> bool {
1005         self.inner.is_empty()
1006     }
1007 
pop(&mut self) -> Option<ControlFrame>1008     fn pop(&mut self) -> Option<ControlFrame> {
1009         self.inner.pop()
1010     }
1011 
push(&mut self, val: ControlFrame)1012     fn push(&mut self, val: ControlFrame) {
1013         self.inner.push(val)
1014     }
1015 }
1016 
1017 impl std::ops::Index<usize> for ControlFrames {
1018     type Output = ControlFrame;
1019 
index(&self, index: usize) -> &Self::Output1020     fn index(&self, index: usize) -> &Self::Output {
1021         self.get(index).unwrap()
1022     }
1023 }
1024 
1025 impl std::ops::IndexMut<usize> for ControlFrames {
index_mut(&mut self, index: usize) -> &mut Self::Output1026     fn index_mut(&mut self, index: usize) -> &mut Self::Output {
1027         self.get_mut(index).unwrap()
1028     }
1029 }
1030 
1031 pub struct MicrowasmConv<'a, M> {
1032     // TODO: Maybe have a `ConvInner` type and have this wrap an `Option` so that
1033     //       we can dealloc everything when we've finished emitting
1034     is_done: bool,
1035     consts_to_emit: Option<Vec<Value>>,
1036     stack: Vec<SignlessType>,
1037     operators: OperatorsReader<'a>,
1038     module: &'a M,
1039     current_id: u32,
1040     pointer_type: SignlessType,
1041     control_frames: ControlFrames,
1042     unreachable: bool,
1043 }
1044 
1045 #[derive(Debug)]
1046 enum SigT {
1047     T,
1048     Concrete(SignlessType),
1049 }
1050 
1051 impl fmt::Display for SigT {
fmt(&self, f: &mut fmt::Formatter) -> fmt::Result1052     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
1053         match self {
1054             Self::T => write!(f, "{{any}}"),
1055             Self::Concrete(ty) => write!(f, "{}", ty),
1056         }
1057     }
1058 }
1059 
1060 impl From<SignlessType> for SigT {
from(other: SignlessType) -> SigT1061     fn from(other: SignlessType) -> SigT {
1062         SigT::Concrete(other)
1063     }
1064 }
1065 
1066 #[derive(Debug)]
1067 pub struct OpSig {
1068     input: SmallVec<[SigT; 3]>,
1069     output: SmallVec<[SigT; 3]>,
1070 }
1071 
1072 impl fmt::Display for OpSig {
fmt(&self, f: &mut fmt::Formatter) -> fmt::Result1073     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
1074         write!(f, "(")?;
1075 
1076         let mut iter = self.input.iter();
1077         if let Some(t) = iter.next() {
1078             write!(f, "{}", t)?;
1079         }
1080 
1081         for t in iter {
1082             write!(f, ", {}", t)?;
1083         }
1084 
1085         write!(f, ") -> (")?;
1086 
1087         let mut iter = self.output.iter();
1088         if let Some(t) = iter.next() {
1089             write!(f, "{}", t)?;
1090         }
1091 
1092         for t in iter {
1093             write!(f, ", {}", t)?;
1094         }
1095 
1096         write!(f, ")")
1097     }
1098 }
1099 
1100 impl OpSig {
1101     #[inline(always)]
new<I0, I1>(input: I0, output: I1) -> Self where I0: IntoIterator<Item = SigT>, I1: IntoIterator<Item = SigT>,1102     fn new<I0, I1>(input: I0, output: I1) -> Self
1103     where
1104         I0: IntoIterator<Item = SigT>,
1105         I1: IntoIterator<Item = SigT>,
1106     {
1107         OpSig {
1108             input: SmallVec::from_iter(input),
1109             output: SmallVec::from_iter(output),
1110         }
1111     }
1112 
none() -> Self1113     fn none() -> Self {
1114         Self::new(None, None)
1115     }
1116 }
1117 
1118 impl<T> From<&'_ T> for OpSig
1119 where
1120     T: Signature,
1121 {
from(other: &T) -> Self1122     fn from(other: &T) -> Self {
1123         OpSig::new(
1124             other
1125                 .params()
1126                 .iter()
1127                 .map(|t| SigT::Concrete(t.to_microwasm_type())),
1128             other
1129                 .returns()
1130                 .iter()
1131                 .map(|t| SigT::Concrete(t.to_microwasm_type())),
1132         )
1133     }
1134 }
1135 
1136 impl<'a, M: ModuleContext> MicrowasmConv<'a, M>
1137 where
1138     for<'any> &'any M::Signature: Into<OpSig>,
1139 {
new( context: &'a M, params: impl IntoIterator<Item = SignlessType>, returns: impl IntoIterator<Item = SignlessType>, func_body: FunctionBody<'a>, pointer_type: SignlessType, ) -> Result<Self, Error>1140     pub fn new(
1141         context: &'a M,
1142         params: impl IntoIterator<Item = SignlessType>,
1143         returns: impl IntoIterator<Item = SignlessType>,
1144         func_body: FunctionBody<'a>,
1145         pointer_type: SignlessType,
1146     ) -> Result<Self, Error> {
1147         let mut locals = Vec::from_iter(params);
1148         let mut consts = Vec::new();
1149 
1150         let local_reader = func_body.get_locals_reader()?;
1151         let operators = func_body.get_operators_reader()?;
1152 
1153         for loc in local_reader {
1154             let (count, ty) =
1155                 loc.map_err(|e| Error::Microwasm(format!("Getting local failed: {}", e)))?;
1156             let ty = Type::from_wasm(ty)
1157                 .map_err(|_| Error::Microwasm("Invalid local type".to_string()))?;
1158 
1159             locals.extend(std::iter::repeat(ty).take(count as _));
1160             consts.extend(
1161                 std::iter::repeat(ty)
1162                     .map(Value::default_for_type)
1163                     .take(count as _),
1164             )
1165         }
1166 
1167         let num_locals = locals.len() as _;
1168 
1169         let mut out = Self {
1170             is_done: false,
1171             stack: locals,
1172             module: context,
1173             consts_to_emit: Some(consts),
1174             operators,
1175             current_id: 0,
1176             control_frames: Default::default(),
1177             pointer_type,
1178             unreachable: false,
1179         };
1180 
1181         let id = out.next_id();
1182         out.control_frames.push(ControlFrame {
1183             id,
1184             arguments: num_locals,
1185             returns: returns.into_iter().collect(),
1186             kind: ControlFrameKind::Function,
1187         });
1188 
1189         Ok(out)
1190     }
1191 
type_or_func_type_to_sig( &self, ty: wasmparser::TypeOrFuncType, ) -> Result< ( impl ExactSizeIterator<Item = SignlessType> + '_, impl ExactSizeIterator<Item = SignlessType> + '_, ), Error, >1192     fn type_or_func_type_to_sig(
1193         &self,
1194         ty: wasmparser::TypeOrFuncType,
1195     ) -> Result<
1196         (
1197             impl ExactSizeIterator<Item = SignlessType> + '_,
1198             impl ExactSizeIterator<Item = SignlessType> + '_,
1199         ),
1200         Error,
1201     > {
1202         match ty {
1203             wasmparser::TypeOrFuncType::Type(ty) => {
1204                 let mwasm_type = Type::from_wasm_block(ty)?;
1205 
1206                 Ok((
1207                     Either::Left(iter::empty()),
1208                     Either::Left(mwasm_type.into_iter()),
1209                 ))
1210             }
1211             wasmparser::TypeOrFuncType::FuncType(ty) => {
1212                 let sig = self.module.signature(ty);
1213                 Ok((
1214                     Either::Right(sig.params().iter().map(|t| t.to_microwasm_type())),
1215                     Either::Right(sig.returns().iter().map(|t| t.to_microwasm_type())),
1216                 ))
1217             }
1218         }
1219     }
1220 
op_sig(&self, op: &WasmOperator) -> Result<OpSig, Error>1221     fn op_sig(&self, op: &WasmOperator) -> Result<OpSig, Error> {
1222         use self::SigT::T;
1223         use std::iter::{empty as none, once};
1224 
1225         #[inline(always)]
1226         fn one<A>(a: A) -> impl IntoIterator<Item = SigT>
1227         where
1228             A: Into<SigT>,
1229         {
1230             once(a.into())
1231         }
1232 
1233         #[inline(always)]
1234         fn two<A, B>(a: A, b: B) -> impl IntoIterator<Item = SigT>
1235         where
1236             A: Into<SigT>,
1237             B: Into<SigT>,
1238         {
1239             once(a.into()).chain(once(b.into()))
1240         }
1241 
1242         #[inline(always)]
1243         fn three<A, B, C>(a: A, b: B, c: C) -> impl IntoIterator<Item = SigT>
1244         where
1245             A: Into<SigT>,
1246             B: Into<SigT>,
1247             C: Into<SigT>,
1248         {
1249             once(a.into()).chain(once(b.into())).chain(once(c.into()))
1250         }
1251 
1252         macro_rules! sig {
1253             (@iter $a:expr, $b:expr, $c:expr) => { three($a, $b, $c) };
1254             (@iter $a:expr, $b:expr) => { two($a, $b) };
1255             (@iter $a:expr) => { one($a) };
1256             (@iter) => { none() };
1257             (($($t:expr),*) -> ($($o:expr),*)) => {
1258                 OpSig::new(sig!(@iter $($t),*), sig!(@iter $($o),*))
1259             };
1260         }
1261 
1262         let o = match op {
1263             WasmOperator::Unreachable => OpSig::none(),
1264             WasmOperator::Nop => OpSig::none(),
1265 
1266             WasmOperator::Block { .. } => OpSig::none(),
1267             WasmOperator::Loop { .. } => OpSig::none(),
1268             WasmOperator::If { .. } => sig!((I32) -> ()),
1269             WasmOperator::Else => OpSig::none(),
1270             WasmOperator::End => OpSig::none(),
1271 
1272             WasmOperator::Br { .. } => OpSig::none(),
1273             WasmOperator::BrIf { .. } => sig!((I32) -> ()),
1274             WasmOperator::BrTable { .. } => sig!((I32) -> ()),
1275             WasmOperator::Return => OpSig::none(),
1276 
1277             WasmOperator::Call { function_index } => {
1278                 let func_type = self.module.func_type(*function_index);
1279                 func_type.into()
1280             }
1281             WasmOperator::CallIndirect { index, .. } => {
1282                 let func_type = self.module.signature(*index);
1283                 let mut out = func_type.into();
1284                 out.input.push(I32.into());
1285                 out
1286             }
1287 
1288             WasmOperator::Drop => sig!((T) -> ()),
1289 
1290             // `Select` pops 3 elements and pushes 1
1291             WasmOperator::Select => sig!((T, T, I32) -> (T)),
1292 
1293             WasmOperator::LocalGet { local_index } => {
1294                 let ty = self.stack[*local_index as usize];
1295 
1296                 sig!(() -> (ty))
1297             }
1298             WasmOperator::LocalSet { local_index } => {
1299                 let ty = self.stack[*local_index as usize];
1300 
1301                 sig!((ty) -> ())
1302             }
1303             WasmOperator::LocalTee { local_index } => {
1304                 let ty = self.stack[*local_index as usize];
1305 
1306                 sig!((ty) -> (ty))
1307             }
1308 
1309             WasmOperator::GlobalGet { global_index } => {
1310                 sig!(() -> (self.module.global_type(*global_index).to_microwasm_type()))
1311             }
1312             WasmOperator::GlobalSet { global_index } => {
1313                 sig!((self.module.global_type(*global_index).to_microwasm_type()) -> ())
1314             }
1315 
1316             WasmOperator::F32Load { .. } => sig!((self.pointer_type) -> (F32)),
1317             WasmOperator::F64Load { .. } => sig!((self.pointer_type) -> (F64)),
1318 
1319             WasmOperator::I32Load { .. }
1320             | WasmOperator::I32Load8S { .. }
1321             | WasmOperator::I32Load8U { .. }
1322             | WasmOperator::I32Load16S { .. }
1323             | WasmOperator::I32Load16U { .. } => sig!((self.pointer_type) -> (I32)),
1324 
1325             WasmOperator::I64Load { .. }
1326             | WasmOperator::I64Load8S { .. }
1327             | WasmOperator::I64Load8U { .. }
1328             | WasmOperator::I64Load16S { .. }
1329             | WasmOperator::I64Load16U { .. }
1330             | WasmOperator::I64Load32S { .. }
1331             | WasmOperator::I64Load32U { .. } => sig!((self.pointer_type) -> (I64)),
1332 
1333             WasmOperator::F32Store { .. } => sig!((self.pointer_type, F32) -> ()),
1334             WasmOperator::F64Store { .. } => sig!((self.pointer_type, F64) -> ()),
1335             WasmOperator::I32Store { .. }
1336             | WasmOperator::I32Store8 { .. }
1337             | WasmOperator::I32Store16 { .. } => sig!((self.pointer_type, I32) -> ()),
1338             WasmOperator::I64Store { .. }
1339             | WasmOperator::I64Store8 { .. }
1340             | WasmOperator::I64Store16 { .. }
1341             | WasmOperator::I64Store32 { .. } => sig!((self.pointer_type, I64) -> ()),
1342 
1343             WasmOperator::MemorySize { .. } => sig!(() -> (self.pointer_type)),
1344             WasmOperator::MemoryGrow { .. } => sig!((self.pointer_type) -> (self.pointer_type)),
1345 
1346             WasmOperator::I32Const { .. } => sig!(() -> (I32)),
1347             WasmOperator::I64Const { .. } => sig!(() -> (I64)),
1348             WasmOperator::F32Const { .. } => sig!(() -> (F32)),
1349             WasmOperator::F64Const { .. } => sig!(() -> (F64)),
1350 
1351             // WasmOperator::RefNull => {
1352             //     return Err(BinaryReaderError {
1353             //         message: "RefNull unimplemented",
1354             //         offset: None,
1355             //     })
1356             // }
1357             // WasmOperator::RefIsNull => {
1358             //     return Err(wasm_reader::Error::new (
1359             //         strerr("RefIsNull unimplemented"),
1360             //         None,
1361             //     ))
1362             // }
1363 
1364             // All comparison operators remove 2 elements and push 1
1365             WasmOperator::I32Eqz => sig!((I32) -> (I32)),
1366             WasmOperator::I32Eq
1367             | WasmOperator::I32Ne
1368             | WasmOperator::I32LtS
1369             | WasmOperator::I32LtU
1370             | WasmOperator::I32GtS
1371             | WasmOperator::I32GtU
1372             | WasmOperator::I32LeS
1373             | WasmOperator::I32LeU
1374             | WasmOperator::I32GeS
1375             | WasmOperator::I32GeU => sig!((I32, I32) -> (I32)),
1376 
1377             WasmOperator::I64Eqz => sig!((I64) -> (I32)),
1378             WasmOperator::I64Eq
1379             | WasmOperator::I64Ne
1380             | WasmOperator::I64LtS
1381             | WasmOperator::I64LtU
1382             | WasmOperator::I64GtS
1383             | WasmOperator::I64GtU
1384             | WasmOperator::I64LeS
1385             | WasmOperator::I64LeU
1386             | WasmOperator::I64GeS
1387             | WasmOperator::I64GeU => sig!((I64, I64) -> (I32)),
1388 
1389             WasmOperator::F32Eq
1390             | WasmOperator::F32Ne
1391             | WasmOperator::F32Lt
1392             | WasmOperator::F32Gt
1393             | WasmOperator::F32Le
1394             | WasmOperator::F32Ge => sig!((F32, F32) -> (I32)),
1395 
1396             WasmOperator::F64Eq
1397             | WasmOperator::F64Ne
1398             | WasmOperator::F64Lt
1399             | WasmOperator::F64Gt
1400             | WasmOperator::F64Le
1401             | WasmOperator::F64Ge => sig!((F64, F64) -> (I32)),
1402 
1403             WasmOperator::I32Clz | WasmOperator::I32Ctz | WasmOperator::I32Popcnt => {
1404                 sig!((I32) -> (I32))
1405             }
1406             WasmOperator::I64Clz | WasmOperator::I64Ctz | WasmOperator::I64Popcnt => {
1407                 sig!((I64) -> (I64))
1408             }
1409 
1410             WasmOperator::I32Add
1411             | WasmOperator::I32Sub
1412             | WasmOperator::I32Mul
1413             | WasmOperator::I32DivS
1414             | WasmOperator::I32DivU
1415             | WasmOperator::I32RemS
1416             | WasmOperator::I32RemU
1417             | WasmOperator::I32And
1418             | WasmOperator::I32Or
1419             | WasmOperator::I32Xor
1420             | WasmOperator::I32Shl
1421             | WasmOperator::I32ShrS
1422             | WasmOperator::I32ShrU
1423             | WasmOperator::I32Rotl
1424             | WasmOperator::I32Rotr => sig!((I32, I32) -> (I32)),
1425 
1426             WasmOperator::I64Add
1427             | WasmOperator::I64Sub
1428             | WasmOperator::I64Mul
1429             | WasmOperator::I64DivS
1430             | WasmOperator::I64DivU
1431             | WasmOperator::I64RemS
1432             | WasmOperator::I64RemU
1433             | WasmOperator::I64And
1434             | WasmOperator::I64Or
1435             | WasmOperator::I64Xor
1436             | WasmOperator::I64Shl
1437             | WasmOperator::I64ShrS
1438             | WasmOperator::I64ShrU
1439             | WasmOperator::I64Rotl
1440             | WasmOperator::I64Rotr => sig!((I64, I64) -> (I64)),
1441 
1442             WasmOperator::F32Abs
1443             | WasmOperator::F32Neg
1444             | WasmOperator::F32Ceil
1445             | WasmOperator::F32Floor
1446             | WasmOperator::F32Trunc
1447             | WasmOperator::F32Nearest
1448             | WasmOperator::F32Sqrt => sig!((F32) -> (F32)),
1449 
1450             WasmOperator::F64Abs
1451             | WasmOperator::F64Neg
1452             | WasmOperator::F64Ceil
1453             | WasmOperator::F64Floor
1454             | WasmOperator::F64Trunc
1455             | WasmOperator::F64Nearest
1456             | WasmOperator::F64Sqrt => sig!((F64) -> (F64)),
1457 
1458             WasmOperator::F32Add
1459             | WasmOperator::F32Sub
1460             | WasmOperator::F32Mul
1461             | WasmOperator::F32Div
1462             | WasmOperator::F32Min
1463             | WasmOperator::F32Max
1464             | WasmOperator::F32Copysign => sig!((F32, F32) -> (F32)),
1465 
1466             WasmOperator::F64Add
1467             | WasmOperator::F64Sub
1468             | WasmOperator::F64Mul
1469             | WasmOperator::F64Div
1470             | WasmOperator::F64Min
1471             | WasmOperator::F64Max
1472             | WasmOperator::F64Copysign => sig!((F64, F64) -> (F64)),
1473 
1474             WasmOperator::I32WrapI64 => sig!((I64) -> (I32)),
1475             WasmOperator::I32TruncF32S | WasmOperator::I32TruncF32U => sig!((F32) -> (I32)),
1476             WasmOperator::I32TruncF64S | WasmOperator::I32TruncF64U => sig!((F64) -> (I32)),
1477             WasmOperator::I64ExtendI32S | WasmOperator::I64ExtendI32U => sig!((I32) -> (I64)),
1478             WasmOperator::I64TruncF32S | WasmOperator::I64TruncF32U => sig!((F32) -> (I64)),
1479             WasmOperator::I64TruncF64S | WasmOperator::I64TruncF64U => sig!((F64) -> (I64)),
1480             WasmOperator::F32ConvertI32S | WasmOperator::F32ConvertI32U => sig!((I32) -> (F32)),
1481             WasmOperator::F32ConvertI64S | WasmOperator::F32ConvertI64U => sig!((I64) -> (F32)),
1482             WasmOperator::F32DemoteF64 => sig!((F64) -> (F32)),
1483             WasmOperator::F64ConvertI32S | WasmOperator::F64ConvertI32U => sig!((I32) -> (F64)),
1484             WasmOperator::F64ConvertI64S | WasmOperator::F64ConvertI64U => sig!((I64) -> (F64)),
1485             WasmOperator::F64PromoteF32 => sig!((F32) -> (F64)),
1486             WasmOperator::I32ReinterpretF32 => sig!((F32) -> (I32)),
1487             WasmOperator::I64ReinterpretF64 => sig!((F64) -> (I64)),
1488             WasmOperator::F32ReinterpretI32 => sig!((I32) -> (F32)),
1489             WasmOperator::F64ReinterpretI64 => sig!((I64) -> (F64)),
1490 
1491             WasmOperator::I32Extend8S => sig!((I32) -> (I32)),
1492             WasmOperator::I32Extend16S => sig!((I32) -> (I32)),
1493             WasmOperator::I64Extend8S => sig!((I32) -> (I64)),
1494             WasmOperator::I64Extend16S => sig!((I32) -> (I64)),
1495             WasmOperator::I64Extend32S => sig!((I32) -> (I64)),
1496 
1497             _ => return Err(Error::Microwasm("Opcode Unimplemented".into())),
1498         };
1499         Ok(o)
1500     }
1501 
next_id(&mut self) -> u321502     fn next_id(&mut self) -> u32 {
1503         let id = self.current_id;
1504         self.current_id += 1;
1505         id
1506     }
1507 
local_depth(&self, idx: u32) -> i321508     fn local_depth(&self, idx: u32) -> i32 {
1509         self.stack.len() as i32 - 1 - idx as i32
1510     }
1511 
apply_op(&mut self, sig: OpSig) -> Result<(), Error>1512     fn apply_op(&mut self, sig: OpSig) -> Result<(), Error> {
1513         let mut ty_param = None;
1514 
1515         for p in sig.input.iter().rev() {
1516             let stack_ty = match self.stack.pop() {
1517                 Some(e) => e,
1518                 None => return Err(Error::Microwasm("Stack is empty".into())),
1519             };
1520 
1521             let ty = match p {
1522                 SigT::T => {
1523                     if let Some(t) = ty_param {
1524                         t
1525                     } else {
1526                         ty_param = Some(stack_ty);
1527                         stack_ty
1528                     }
1529                 }
1530                 SigT::Concrete(ty) => *ty,
1531             };
1532 
1533             if ty != stack_ty {
1534                 return Err(Error::Microwasm(format!(
1535                     "Error in params for op (sig {}): expected {}, found {}",
1536                     sig, ty, stack_ty
1537                 )));
1538             }
1539         }
1540 
1541         for p in sig.output.into_iter().rev() {
1542             let ty = match p {
1543                 SigT::T => match ty_param {
1544                     Some(e) => e,
1545                     None => return Err(Error::Microwasm("Type parameter was not set".into())),
1546                 },
1547                 SigT::Concrete(ty) => ty,
1548             };
1549             self.stack.push(ty);
1550         }
1551         Ok(())
1552     }
1553 
block_params(&self) -> Vec<SignlessType>1554     fn block_params(&self) -> Vec<SignlessType> {
1555         self.stack.clone()
1556     }
1557 
block_params_with_wasm_type( &self, ty: wasmparser::TypeOrFuncType, ) -> Result<impl Iterator<Item = SignlessType> + '_, Error>1558     fn block_params_with_wasm_type(
1559         &self,
1560         ty: wasmparser::TypeOrFuncType,
1561     ) -> Result<impl Iterator<Item = SignlessType> + '_, Error> {
1562         let (params, returns) = self.type_or_func_type_to_sig(ty)?;
1563         Ok(self.stack[0..self.stack.len() - params.len()]
1564             .iter()
1565             .copied()
1566             .chain(returns))
1567     }
1568 
1569     // Separate from `<Self as Iterator>::next` so we can use `?` to return errors (as
1570     // `Iterator::next` returns an option and so we'd only be able to use `?` for `None`)
1571     #[inline(always)]
next( &mut self, ) -> Result<Option<impl ExactSizeIterator<Item = OperatorFromWasm> + '_>, Error>1572     fn next(
1573         &mut self,
1574     ) -> Result<Option<impl ExactSizeIterator<Item = OperatorFromWasm> + '_>, Error> {
1575         use derive_more::From;
1576         use iter_enum::{ExactSizeIterator, Iterator};
1577         use staticvec::{staticvec, StaticVec, StaticVecIntoIter};
1578 
1579         struct Consts {
1580             inner: <Vec<Value> as IntoIterator>::IntoIter,
1581         }
1582 
1583         impl Iterator for Consts {
1584             type Item = OperatorFromWasm;
1585 
1586             fn size_hint(&self) -> (usize, Option<usize>) {
1587                 self.inner.size_hint()
1588             }
1589 
1590             fn next(&mut self) -> Option<Self::Item> {
1591                 self.inner.next().map(Operator::Const)
1592             }
1593         }
1594 
1595         impl ExactSizeIterator for Consts {}
1596 
1597         fn consts(consts: Vec<Value>) -> Output {
1598             fn impl_trait_hack(consts: Vec<Value>) -> Consts {
1599                 Consts {
1600                     inner: consts.into_iter(),
1601                 }
1602             }
1603 
1604             Output::Consts(impl_trait_hack(consts))
1605         }
1606 
1607         fn vec(vals: impl Into<StaticVec<OperatorFromWasm, 5>>) -> Output {
1608             vals.into().into_iter().into()
1609         }
1610 
1611         fn iter(vals: impl IntoIterator<Item = OperatorFromWasm>) -> Output {
1612             let mut vals = vals.into_iter();
1613             let v = StaticVec::from_iter(vals.by_ref());
1614             if let Some(next) = vals.next() {
1615                 let mut v = Vec::from_iter(v);
1616                 v.push(next);
1617                 v.extend(vals);
1618                 Output::VariableLength(v.into_iter())
1619             } else {
1620                 vec(v)
1621             }
1622         }
1623 
1624         fn none() -> Output {
1625             Output::None(std::iter::empty())
1626         }
1627 
1628         fn one(op: OperatorFromWasm) -> Output {
1629             Output::One(std::iter::once(op))
1630         }
1631 
1632         #[derive(From, Iterator, ExactSizeIterator)]
1633         enum Output {
1634             Consts(Consts),
1635             FixedLength(StaticVecIntoIter<OperatorFromWasm, 5>),
1636             VariableLength(std::vec::IntoIter<OperatorFromWasm>),
1637             None(std::iter::Empty<OperatorFromWasm>),
1638             One(std::iter::Once<OperatorFromWasm>),
1639         }
1640 
1641         macro_rules! to_drop {
1642             ($block:expr) => {
1643                 to_drop!($block, self.stack)
1644             };
1645             ($block:expr, $stack:expr) => {{
1646                 let block = &$block;
1647                 let len = $stack.len();
1648                 let first_non_local_depth = block.returns.len() as u32;
1649 
1650                 (|| {
1651                     let last_non_local_depth =
1652                         (len as u32).checked_sub(1)?.checked_sub(block.arguments)?;
1653 
1654                     if first_non_local_depth <= last_non_local_depth {
1655                         Some(first_non_local_depth..=last_non_local_depth)
1656                     } else {
1657                         None
1658                     }
1659                 })()
1660             }};
1661         }
1662 
1663         if let Some(consts_to_emit) = self.consts_to_emit.take() {
1664             return Ok(Some(consts(consts_to_emit)));
1665         }
1666 
1667         if self.unreachable {
1668             self.unreachable = false;
1669             let mut depth = 0;
1670 
1671             // `if..then..else`/`br_if` means that there may be branches in which
1672             // the instruction that caused us to mark this as unreachable to not
1673             // be executed. Tracking this in the microwasm translation step is
1674             // very complicated so we just do basic code removal here and leave
1675             // the removal of uncalled blocks to the backend.
1676             return Ok(Some(loop {
1677                 if self.is_done {
1678                     return Ok(None);
1679                 }
1680 
1681                 let op = self.operators.read()?;
1682 
1683                 match op {
1684                     WasmOperator::Block { .. }
1685                     | WasmOperator::Loop { .. }
1686                     | WasmOperator::If { .. } => {
1687                         depth += 1;
1688                     }
1689                     WasmOperator::Else => {
1690                         if depth == 0 {
1691                             let block = self.control_frames.top_mut().ok_or_else(|| {
1692                                 Error::Microwasm("unreachable Block else Failed".into())
1693                             })?;
1694 
1695                             self.stack.truncate(block.arguments as _);
1696 
1697                             if let ControlFrameKind::If { has_else, .. } = &mut block.kind {
1698                                 *has_else = true;
1699                             }
1700 
1701                             break one(Operator::Label((block.id, NameTag::Else)));
1702                         }
1703                     }
1704                     WasmOperator::End => {
1705                         if depth == 0 {
1706                             let block = self.control_frames.pop().ok_or_else(|| {
1707                                 Error::Microwasm("unreachable Block end Failed".into())
1708                             })?;
1709 
1710                             if self.control_frames.is_empty() {
1711                                 self.is_done = true;
1712                                 return Ok(Some(none()));
1713                             }
1714 
1715                             self.stack.truncate(block.arguments as _);
1716                             self.stack.extend(block.returns);
1717 
1718                             let end_label = (block.id, NameTag::End);
1719 
1720                             if let ControlFrameKind::If {
1721                                 has_else: false, ..
1722                             } = block.kind
1723                             {
1724                                 break vec([
1725                                     Operator::Label((block.id, NameTag::Else)),
1726                                     Operator::Br {
1727                                         target: BrTarget::Label(end_label),
1728                                     },
1729                                     Operator::Label(end_label),
1730                                 ]);
1731                             } else {
1732                                 break one(Operator::Label((block.id, NameTag::End)));
1733                             }
1734                         } else {
1735                             depth -= 1;
1736                         }
1737                     }
1738                     _ => {}
1739                 }
1740             }));
1741         }
1742 
1743         if self.is_done {
1744             return Ok(None);
1745         }
1746 
1747         let op = self.operators.read()?;
1748 
1749         let op_sig = self.op_sig(&op)?;
1750 
1751         self.apply_op(op_sig)
1752             .map_err(|e| Error::Microwasm(format!("{} (in {:?})", e, op)))?;
1753 
1754         Ok(Some(match op {
1755             WasmOperator::Unreachable => {
1756                 self.unreachable = true;
1757                 one(Operator::Unreachable)
1758             }
1759             WasmOperator::Nop => none(),
1760             WasmOperator::Block { ty } => {
1761                 let id = self.next_id();
1762                 let (_, returns) = self.type_or_func_type_to_sig(ty)?;
1763                 let returns = returns.collect();
1764                 self.control_frames.push(ControlFrame {
1765                     id,
1766                     arguments: self.stack.len() as u32,
1767                     returns,
1768                     kind: ControlFrameKind::Block {
1769                         needs_end_label: false,
1770                     },
1771                 });
1772 
1773                 let block_param_type_wasm = self.block_params_with_wasm_type(ty)?;
1774 
1775                 one(Operator::end(
1776                     block_param_type_wasm.collect(),
1777                     (id, NameTag::End),
1778                 ))
1779             }
1780             WasmOperator::Loop { ty } => {
1781                 let id = self.next_id();
1782                 let (_, returns) = self.type_or_func_type_to_sig(ty)?;
1783                 let returns = returns.collect();
1784                 self.control_frames.push(ControlFrame {
1785                     id,
1786                     arguments: self.stack.len() as u32,
1787                     returns,
1788                     kind: ControlFrameKind::Loop,
1789                 });
1790 
1791                 let block_param_type_wasm = self.block_params_with_wasm_type(ty)?;
1792                 let label = (id, NameTag::Header);
1793 
1794                 vec([
1795                     Operator::loop_(self.block_params(), label),
1796                     Operator::end(block_param_type_wasm.collect(), (id, NameTag::End)),
1797                     Operator::Br {
1798                         target: BrTarget::Label(label),
1799                     },
1800                     Operator::Label(label),
1801                 ])
1802             }
1803             WasmOperator::If { ty } => {
1804                 let id = self.next_id();
1805                 let (_, returns) = self.type_or_func_type_to_sig(ty)?;
1806                 let returns = returns.collect();
1807                 self.control_frames.push(ControlFrame {
1808                     id,
1809                     arguments: self.stack.len() as u32,
1810                     returns,
1811                     kind: ControlFrameKind::If { has_else: false },
1812                 });
1813                 let block_param_type_wasm = self.block_params_with_wasm_type(ty)?;
1814 
1815                 let (then, else_, end) = (
1816                     (id, NameTag::Header),
1817                     (id, NameTag::Else),
1818                     (id, NameTag::End),
1819                 );
1820                 vec([
1821                     Operator::block(self.block_params(), then),
1822                     Operator::block(self.block_params(), else_),
1823                     Operator::end(block_param_type_wasm.collect(), end),
1824                     Operator::BrIf {
1825                         then: BrTarget::Label(then).into(),
1826                         else_: BrTarget::Label(else_).into(),
1827                     },
1828                     Operator::Label(then),
1829                 ])
1830             }
1831             WasmOperator::Else => {
1832                 let block = self
1833                     .control_frames
1834                     .top()
1835                     .ok_or_else(|| Error::Microwasm("Block else Failed".into()))?;
1836                 let to_drop = to_drop!(block);
1837                 let block = self
1838                     .control_frames
1839                     .top_mut()
1840                     .ok_or_else(|| Error::Microwasm("Block else Failed".into()))?;
1841 
1842                 if let ControlFrameKind::If { has_else, .. } = &mut block.kind {
1843                     *has_else = true;
1844                 }
1845 
1846                 self.stack.truncate(block.arguments as _);
1847 
1848                 let label = (block.id, NameTag::Else);
1849 
1850                 iter(to_drop.into_iter().map(Operator::Drop).chain(staticvec![
1851                     Operator::Br {
1852                         target: BrTarget::Label((block.id, NameTag::End)),
1853                     },
1854                     Operator::Label(label)
1855                 ]))
1856             }
1857             WasmOperator::End => {
1858                 let block = self
1859                     .control_frames
1860                     .pop()
1861                     .ok_or_else(|| Error::Microwasm("Block End Failed".into()))?;
1862 
1863                 let to_drop = to_drop!(block);
1864 
1865                 self.stack.truncate(block.arguments as _);
1866                 self.stack.extend(block.returns.iter().cloned());
1867 
1868                 if let ControlFrameKind::If {
1869                     has_else: false, ..
1870                 } = block.kind
1871                 {
1872                     let else_ = (block.id, NameTag::Else);
1873                     let end = (block.id, NameTag::End);
1874 
1875                     iter(to_drop.map(Operator::Drop).into_iter().chain(staticvec![
1876                         Operator::Br {
1877                             target: BrTarget::Label(end),
1878                         },
1879                         Operator::Label(else_),
1880                         Operator::Br {
1881                             target: BrTarget::Label(end),
1882                         },
1883                         Operator::Label(end),
1884                     ]))
1885                 } else {
1886                     if self.control_frames.is_empty() {
1887                         self.is_done = true;
1888 
1889                         one(Operator::Br {
1890                             target: BrTarget::Return,
1891                         })
1892                     } else if block.needs_end_label() {
1893                         let label = (block.id, NameTag::End);
1894 
1895                         iter(to_drop.map(Operator::Drop).into_iter().chain(staticvec![
1896                             Operator::Br {
1897                                 target: BrTarget::Label(label),
1898                             },
1899                             Operator::Label(label)
1900                         ]))
1901                     } else {
1902                         iter(to_drop.map(Operator::Drop).into_iter())
1903                     }
1904                 }
1905             }
1906             WasmOperator::Br { relative_depth } => {
1907                 self.unreachable = true;
1908                 let to_drop = to_drop!(self.control_frames[relative_depth as _]);
1909 
1910                 let block = &mut self.control_frames[relative_depth as _];
1911                 block.mark_branched_to();
1912                 iter(
1913                     to_drop
1914                         .into_iter()
1915                         .map(Operator::Drop)
1916                         .chain(iter::once(Operator::Br {
1917                             target: block.br_target(),
1918                         })),
1919                 )
1920             }
1921             WasmOperator::BrIf { relative_depth } => {
1922                 let to_drop = to_drop!(self.control_frames[relative_depth as _]);
1923 
1924                 let label = (self.next_id(), NameTag::Header);
1925                 let params = self.block_params();
1926                 let block = &mut self.control_frames[relative_depth as _];
1927                 block.mark_branched_to();
1928 
1929                 vec([
1930                     Operator::block(params, label),
1931                     Operator::BrIf {
1932                         then: BrTargetDrop {
1933                             to_drop,
1934                             target: block.br_target(),
1935                         },
1936                         else_: BrTarget::Label(label).into(),
1937                     },
1938                     Operator::Label(label),
1939                 ])
1940             }
1941             WasmOperator::BrTable { table } => {
1942                 self.unreachable = true;
1943                 let (targets, default) = table.read_table()?;
1944                 let control_frames = &mut self.control_frames;
1945                 let stack = &self.stack;
1946                 let targets = targets
1947                     .into_iter()
1948                     .map(|&depth| {
1949                         control_frames[depth as _].mark_branched_to();
1950                         let block = &control_frames[depth as _];
1951 
1952                         let target = block.br_target();
1953                         BrTargetDrop {
1954                             to_drop: to_drop!(block, stack),
1955                             target,
1956                         }
1957                     })
1958                     .collect::<Vec<_>>();
1959 
1960                 self.control_frames[default as _].mark_branched_to();
1961 
1962                 let default = &self.control_frames[default as _];
1963                 let target = default.br_target();
1964                 let default = BrTargetDrop {
1965                     to_drop: to_drop!(default),
1966                     target,
1967                 };
1968 
1969                 one(Operator::BrTable(BrTable { targets, default }))
1970             }
1971             WasmOperator::Return => {
1972                 self.unreachable = true;
1973 
1974                 let block = self.control_frames.function_block();
1975                 let to_drop = to_drop!(block);
1976 
1977                 iter(
1978                     to_drop
1979                         .into_iter()
1980                         .map(Operator::Drop)
1981                         .chain(iter::once(Operator::Br {
1982                             target: block.br_target(),
1983                         })),
1984                 )
1985             }
1986             WasmOperator::Call { function_index } => one(Operator::Call { function_index }),
1987             WasmOperator::CallIndirect { index, table_index } => one(Operator::CallIndirect {
1988                 type_index: index,
1989                 table_index,
1990             }),
1991             WasmOperator::Drop => one(Operator::Drop(0..=0)),
1992             WasmOperator::Select => one(Operator::Select),
1993 
1994             WasmOperator::LocalGet { local_index } => {
1995                 let depth = self
1996                     .local_depth(local_index)
1997                     .checked_sub(1)
1998                     .ok_or_else(|| Error::Microwasm("LocalGet - Local out of range".into()))?;
1999                 let depth = depth
2000                     .try_into()
2001                     .map_err(|_| Error::Microwasm("LocalGet - Local out of range".into()))?;
2002                 one(Operator::Pick(depth))
2003             }
2004             WasmOperator::LocalSet { local_index } => {
2005                 let depth = self
2006                     .local_depth(local_index)
2007                     .checked_add(1)
2008                     .ok_or_else(|| Error::Microwasm("LocalSet - Local out of range".into()))?;
2009                 let depth = depth
2010                     .try_into()
2011                     .map_err(|_| Error::Microwasm("LocalSet - Local out of range".into()))?;
2012                 vec([Operator::Swap(depth), Operator::Drop(0..=0)])
2013             }
2014             WasmOperator::LocalTee { local_index } => {
2015                 let depth = self
2016                     .local_depth(local_index)
2017                     .checked_add(1)
2018                     .ok_or_else(|| Error::Microwasm("LocalTee - Local out of range".into()))?;
2019                 let depth = depth
2020                     .try_into()
2021                     .map_err(|_| Error::Microwasm("LocalTee - Local out of range".into()))?;
2022                 vec([
2023                     Operator::Pick(0),
2024                     Operator::Swap(depth),
2025                     Operator::Drop(0..=0),
2026                 ])
2027             }
2028             WasmOperator::GlobalGet { global_index } => one(Operator::GlobalGet(global_index)),
2029             WasmOperator::GlobalSet { global_index } => one(Operator::GlobalSet(global_index)),
2030 
2031             WasmOperator::I32Load { memarg } => one(Operator::Load {
2032                 ty: I32,
2033                 memarg: memarg.into(),
2034             }),
2035             WasmOperator::I64Load { memarg } => one(Operator::Load {
2036                 ty: I64,
2037                 memarg: memarg.into(),
2038             }),
2039             WasmOperator::F32Load { memarg } => one(Operator::Load {
2040                 ty: F32,
2041                 memarg: memarg.into(),
2042             }),
2043             WasmOperator::F64Load { memarg } => one(Operator::Load {
2044                 ty: F64,
2045                 memarg: memarg.into(),
2046             }),
2047             WasmOperator::I32Load8S { memarg } => one(Operator::Load8 {
2048                 ty: sint::I32,
2049                 memarg: memarg.into(),
2050             }),
2051             WasmOperator::I32Load8U { memarg } => one(Operator::Load8 {
2052                 ty: sint::U32,
2053                 memarg: memarg.into(),
2054             }),
2055             WasmOperator::I32Load16S { memarg } => one(Operator::Load16 {
2056                 ty: sint::I32,
2057                 memarg: memarg.into(),
2058             }),
2059             WasmOperator::I32Load16U { memarg } => one(Operator::Load16 {
2060                 ty: sint::U32,
2061                 memarg: memarg.into(),
2062             }),
2063             WasmOperator::I64Load8S { memarg } => one(Operator::Load8 {
2064                 ty: sint::I64,
2065                 memarg: memarg.into(),
2066             }),
2067             WasmOperator::I64Load8U { memarg } => one(Operator::Load8 {
2068                 ty: sint::U64,
2069                 memarg: memarg.into(),
2070             }),
2071             WasmOperator::I64Load16S { memarg } => one(Operator::Load16 {
2072                 ty: sint::I64,
2073                 memarg: memarg.into(),
2074             }),
2075             WasmOperator::I64Load16U { memarg } => one(Operator::Load16 {
2076                 ty: sint::U64,
2077                 memarg: memarg.into(),
2078             }),
2079             WasmOperator::I64Load32S { memarg } => one(Operator::Load32 {
2080                 sign: Signedness::Signed,
2081                 memarg: memarg.into(),
2082             }),
2083             WasmOperator::I64Load32U { memarg } => one(Operator::Load32 {
2084                 sign: Signedness::Unsigned,
2085                 memarg: memarg.into(),
2086             }),
2087 
2088             WasmOperator::I32Store { memarg } => one(Operator::Store {
2089                 ty: I32,
2090                 memarg: memarg.into(),
2091             }),
2092             WasmOperator::I64Store { memarg } => one(Operator::Store {
2093                 ty: I64,
2094                 memarg: memarg.into(),
2095             }),
2096             WasmOperator::F32Store { memarg } => one(Operator::Store {
2097                 ty: F32,
2098                 memarg: memarg.into(),
2099             }),
2100             WasmOperator::F64Store { memarg } => one(Operator::Store {
2101                 ty: F64,
2102                 memarg: memarg.into(),
2103             }),
2104 
2105             WasmOperator::I32Store8 { memarg } => one(Operator::Store8 {
2106                 ty: Size::_32,
2107                 memarg: memarg.into(),
2108             }),
2109             WasmOperator::I32Store16 { memarg } => one(Operator::Store16 {
2110                 ty: Size::_32,
2111                 memarg: memarg.into(),
2112             }),
2113             WasmOperator::I64Store8 { memarg } => one(Operator::Store8 {
2114                 ty: Size::_64,
2115                 memarg: memarg.into(),
2116             }),
2117             WasmOperator::I64Store16 { memarg } => one(Operator::Store16 {
2118                 ty: Size::_64,
2119                 memarg: memarg.into(),
2120             }),
2121             WasmOperator::I64Store32 { memarg } => one(Operator::Store32 {
2122                 memarg: memarg.into(),
2123             }),
2124             WasmOperator::MemorySize { reserved } => one(Operator::MemorySize { reserved }),
2125             WasmOperator::MemoryGrow { reserved } => one(Operator::MemoryGrow { reserved }),
2126             WasmOperator::I32Const { value } => one(Operator::Const(Value::I32(value))),
2127             WasmOperator::I64Const { value } => one(Operator::Const(Value::I64(value))),
2128             WasmOperator::F32Const { value } => one(Operator::Const(Value::F32(value.into()))),
2129             WasmOperator::F64Const { value } => one(Operator::Const(Value::F64(value.into()))),
2130             WasmOperator::RefNull { ty: _ } => {
2131                 return Err(Error::Microwasm("RefNull unimplemented".into()))
2132             }
2133             WasmOperator::RefIsNull { ty: _ } => {
2134                 return Err(Error::Microwasm("RefIsNull unimplemented".into()))
2135             }
2136             WasmOperator::I32Eqz => one(Operator::Eqz(Size::_32)),
2137             WasmOperator::I32Eq => one(Operator::Eq(I32)),
2138             WasmOperator::I32Ne => one(Operator::Ne(I32)),
2139             WasmOperator::I32LtS => one(Operator::Lt(SI32)),
2140             WasmOperator::I32LtU => one(Operator::Lt(SU32)),
2141             WasmOperator::I32GtS => one(Operator::Gt(SI32)),
2142             WasmOperator::I32GtU => one(Operator::Gt(SU32)),
2143             WasmOperator::I32LeS => one(Operator::Le(SI32)),
2144             WasmOperator::I32LeU => one(Operator::Le(SU32)),
2145             WasmOperator::I32GeS => one(Operator::Ge(SI32)),
2146             WasmOperator::I32GeU => one(Operator::Ge(SU32)),
2147             WasmOperator::I64Eqz => one(Operator::Eqz(Size::_64)),
2148             WasmOperator::I64Eq => one(Operator::Eq(I64)),
2149             WasmOperator::I64Ne => one(Operator::Ne(I64)),
2150             WasmOperator::I64LtS => one(Operator::Lt(SI64)),
2151             WasmOperator::I64LtU => one(Operator::Lt(SU64)),
2152             WasmOperator::I64GtS => one(Operator::Gt(SI64)),
2153             WasmOperator::I64GtU => one(Operator::Gt(SU64)),
2154             WasmOperator::I64LeS => one(Operator::Le(SI64)),
2155             WasmOperator::I64LeU => one(Operator::Le(SU64)),
2156             WasmOperator::I64GeS => one(Operator::Ge(SI64)),
2157             WasmOperator::I64GeU => one(Operator::Ge(SU64)),
2158             WasmOperator::F32Eq => one(Operator::Eq(F32)),
2159             WasmOperator::F32Ne => one(Operator::Ne(F32)),
2160             WasmOperator::F32Lt => one(Operator::Lt(SF32)),
2161             WasmOperator::F32Gt => one(Operator::Gt(SF32)),
2162             WasmOperator::F32Le => one(Operator::Le(SF32)),
2163             WasmOperator::F32Ge => one(Operator::Ge(SF32)),
2164             WasmOperator::F64Eq => one(Operator::Eq(F64)),
2165             WasmOperator::F64Ne => one(Operator::Ne(F64)),
2166             WasmOperator::F64Lt => one(Operator::Lt(SF64)),
2167             WasmOperator::F64Gt => one(Operator::Gt(SF64)),
2168             WasmOperator::F64Le => one(Operator::Le(SF64)),
2169             WasmOperator::F64Ge => one(Operator::Ge(SF64)),
2170             WasmOperator::I32Clz => one(Operator::Clz(Size::_32)),
2171             WasmOperator::I32Ctz => one(Operator::Ctz(Size::_32)),
2172             WasmOperator::I32Popcnt => one(Operator::Popcnt(Size::_32)),
2173             WasmOperator::I32Add => one(Operator::Add(I32)),
2174             WasmOperator::I32Sub => one(Operator::Sub(I32)),
2175             WasmOperator::I32Mul => one(Operator::Mul(I32)),
2176             WasmOperator::I32DivS => one(Operator::Div(SI32)),
2177             WasmOperator::I32DivU => one(Operator::Div(SU32)),
2178             WasmOperator::I32RemS => one(Operator::Rem(sint::I32)),
2179 
2180             WasmOperator::I32RemU => one(Operator::Rem(sint::U32)),
2181             WasmOperator::I32And => one(Operator::And(Size::_32)),
2182             WasmOperator::I32Or => one(Operator::Or(Size::_32)),
2183             WasmOperator::I32Xor => one(Operator::Xor(Size::_32)),
2184             WasmOperator::I32Shl => one(Operator::Shl(Size::_32)),
2185             WasmOperator::I32ShrS => one(Operator::Shr(sint::I32)),
2186             WasmOperator::I32ShrU => one(Operator::Shr(sint::U32)),
2187             WasmOperator::I32Rotl => one(Operator::Rotl(Size::_32)),
2188             WasmOperator::I32Rotr => one(Operator::Rotr(Size::_32)),
2189             WasmOperator::I64Clz => one(Operator::Clz(Size::_64)),
2190             WasmOperator::I64Ctz => one(Operator::Ctz(Size::_64)),
2191             WasmOperator::I64Popcnt => one(Operator::Popcnt(Size::_64)),
2192             WasmOperator::I64Add => one(Operator::Add(I64)),
2193             WasmOperator::I64Sub => one(Operator::Sub(I64)),
2194             WasmOperator::I64Mul => one(Operator::Mul(I64)),
2195             WasmOperator::I64DivS => one(Operator::Div(SI64)),
2196             WasmOperator::I64DivU => one(Operator::Div(SU64)),
2197             WasmOperator::I64RemS => one(Operator::Rem(sint::I64)),
2198 
2199             WasmOperator::I64RemU => one(Operator::Rem(sint::U64)),
2200             WasmOperator::I64And => one(Operator::And(Size::_64)),
2201             WasmOperator::I64Or => one(Operator::Or(Size::_64)),
2202             WasmOperator::I64Xor => one(Operator::Xor(Size::_64)),
2203             WasmOperator::I64Shl => one(Operator::Shl(Size::_64)),
2204             WasmOperator::I64ShrS => one(Operator::Shr(sint::I64)),
2205             WasmOperator::I64ShrU => one(Operator::Shr(sint::U64)),
2206             WasmOperator::I64Rotl => one(Operator::Rotl(Size::_64)),
2207             WasmOperator::I64Rotr => one(Operator::Rotr(Size::_64)),
2208             WasmOperator::F32Abs => one(Operator::Abs(Size::_32)),
2209             WasmOperator::F32Neg => one(Operator::Neg(Size::_32)),
2210             WasmOperator::F32Ceil => one(Operator::Ceil(Size::_32)),
2211             WasmOperator::F32Floor => one(Operator::Floor(Size::_32)),
2212             WasmOperator::F32Trunc => one(Operator::Trunc(Size::_32)),
2213             WasmOperator::F32Nearest => one(Operator::Nearest(Size::_32)),
2214             WasmOperator::F32Sqrt => one(Operator::Sqrt(Size::_32)),
2215             WasmOperator::F32Add => one(Operator::Add(F32)),
2216             WasmOperator::F32Sub => one(Operator::Sub(F32)),
2217             WasmOperator::F32Mul => one(Operator::Mul(F32)),
2218             WasmOperator::F32Div => one(Operator::Div(SF32)),
2219             WasmOperator::F32Min => one(Operator::Min(Size::_32)),
2220             WasmOperator::F32Max => one(Operator::Max(Size::_32)),
2221             WasmOperator::F32Copysign => one(Operator::Copysign(Size::_32)),
2222             WasmOperator::F64Abs => one(Operator::Abs(Size::_64)),
2223             WasmOperator::F64Neg => one(Operator::Neg(Size::_64)),
2224             WasmOperator::F64Ceil => one(Operator::Ceil(Size::_64)),
2225             WasmOperator::F64Floor => one(Operator::Floor(Size::_64)),
2226             WasmOperator::F64Trunc => one(Operator::Trunc(Size::_64)),
2227             WasmOperator::F64Nearest => one(Operator::Nearest(Size::_64)),
2228             WasmOperator::F64Sqrt => one(Operator::Sqrt(Size::_64)),
2229             WasmOperator::F64Add => one(Operator::Add(F64)),
2230             WasmOperator::F64Sub => one(Operator::Sub(F64)),
2231             WasmOperator::F64Mul => one(Operator::Mul(F64)),
2232             WasmOperator::F64Div => one(Operator::Div(SF64)),
2233             WasmOperator::F64Min => one(Operator::Min(Size::_64)),
2234             WasmOperator::F64Max => one(Operator::Max(Size::_64)),
2235             WasmOperator::F64Copysign => one(Operator::Copysign(Size::_64)),
2236             WasmOperator::I32WrapI64 => one(Operator::I32WrapFromI64),
2237             WasmOperator::I32TruncF32S => one(Operator::ITruncFromF {
2238                 input_ty: Size::_32,
2239                 output_ty: sint::I32,
2240             }),
2241             WasmOperator::I32TruncF32U => one(Operator::ITruncFromF {
2242                 input_ty: Size::_32,
2243                 output_ty: sint::U32,
2244             }),
2245             WasmOperator::I32TruncF64S => one(Operator::ITruncFromF {
2246                 input_ty: Size::_64,
2247                 output_ty: sint::I32,
2248             }),
2249             WasmOperator::I32TruncF64U => one(Operator::ITruncFromF {
2250                 input_ty: Size::_64,
2251                 output_ty: sint::U32,
2252             }),
2253             WasmOperator::I64ExtendI32S => one(Operator::Extend {
2254                 sign: Signedness::Signed,
2255             }),
2256             WasmOperator::I64ExtendI32U => one(Operator::Extend {
2257                 sign: Signedness::Unsigned,
2258             }),
2259             WasmOperator::I64TruncF32S => one(Operator::ITruncFromF {
2260                 input_ty: Size::_32,
2261                 output_ty: sint::I64,
2262             }),
2263             WasmOperator::I64TruncF32U => one(Operator::ITruncFromF {
2264                 input_ty: Size::_32,
2265                 output_ty: sint::U64,
2266             }),
2267             WasmOperator::I64TruncF64S => one(Operator::ITruncFromF {
2268                 input_ty: Size::_64,
2269                 output_ty: sint::I64,
2270             }),
2271             WasmOperator::I64TruncF64U => one(Operator::ITruncFromF {
2272                 input_ty: Size::_64,
2273                 output_ty: sint::U64,
2274             }),
2275             WasmOperator::F32ConvertI32S => one(Operator::FConvertFromI {
2276                 input_ty: sint::I32,
2277                 output_ty: Size::_32,
2278             }),
2279             WasmOperator::F32ConvertI32U => one(Operator::FConvertFromI {
2280                 input_ty: sint::U32,
2281                 output_ty: Size::_32,
2282             }),
2283             WasmOperator::F32ConvertI64S => one(Operator::FConvertFromI {
2284                 input_ty: sint::I64,
2285                 output_ty: Size::_32,
2286             }),
2287             WasmOperator::F32ConvertI64U => one(Operator::FConvertFromI {
2288                 input_ty: sint::U64,
2289                 output_ty: Size::_32,
2290             }),
2291             WasmOperator::F64ConvertI32S => one(Operator::FConvertFromI {
2292                 input_ty: sint::I32,
2293                 output_ty: Size::_64,
2294             }),
2295             WasmOperator::F64ConvertI32U => one(Operator::FConvertFromI {
2296                 input_ty: sint::U32,
2297                 output_ty: Size::_64,
2298             }),
2299             WasmOperator::F64ConvertI64S => one(Operator::FConvertFromI {
2300                 input_ty: sint::I64,
2301                 output_ty: Size::_64,
2302             }),
2303             WasmOperator::F64ConvertI64U => one(Operator::FConvertFromI {
2304                 input_ty: sint::U64,
2305                 output_ty: Size::_64,
2306             }),
2307             WasmOperator::F32DemoteF64 => one(Operator::F32DemoteFromF64),
2308             WasmOperator::F64PromoteF32 => one(Operator::F64PromoteFromF32),
2309             WasmOperator::I32ReinterpretF32 => one(Operator::I32ReinterpretFromF32),
2310             WasmOperator::I64ReinterpretF64 => one(Operator::I64ReinterpretFromF64),
2311             WasmOperator::F32ReinterpretI32 => one(Operator::F32ReinterpretFromI32),
2312             WasmOperator::F64ReinterpretI64 => one(Operator::F64ReinterpretFromI64),
2313             WasmOperator::I32Extend8S => {
2314                 return Err(Error::Microwasm("I32Extend8S unimplemented".into()))
2315             }
2316             WasmOperator::I32Extend16S => {
2317                 return Err(Error::Microwasm("I32Extend16S unimplemented".into()))
2318             }
2319             WasmOperator::I64Extend8S => {
2320                 return Err(Error::Microwasm("I64Extend8S unimplemented".into()))
2321             }
2322             WasmOperator::I64Extend16S => {
2323                 return Err(Error::Microwasm("I64Extend16S unimplemented".into()))
2324             }
2325             WasmOperator::I64Extend32S => {
2326                 return Err(Error::Microwasm("I64Extend32S unimplemented".into()))
2327             }
2328 
2329             WasmOperator::I32TruncSatF32S => {
2330                 return Err(Error::Microwasm("I32TruncSatF32S unimplemented".into()))
2331             }
2332             WasmOperator::I32TruncSatF32U => {
2333                 return Err(Error::Microwasm("I32TruncSatF32U unimplemented".into()))
2334             }
2335             WasmOperator::I32TruncSatF64S => {
2336                 return Err(Error::Microwasm("I32TruncSatF64S unimplemented".into()))
2337             }
2338             WasmOperator::I32TruncSatF64U => {
2339                 return Err(Error::Microwasm("I32TruncSatF64U unimplemented".into()))
2340             }
2341             WasmOperator::I64TruncSatF32S => {
2342                 return Err(Error::Microwasm("I64TruncSatF32S unimplemented".into()))
2343             }
2344             WasmOperator::I64TruncSatF32U => {
2345                 return Err(Error::Microwasm("I64TruncSatF32U unimplemented".into()))
2346             }
2347             WasmOperator::I64TruncSatF64S => {
2348                 return Err(Error::Microwasm("I64TruncSatF64S unimplemented".into()))
2349             }
2350             WasmOperator::I64TruncSatF64U => {
2351                 return Err(Error::Microwasm("I64TruncSatF64U unimplemented".into()))
2352             }
2353             _other => return Err(Error::Microwasm("Opcode unimplemented".into())),
2354         }))
2355     }
2356 }
2357 
2358 impl<M: ModuleContext> Iterator for MicrowasmConv<'_, M>
2359 where
2360     for<'any> &'any M::Signature: Into<OpSig>,
2361 {
2362     type Item = Result<SmallVec<[OperatorFromWasm; 1]>, Error>;
2363 
next(&mut self) -> Option<Self::Item>2364     fn next(&mut self) -> Option<Self::Item> {
2365         match self.next() {
2366             Ok(Some(ops)) => Some(Ok(ops.collect())),
2367             Ok(None) => None,
2368             Err(e) => Some(Err(e)),
2369         }
2370     }
2371 }
2372