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