1use super::{Config, Print, PrintTermcolor, Printer, State};
2use anyhow::{Result, anyhow, bail};
3use termcolor::{Ansi, NoColor};
4use wasmparser::VisitSimdOperator;
5use wasmparser::{
6 BlockType, BrTable, Catch, CompositeInnerType, ContType, FrameKind, FuncType, Handle, MemArg,
7 ModuleArity, Operator, OperatorsReader, Ordering, RefType, ResumeTable, SubType, TryTable,
8 VisitOperator,
9};
10
11pub struct OperatorState {
12 op_offset: usize,
13 nesting_start: u32,
14 label: u32,
15 label_indices: Vec<u32>,
16 sep: OperatorSeparator,
17}
18
19impl OperatorState {
20 pub fn new(printer: &Printer, sep: OperatorSeparator) -> Self {
21 OperatorState {
22 op_offset: 0,
23 nesting_start: printer.nesting,
24 label: 0,
25 label_indices: Vec::new(),
26 sep,
27 }
28 }
29}
30
31pub struct PrintOperator<'printer, 'state, 'a, 'b> {
32 pub(super) printer: &'printer mut Printer<'a, 'b>,
33 state: &'state mut State,
34 operator_state: &'printer mut OperatorState,
35}
36
37struct FoldedInstruction {
38 plain: String,
39 folded: Vec<FoldedInstruction>,
40 results: u32,
41 offset: usize,
42}
43
44struct Block {
45 ty: BlockType,
46 kind: FrameKind,
47 plain: String,
48 folded: Vec<FoldedInstruction>,
49 predicate: Option<Vec<FoldedInstruction>>,
50 consequent: Option<(Vec<FoldedInstruction>, usize)>,
51 offset: usize,
52}
53
54pub struct PrintOperatorFolded<'printer, 'state, 'a, 'b> {
55 pub(super) printer: &'printer mut Printer<'a, 'b>,
56 state: &'state mut State,
57 operator_state: &'printer mut OperatorState,
58 control: Vec<Block>,
59 branch_hint: Option<FoldedInstruction>,
60 original_separator: OperatorSeparator,
61}
62
63#[derive(Copy, Clone)]
64pub enum OperatorSeparator {
65 Newline,
66 None,
67 NoneThenSpace,
68 Space,
69}
70
71impl<'printer, 'state, 'a, 'b> PrintOperator<'printer, 'state, 'a, 'b> {
72 pub(super) fn new(
73 printer: &'printer mut Printer<'a, 'b>,
74 state: &'state mut State,
75 operator_state: &'printer mut OperatorState,
76 ) -> Self {
77 PrintOperator {
78 printer,
79 state,
80 operator_state,
81 }
82 }
83
84 fn push_str(&mut self, s: &str) -> Result<()> {
85 self.printer.result.write_str(s)?;
86 Ok(())
87 }
88
89 fn result(&mut self) -> &mut dyn Print {
90 self.printer.result
91 }
92
93 fn separator(&mut self) -> Result<()> {
94 match self.operator_state.sep {
95 OperatorSeparator::Newline => self.printer.newline(self.operator_state.op_offset),
96 OperatorSeparator::None => Ok(()),
97 OperatorSeparator::NoneThenSpace => {
98 self.operator_state.sep = OperatorSeparator::Space;
99 Ok(())
100 }
101 OperatorSeparator::Space => self.push_str(" "),
102 }
103 }
104
105 fn block_start(&mut self) -> Result<()> {
108 self.separator()?;
109 self.printer.nesting += 1;
110 self.operator_state
111 .label_indices
112 .push(self.operator_state.label);
113 Ok(())
114 }
115
116 fn block_mid(&mut self) -> Result<()> {
118 self.printer.nesting -= 1;
119 self.separator()?;
120 self.printer.nesting += 1;
121 Ok(())
122 }
123
124 fn block_end(&mut self) -> Result<()> {
126 if self.printer.nesting > self.operator_state.nesting_start {
127 self.printer.nesting -= 1;
128 }
129 self.separator()?;
130 Ok(())
131 }
132
133 fn blockty(&mut self, ty: BlockType) -> Result<()> {
134 let has_name = self.blockty_without_label_comment(ty)?;
135 self.maybe_blockty_label_comment(has_name)
136 }
137
138 fn blockty_without_label_comment(&mut self, ty: BlockType) -> Result<bool> {
139 let key = (self.state.core.funcs, self.operator_state.label);
140 let has_name = match self.state.core.label_names.index_to_name.get(&key) {
141 Some(name) => {
142 write!(self.printer.result, " ")?;
143 name.write(self.printer)?;
144 true
145 }
146 None if self.printer.config.name_unnamed => {
147 let depth = self.cur_depth() - 1;
151 write!(self.result(), " $#label{depth}")?;
152 true
153 }
154 None => false,
155 };
156 match ty {
157 BlockType::Empty => {}
158 BlockType::Type(t) => {
159 self.push_str(" ")?;
160 self.printer.start_group("result ")?;
161 self.printer.print_valtype(self.state, t)?;
162 self.printer.end_group()?;
163 }
164 BlockType::FuncType(idx) => {
165 self.push_str(" ")?;
166 self.printer
167 .print_core_functype_idx(self.state, idx, None)?;
168 }
169 }
170 Ok(has_name)
171 }
172
173 fn maybe_blockty_label_comment(&mut self, has_name: bool) -> Result<()> {
174 if !has_name {
175 let depth = self.cur_depth();
176 self.push_str(" ")?;
177 self.result().start_comment()?;
178 match self.operator_state.sep {
179 OperatorSeparator::Newline | OperatorSeparator::None => {
180 write!(self.result(), ";; label = @{depth}")
181 }
182 _ => write!(self.result(), " (; label = @{depth} ;)"),
183 }?;
184 self.result().reset_color()?;
185 }
186
187 self.operator_state.label += 1;
188 Ok(())
189 }
190
191 fn cur_depth(&self) -> u32 {
192 self.printer.nesting - self.operator_state.nesting_start
193 }
194
195 fn tag_index(&mut self, index: u32) -> Result<()> {
196 self.push_str(" ")?;
197 self.printer.print_idx(&self.state.core.tag_names, index)?;
198 Ok(())
199 }
200
201 fn relative_depth(&mut self, depth: u32) -> Result<()> {
202 self.push_str(" ")?;
203 match self.cur_depth().checked_sub(depth) {
204 Some(i) => {
210 let name = i
211 .checked_sub(1)
212 .and_then(|idx| self.operator_state.label_indices.get(idx as usize).copied())
213 .and_then(|label_idx| {
214 let key = (self.state.core.funcs, label_idx);
215 self.state.core.label_names.index_to_name.get(&key)
216 });
217
218 let name_conflict = name.is_some()
225 && self.operator_state.label_indices[i as usize..]
226 .iter()
227 .any(|other_label| {
228 let key = (self.state.core.funcs, *other_label);
229 if let Some(other) = self.state.core.label_names.index_to_name.get(&key)
230 {
231 if name.unwrap().name == other.name {
232 return true;
233 }
234 }
235 false
236 });
237
238 match name {
239 Some(name) if !name_conflict => name.write(self.printer)?,
242
243 None if !name_conflict && self.printer.config.name_unnamed && i > 0 => {
251 self.result().start_name()?;
252 write!(self.result(), "$#label{}", i - 1)?;
253 self.result().reset_color()?;
254 }
255
256 _ => {
257 self.result().start_name()?;
259 write!(self.result(), "{depth}")?;
260 self.result().reset_color()?;
261
262 if !name_conflict && i > 0 {
269 self.result().start_comment()?;
270 write!(self.result(), " (;@{i};)")?;
271 self.result().reset_color()?;
272 }
273 }
274 }
275 }
276
277 None => write!(self.result(), "{depth} (; INVALID ;)")?,
280 }
281 Ok(())
282 }
283
284 fn targets(&mut self, targets: BrTable<'_>) -> Result<()> {
285 for item in targets.targets().chain([Ok(targets.default())]) {
286 self.relative_depth(item?)?;
287 }
288 Ok(())
289 }
290
291 fn function_index(&mut self, idx: u32) -> Result<()> {
292 self.push_str(" ")?;
293 self.printer.print_idx(&self.state.core.func_names, idx)
294 }
295
296 fn local_index(&mut self, idx: u32) -> Result<()> {
297 self.push_str(" ")?;
298 self.printer
299 .print_local_idx(self.state, self.state.core.funcs, idx)
300 }
301
302 fn global_index(&mut self, idx: u32) -> Result<()> {
303 self.push_str(" ")?;
304 self.printer.print_idx(&self.state.core.global_names, idx)
305 }
306
307 fn table_index(&mut self, idx: u32) -> Result<()> {
308 self.push_str(" ")?;
309 self.printer.print_idx(&self.state.core.table_names, idx)
310 }
311
312 fn table(&mut self, idx: u32) -> Result<()> {
313 self.table_index(idx)
314 }
315
316 fn memory_index(&mut self, idx: u32) -> Result<()> {
317 self.push_str(" ")?;
318 self.printer.print_idx(&self.state.core.memory_names, idx)
319 }
320
321 fn type_index(&mut self, idx: u32) -> Result<()> {
322 self.push_str(" ")?;
323 self.printer.print_core_type_ref(self.state, idx)
324 }
325
326 fn cont_type_index(&mut self, idx: u32) -> Result<()> {
327 self.push_str(" ")?;
328 self.printer.print_idx(&self.state.core.type_names, idx)
329 }
330
331 fn argument_index(&mut self, idx: u32) -> Result<()> {
332 self.cont_type_index(idx)
333 }
334
335 fn result_index(&mut self, idx: u32) -> Result<()> {
336 self.cont_type_index(idx)
337 }
338
339 fn array_type_index(&mut self, idx: u32) -> Result<()> {
340 self.push_str(" ")?;
341 self.printer.print_idx(&self.state.core.type_names, idx)
342 }
343
344 fn array_type_index_dst(&mut self, idx: u32) -> Result<()> {
345 self.push_str(" ")?;
346 self.printer.print_idx(&self.state.core.type_names, idx)
347 }
348
349 fn array_type_index_src(&mut self, idx: u32) -> Result<()> {
350 self.push_str(" ")?;
351 self.printer.print_idx(&self.state.core.type_names, idx)
352 }
353
354 fn array_size(&mut self, array_size: u32) -> Result<()> {
355 write!(&mut self.printer.result, " {array_size}")?;
356 Ok(())
357 }
358
359 fn struct_type_index(&mut self, idx: u32) -> Result<()> {
360 self.push_str(" ")?;
361 self.printer.print_idx(&self.state.core.type_names, idx)
362 }
363
364 fn from_ref_type(&mut self, ref_ty: RefType) -> Result<()> {
365 self.push_str(" ")?;
366 self.printer.print_reftype(self.state, ref_ty)
367 }
368
369 fn to_ref_type(&mut self, ref_ty: RefType) -> Result<()> {
370 self.push_str(" ")?;
371 self.printer.print_reftype(self.state, ref_ty)
372 }
373
374 fn data_index(&mut self, idx: u32) -> Result<()> {
375 self.push_str(" ")?;
376 self.printer.print_idx(&self.state.core.data_names, idx)
377 }
378
379 fn array_data_index(&mut self, idx: u32) -> Result<()> {
380 self.push_str(" ")?;
381 self.printer.print_idx(&self.state.core.data_names, idx)
382 }
383
384 fn elem_index(&mut self, idx: u32) -> Result<()> {
385 self.push_str(" ")?;
386 self.printer.print_idx(&self.state.core.element_names, idx)
387 }
388
389 fn array_elem_index(&mut self, idx: u32) -> Result<()> {
390 self.push_str(" ")?;
391 self.printer.print_idx(&self.state.core.element_names, idx)
392 }
393
394 fn lane(&mut self, lane: u8) -> Result<()> {
395 write!(self.result(), " {lane}")?;
396 Ok(())
397 }
398
399 fn lanes(&mut self, lanes: [u8; 16]) -> Result<()> {
400 for lane in lanes.iter() {
401 write!(self.result(), " {lane}")?;
402 }
403 Ok(())
404 }
405
406 fn memarg(&mut self, memarg: MemArg) -> Result<()> {
407 if memarg.memory != 0 {
408 self.memory_index(memarg.memory)?;
409 }
410 if memarg.offset != 0 {
411 write!(self.result(), " offset={}", memarg.offset)?;
412 }
413 if memarg.align != memarg.max_align {
414 let align = 1_u64 << memarg.align;
415 write!(self.result(), " align={align}")?;
416 }
417 Ok(())
418 }
419
420 fn ordering(&mut self, ordering: Ordering) -> Result<()> {
421 write!(
422 self.result(),
423 " {}",
424 match ordering {
425 Ordering::SeqCst => "seq_cst",
426 Ordering::AcqRel => "acq_rel",
427 }
428 )?;
429 Ok(())
430 }
431
432 fn try_table(&mut self, table: TryTable) -> Result<()> {
433 let has_name = self.blockty_without_label_comment(table.ty)?;
434
435 self.printer.nesting -= 2;
439 let try_table_label = self.operator_state.label_indices.pop().unwrap();
440
441 for catch in table.catches {
442 self.result().write_str(" ")?;
443 match catch {
444 Catch::One { tag, label } => {
445 self.printer.start_group("catch")?;
446 self.tag_index(tag)?;
447 self.relative_depth(label)?;
448 self.printer.end_group()?;
449 }
450 Catch::OneRef { tag, label } => {
451 self.printer.start_group("catch_ref")?;
452 self.tag_index(tag)?;
453 self.relative_depth(label)?;
454 self.printer.end_group()?;
455 }
456 Catch::All { label } => {
457 self.printer.start_group("catch_all")?;
458 self.relative_depth(label)?;
459 self.printer.end_group()?;
460 }
461 Catch::AllRef { label } => {
462 self.printer.start_group("catch_all_ref")?;
463 self.relative_depth(label)?;
464 self.printer.end_group()?;
465 }
466 }
467 }
468 self.operator_state.label_indices.push(try_table_label);
469 self.printer.nesting += 2;
470 self.maybe_blockty_label_comment(has_name)?;
471 Ok(())
472 }
473
474 fn resume_table(&mut self, table: ResumeTable) -> Result<()> {
475 self.printer.nesting -= 1;
481 for handle in table.handlers {
482 self.result().write_str(" ")?;
483 self.printer.start_group("on")?;
484 match handle {
485 Handle::OnLabel { tag, label } => {
486 self.tag_index(tag)?;
487 self.relative_depth(label)?;
488 }
489 Handle::OnSwitch { tag } => {
490 self.tag_index(tag)?;
491 self.result().write_str(" switch")?;
492 }
493 }
494 self.printer.end_group()?;
495 }
496 self.printer.nesting += 1;
497 Ok(())
498 }
499}
500
501macro_rules! define_visit {
502 ($(@$proposal:ident $op:ident $({ $($arg:ident: $argty:ty),* })? => $visit:ident ($($ann:tt)*) )*) => ($(
507 fn $visit(&mut self $( , $($arg: $argty),* )?) -> Self::Output {
508 define_visit!(before_op self $op);
509 self.push_str(define_visit!(name $op))?;
510 $(
511 define_visit!(payload self $op $($arg)*);
512 )?
513
514 define_visit!(after_op self $op);
515 Ok(())
516 }
517 )*);
518
519 (before_op $self:ident Loop) => ($self.block_start()?;);
524 (before_op $self:ident Block) => ($self.block_start()?;);
525 (before_op $self:ident If) => ($self.block_start()?;);
526 (before_op $self:ident Try) => ($self.block_start()?;);
527 (before_op $self:ident TryTable) => ($self.block_start()?;);
528 (before_op $self:ident Catch) => ($self.block_mid()?;);
529 (before_op $self:ident CatchAll) => ($self.block_mid()?;);
530 (before_op $self:ident Delegate) => ($self.block_end()?;);
531 (before_op $self:ident Else) => ($self.block_mid()?;);
532 (before_op $self:ident End) => ($self.block_end()?;);
533 (before_op $self:ident $op:ident) => ($self.separator()?;);
534
535 (after_op $self:ident End) => ($self.operator_state.label_indices.pop(););
538 (after_op $self:ident $op:ident) => ();
539
540 (payload $self:ident CallIndirect $ty:ident $table:ident) => (
546 if $table != 0 {
547 $self.table_index($table)?;
548 }
549 $self.type_index($ty)?;
550 );
551 (payload $self:ident ReturnCallIndirect $ty:ident $table:ident) => (
552 if $table != 0 {
553 $self.table_index($table)?;
554 }
555 $self.type_index($ty)?;
556 );
557 (payload $self:ident CallRef $ty:ident) => (
558 $self.push_str(" ")?;
559 $self.printer.print_idx(&$self.state.core.type_names, $ty)?;
560 );
561 (payload $self:ident ReturnCallRef $ty:ident) => (
562 $self.push_str(" ")?;
563 $self.printer.print_idx(&$self.state.core.type_names, $ty)?;
564 );
565 (payload $self:ident TypedSelect $select_ty:ident) => (
566 $self.push_str(" ")?;
567 $self.printer.start_group("result ")?;
568 $self.printer.print_valtype($self.state, $select_ty)?;
569 $self.printer.end_group()?;
570 );
571 (payload $self:ident TypedSelectMulti $select_tys:ident) => (
572 $self.push_str(" ")?;
573 $self.printer.start_group("result")?;
574 $self.printer.print_valtypes($self.state, $select_tys)?;
575 $self.printer.end_group()?;
576 );
577 (payload $self:ident RefNull $hty:ident) => (
578 $self.push_str(" ")?;
579 $self.printer.print_heaptype($self.state, $hty)?;
580 );
581 (payload $self:ident TableInit $segment:ident $table:ident) => (
582 if $table != 0 {
583 $self.table_index($table)?;
584 }
585 $self.elem_index($segment)?;
586 );
587 (payload $self:ident TableCopy $dst:ident $src:ident) => (
588 if $src != 0 || $dst != 0 {
589 $self.table_index($dst)?;
590 $self.table_index($src)?;
591 }
592 );
593 (payload $self:ident MemoryGrow $mem:ident) => (
594 if $mem != 0 {
595 $self.memory_index($mem)?;
596 }
597 );
598 (payload $self:ident MemorySize $mem:ident) => (
599 if $mem != 0 {
600 $self.memory_index($mem)?;
601 }
602 );
603 (payload $self:ident MemoryInit $segment:ident $mem:ident) => (
604 if $mem != 0 {
605 $self.memory_index($mem)?;
606 }
607 $self.data_index($segment)?;
608 );
609 (payload $self:ident MemoryCopy $dst:ident $src:ident) => (
610 if $src != 0 || $dst != 0 {
611 $self.memory_index($dst)?;
612 $self.memory_index($src)?;
613 }
614 );
615 (payload $self:ident MemoryFill $mem:ident) => (
616 if $mem != 0 {
617 $self.memory_index($mem)?;
618 }
619 );
620 (payload $self:ident MemoryDiscard $mem:ident) => (
621 if $mem != 0 {
622 $self.memory_index($mem)?;
623 }
624 );
625 (payload $self:ident I32Const $val:ident) => (
626 $self.result().start_literal()?;
627 write!($self.result(), " {}", $val)?;
628 $self.result().reset_color()?;
629 );
630 (payload $self:ident I64Const $val:ident) => (
631 $self.result().start_literal()?;
632 write!($self.result(), " {}", $val)?;
633 $self.result().reset_color()?;
634 );
635 (payload $self:ident F32Const $val:ident) => (
636 $self.push_str(" ")?;
637 $self.printer.print_f32($val.bits())?;
638 );
639 (payload $self:ident F64Const $val:ident) => (
640 $self.push_str(" ")?;
641 $self.printer.print_f64($val.bits())?;
642 );
643 (payload $self:ident V128Const $val:ident) => (
644 $self.printer.print_type_keyword(" i32x4")?;
645 $self.result().start_literal()?;
646 for chunk in $val.bytes().chunks(4) {
647 write!(
648 $self.result(),
649 " 0x{:02x}{:02x}{:02x}{:02x}",
650 chunk[3],
651 chunk[2],
652 chunk[1],
653 chunk[0],
654 )?;
655 }
656 $self.result().reset_color()?;
657 );
658 (payload $self:ident RefTestNonNull $hty:ident) => (
659 $self.push_str(" ")?;
660 let rty = RefType::new(false, $hty)
661 .ok_or_else(|| anyhow!("implementation limit: type index too large"))?;
662 $self.printer.print_reftype($self.state, rty)?;
663 );
664 (payload $self:ident RefTestNullable $hty:ident) => (
665 $self.push_str(" ")?;
666 let rty = RefType::new(true, $hty)
667 .ok_or_else(|| anyhow!("implementation limit: type index too large"))?;
668 $self.printer.print_reftype($self.state, rty)?;
669 );
670 (payload $self:ident RefCastNonNull $hty:ident) => (
671 $self.push_str(" ")?;
672 let rty = RefType::new(false, $hty)
673 .ok_or_else(|| anyhow!("implementation limit: type index too large"))?;
674 $self.printer.print_reftype($self.state, rty)?;
675 );
676 (payload $self:ident RefCastNullable $hty:ident) => (
677 $self.push_str(" ")?;
678 let rty = RefType::new(true, $hty)
679 .ok_or_else(|| anyhow!("implementation limit: type index too large"))?;
680 $self.printer.print_reftype($self.state, rty)?;
681 );
682 (payload $self:ident StructGet $ty:ident $field:ident) => (
683 $self.struct_type_index($ty)?;
684 $self.push_str(" ")?;
685 $self.printer.print_field_idx($self.state, $ty, $field)?;
686 );
687 (payload $self:ident StructGetS $ty:ident $field:ident) => (
688 $self.struct_type_index($ty)?;
689 $self.push_str(" ")?;
690 $self.printer.print_field_idx($self.state, $ty, $field)?;
691 );
692 (payload $self:ident StructGetU $ty:ident $field:ident) => (
693 $self.struct_type_index($ty)?;
694 $self.push_str(" ")?;
695 $self.printer.print_field_idx($self.state, $ty, $field)?;
696 );
697 (payload $self:ident StructSet $ty:ident $field:ident) => (
698 $self.struct_type_index($ty)?;
699 $self.push_str(" ")?;
700 $self.printer.print_field_idx($self.state, $ty, $field)?;
701 );
702 (payload $self:ident StructAtomicGet $order:ident $ty:ident $field:ident) => (
703 $self.ordering($order)?;
704 $self.struct_type_index($ty)?;
705 $self.push_str(" ")?;
706 $self.printer.print_field_idx($self.state, $ty, $field)?;
707 );
708 (payload $self:ident StructAtomicGetS $order:ident $ty:ident $field:ident) => (
709 $self.ordering($order)?;
710 $self.struct_type_index($ty)?;
711 $self.push_str(" ")?;
712 $self.printer.print_field_idx($self.state, $ty, $field)?;
713 );
714 (payload $self:ident StructAtomicGetU $order:ident $ty:ident $field:ident) => (
715 $self.ordering($order)?;
716 $self.struct_type_index($ty)?;
717 $self.push_str(" ")?;
718 $self.printer.print_field_idx($self.state, $ty, $field)?;
719 );
720 (payload $self:ident StructAtomicSet $order:ident $ty:ident $field:ident) => (
721 $self.ordering($order)?;
722 $self.struct_type_index($ty)?;
723 $self.push_str(" ")?;
724 $self.printer.print_field_idx($self.state, $ty, $field)?;
725 );
726 (payload $self:ident StructAtomicRmwAdd $order:ident $ty:ident $field:ident) => (
727 $self.ordering($order)?;
728 $self.struct_type_index($ty)?;
729 $self.push_str(" ")?;
730 $self.printer.print_field_idx($self.state, $ty, $field)?;
731 );
732 (payload $self:ident StructAtomicRmwSub $order:ident $ty:ident $field:ident) => (
733 $self.ordering($order)?;
734 $self.struct_type_index($ty)?;
735 $self.push_str(" ")?;
736 $self.printer.print_field_idx($self.state, $ty, $field)?;
737 );
738 (payload $self:ident StructAtomicRmwAnd $order:ident $ty:ident $field:ident) => (
739 $self.ordering($order)?;
740 $self.struct_type_index($ty)?;
741 $self.push_str(" ")?;
742 $self.printer.print_field_idx($self.state, $ty, $field)?;
743 );
744 (payload $self:ident StructAtomicRmwOr $order:ident $ty:ident $field:ident) => (
745 $self.ordering($order)?;
746 $self.struct_type_index($ty)?;
747 $self.push_str(" ")?;
748 $self.printer.print_field_idx($self.state, $ty, $field)?;
749 );
750 (payload $self:ident StructAtomicRmwXor $order:ident $ty:ident $field:ident) => (
751 $self.ordering($order)?;
752 $self.struct_type_index($ty)?;
753 $self.push_str(" ")?;
754 $self.printer.print_field_idx($self.state, $ty, $field)?;
755 );
756 (payload $self:ident StructAtomicRmwXchg $order:ident $ty:ident $field:ident) => (
757 $self.ordering($order)?;
758 $self.struct_type_index($ty)?;
759 $self.push_str(" ")?;
760 $self.printer.print_field_idx($self.state, $ty, $field)?;
761 );
762 (payload $self:ident StructAtomicRmwCmpxchg $order:ident $ty:ident $field:ident) => (
763 $self.ordering($order)?;
764 $self.struct_type_index($ty)?;
765 $self.push_str(" ")?;
766 $self.printer.print_field_idx($self.state, $ty, $field)?;
767 );
768 (payload $self:ident $op:ident $($arg:ident)*) => (
769 $($self.$arg($arg)?;)*
770 );
771
772 (name Block) => ("block");
773 (name If) => ("if");
774 (name Else) => ("else");
775 (name Loop) => ("loop");
776 (name End) => ("end");
777 (name Unreachable) => ("unreachable");
778 (name Nop) => ("nop");
779 (name Br) => ("br");
780 (name BrIf) => ("br_if");
781 (name BrOnNull) => ("br_on_null");
782 (name BrOnNonNull) => ("br_on_non_null");
783 (name BrTable) => ("br_table");
784 (name Return) => ("return");
785 (name Call) => ("call");
786 (name CallIndirect) => ("call_indirect");
787 (name CallRef) => ("call_ref");
788 (name ReturnCall) => ("return_call");
789 (name ReturnCallIndirect) => ("return_call_indirect");
790 (name ReturnCallRef) => ("return_call_ref");
791 (name Drop) => ("drop");
792 (name Select) => ("select");
793 (name TypedSelect) => ("select");
794 (name TypedSelectMulti) => ("select");
795 (name LocalGet) => ("local.get");
796 (name LocalSet) => ("local.set");
797 (name LocalTee) => ("local.tee");
798 (name GlobalGet) => ("global.get");
799 (name GlobalSet) => ("global.set");
800 (name TableGet) => ("table.get");
801 (name TableSet) => ("table.set");
802 (name I32Load) => ("i32.load");
803 (name I64Load) => ("i64.load");
804 (name F32Load) => ("f32.load");
805 (name F64Load) => ("f64.load");
806 (name I32Load8S) => ("i32.load8_s");
807 (name I32Load8U) => ("i32.load8_u");
808 (name I32Load16S) => ("i32.load16_s");
809 (name I32Load16U) => ("i32.load16_u");
810 (name I64Load8S) => ("i64.load8_s");
811 (name I64Load8U) => ("i64.load8_u");
812 (name I64Load16S) => ("i64.load16_s");
813 (name I64Load16U) => ("i64.load16_u");
814 (name I64Load32S) => ("i64.load32_s");
815 (name I64Load32U) => ("i64.load32_u");
816 (name I32Store) => ("i32.store");
817 (name I64Store) => ("i64.store");
818 (name F32Store) => ("f32.store");
819 (name F64Store) => ("f64.store");
820 (name I32Store8) => ("i32.store8");
821 (name I32Store16) => ("i32.store16");
822 (name I64Store8) => ("i64.store8");
823 (name I64Store16) => ("i64.store16");
824 (name I64Store32) => ("i64.store32");
825 (name MemorySize) => ("memory.size");
826 (name MemoryGrow) => ("memory.grow");
827 (name MemoryInit) => ("memory.init");
828 (name MemoryCopy) => ("memory.copy");
829 (name MemoryFill) => ("memory.fill");
830 (name MemoryDiscard) => ("memory.discard");
831 (name DataDrop) => ("data.drop");
832 (name ElemDrop) => ("elem.drop");
833 (name TableInit) => ("table.init");
834 (name TableCopy) => ("table.copy");
835 (name TableFill) => ("table.fill");
836 (name TableSize) => ("table.size");
837 (name TableGrow) => ("table.grow");
838 (name RefAsNonNull) => ("ref.as_non_null");
839 (name RefNull) => ("ref.null");
840 (name RefEq) => ("ref.eq");
841 (name RefIsNull) => ("ref.is_null");
842 (name RefFunc) => ("ref.func");
843 (name I32Const) => ("i32.const");
844 (name I64Const) => ("i64.const");
845 (name F32Const) => ("f32.const");
846 (name F64Const) => ("f64.const");
847 (name I32Clz) => ("i32.clz");
848 (name I32Ctz) => ("i32.ctz");
849 (name I32Popcnt) => ("i32.popcnt");
850 (name I32Add) => ("i32.add");
851 (name I32Sub) => ("i32.sub");
852 (name I32Mul) => ("i32.mul");
853 (name I32DivS) => ("i32.div_s");
854 (name I32DivU) => ("i32.div_u");
855 (name I32RemS) => ("i32.rem_s");
856 (name I32RemU) => ("i32.rem_u");
857 (name I32And) => ("i32.and");
858 (name I32Or) => ("i32.or");
859 (name I32Xor) => ("i32.xor");
860 (name I32Shl) => ("i32.shl");
861 (name I32ShrS) => ("i32.shr_s");
862 (name I32ShrU) => ("i32.shr_u");
863 (name I32Rotl) => ("i32.rotl");
864 (name I32Rotr) => ("i32.rotr");
865 (name I64Clz) => ("i64.clz");
866 (name I64Ctz) => ("i64.ctz");
867 (name I64Popcnt) => ("i64.popcnt");
868 (name I64Add) => ("i64.add");
869 (name I64Sub) => ("i64.sub");
870 (name I64Mul) => ("i64.mul");
871 (name I64DivS) => ("i64.div_s");
872 (name I64DivU) => ("i64.div_u");
873 (name I64RemS) => ("i64.rem_s");
874 (name I64RemU) => ("i64.rem_u");
875 (name I64And) => ("i64.and");
876 (name I64Or) => ("i64.or");
877 (name I64Xor) => ("i64.xor");
878 (name I64Shl) => ("i64.shl");
879 (name I64ShrS) => ("i64.shr_s");
880 (name I64ShrU) => ("i64.shr_u");
881 (name I64Rotl) => ("i64.rotl");
882 (name I64Rotr) => ("i64.rotr");
883 (name F32Abs) => ("f32.abs");
884 (name F32Neg) => ("f32.neg");
885 (name F32Ceil) => ("f32.ceil");
886 (name F32Floor) => ("f32.floor");
887 (name F32Trunc) => ("f32.trunc");
888 (name F32Nearest) => ("f32.nearest");
889 (name F32Sqrt) => ("f32.sqrt");
890 (name F32Add) => ("f32.add");
891 (name F32Sub) => ("f32.sub");
892 (name F32Mul) => ("f32.mul");
893 (name F32Div) => ("f32.div");
894 (name F32Min) => ("f32.min");
895 (name F32Max) => ("f32.max");
896 (name F32Copysign) => ("f32.copysign");
897 (name F64Abs) => ("f64.abs");
898 (name F64Neg) => ("f64.neg");
899 (name F64Ceil) => ("f64.ceil");
900 (name F64Floor) => ("f64.floor");
901 (name F64Trunc) => ("f64.trunc");
902 (name F64Nearest) => ("f64.nearest");
903 (name F64Sqrt) => ("f64.sqrt");
904 (name F64Add) => ("f64.add");
905 (name F64Sub) => ("f64.sub");
906 (name F64Mul) => ("f64.mul");
907 (name F64Div) => ("f64.div");
908 (name F64Min) => ("f64.min");
909 (name F64Max) => ("f64.max");
910 (name F64Copysign) => ("f64.copysign");
911 (name I32Eqz) => ("i32.eqz");
912 (name I32Eq) => ("i32.eq");
913 (name I32Ne) => ("i32.ne");
914 (name I32LtS) => ("i32.lt_s");
915 (name I32LtU) => ("i32.lt_u");
916 (name I32GtS) => ("i32.gt_s");
917 (name I32GtU) => ("i32.gt_u");
918 (name I32LeS) => ("i32.le_s");
919 (name I32LeU) => ("i32.le_u");
920 (name I32GeS) => ("i32.ge_s");
921 (name I32GeU) => ("i32.ge_u");
922 (name I64Eqz) => ("i64.eqz");
923 (name I64Eq) => ("i64.eq");
924 (name I64Ne) => ("i64.ne");
925 (name I64LtS) => ("i64.lt_s");
926 (name I64LtU) => ("i64.lt_u");
927 (name I64GtS) => ("i64.gt_s");
928 (name I64GtU) => ("i64.gt_u");
929 (name I64LeS) => ("i64.le_s");
930 (name I64LeU) => ("i64.le_u");
931 (name I64GeS) => ("i64.ge_s");
932 (name I64GeU) => ("i64.ge_u");
933 (name F32Eq) => ("f32.eq");
934 (name F32Ne) => ("f32.ne");
935 (name F32Lt) => ("f32.lt");
936 (name F32Gt) => ("f32.gt");
937 (name F32Le) => ("f32.le");
938 (name F32Ge) => ("f32.ge");
939 (name F64Eq) => ("f64.eq");
940 (name F64Ne) => ("f64.ne");
941 (name F64Lt) => ("f64.lt");
942 (name F64Gt) => ("f64.gt");
943 (name F64Le) => ("f64.le");
944 (name F64Ge) => ("f64.ge");
945 (name I32WrapI64) => ("i32.wrap_i64");
946 (name I32TruncF32S) => ("i32.trunc_f32_s");
947 (name I32TruncF32U) => ("i32.trunc_f32_u");
948 (name I32TruncF64S) => ("i32.trunc_f64_s");
949 (name I32TruncF64U) => ("i32.trunc_f64_u");
950 (name I64ExtendI32S) => ("i64.extend_i32_s");
951 (name I64ExtendI32U) => ("i64.extend_i32_u");
952 (name I64TruncF32S) => ("i64.trunc_f32_s");
953 (name I64TruncF32U) => ("i64.trunc_f32_u");
954 (name I64TruncF64S) => ("i64.trunc_f64_s");
955 (name I64TruncF64U) => ("i64.trunc_f64_u");
956 (name F32ConvertI32S) => ("f32.convert_i32_s");
957 (name F32ConvertI32U) => ("f32.convert_i32_u");
958 (name F32ConvertI64S) => ("f32.convert_i64_s");
959 (name F32ConvertI64U) => ("f32.convert_i64_u");
960 (name F32DemoteF64) => ("f32.demote_f64");
961 (name F64ConvertI32S) => ("f64.convert_i32_s");
962 (name F64ConvertI32U) => ("f64.convert_i32_u");
963 (name F64ConvertI64S) => ("f64.convert_i64_s");
964 (name F64ConvertI64U) => ("f64.convert_i64_u");
965 (name F64PromoteF32) => ("f64.promote_f32");
966 (name I32ReinterpretF32) => ("i32.reinterpret_f32");
967 (name I64ReinterpretF64) => ("i64.reinterpret_f64");
968 (name F32ReinterpretI32) => ("f32.reinterpret_i32");
969 (name F64ReinterpretI64) => ("f64.reinterpret_i64");
970 (name I32TruncSatF32S) => ("i32.trunc_sat_f32_s");
971 (name I32TruncSatF32U) => ("i32.trunc_sat_f32_u");
972 (name I32TruncSatF64S) => ("i32.trunc_sat_f64_s");
973 (name I32TruncSatF64U) => ("i32.trunc_sat_f64_u");
974 (name I64TruncSatF32S) => ("i64.trunc_sat_f32_s");
975 (name I64TruncSatF32U) => ("i64.trunc_sat_f32_u");
976 (name I64TruncSatF64S) => ("i64.trunc_sat_f64_s");
977 (name I64TruncSatF64U) => ("i64.trunc_sat_f64_u");
978 (name I32Extend8S) => ("i32.extend8_s");
979 (name I32Extend16S) => ("i32.extend16_s");
980 (name I64Extend8S) => ("i64.extend8_s");
981 (name I64Extend16S) => ("i64.extend16_s");
982 (name I64Extend32S) => ("i64.extend32_s");
983 (name MemoryAtomicNotify) => ("memory.atomic.notify");
984 (name MemoryAtomicWait32) => ("memory.atomic.wait32");
985 (name MemoryAtomicWait64) => ("memory.atomic.wait64");
986 (name AtomicFence) => ("atomic.fence");
987 (name I32AtomicLoad) => ("i32.atomic.load");
988 (name I64AtomicLoad) => ("i64.atomic.load");
989 (name I32AtomicLoad8U) => ("i32.atomic.load8_u");
990 (name I32AtomicLoad16U) => ("i32.atomic.load16_u");
991 (name I64AtomicLoad8U) => ("i64.atomic.load8_u");
992 (name I64AtomicLoad16U) => ("i64.atomic.load16_u");
993 (name I64AtomicLoad32U) => ("i64.atomic.load32_u");
994 (name I32AtomicStore) => ("i32.atomic.store");
995 (name I64AtomicStore) => ("i64.atomic.store");
996 (name I32AtomicStore8) => ("i32.atomic.store8");
997 (name I32AtomicStore16) => ("i32.atomic.store16");
998 (name I64AtomicStore8) => ("i64.atomic.store8");
999 (name I64AtomicStore16) => ("i64.atomic.store16");
1000 (name I64AtomicStore32) => ("i64.atomic.store32");
1001 (name I32AtomicRmwAdd) => ("i32.atomic.rmw.add");
1002 (name I64AtomicRmwAdd) => ("i64.atomic.rmw.add");
1003 (name I32AtomicRmw8AddU) => ("i32.atomic.rmw8.add_u");
1004 (name I32AtomicRmw16AddU) => ("i32.atomic.rmw16.add_u");
1005 (name I64AtomicRmw8AddU) => ("i64.atomic.rmw8.add_u");
1006 (name I64AtomicRmw16AddU) => ("i64.atomic.rmw16.add_u");
1007 (name I64AtomicRmw32AddU) => ("i64.atomic.rmw32.add_u");
1008 (name I32AtomicRmwSub) => ("i32.atomic.rmw.sub");
1009 (name I64AtomicRmwSub) => ("i64.atomic.rmw.sub");
1010 (name I32AtomicRmw8SubU) => ("i32.atomic.rmw8.sub_u");
1011 (name I32AtomicRmw16SubU) => ("i32.atomic.rmw16.sub_u");
1012 (name I64AtomicRmw8SubU) => ("i64.atomic.rmw8.sub_u");
1013 (name I64AtomicRmw16SubU) => ("i64.atomic.rmw16.sub_u");
1014 (name I64AtomicRmw32SubU) => ("i64.atomic.rmw32.sub_u");
1015 (name I32AtomicRmwAnd) => ("i32.atomic.rmw.and");
1016 (name I64AtomicRmwAnd) => ("i64.atomic.rmw.and");
1017 (name I32AtomicRmw8AndU) => ("i32.atomic.rmw8.and_u");
1018 (name I32AtomicRmw16AndU) => ("i32.atomic.rmw16.and_u");
1019 (name I64AtomicRmw8AndU) => ("i64.atomic.rmw8.and_u");
1020 (name I64AtomicRmw16AndU) => ("i64.atomic.rmw16.and_u");
1021 (name I64AtomicRmw32AndU) => ("i64.atomic.rmw32.and_u");
1022 (name I32AtomicRmwOr) => ("i32.atomic.rmw.or");
1023 (name I64AtomicRmwOr) => ("i64.atomic.rmw.or");
1024 (name I32AtomicRmw8OrU) => ("i32.atomic.rmw8.or_u");
1025 (name I32AtomicRmw16OrU) => ("i32.atomic.rmw16.or_u");
1026 (name I64AtomicRmw8OrU) => ("i64.atomic.rmw8.or_u");
1027 (name I64AtomicRmw16OrU) => ("i64.atomic.rmw16.or_u");
1028 (name I64AtomicRmw32OrU) => ("i64.atomic.rmw32.or_u");
1029 (name I32AtomicRmwXor) => ("i32.atomic.rmw.xor");
1030 (name I64AtomicRmwXor) => ("i64.atomic.rmw.xor");
1031 (name I32AtomicRmw8XorU) => ("i32.atomic.rmw8.xor_u");
1032 (name I32AtomicRmw16XorU) => ("i32.atomic.rmw16.xor_u");
1033 (name I64AtomicRmw8XorU) => ("i64.atomic.rmw8.xor_u");
1034 (name I64AtomicRmw16XorU) => ("i64.atomic.rmw16.xor_u");
1035 (name I64AtomicRmw32XorU) => ("i64.atomic.rmw32.xor_u");
1036 (name I32AtomicRmwXchg) => ("i32.atomic.rmw.xchg");
1037 (name I64AtomicRmwXchg) => ("i64.atomic.rmw.xchg");
1038 (name I32AtomicRmw8XchgU) => ("i32.atomic.rmw8.xchg_u");
1039 (name I32AtomicRmw16XchgU) => ("i32.atomic.rmw16.xchg_u");
1040 (name I64AtomicRmw8XchgU) => ("i64.atomic.rmw8.xchg_u");
1041 (name I64AtomicRmw16XchgU) => ("i64.atomic.rmw16.xchg_u");
1042 (name I64AtomicRmw32XchgU) => ("i64.atomic.rmw32.xchg_u");
1043 (name I32AtomicRmwCmpxchg) => ("i32.atomic.rmw.cmpxchg");
1044 (name I64AtomicRmwCmpxchg) => ("i64.atomic.rmw.cmpxchg");
1045 (name I32AtomicRmw8CmpxchgU) => ("i32.atomic.rmw8.cmpxchg_u");
1046 (name I32AtomicRmw16CmpxchgU) => ("i32.atomic.rmw16.cmpxchg_u");
1047 (name I64AtomicRmw8CmpxchgU) => ("i64.atomic.rmw8.cmpxchg_u");
1048 (name I64AtomicRmw16CmpxchgU) => ("i64.atomic.rmw16.cmpxchg_u");
1049 (name I64AtomicRmw32CmpxchgU) => ("i64.atomic.rmw32.cmpxchg_u");
1050 (name V128Load) => ("v128.load");
1051 (name V128Load8x8S) => ("v128.load8x8_s");
1052 (name V128Load8x8U) => ("v128.load8x8_u");
1053 (name V128Load16x4S) => ("v128.load16x4_s");
1054 (name V128Load16x4U) => ("v128.load16x4_u");
1055 (name V128Load32x2S) => ("v128.load32x2_s");
1056 (name V128Load32x2U) => ("v128.load32x2_u");
1057 (name V128Load8Splat) => ("v128.load8_splat");
1058 (name V128Load16Splat) => ("v128.load16_splat");
1059 (name V128Load32Splat) => ("v128.load32_splat");
1060 (name V128Load64Splat) => ("v128.load64_splat");
1061 (name V128Load32Zero) => ("v128.load32_zero");
1062 (name V128Load64Zero) => ("v128.load64_zero");
1063 (name V128Store) => ("v128.store");
1064 (name V128Load8Lane) => ("v128.load8_lane");
1065 (name V128Load16Lane) => ("v128.load16_lane");
1066 (name V128Load32Lane) => ("v128.load32_lane");
1067 (name V128Load64Lane) => ("v128.load64_lane");
1068 (name V128Store8Lane) => ("v128.store8_lane");
1069 (name V128Store16Lane) => ("v128.store16_lane");
1070 (name V128Store32Lane) => ("v128.store32_lane");
1071 (name V128Store64Lane) => ("v128.store64_lane");
1072 (name V128Const) => ("v128.const");
1073 (name I8x16Shuffle) => ("i8x16.shuffle");
1074 (name I8x16ExtractLaneS) => ("i8x16.extract_lane_s");
1075 (name I8x16ExtractLaneU) => ("i8x16.extract_lane_u");
1076 (name I8x16ReplaceLane) => ("i8x16.replace_lane");
1077 (name I16x8ExtractLaneS) => ("i16x8.extract_lane_s");
1078 (name I16x8ExtractLaneU) => ("i16x8.extract_lane_u");
1079 (name I16x8ReplaceLane) => ("i16x8.replace_lane");
1080 (name I32x4ExtractLane) => ("i32x4.extract_lane");
1081 (name I32x4ReplaceLane) => ("i32x4.replace_lane");
1082 (name I64x2ExtractLane) => ("i64x2.extract_lane");
1083 (name I64x2ReplaceLane) => ("i64x2.replace_lane");
1084 (name F32x4ExtractLane) => ("f32x4.extract_lane");
1085 (name F32x4ReplaceLane) => ("f32x4.replace_lane");
1086 (name F64x2ExtractLane) => ("f64x2.extract_lane");
1087 (name F64x2ReplaceLane) => ("f64x2.replace_lane");
1088 (name I8x16Swizzle) => ("i8x16.swizzle");
1089 (name I8x16Splat) => ("i8x16.splat");
1090 (name I16x8Splat) => ("i16x8.splat");
1091 (name I32x4Splat) => ("i32x4.splat");
1092 (name I64x2Splat) => ("i64x2.splat");
1093 (name F32x4Splat) => ("f32x4.splat");
1094 (name F64x2Splat) => ("f64x2.splat");
1095 (name I8x16Eq) => ("i8x16.eq");
1096 (name I8x16Ne) => ("i8x16.ne");
1097 (name I8x16LtS) => ("i8x16.lt_s");
1098 (name I8x16LtU) => ("i8x16.lt_u");
1099 (name I8x16GtS) => ("i8x16.gt_s");
1100 (name I8x16GtU) => ("i8x16.gt_u");
1101 (name I8x16LeS) => ("i8x16.le_s");
1102 (name I8x16LeU) => ("i8x16.le_u");
1103 (name I8x16GeS) => ("i8x16.ge_s");
1104 (name I8x16GeU) => ("i8x16.ge_u");
1105 (name I16x8Eq) => ("i16x8.eq");
1106 (name I16x8Ne) => ("i16x8.ne");
1107 (name I16x8LtS) => ("i16x8.lt_s");
1108 (name I16x8LtU) => ("i16x8.lt_u");
1109 (name I16x8GtS) => ("i16x8.gt_s");
1110 (name I16x8GtU) => ("i16x8.gt_u");
1111 (name I16x8LeS) => ("i16x8.le_s");
1112 (name I16x8LeU) => ("i16x8.le_u");
1113 (name I16x8GeS) => ("i16x8.ge_s");
1114 (name I16x8GeU) => ("i16x8.ge_u");
1115 (name I32x4Eq) => ("i32x4.eq");
1116 (name I32x4Ne) => ("i32x4.ne");
1117 (name I32x4LtS) => ("i32x4.lt_s");
1118 (name I32x4LtU) => ("i32x4.lt_u");
1119 (name I32x4GtS) => ("i32x4.gt_s");
1120 (name I32x4GtU) => ("i32x4.gt_u");
1121 (name I32x4LeS) => ("i32x4.le_s");
1122 (name I32x4LeU) => ("i32x4.le_u");
1123 (name I32x4GeS) => ("i32x4.ge_s");
1124 (name I32x4GeU) => ("i32x4.ge_u");
1125 (name I64x2Eq) => ("i64x2.eq");
1126 (name I64x2Ne) => ("i64x2.ne");
1127 (name I64x2LtS) => ("i64x2.lt_s");
1128 (name I64x2GtS) => ("i64x2.gt_s");
1129 (name I64x2LeS) => ("i64x2.le_s");
1130 (name I64x2GeS) => ("i64x2.ge_s");
1131 (name F32x4Eq) => ("f32x4.eq");
1132 (name F32x4Ne) => ("f32x4.ne");
1133 (name F32x4Lt) => ("f32x4.lt");
1134 (name F32x4Gt) => ("f32x4.gt");
1135 (name F32x4Le) => ("f32x4.le");
1136 (name F32x4Ge) => ("f32x4.ge");
1137 (name F64x2Eq) => ("f64x2.eq");
1138 (name F64x2Ne) => ("f64x2.ne");
1139 (name F64x2Lt) => ("f64x2.lt");
1140 (name F64x2Gt) => ("f64x2.gt");
1141 (name F64x2Le) => ("f64x2.le");
1142 (name F64x2Ge) => ("f64x2.ge");
1143 (name V128Not) => ("v128.not");
1144 (name V128And) => ("v128.and");
1145 (name V128AndNot) => ("v128.andnot");
1146 (name V128Or) => ("v128.or");
1147 (name V128Xor) => ("v128.xor");
1148 (name V128Bitselect) => ("v128.bitselect");
1149 (name V128AnyTrue) => ("v128.any_true");
1150 (name I8x16Abs) => ("i8x16.abs");
1151 (name I8x16Neg) => ("i8x16.neg");
1152 (name I8x16Popcnt) => ("i8x16.popcnt");
1153 (name I8x16AllTrue) => ("i8x16.all_true");
1154 (name I8x16Bitmask) => ("i8x16.bitmask");
1155 (name I8x16NarrowI16x8S) => ("i8x16.narrow_i16x8_s");
1156 (name I8x16NarrowI16x8U) => ("i8x16.narrow_i16x8_u");
1157 (name I8x16Shl) => ("i8x16.shl");
1158 (name I8x16ShrS) => ("i8x16.shr_s");
1159 (name I8x16ShrU) => ("i8x16.shr_u");
1160 (name I8x16Add) => ("i8x16.add");
1161 (name I8x16AddSatS) => ("i8x16.add_sat_s");
1162 (name I8x16AddSatU) => ("i8x16.add_sat_u");
1163 (name I8x16Sub) => ("i8x16.sub");
1164 (name I8x16SubSatS) => ("i8x16.sub_sat_s");
1165 (name I8x16SubSatU) => ("i8x16.sub_sat_u");
1166 (name I8x16MinS) => ("i8x16.min_s");
1167 (name I8x16MinU) => ("i8x16.min_u");
1168 (name I8x16MaxS) => ("i8x16.max_s");
1169 (name I8x16MaxU) => ("i8x16.max_u");
1170 (name I8x16AvgrU) => ("i8x16.avgr_u");
1171 (name I16x8ExtAddPairwiseI8x16S) => ("i16x8.extadd_pairwise_i8x16_s");
1172 (name I16x8ExtAddPairwiseI8x16U) => ("i16x8.extadd_pairwise_i8x16_u");
1173 (name I16x8Abs) => ("i16x8.abs");
1174 (name I16x8Neg) => ("i16x8.neg");
1175 (name I16x8Q15MulrSatS) => ("i16x8.q15mulr_sat_s");
1176 (name I16x8AllTrue) => ("i16x8.all_true");
1177 (name I16x8Bitmask) => ("i16x8.bitmask");
1178 (name I16x8NarrowI32x4S) => ("i16x8.narrow_i32x4_s");
1179 (name I16x8NarrowI32x4U) => ("i16x8.narrow_i32x4_u");
1180 (name I16x8ExtendLowI8x16S) => ("i16x8.extend_low_i8x16_s");
1181 (name I16x8ExtendHighI8x16S) => ("i16x8.extend_high_i8x16_s");
1182 (name I16x8ExtendLowI8x16U) => ("i16x8.extend_low_i8x16_u");
1183 (name I16x8ExtendHighI8x16U) => ("i16x8.extend_high_i8x16_u");
1184 (name I16x8Shl) => ("i16x8.shl");
1185 (name I16x8ShrS) => ("i16x8.shr_s");
1186 (name I16x8ShrU) => ("i16x8.shr_u");
1187 (name I16x8Add) => ("i16x8.add");
1188 (name I16x8AddSatS) => ("i16x8.add_sat_s");
1189 (name I16x8AddSatU) => ("i16x8.add_sat_u");
1190 (name I16x8Sub) => ("i16x8.sub");
1191 (name I16x8SubSatS) => ("i16x8.sub_sat_s");
1192 (name I16x8SubSatU) => ("i16x8.sub_sat_u");
1193 (name I16x8Mul) => ("i16x8.mul");
1194 (name I16x8MinS) => ("i16x8.min_s");
1195 (name I16x8MinU) => ("i16x8.min_u");
1196 (name I16x8MaxS) => ("i16x8.max_s");
1197 (name I16x8MaxU) => ("i16x8.max_u");
1198 (name I16x8AvgrU) => ("i16x8.avgr_u");
1199 (name I16x8ExtMulLowI8x16S) => ("i16x8.extmul_low_i8x16_s");
1200 (name I16x8ExtMulHighI8x16S) => ("i16x8.extmul_high_i8x16_s");
1201 (name I16x8ExtMulLowI8x16U) => ("i16x8.extmul_low_i8x16_u");
1202 (name I16x8ExtMulHighI8x16U) => ("i16x8.extmul_high_i8x16_u");
1203 (name I32x4ExtAddPairwiseI16x8S) => ("i32x4.extadd_pairwise_i16x8_s");
1204 (name I32x4ExtAddPairwiseI16x8U) => ("i32x4.extadd_pairwise_i16x8_u");
1205 (name I32x4Abs) => ("i32x4.abs");
1206 (name I32x4Neg) => ("i32x4.neg");
1207 (name I32x4AllTrue) => ("i32x4.all_true");
1208 (name I32x4Bitmask) => ("i32x4.bitmask");
1209 (name I32x4ExtendLowI16x8S) => ("i32x4.extend_low_i16x8_s");
1210 (name I32x4ExtendHighI16x8S) => ("i32x4.extend_high_i16x8_s");
1211 (name I32x4ExtendLowI16x8U) => ("i32x4.extend_low_i16x8_u");
1212 (name I32x4ExtendHighI16x8U) => ("i32x4.extend_high_i16x8_u");
1213 (name I32x4Shl) => ("i32x4.shl");
1214 (name I32x4ShrS) => ("i32x4.shr_s");
1215 (name I32x4ShrU) => ("i32x4.shr_u");
1216 (name I32x4Add) => ("i32x4.add");
1217 (name I32x4Sub) => ("i32x4.sub");
1218 (name I32x4Mul) => ("i32x4.mul");
1219 (name I32x4MinS) => ("i32x4.min_s");
1220 (name I32x4MinU) => ("i32x4.min_u");
1221 (name I32x4MaxS) => ("i32x4.max_s");
1222 (name I32x4MaxU) => ("i32x4.max_u");
1223 (name I32x4DotI16x8S) => ("i32x4.dot_i16x8_s");
1224 (name I32x4ExtMulLowI16x8S) => ("i32x4.extmul_low_i16x8_s");
1225 (name I32x4ExtMulHighI16x8S) => ("i32x4.extmul_high_i16x8_s");
1226 (name I32x4ExtMulLowI16x8U) => ("i32x4.extmul_low_i16x8_u");
1227 (name I32x4ExtMulHighI16x8U) => ("i32x4.extmul_high_i16x8_u");
1228 (name I64x2Abs) => ("i64x2.abs");
1229 (name I64x2Neg) => ("i64x2.neg");
1230 (name I64x2AllTrue) => ("i64x2.all_true");
1231 (name I64x2Bitmask) => ("i64x2.bitmask");
1232 (name I64x2ExtendLowI32x4S) => ("i64x2.extend_low_i32x4_s");
1233 (name I64x2ExtendHighI32x4S) => ("i64x2.extend_high_i32x4_s");
1234 (name I64x2ExtendLowI32x4U) => ("i64x2.extend_low_i32x4_u");
1235 (name I64x2ExtendHighI32x4U) => ("i64x2.extend_high_i32x4_u");
1236 (name I64x2Shl) => ("i64x2.shl");
1237 (name I64x2ShrS) => ("i64x2.shr_s");
1238 (name I64x2ShrU) => ("i64x2.shr_u");
1239 (name I64x2Add) => ("i64x2.add");
1240 (name I64x2Sub) => ("i64x2.sub");
1241 (name I64x2Mul) => ("i64x2.mul");
1242 (name I64x2ExtMulLowI32x4S) => ("i64x2.extmul_low_i32x4_s");
1243 (name I64x2ExtMulHighI32x4S) => ("i64x2.extmul_high_i32x4_s");
1244 (name I64x2ExtMulLowI32x4U) => ("i64x2.extmul_low_i32x4_u");
1245 (name I64x2ExtMulHighI32x4U) => ("i64x2.extmul_high_i32x4_u");
1246 (name F32x4Ceil) => ("f32x4.ceil");
1247 (name F32x4Floor) => ("f32x4.floor");
1248 (name F32x4Trunc) => ("f32x4.trunc");
1249 (name F32x4Nearest) => ("f32x4.nearest");
1250 (name F32x4Abs) => ("f32x4.abs");
1251 (name F32x4Neg) => ("f32x4.neg");
1252 (name F32x4Sqrt) => ("f32x4.sqrt");
1253 (name F32x4Add) => ("f32x4.add");
1254 (name F32x4Sub) => ("f32x4.sub");
1255 (name F32x4Mul) => ("f32x4.mul");
1256 (name F32x4Div) => ("f32x4.div");
1257 (name F32x4Min) => ("f32x4.min");
1258 (name F32x4Max) => ("f32x4.max");
1259 (name F32x4PMin) => ("f32x4.pmin");
1260 (name F32x4PMax) => ("f32x4.pmax");
1261 (name F64x2Ceil) => ("f64x2.ceil");
1262 (name F64x2Floor) => ("f64x2.floor");
1263 (name F64x2Trunc) => ("f64x2.trunc");
1264 (name F64x2Nearest) => ("f64x2.nearest");
1265 (name F64x2Abs) => ("f64x2.abs");
1266 (name F64x2Neg) => ("f64x2.neg");
1267 (name F64x2Sqrt) => ("f64x2.sqrt");
1268 (name F64x2Add) => ("f64x2.add");
1269 (name F64x2Sub) => ("f64x2.sub");
1270 (name F64x2Mul) => ("f64x2.mul");
1271 (name F64x2Div) => ("f64x2.div");
1272 (name F64x2Min) => ("f64x2.min");
1273 (name F64x2Max) => ("f64x2.max");
1274 (name F64x2PMin) => ("f64x2.pmin");
1275 (name F64x2PMax) => ("f64x2.pmax");
1276 (name I32x4TruncSatF32x4S) => ("i32x4.trunc_sat_f32x4_s");
1277 (name I32x4TruncSatF32x4U) => ("i32x4.trunc_sat_f32x4_u");
1278 (name F32x4ConvertI32x4S) => ("f32x4.convert_i32x4_s");
1279 (name F32x4ConvertI32x4U) => ("f32x4.convert_i32x4_u");
1280 (name I32x4TruncSatF64x2SZero) => ("i32x4.trunc_sat_f64x2_s_zero");
1281 (name I32x4TruncSatF64x2UZero) => ("i32x4.trunc_sat_f64x2_u_zero");
1282 (name F64x2ConvertLowI32x4S) => ("f64x2.convert_low_i32x4_s");
1283 (name F64x2ConvertLowI32x4U) => ("f64x2.convert_low_i32x4_u");
1284 (name F32x4DemoteF64x2Zero) => ("f32x4.demote_f64x2_zero");
1285 (name F64x2PromoteLowF32x4) => ("f64x2.promote_low_f32x4");
1286 (name I8x16RelaxedSwizzle) => ("i8x16.relaxed_swizzle");
1287 (name I32x4RelaxedTruncF32x4S) => ("i32x4.relaxed_trunc_f32x4_s");
1288 (name I32x4RelaxedTruncF32x4U) => ("i32x4.relaxed_trunc_f32x4_u");
1289 (name I32x4RelaxedTruncF64x2SZero) => ("i32x4.relaxed_trunc_f64x2_s_zero");
1290 (name I32x4RelaxedTruncF64x2UZero) => ("i32x4.relaxed_trunc_f64x2_u_zero");
1291 (name F32x4RelaxedMadd) => ("f32x4.relaxed_madd");
1292 (name F32x4RelaxedNmadd) => ("f32x4.relaxed_nmadd");
1293 (name F64x2RelaxedMadd) => ("f64x2.relaxed_madd");
1294 (name F64x2RelaxedNmadd) => ("f64x2.relaxed_nmadd");
1295 (name I8x16RelaxedLaneselect) => ("i8x16.relaxed_laneselect");
1296 (name I16x8RelaxedLaneselect) => ("i16x8.relaxed_laneselect");
1297 (name I32x4RelaxedLaneselect) => ("i32x4.relaxed_laneselect");
1298 (name I64x2RelaxedLaneselect) => ("i64x2.relaxed_laneselect");
1299 (name F32x4RelaxedMin) => ("f32x4.relaxed_min");
1300 (name F32x4RelaxedMax) => ("f32x4.relaxed_max");
1301 (name F64x2RelaxedMin) => ("f64x2.relaxed_min");
1302 (name F64x2RelaxedMax) => ("f64x2.relaxed_max");
1303 (name I16x8RelaxedQ15mulrS) => ("i16x8.relaxed_q15mulr_s");
1304 (name I16x8RelaxedDotI8x16I7x16S) => ("i16x8.relaxed_dot_i8x16_i7x16_s");
1305 (name I32x4RelaxedDotI8x16I7x16AddS) => ("i32x4.relaxed_dot_i8x16_i7x16_add_s");
1306 (name StructNew) => ("struct.new");
1307 (name StructNewDefault) => ("struct.new_default");
1308 (name StructGet) => ("struct.get");
1309 (name StructGetS) => ("struct.get_s");
1310 (name StructGetU) => ("struct.get_u");
1311 (name StructSet) => ("struct.set");
1312 (name ArrayNew) => ("array.new");
1313 (name ArrayNewDefault) => ("array.new_default");
1314 (name ArrayNewFixed) => ("array.new_fixed");
1315 (name ArrayNewData) => ("array.new_data");
1316 (name ArrayNewElem) => ("array.new_elem");
1317 (name ArrayGet) => ("array.get");
1318 (name ArrayGetS) => ("array.get_s");
1319 (name ArrayGetU) => ("array.get_u");
1320 (name ArraySet) => ("array.set");
1321 (name ArrayLen) => ("array.len");
1322 (name ArrayFill) => ("array.fill");
1323 (name ArrayCopy) => ("array.copy");
1324 (name ArrayInitData) => ("array.init_data");
1325 (name ArrayInitElem) => ("array.init_elem");
1326 (name AnyConvertExtern) => ("any.convert_extern");
1327 (name ExternConvertAny) => ("extern.convert_any");
1328 (name RefTestNonNull) => ("ref.test");
1329 (name RefTestNullable) => ("ref.test");
1330 (name RefCastNonNull) => ("ref.cast");
1331 (name RefCastNullable) => ("ref.cast");
1332 (name BrOnCast) => ("br_on_cast");
1333 (name BrOnCastFail) => ("br_on_cast_fail");
1334 (name RefI31) => ("ref.i31");
1335 (name I31GetS) => ("i31.get_s");
1336 (name I31GetU) => ("i31.get_u");
1337 (name TryTable) => ("try_table");
1338 (name Throw) => ("throw");
1339 (name ThrowRef) => ("throw_ref");
1340 (name Rethrow) => ("rethrow");
1341 (name Try) => ("try");
1342 (name Catch) => ("catch");
1343 (name CatchAll) => ("catch_all");
1344 (name Delegate) => ("delegate");
1345 (name GlobalAtomicGet) => ("global.atomic.get");
1346 (name GlobalAtomicSet) => ("global.atomic.set");
1347 (name GlobalAtomicRmwAdd) => ("global.atomic.rmw.add");
1348 (name GlobalAtomicRmwSub) => ("global.atomic.rmw.sub");
1349 (name GlobalAtomicRmwAnd) => ("global.atomic.rmw.and");
1350 (name GlobalAtomicRmwOr) => ("global.atomic.rmw.or");
1351 (name GlobalAtomicRmwXor) => ("global.atomic.rmw.xor");
1352 (name GlobalAtomicRmwXchg) => ("global.atomic.rmw.xchg");
1353 (name GlobalAtomicRmwCmpxchg) => ("global.atomic.rmw.cmpxchg");
1354 (name TableAtomicGet) => ("table.atomic.get");
1355 (name TableAtomicSet) => ("table.atomic.set");
1356 (name TableAtomicRmwXchg) => ("table.atomic.rmw.xchg");
1357 (name TableAtomicRmwCmpxchg) => ("table.atomic.rmw.cmpxchg");
1358 (name StructAtomicGet) => ("struct.atomic.get");
1359 (name StructAtomicGetS) => ("struct.atomic.get_s");
1360 (name StructAtomicGetU) => ("struct.atomic.get_u");
1361 (name StructAtomicSet) => ("struct.atomic.set");
1362 (name StructAtomicRmwAdd) => ("struct.atomic.rmw.add");
1363 (name StructAtomicRmwSub) => ("struct.atomic.rmw.sub");
1364 (name StructAtomicRmwAnd) => ("struct.atomic.rmw.and");
1365 (name StructAtomicRmwOr) => ("struct.atomic.rmw.or");
1366 (name StructAtomicRmwXor) => ("struct.atomic.rmw.xor");
1367 (name StructAtomicRmwXchg) => ("struct.atomic.rmw.xchg");
1368 (name StructAtomicRmwCmpxchg) => ("struct.atomic.rmw.cmpxchg");
1369 (name ArrayAtomicGet) => ("array.atomic.get");
1370 (name ArrayAtomicGetS) => ("array.atomic.get_s");
1371 (name ArrayAtomicGetU) => ("array.atomic.get_u");
1372 (name ArrayAtomicSet) => ("array.atomic.set");
1373 (name ArrayAtomicRmwAdd) => ("array.atomic.rmw.add");
1374 (name ArrayAtomicRmwSub) => ("array.atomic.rmw.sub");
1375 (name ArrayAtomicRmwAnd) => ("array.atomic.rmw.and");
1376 (name ArrayAtomicRmwOr) => ("array.atomic.rmw.or");
1377 (name ArrayAtomicRmwXor) => ("array.atomic.rmw.xor");
1378 (name ArrayAtomicRmwXchg) => ("array.atomic.rmw.xchg");
1379 (name ArrayAtomicRmwCmpxchg) => ("array.atomic.rmw.cmpxchg");
1380 (name RefI31Shared) => ("ref.i31_shared");
1381 (name ContNew) => ("cont.new");
1382 (name ContBind) => ("cont.bind");
1383 (name Suspend) => ("suspend");
1384 (name Resume) => ("resume");
1385 (name ResumeThrow) => ("resume_throw");
1386 (name Switch) => ("switch");
1387 (name I64Add128) => ("i64.add128");
1388 (name I64Sub128) => ("i64.sub128");
1389 (name I64MulWideS) => ("i64.mul_wide_s");
1390 (name I64MulWideU) => ("i64.mul_wide_u");
1391}
1392
1393impl<'a> VisitOperator<'a> for PrintOperator<'_, '_, '_, '_> {
1394 type Output = Result<()>;
1395
1396 fn simd_visitor(&mut self) -> Option<&mut dyn VisitSimdOperator<'a, Output = Self::Output>> {
1397 Some(self)
1398 }
1399
1400 wasmparser::for_each_visit_operator!(define_visit);
1401}
1402
1403impl<'a> VisitSimdOperator<'a> for PrintOperator<'_, '_, '_, '_> {
1404 wasmparser::for_each_visit_simd_operator!(define_visit);
1405}
1406
1407pub trait OpPrinter {
1408 fn branch_hint(&mut self, offset: usize, taken: bool) -> Result<()>;
1409 fn set_offset(&mut self, offset: usize);
1410 fn visit_operator(
1411 &mut self,
1412 reader: &mut OperatorsReader<'_>,
1413 annotation: Option<&str>,
1414 ) -> Result<()>;
1415 fn finalize(&mut self, annotation: Option<&str>) -> Result<()>;
1416 fn use_color(&self) -> bool;
1417}
1418
1419impl OpPrinter for PrintOperator<'_, '_, '_, '_> {
1420 fn branch_hint(&mut self, offset: usize, taken: bool) -> Result<()> {
1421 self.printer.newline(offset)?;
1422 let desc = if taken { "\"\\01\"" } else { "\"\\00\"" };
1423 self.printer.result.start_comment()?;
1424 write!(self.printer.result, "(@metadata.code.branch_hint {desc})")?;
1425 self.printer.result.reset_color()?;
1426 Ok(())
1427 }
1428
1429 fn set_offset(&mut self, offset: usize) {
1430 self.operator_state.op_offset = offset;
1431 }
1432
1433 fn visit_operator(
1434 &mut self,
1435 reader: &mut OperatorsReader<'_>,
1436 annotation: Option<&str>,
1437 ) -> Result<()> {
1438 reader.visit_operator(self)??;
1439 if let Some(s) = annotation {
1440 self.printer.newline_unknown_pos()?;
1441 self.result().start_comment()?;
1442 write!(self.result(), ";; {s}")?;
1443 self.result().reset_color()?;
1444 }
1445 Ok(())
1446 }
1447
1448 fn finalize(&mut self, annotation: Option<&str>) -> Result<()> {
1449 if let Some(s) = annotation {
1450 self.printer.newline_unknown_pos()?;
1451 self.result().start_comment()?;
1452 write!(self.printer.result, ";; {s}")?;
1453 self.result().reset_color()?;
1454 }
1455 Ok(())
1456 }
1457
1458 fn use_color(&self) -> bool {
1459 self.printer.result.supports_async_color()
1460 }
1461}
1462
1463impl OpPrinter for PrintOperatorFolded<'_, '_, '_, '_> {
1464 fn branch_hint(&mut self, offset: usize, taken: bool) -> Result<()> {
1465 let mut hint = String::new();
1466 hint.push_str("@metadata.code.branch_hint ");
1467 hint.push_str(if taken { "\"\\01\"" } else { "\"\\00\"" });
1468 self.branch_hint = Some(FoldedInstruction {
1469 plain: hint,
1470 folded: Vec::new(),
1471 results: 0,
1472 offset,
1473 });
1474 Ok(())
1475 }
1476
1477 fn set_offset(&mut self, offset: usize) {
1478 self.operator_state.op_offset = offset;
1479 }
1480
1481 fn visit_operator(
1482 &mut self,
1483 reader: &mut OperatorsReader<'_>,
1484 annotation: Option<&str>,
1485 ) -> Result<()> {
1486 let operator = reader.clone().read()?;
1487 let (params, results) = operator.operator_arity(self).unwrap_or((0, 0));
1488 let mut buf_color = PrintTermcolor(Ansi::new(Vec::new()));
1489 let mut buf_nocolor = PrintTermcolor(NoColor::new(Vec::new()));
1490 let internal_config = Config {
1491 name_unnamed: self.printer.config.name_unnamed,
1492 ..Default::default()
1493 };
1494 let mut internal_printer = Printer {
1495 config: &internal_config,
1496 result: if self.use_color() {
1497 &mut buf_color
1498 } else {
1499 &mut buf_nocolor
1500 },
1501 nesting: self.printer.nesting,
1502 line: self.printer.line,
1503 group_lines: Vec::new(),
1504 code_section_hints: Vec::new(),
1505 };
1506
1507 let mut op_printer =
1508 PrintOperator::new(&mut internal_printer, self.state, self.operator_state);
1509 reader.visit_operator(&mut op_printer)??;
1510 if let Some(s) = annotation {
1511 internal_printer.result.start_comment()?;
1512 write!(internal_printer.result, " (; {s}")?;
1513 internal_printer.result.start_comment()?;
1514 write!(internal_printer.result, " ;)")?;
1515 internal_printer.result.reset_color()?;
1516 }
1517
1518 self.printer.nesting = internal_printer.nesting;
1519 self.printer.line = internal_printer.line;
1520
1521 let inst = String::from_utf8(if self.use_color() {
1522 buf_color.0.into_inner()
1523 } else {
1524 buf_nocolor.0.into_inner()
1525 })
1526 .expect("invalid UTF-8");
1527
1528 match operator {
1529 Operator::Loop { blockty } => self.push_block(blockty, FrameKind::Loop, inst),
1530 Operator::Block { blockty } => self.push_block(blockty, FrameKind::Block, inst),
1531 Operator::TryTable { try_table } => {
1532 self.push_block(try_table.ty, FrameKind::TryTable, inst)
1533 }
1534 Operator::If { blockty } => self.push_if(blockty, inst),
1535 Operator::Else => self.handle_else(),
1536 Operator::End => self.handle_end(results),
1537
1538 Operator::Try { .. }
1539 | Operator::Catch { .. }
1540 | Operator::CatchAll { .. }
1541 | Operator::Delegate { .. } => {
1542 bail!("legacy-exceptions not supported")
1543 }
1544 _ => self.handle_plain(inst, params, results),
1545 }
1546 }
1547
1548 fn finalize(&mut self, annotation: Option<&str>) -> Result<()> {
1550 if self.control.len() != 1 {
1551 bail!("instruction sequence not closed");
1552 }
1553 for inst in &self.control.last().unwrap().folded {
1554 PrintOperatorFolded::print(&mut self.printer, &mut self.original_separator, &inst)?;
1555 }
1556 if let Some(s) = annotation {
1557 self.printer.newline_unknown_pos()?;
1558 self.printer.result.start_comment()?;
1559 write!(self.printer.result, ";; {s}")?;
1560 self.printer.result.reset_color()?;
1561 }
1562 Ok(())
1563 }
1564
1565 fn use_color(&self) -> bool {
1566 self.printer.result.supports_async_color()
1567 }
1568}
1569
1570impl ModuleArity for PrintOperatorFolded<'_, '_, '_, '_> {
1571 fn tag_type_arity(&self, tag_idx: u32) -> Option<(u32, u32)> {
1572 self.sub_type_arity(
1573 self.sub_type_at(
1574 *self
1575 .state
1576 .core
1577 .tag_to_type
1578 .get(tag_idx as usize)?
1579 .as_ref()?,
1580 )?,
1581 )
1582 }
1583
1584 fn type_index_of_function(&self, func_idx: u32) -> Option<u32> {
1585 *self.state.core.func_to_type.get(func_idx as usize)?
1586 }
1587
1588 fn sub_type_at(&self, type_idx: u32) -> Option<&SubType> {
1589 self.state.core.types.get(type_idx as usize)?.as_ref()
1590 }
1591
1592 fn func_type_of_cont_type(&self, c: &ContType) -> Option<&FuncType> {
1593 let st = self.sub_type_at(c.0.unpack().as_module_index()?)?;
1594 if let CompositeInnerType::Func(ft) = &st.composite_type.inner {
1595 Some(ft)
1596 } else {
1597 None
1598 }
1599 }
1600
1601 fn sub_type_of_ref_type(&self, rt: &RefType) -> Option<&SubType> {
1602 self.sub_type_at(rt.type_index()?.as_module_index()?)
1603 }
1604
1605 fn control_stack_height(&self) -> u32 {
1606 self.control.len() as u32
1607 }
1608
1609 fn label_block(&self, depth: u32) -> Option<(BlockType, FrameKind)> {
1610 let cur_depth = self.printer.nesting - self.operator_state.nesting_start;
1611 if self.control.len() != cur_depth as usize + 1 {
1612 return None;
1613 }
1614 match (self.control.len() - 1).checked_sub(depth as usize) {
1615 Some(i) => Some((self.control[i].ty, self.control[i].kind)),
1616 None => None,
1617 }
1618 }
1619}
1620
1621impl<'printer, 'state, 'a, 'b> PrintOperatorFolded<'printer, 'state, 'a, 'b> {
1622 pub(super) fn new(
1623 printer: &'printer mut Printer<'a, 'b>,
1624 state: &'state mut State,
1625 operator_state: &'printer mut OperatorState,
1626 ) -> Self {
1627 let original_separator = operator_state.sep;
1628 operator_state.sep = OperatorSeparator::None;
1629
1630 PrintOperatorFolded {
1631 printer,
1632 state,
1633 operator_state,
1634 control: Vec::new(),
1635 branch_hint: None,
1636 original_separator,
1637 }
1638 }
1639
1640 pub fn begin_function(&mut self, func_idx: u32) -> Result<()> {
1642 match self.state.core.func_to_type.get(func_idx as usize) {
1643 Some(Some(type_idx)) => self.control.push(Block {
1644 ty: BlockType::FuncType(*type_idx),
1645 kind: FrameKind::Block,
1646 plain: String::new(),
1647 folded: Vec::new(),
1648 predicate: None,
1649 consequent: None,
1650 offset: self.operator_state.op_offset,
1651 }),
1652 _ => bail!("invalid func_idx"),
1653 }
1654
1655 Ok(())
1656 }
1657
1658 pub fn begin_const_expr(&mut self) {
1660 self.control.push(Block {
1661 ty: BlockType::Empty,
1662 kind: FrameKind::Block,
1663 plain: String::new(),
1664 folded: Vec::new(),
1665 predicate: None,
1666 consequent: None,
1667 offset: 0,
1668 });
1669 }
1670
1671 fn handle_plain(&mut self, plain: String, params: u32, mut results: u32) -> Result<()> {
1677 let stack = match self.control.last_mut() {
1678 Some(stack) => stack,
1679 None => bail!("instruction without enclosing block"),
1680 };
1681
1682 let mut first_param = stack.folded.len();
1683 let mut param_count: u32 = 0;
1684 if params > 0 {
1685 for (pos, inst) in stack.folded.iter().enumerate().rev() {
1686 param_count = param_count.saturating_add(inst.results);
1687 if param_count == params {
1688 first_param = pos;
1689 break;
1690 } else if param_count > params {
1691 results = u32::MAX;
1693 break;
1694 }
1695 }
1696 }
1697
1698 let mut inst = FoldedInstruction {
1699 plain,
1700 folded: stack.folded.drain(first_param..).collect(),
1701 results,
1702 offset: self.operator_state.op_offset,
1703 };
1704 if let Some(hint) = self.branch_hint.take() {
1705 inst.folded.push(hint);
1706 }
1707 stack.folded.push(inst);
1708
1709 Ok(())
1710 }
1711
1712 fn print(
1716 printer: &mut Printer,
1717 sep: &mut OperatorSeparator,
1718 inst: &FoldedInstruction,
1719 ) -> Result<()> {
1720 match sep {
1721 OperatorSeparator::Newline => printer.newline(inst.offset)?,
1722 OperatorSeparator::None => (),
1723 OperatorSeparator::NoneThenSpace => *sep = OperatorSeparator::Space,
1724 OperatorSeparator::Space => printer.result.write_str(" ")?,
1725 }
1726
1727 printer.result.write_str("(")?;
1728 printer.result.write_str(&inst.plain)?;
1729 if inst.folded.is_empty() && inst.plain.contains(";;") {
1730 printer.newline(inst.offset)?;
1732 }
1733 printer.nesting += 1;
1734 for fi in &inst.folded {
1735 PrintOperatorFolded::print(printer, sep, &fi)?;
1736 }
1737 printer.nesting -= 1;
1738 printer.result.write_str(")")?;
1739 Ok(())
1740 }
1741
1742 fn reject_branch_hint(&mut self) -> Result<()> {
1744 if self.branch_hint.is_some() {
1745 bail!("branch hints are only supported on an `if` or a plain instructions");
1746 }
1747 Ok(())
1748 }
1749
1750 fn push_block(&mut self, ty: BlockType, kind: FrameKind, plain: String) -> Result<()> {
1751 self.reject_branch_hint()?;
1752 self.control.push(Block {
1753 ty,
1754 kind,
1755 plain,
1756 folded: Vec::new(),
1757 predicate: None,
1758 consequent: None,
1759 offset: self.operator_state.op_offset,
1760 });
1761 Ok(())
1762 }
1763
1764 fn push_if(&mut self, ty: BlockType, plain: String) -> Result<()> {
1765 let mut predicate = Vec::new();
1766 if let Some(phrase) = self
1767 .control
1768 .last_mut()
1769 .ok_or_else(|| anyhow!("no enclosing block"))?
1770 .folded
1771 .pop()
1772 {
1773 predicate.push(phrase)
1774 }
1775 if let Some(hint) = self.branch_hint.take() {
1776 predicate.push(hint);
1777 }
1778 self.control.push(Block {
1779 ty,
1780 kind: FrameKind::If,
1781 plain,
1782 folded: Vec::new(),
1783 predicate: Some(predicate),
1784 consequent: None,
1785 offset: self.operator_state.op_offset,
1786 });
1787 Ok(())
1788 }
1789
1790 fn handle_else(&mut self) -> Result<()> {
1791 self.reject_branch_hint()?;
1792 match self.control.pop() {
1793 Some(Block {
1794 ty,
1795 kind: FrameKind::If,
1796 plain,
1797 predicate,
1798 folded,
1799 offset,
1800 ..
1801 }) => self.control.push(Block {
1802 ty,
1803 kind: FrameKind::Else,
1804 plain,
1805 folded: Vec::new(),
1806 predicate,
1807 consequent: Some((folded, offset)),
1808 offset: self.operator_state.op_offset,
1809 }),
1810 _ => bail!("no enclosing if block"),
1811 }
1812
1813 Ok(())
1814 }
1815
1816 fn handle_end(&mut self, results: u32) -> Result<()> {
1821 self.reject_branch_hint()?;
1822 let frame = self.control.pop();
1823 let inst = match frame {
1824 Some(Block {
1825 kind: FrameKind::Block | FrameKind::Loop | FrameKind::TryTable,
1826 plain,
1827 folded,
1828 offset,
1829 ..
1830 }) => FoldedInstruction {
1831 plain,
1832 folded,
1833 results,
1834 offset,
1835 },
1836 Some(Block {
1837 kind: FrameKind::If,
1838 plain,
1839 folded,
1840 predicate: Some(predicate),
1841 offset,
1842 ..
1843 }) => {
1844 let then_clause = FoldedInstruction {
1845 plain: String::from("then"),
1846 folded,
1847 results,
1848 offset,
1849 };
1850 let mut folded = predicate;
1851 folded.push(then_clause);
1852 FoldedInstruction {
1853 plain,
1854 folded,
1855 results,
1856 offset,
1857 }
1858 }
1859 Some(Block {
1860 kind: FrameKind::Else,
1861 plain,
1862 folded,
1863 predicate: Some(predicate),
1864 consequent: Some((consequent, if_offset)),
1865 offset,
1866 ..
1867 }) => {
1868 let then_clause = FoldedInstruction {
1869 plain: String::from("then"),
1870 folded: consequent,
1871 results,
1872 offset: if_offset,
1873 };
1874 let else_clause = FoldedInstruction {
1875 plain: String::from("else"),
1876 folded,
1877 results,
1878 offset,
1879 };
1880 let mut folded = predicate;
1881 folded.push(then_clause);
1882 folded.push(else_clause);
1883 FoldedInstruction {
1884 plain,
1885 folded,
1886 results,
1887 offset: if_offset,
1888 }
1889 }
1890 _ => bail!("unhandled frame kind"),
1891 };
1892
1893 self.control
1894 .last_mut()
1895 .ok_or_else(|| anyhow!("end without outer block"))?
1896 .folded
1897 .push(inst);
1898 Ok(())
1899 }
1900}