1use crate::{
26 limits::MAX_WASM_FUNCTION_LOCALS, BinaryReaderError, BlockType, BrTable, Ieee32, Ieee64,
27 MemArg, Result, ValType, VisitOperator, WasmFeatures, WasmFuncType, WasmModuleResources, V128,
28};
29use ::alloc::vec::Vec;
30use ::core::ops::{Deref, DerefMut};
31
32pub(crate) struct OperatorValidator {
33 pub(super) locals: Locals,
34
35 pub(crate) features: WasmFeatures,
38
39 br_table_tmp: Vec<Option<ValType>>,
41
42 control: Vec<Frame>,
44 operands: Vec<Option<ValType>>,
46
47 end_which_emptied_control: Option<usize>,
50}
51
52const MAX_LOCALS_TO_TRACK: usize = 50;
55
56pub(super) struct Locals {
57 num_locals: u32,
59
60 first: Vec<ValType>,
65
66 all: Vec<(u32, ValType)>,
77}
78
79#[derive(Debug, Copy, Clone)]
86pub struct Frame {
87 pub kind: FrameKind,
89 pub block_type: BlockType,
92 pub height: usize,
94 pub unreachable: bool,
96}
97
98#[derive(Copy, Clone, Debug, PartialEq, Eq)]
100pub enum FrameKind {
101 Block,
103 If,
105 Else,
107 Loop,
109 Try,
115 Catch,
121 CatchAll,
127}
128
129struct OperatorValidatorTemp<'validator, 'resources, T> {
130 offset: usize,
131 inner: &'validator mut OperatorValidator,
132 resources: &'resources T,
133}
134
135#[derive(Default)]
136pub struct OperatorValidatorAllocations {
137 br_table_tmp: Vec<Option<ValType>>,
138 control: Vec<Frame>,
139 operands: Vec<Option<ValType>>,
140 locals_first: Vec<ValType>,
141 locals_all: Vec<(u32, ValType)>,
142}
143
144impl OperatorValidator {
145 fn new(features: &WasmFeatures, allocs: OperatorValidatorAllocations) -> Self {
146 let OperatorValidatorAllocations {
147 br_table_tmp,
148 control,
149 operands,
150 locals_first,
151 locals_all,
152 } = allocs;
153 debug_assert!(br_table_tmp.is_empty());
154 debug_assert!(control.is_empty());
155 debug_assert!(operands.is_empty());
156 debug_assert!(locals_first.is_empty());
157 debug_assert!(locals_all.is_empty());
158 OperatorValidator {
159 locals: Locals {
160 num_locals: 0,
161 first: locals_first,
162 all: locals_all,
163 },
164 features: *features,
165 br_table_tmp,
166 operands,
167 control,
168 end_which_emptied_control: None,
169 }
170 }
171
172 pub fn new_func<T>(
178 ty: u32,
179 offset: usize,
180 features: &WasmFeatures,
181 resources: &T,
182 allocs: OperatorValidatorAllocations,
183 ) -> Result<Self>
184 where
185 T: WasmModuleResources,
186 {
187 let mut ret = OperatorValidator::new(features, allocs);
188 ret.control.push(Frame {
189 kind: FrameKind::Block,
190 block_type: BlockType::FuncType(ty),
191 height: 0,
192 unreachable: false,
193 });
194 let params = OperatorValidatorTemp {
195 offset,
197 inner: &mut ret,
198 resources,
199 }
200 .func_type_at(ty)?
201 .inputs();
202 for ty in params {
203 ret.locals.define(1, ty);
204 }
205 Ok(ret)
206 }
207
208 pub fn new_const_expr(
212 features: &WasmFeatures,
213 ty: ValType,
214 allocs: OperatorValidatorAllocations,
215 ) -> Self {
216 let mut ret = OperatorValidator::new(features, allocs);
217 ret.control.push(Frame {
218 kind: FrameKind::Block,
219 block_type: BlockType::Type(ty),
220 height: 0,
221 unreachable: false,
222 });
223 ret
224 }
225
226 pub fn define_locals(&mut self, offset: usize, count: u32, ty: ValType) -> Result<()> {
227 self.features
228 .check_value_type(ty)
229 .map_err(|e| BinaryReaderError::new(e, offset))?;
230 if count == 0 {
231 return Ok(());
232 }
233 if !self.locals.define(count, ty) {
234 return Err(BinaryReaderError::new(
235 "too many locals: locals exceed maximum",
236 offset,
237 ));
238 }
239 Ok(())
240 }
241
242 pub fn operand_stack_height(&self) -> usize {
244 self.operands.len()
245 }
246
247 pub fn peek_operand_at(&self, depth: usize) -> Option<Option<ValType>> {
258 self.operands.iter().rev().nth(depth).copied()
259 }
260
261 pub fn control_stack_height(&self) -> usize {
263 self.control.len()
264 }
265
266 pub fn get_frame(&self, depth: usize) -> Option<&Frame> {
267 self.control.iter().rev().nth(depth)
268 }
269
270 pub fn with_resources<'a, 'validator, 'resources, T>(
272 &'validator mut self,
273 resources: &'resources T,
274 offset: usize,
275 ) -> impl VisitOperator<'a, Output = Result<()>> + 'validator
276 where
277 T: WasmModuleResources,
278 'resources: 'validator,
279 {
280 WasmProposalValidator(OperatorValidatorTemp {
281 offset,
282 inner: self,
283 resources,
284 })
285 }
286
287 pub fn finish(&mut self, offset: usize) -> Result<()> {
288 if self.control.last().is_some() {
289 bail!(
290 offset,
291 "control frames remain at end of function: END opcode expected"
292 );
293 }
294
295 if offset != self.end_which_emptied_control.unwrap() + 1 {
300 return Err(self.err_beyond_end(offset));
301 }
302 Ok(())
303 }
304
305 fn err_beyond_end(&self, offset: usize) -> BinaryReaderError {
306 format_err!(offset, "operators remaining after end of function")
307 }
308
309 pub fn into_allocations(self) -> OperatorValidatorAllocations {
310 fn truncate<T>(mut tmp: Vec<T>) -> Vec<T> {
311 tmp.truncate(0);
312 tmp
313 }
314 OperatorValidatorAllocations {
315 br_table_tmp: truncate(self.br_table_tmp),
316 control: truncate(self.control),
317 operands: truncate(self.operands),
318 locals_first: truncate(self.locals.first),
319 locals_all: truncate(self.locals.all),
320 }
321 }
322}
323
324impl<R> Deref for OperatorValidatorTemp<'_, '_, R> {
325 type Target = OperatorValidator;
326 fn deref(&self) -> &OperatorValidator {
327 self.inner
328 }
329}
330
331impl<R> DerefMut for OperatorValidatorTemp<'_, '_, R> {
332 fn deref_mut(&mut self) -> &mut OperatorValidator {
333 self.inner
334 }
335}
336
337impl<'resources, R: WasmModuleResources> OperatorValidatorTemp<'_, 'resources, R> {
338 fn push_operand<T>(&mut self, ty: T) -> Result<()>
344 where
345 T: Into<Option<ValType>>,
346 {
347 let maybe_ty = ty.into();
348 self.operands.push(maybe_ty);
349 Ok(())
350 }
351
352 fn pop_operand(&mut self, expected: Option<ValType>) -> Result<Option<ValType>> {
371 let popped = if let Some(actual_ty) = self.operands.pop() {
383 if actual_ty == expected {
384 if let Some(control) = self.control.last() {
385 if self.operands.len() >= control.height {
386 return Ok(actual_ty);
387 }
388 }
389 }
390 Some(actual_ty)
391 } else {
392 None
393 };
394
395 self._pop_operand(expected, popped)
396 }
397
398 #[cold]
402 fn _pop_operand(
403 &mut self,
404 expected: Option<ValType>,
405 popped: Option<Option<ValType>>,
406 ) -> Result<Option<ValType>> {
407 self.operands.extend(popped);
408 let control = match self.control.last() {
409 Some(c) => c,
410 None => return Err(self.err_beyond_end(self.offset)),
411 };
412 let actual = if self.operands.len() == control.height {
413 if control.unreachable {
414 None
415 } else {
416 let desc = match expected {
417 Some(ty) => ty_to_str(ty),
418 None => "a type",
419 };
420 bail!(
421 self.offset,
422 "type mismatch: expected {desc} but nothing on stack"
423 )
424 }
425 } else {
426 self.operands.pop().unwrap()
427 };
428 if let (Some(actual_ty), Some(expected_ty)) = (actual, expected) {
429 if actual_ty != expected_ty {
430 bail!(
431 self.offset,
432 "type mismatch: expected {}, found {}",
433 ty_to_str(expected_ty),
434 ty_to_str(actual_ty)
435 )
436 }
437 }
438 Ok(actual)
439 }
440
441 fn local(&self, idx: u32) -> Result<ValType> {
444 match self.locals.get(idx) {
445 Some(ty) => Ok(ty),
446 None => bail!(
447 self.offset,
448 "unknown local {}: local index out of bounds",
449 idx
450 ),
451 }
452 }
453
454 fn unreachable(&mut self) -> Result<()> {
457 let control = match self.control.last_mut() {
458 Some(frame) => frame,
459 None => return Err(self.err_beyond_end(self.offset)),
460 };
461 control.unreachable = true;
462 let new_height = control.height;
463 self.operands.truncate(new_height);
464 Ok(())
465 }
466
467 fn push_ctrl(&mut self, kind: FrameKind, ty: BlockType) -> Result<()> {
474 let height = self.operands.len();
477 self.control.push(Frame {
478 kind,
479 block_type: ty,
480 height,
481 unreachable: false,
482 });
483 for ty in self.params(ty)? {
486 self.push_operand(ty)?;
487 }
488 Ok(())
489 }
490
491 fn pop_ctrl(&mut self) -> Result<Frame> {
496 let frame = match self.control.last() {
499 Some(f) => f,
500 None => return Err(self.err_beyond_end(self.offset)),
501 };
502 let ty = frame.block_type;
503 let height = frame.height;
504
505 for ty in self.results(ty)?.rev() {
508 self.pop_operand(Some(ty))?;
509 }
510
511 if self.operands.len() != height {
514 bail!(
515 self.offset,
516 "type mismatch: values remaining on stack at end of block"
517 );
518 }
519
520 Ok(self.control.pop().unwrap())
522 }
523
524 fn jump(&self, depth: u32) -> Result<(BlockType, FrameKind)> {
529 if self.control.is_empty() {
530 return Err(self.err_beyond_end(self.offset));
531 }
532 match (self.control.len() - 1).checked_sub(depth as usize) {
533 Some(i) => {
534 let frame = &self.control[i];
535 Ok((frame.block_type, frame.kind))
536 }
537 None => bail!(self.offset, "unknown label: branch depth too large"),
538 }
539 }
540
541 fn check_memory_index(&self, memory_index: u32) -> Result<ValType> {
544 match self.resources.memory_at(memory_index) {
545 Some(mem) => Ok(mem.index_type()),
546 None => bail!(self.offset, "unknown memory {}", memory_index),
547 }
548 }
549
550 fn check_memarg(&self, memarg: MemArg) -> Result<ValType> {
553 let index_ty = self.check_memory_index(memarg.memory)?;
554 if memarg.align > memarg.max_align {
555 bail!(self.offset, "alignment must not be larger than natural");
556 }
557 if index_ty == ValType::I32 && memarg.offset > u64::from(u32::MAX) {
558 bail!(self.offset, "offset out of range: must be <= 2**32");
559 }
560 Ok(index_ty)
561 }
562
563 fn check_floats_enabled(&self) -> Result<()> {
564 if !self.features.floats {
565 bail!(self.offset, "floating-point instruction disallowed");
566 }
567 Ok(())
568 }
569
570 fn check_shared_memarg(&self, memarg: MemArg) -> Result<ValType> {
571 if memarg.align != memarg.max_align {
572 bail!(
573 self.offset,
574 "atomic instructions must always specify maximum alignment"
575 );
576 }
577 self.check_memory_index(memarg.memory)
578 }
579
580 fn check_simd_lane_index(&self, index: u8, max: u8) -> Result<()> {
581 if index >= max {
582 bail!(self.offset, "SIMD index out of bounds");
583 }
584 Ok(())
585 }
586
587 fn check_block_type(&self, ty: BlockType) -> Result<()> {
589 match ty {
590 BlockType::Empty => Ok(()),
591 BlockType::Type(ty) => self
592 .features
593 .check_value_type(ty)
594 .map_err(|e| BinaryReaderError::new(e, self.offset)),
595 BlockType::FuncType(idx) => {
596 if !self.features.multi_value {
597 bail!(
598 self.offset,
599 "blocks, loops, and ifs may only produce a resulttype \
600 when multi-value is not enabled",
601 );
602 }
603 self.func_type_at(idx)?;
604 Ok(())
605 }
606 }
607 }
608
609 fn check_call(&mut self, function_index: u32) -> Result<()> {
612 let ty = match self.resources.type_of_function(function_index) {
613 Some(i) => i,
614 None => {
615 bail!(
616 self.offset,
617 "unknown function {}: function index out of bounds",
618 function_index
619 );
620 }
621 };
622 for ty in ty.inputs().rev() {
623 self.pop_operand(Some(ty))?;
624 }
625 for ty in ty.outputs() {
626 self.push_operand(ty)?;
627 }
628 Ok(())
629 }
630
631 fn check_call_indirect(&mut self, index: u32, table_index: u32) -> Result<()> {
633 match self.resources.table_at(table_index) {
634 None => {
635 bail!(self.offset, "unknown table: table index out of bounds");
636 }
637 Some(tab) => {
638 if tab.element_type != ValType::FuncRef {
639 bail!(
640 self.offset,
641 "indirect calls must go through a table of funcref"
642 );
643 }
644 }
645 }
646 let ty = self.func_type_at(index)?;
647 self.pop_operand(Some(ValType::I32))?;
648 for ty in ty.inputs().rev() {
649 self.pop_operand(Some(ty))?;
650 }
651 for ty in ty.outputs() {
652 self.push_operand(ty)?;
653 }
654 Ok(())
655 }
656
657 fn check_return(&mut self) -> Result<()> {
660 if self.control.is_empty() {
661 return Err(self.err_beyond_end(self.offset));
662 }
663 for ty in self.results(self.control[0].block_type)?.rev() {
664 self.pop_operand(Some(ty))?;
665 }
666 self.unreachable()?;
667 Ok(())
668 }
669
670 fn check_cmp_op(&mut self, ty: ValType) -> Result<()> {
672 self.pop_operand(Some(ty))?;
673 self.pop_operand(Some(ty))?;
674 self.push_operand(ValType::I32)?;
675 Ok(())
676 }
677
678 fn check_fcmp_op(&mut self, ty: ValType) -> Result<()> {
680 debug_assert!(matches!(ty, ValType::F32 | ValType::F64));
681 self.check_floats_enabled()?;
682 self.check_cmp_op(ty)
683 }
684
685 fn check_unary_op(&mut self, ty: ValType) -> Result<()> {
687 self.pop_operand(Some(ty))?;
688 self.push_operand(ty)?;
689 Ok(())
690 }
691
692 fn check_funary_op(&mut self, ty: ValType) -> Result<()> {
694 debug_assert!(matches!(ty, ValType::F32 | ValType::F64));
695 self.check_floats_enabled()?;
696 self.check_unary_op(ty)
697 }
698
699 fn check_conversion_op(&mut self, into: ValType, from: ValType) -> Result<()> {
701 self.pop_operand(Some(from))?;
702 self.push_operand(into)?;
703 Ok(())
704 }
705
706 fn check_fconversion_op(&mut self, into: ValType, from: ValType) -> Result<()> {
708 debug_assert!(matches!(into, ValType::F32 | ValType::F64));
709 self.check_floats_enabled()?;
710 self.check_conversion_op(into, from)
711 }
712
713 fn check_binary_op(&mut self, ty: ValType) -> Result<()> {
715 self.pop_operand(Some(ty))?;
716 self.pop_operand(Some(ty))?;
717 self.push_operand(ty)?;
718 Ok(())
719 }
720
721 fn check_fbinary_op(&mut self, ty: ValType) -> Result<()> {
723 debug_assert!(matches!(ty, ValType::F32 | ValType::F64));
724 self.check_floats_enabled()?;
725 self.check_binary_op(ty)
726 }
727
728 fn check_atomic_load(&mut self, memarg: MemArg, load_ty: ValType) -> Result<()> {
730 let ty = self.check_shared_memarg(memarg)?;
731 self.pop_operand(Some(ty))?;
732 self.push_operand(load_ty)?;
733 Ok(())
734 }
735
736 fn check_atomic_store(&mut self, memarg: MemArg, store_ty: ValType) -> Result<()> {
738 let ty = self.check_shared_memarg(memarg)?;
739 self.pop_operand(Some(store_ty))?;
740 self.pop_operand(Some(ty))?;
741 Ok(())
742 }
743
744 fn check_atomic_binary_op(&mut self, memarg: MemArg, op_ty: ValType) -> Result<()> {
746 let ty = self.check_shared_memarg(memarg)?;
747 self.pop_operand(Some(op_ty))?;
748 self.pop_operand(Some(ty))?;
749 self.push_operand(op_ty)?;
750 Ok(())
751 }
752
753 fn check_atomic_binary_cmpxchg(&mut self, memarg: MemArg, op_ty: ValType) -> Result<()> {
755 let ty = self.check_shared_memarg(memarg)?;
756 self.pop_operand(Some(op_ty))?;
757 self.pop_operand(Some(op_ty))?;
758 self.pop_operand(Some(ty))?;
759 self.push_operand(op_ty)?;
760 Ok(())
761 }
762
763 fn check_v128_splat(&mut self, src_ty: ValType) -> Result<()> {
765 self.pop_operand(Some(src_ty))?;
766 self.push_operand(ValType::V128)?;
767 Ok(())
768 }
769
770 fn check_v128_binary_op(&mut self) -> Result<()> {
772 self.pop_operand(Some(ValType::V128))?;
773 self.pop_operand(Some(ValType::V128))?;
774 self.push_operand(ValType::V128)?;
775 Ok(())
776 }
777
778 fn check_v128_fbinary_op(&mut self) -> Result<()> {
780 self.check_floats_enabled()?;
781 self.check_v128_binary_op()
782 }
783
784 fn check_v128_relaxed_binary_op(&mut self) -> Result<()> {
786 self.pop_operand(Some(ValType::V128))?;
787 self.pop_operand(Some(ValType::V128))?;
788 self.push_operand(ValType::V128)?;
789 Ok(())
790 }
791
792 fn check_v128_unary_op(&mut self) -> Result<()> {
794 self.pop_operand(Some(ValType::V128))?;
795 self.push_operand(ValType::V128)?;
796 Ok(())
797 }
798
799 fn check_v128_funary_op(&mut self) -> Result<()> {
801 self.check_floats_enabled()?;
802 self.check_v128_unary_op()
803 }
804
805 fn check_v128_relaxed_unary_op(&mut self) -> Result<()> {
807 self.pop_operand(Some(ValType::V128))?;
808 self.push_operand(ValType::V128)?;
809 Ok(())
810 }
811
812 fn check_v128_relaxed_ternary_op(&mut self) -> Result<()> {
814 self.pop_operand(Some(ValType::V128))?;
815 self.pop_operand(Some(ValType::V128))?;
816 self.pop_operand(Some(ValType::V128))?;
817 self.push_operand(ValType::V128)?;
818 Ok(())
819 }
820
821 fn check_v128_bitmask_op(&mut self) -> Result<()> {
823 self.pop_operand(Some(ValType::V128))?;
824 self.push_operand(ValType::I32)?;
825 Ok(())
826 }
827
828 fn check_v128_shift_op(&mut self) -> Result<()> {
830 self.pop_operand(Some(ValType::I32))?;
831 self.pop_operand(Some(ValType::V128))?;
832 self.push_operand(ValType::V128)?;
833 Ok(())
834 }
835
836 fn check_v128_load_op(&mut self, memarg: MemArg) -> Result<()> {
838 let idx = self.check_memarg(memarg)?;
839 self.pop_operand(Some(idx))?;
840 self.push_operand(ValType::V128)?;
841 Ok(())
842 }
843
844 fn func_type_at(&self, at: u32) -> Result<&'resources R::FuncType> {
845 self.resources
846 .func_type_at(at)
847 .ok_or_else(|| format_err!(self.offset, "unknown type: type index out of bounds"))
848 }
849
850 fn tag_at(&self, at: u32) -> Result<&'resources R::FuncType> {
851 self.resources
852 .tag_at(at)
853 .ok_or_else(|| format_err!(self.offset, "unknown tag {}: tag index out of bounds", at))
854 }
855
856 fn params(&self, ty: BlockType) -> Result<impl PreciseIterator<Item = ValType> + 'resources> {
857 Ok(match ty {
858 BlockType::Empty | BlockType::Type(_) => Either::B(None.into_iter()),
859 BlockType::FuncType(t) => Either::A(self.func_type_at(t)?.inputs()),
860 })
861 }
862
863 fn results(&self, ty: BlockType) -> Result<impl PreciseIterator<Item = ValType> + 'resources> {
864 Ok(match ty {
865 BlockType::Empty => Either::B(None.into_iter()),
866 BlockType::Type(t) => Either::B(Some(t).into_iter()),
867 BlockType::FuncType(t) => Either::A(self.func_type_at(t)?.outputs()),
868 })
869 }
870
871 fn label_types(
872 &self,
873 ty: BlockType,
874 kind: FrameKind,
875 ) -> Result<impl PreciseIterator<Item = ValType> + 'resources> {
876 Ok(match kind {
877 FrameKind::Loop => Either::A(self.params(ty)?),
878 _ => Either::B(self.results(ty)?),
879 })
880 }
881}
882
883fn ty_to_str(ty: ValType) -> &'static str {
884 match ty {
885 ValType::I32 => "i32",
886 ValType::I64 => "i64",
887 ValType::F32 => "f32",
888 ValType::F64 => "f64",
889 ValType::V128 => "v128",
890 ValType::FuncRef => "funcref",
891 ValType::ExternRef => "externref",
892 }
893}
894
895struct WasmProposalValidator<'validator, 'resources, T>(
904 OperatorValidatorTemp<'validator, 'resources, T>,
905);
906
907impl<T> WasmProposalValidator<'_, '_, T> {
908 fn check_enabled(&self, flag: bool, desc: &str) -> Result<()> {
909 if flag {
910 return Ok(());
911 }
912 bail!(self.0.offset, "{desc} support is not enabled");
913 }
914}
915
916macro_rules! validate_proposal {
917 ($( @$proposal:ident $op:ident $({ $($arg:ident: $argty:ty),* })? => $visit:ident)*) => {
918 $(
919 fn $visit(&mut self $($(,$arg: $argty)*)?) -> Result<()> {
920 validate_proposal!(validate self $proposal);
921 self.0.$visit($( $($arg),* )?)
922 }
923 )*
924 };
925
926 (validate self mvp) => {};
927 (validate $self:ident $proposal:ident) => {
928 $self.check_enabled($self.0.features.$proposal, validate_proposal!(desc $proposal))?
929 };
930
931 (desc simd) => ("SIMD");
932 (desc relaxed_simd) => ("relaxed SIMD");
933 (desc threads) => ("threads");
934 (desc saturating_float_to_int) => ("saturating float to int conversions");
935 (desc reference_types) => ("reference types");
936 (desc bulk_memory) => ("bulk memory");
937 (desc sign_extension) => ("sign extension operations");
938 (desc exceptions) => ("exceptions");
939 (desc tail_call) => ("tail calls");
940 (desc memory_control) => ("memory control");
941}
942
943impl<'a, T> VisitOperator<'a> for WasmProposalValidator<'_, '_, T>
944where
945 T: WasmModuleResources,
946{
947 type Output = Result<()>;
948
949 for_each_operator!(validate_proposal);
950}
951
952impl<'a, T> VisitOperator<'a> for OperatorValidatorTemp<'_, '_, T>
953where
954 T: WasmModuleResources,
955{
956 type Output = Result<()>;
957
958 fn visit_nop(&mut self) -> Self::Output {
959 Ok(())
960 }
961 fn visit_unreachable(&mut self) -> Self::Output {
962 self.unreachable()?;
963 Ok(())
964 }
965 fn visit_block(&mut self, ty: BlockType) -> Self::Output {
966 self.check_block_type(ty)?;
967 for ty in self.params(ty)?.rev() {
968 self.pop_operand(Some(ty))?;
969 }
970 self.push_ctrl(FrameKind::Block, ty)?;
971 Ok(())
972 }
973 fn visit_loop(&mut self, ty: BlockType) -> Self::Output {
974 self.check_block_type(ty)?;
975 for ty in self.params(ty)?.rev() {
976 self.pop_operand(Some(ty))?;
977 }
978 self.push_ctrl(FrameKind::Loop, ty)?;
979 Ok(())
980 }
981 fn visit_if(&mut self, ty: BlockType) -> Self::Output {
982 self.check_block_type(ty)?;
983 self.pop_operand(Some(ValType::I32))?;
984 for ty in self.params(ty)?.rev() {
985 self.pop_operand(Some(ty))?;
986 }
987 self.push_ctrl(FrameKind::If, ty)?;
988 Ok(())
989 }
990 fn visit_else(&mut self) -> Self::Output {
991 let frame = self.pop_ctrl()?;
992 if frame.kind != FrameKind::If {
993 bail!(self.offset, "else found outside of an `if` block");
994 }
995 self.push_ctrl(FrameKind::Else, frame.block_type)?;
996 Ok(())
997 }
998 fn visit_try(&mut self, ty: BlockType) -> Self::Output {
999 self.check_block_type(ty)?;
1000 for ty in self.params(ty)?.rev() {
1001 self.pop_operand(Some(ty))?;
1002 }
1003 self.push_ctrl(FrameKind::Try, ty)?;
1004 Ok(())
1005 }
1006 fn visit_catch(&mut self, index: u32) -> Self::Output {
1007 let frame = self.pop_ctrl()?;
1008 if frame.kind != FrameKind::Try && frame.kind != FrameKind::Catch {
1009 bail!(self.offset, "catch found outside of an `try` block");
1010 }
1011 let height = self.operands.len();
1013 self.control.push(Frame {
1014 kind: FrameKind::Catch,
1015 block_type: frame.block_type,
1016 height,
1017 unreachable: false,
1018 });
1019 let ty = self.tag_at(index)?;
1021 for ty in ty.inputs() {
1022 self.push_operand(ty)?;
1023 }
1024 Ok(())
1025 }
1026 fn visit_throw(&mut self, index: u32) -> Self::Output {
1027 let ty = self.tag_at(index)?;
1029 for ty in ty.inputs().rev() {
1030 self.pop_operand(Some(ty))?;
1031 }
1032 if ty.outputs().len() > 0 {
1033 bail!(
1034 self.offset,
1035 "result type expected to be empty for exception"
1036 );
1037 }
1038 self.unreachable()?;
1039 Ok(())
1040 }
1041 fn visit_rethrow(&mut self, relative_depth: u32) -> Self::Output {
1042 let (_, kind) = self.jump(relative_depth)?;
1045 if kind != FrameKind::Catch && kind != FrameKind::CatchAll {
1046 bail!(
1047 self.offset,
1048 "invalid rethrow label: target was not a `catch` block"
1049 );
1050 }
1051 self.unreachable()?;
1052 Ok(())
1053 }
1054 fn visit_delegate(&mut self, relative_depth: u32) -> Self::Output {
1055 let frame = self.pop_ctrl()?;
1056 if frame.kind != FrameKind::Try {
1057 bail!(self.offset, "delegate found outside of an `try` block");
1058 }
1059 let _ = self.jump(relative_depth)?;
1062 for ty in self.results(frame.block_type)? {
1063 self.push_operand(ty)?;
1064 }
1065 Ok(())
1066 }
1067 fn visit_catch_all(&mut self) -> Self::Output {
1068 let frame = self.pop_ctrl()?;
1069 if frame.kind == FrameKind::CatchAll {
1070 bail!(self.offset, "only one catch_all allowed per `try` block");
1071 } else if frame.kind != FrameKind::Try && frame.kind != FrameKind::Catch {
1072 bail!(self.offset, "catch_all found outside of a `try` block");
1073 }
1074 let height = self.operands.len();
1075 self.control.push(Frame {
1076 kind: FrameKind::CatchAll,
1077 block_type: frame.block_type,
1078 height,
1079 unreachable: false,
1080 });
1081 Ok(())
1082 }
1083 fn visit_end(&mut self) -> Self::Output {
1084 let mut frame = self.pop_ctrl()?;
1085
1086 if frame.kind == FrameKind::If {
1091 self.push_ctrl(FrameKind::Else, frame.block_type)?;
1092 frame = self.pop_ctrl()?;
1093 }
1094 for ty in self.results(frame.block_type)? {
1095 self.push_operand(ty)?;
1096 }
1097
1098 if self.control.is_empty() && self.end_which_emptied_control.is_none() {
1099 assert_ne!(self.offset, 0);
1100 self.end_which_emptied_control = Some(self.offset);
1101 }
1102 Ok(())
1103 }
1104 fn visit_br(&mut self, relative_depth: u32) -> Self::Output {
1105 let (ty, kind) = self.jump(relative_depth)?;
1106 for ty in self.label_types(ty, kind)?.rev() {
1107 self.pop_operand(Some(ty))?;
1108 }
1109 self.unreachable()?;
1110 Ok(())
1111 }
1112 fn visit_br_if(&mut self, relative_depth: u32) -> Self::Output {
1113 self.pop_operand(Some(ValType::I32))?;
1114 let (ty, kind) = self.jump(relative_depth)?;
1115 let types = self.label_types(ty, kind)?;
1116 for ty in types.clone().rev() {
1117 self.pop_operand(Some(ty))?;
1118 }
1119 for ty in types {
1120 self.push_operand(ty)?;
1121 }
1122 Ok(())
1123 }
1124 fn visit_br_table(&mut self, table: BrTable) -> Self::Output {
1125 self.pop_operand(Some(ValType::I32))?;
1126 let default = self.jump(table.default())?;
1127 let default_types = self.label_types(default.0, default.1)?;
1128 for element in table.targets() {
1129 let relative_depth = element?;
1130 let block = self.jump(relative_depth)?;
1131 let tys = self.label_types(block.0, block.1)?;
1132 if tys.len() != default_types.len() {
1133 bail!(
1134 self.offset,
1135 "type mismatch: br_table target labels have different number of types"
1136 );
1137 }
1138 debug_assert!(self.br_table_tmp.is_empty());
1139 for ty in tys.rev() {
1140 let ty = self.pop_operand(Some(ty))?;
1141 self.br_table_tmp.push(ty);
1142 }
1143 for ty in self.inner.br_table_tmp.drain(..).rev() {
1144 self.inner.operands.push(ty);
1145 }
1146 }
1147 for ty in default_types.rev() {
1148 self.pop_operand(Some(ty))?;
1149 }
1150 self.unreachable()?;
1151 Ok(())
1152 }
1153 fn visit_return(&mut self) -> Self::Output {
1154 self.check_return()?;
1155 Ok(())
1156 }
1157 fn visit_call(&mut self, function_index: u32) -> Self::Output {
1158 self.check_call(function_index)?;
1159 Ok(())
1160 }
1161 fn visit_return_call(&mut self, function_index: u32) -> Self::Output {
1162 self.check_call(function_index)?;
1163 self.check_return()?;
1164 Ok(())
1165 }
1166 fn visit_call_indirect(
1167 &mut self,
1168 index: u32,
1169 table_index: u32,
1170 table_byte: u8,
1171 ) -> Self::Output {
1172 if table_byte != 0 && !self.features.reference_types {
1173 bail!(
1174 self.offset,
1175 "reference-types not enabled: zero byte expected"
1176 );
1177 }
1178 self.check_call_indirect(index, table_index)?;
1179 Ok(())
1180 }
1181 fn visit_return_call_indirect(&mut self, index: u32, table_index: u32) -> Self::Output {
1182 self.check_call_indirect(index, table_index)?;
1183 self.check_return()?;
1184 Ok(())
1185 }
1186 fn visit_drop(&mut self) -> Self::Output {
1187 self.pop_operand(None)?;
1188 Ok(())
1189 }
1190 fn visit_select(&mut self) -> Self::Output {
1191 self.pop_operand(Some(ValType::I32))?;
1192 let ty1 = self.pop_operand(None)?;
1193 let ty2 = self.pop_operand(None)?;
1194 fn is_num(ty: Option<ValType>) -> bool {
1195 matches!(
1196 ty,
1197 Some(ValType::I32)
1198 | Some(ValType::I64)
1199 | Some(ValType::F32)
1200 | Some(ValType::F64)
1201 | Some(ValType::V128)
1202 | None
1203 )
1204 }
1205 if !is_num(ty1) || !is_num(ty2) {
1206 bail!(
1207 self.offset,
1208 "type mismatch: select only takes integral types"
1209 )
1210 }
1211 if ty1 != ty2 && ty1.is_some() && ty2.is_some() {
1212 bail!(
1213 self.offset,
1214 "type mismatch: select operands have different types"
1215 )
1216 }
1217 self.push_operand(ty1.or(ty2))?;
1218 Ok(())
1219 }
1220 fn visit_typed_select(&mut self, ty: ValType) -> Self::Output {
1221 self.features
1222 .check_value_type(ty)
1223 .map_err(|e| BinaryReaderError::new(e, self.offset))?;
1224 self.pop_operand(Some(ValType::I32))?;
1225 self.pop_operand(Some(ty))?;
1226 self.pop_operand(Some(ty))?;
1227 self.push_operand(ty)?;
1228 Ok(())
1229 }
1230 fn visit_local_get(&mut self, local_index: u32) -> Self::Output {
1231 let ty = self.local(local_index)?;
1232 self.push_operand(ty)?;
1233 Ok(())
1234 }
1235 fn visit_local_set(&mut self, local_index: u32) -> Self::Output {
1236 let ty = self.local(local_index)?;
1237 self.pop_operand(Some(ty))?;
1238 Ok(())
1239 }
1240 fn visit_local_tee(&mut self, local_index: u32) -> Self::Output {
1241 let ty = self.local(local_index)?;
1242 self.pop_operand(Some(ty))?;
1243 self.push_operand(ty)?;
1244 Ok(())
1245 }
1246 fn visit_global_get(&mut self, global_index: u32) -> Self::Output {
1247 if let Some(ty) = self.resources.global_at(global_index) {
1248 self.push_operand(ty.content_type)?;
1249 } else {
1250 bail!(self.offset, "unknown global: global index out of bounds");
1251 };
1252 Ok(())
1253 }
1254 fn visit_global_set(&mut self, global_index: u32) -> Self::Output {
1255 if let Some(ty) = self.resources.global_at(global_index) {
1256 if !ty.mutable {
1257 bail!(
1258 self.offset,
1259 "global is immutable: cannot modify it with `global.set`"
1260 );
1261 }
1262 self.pop_operand(Some(ty.content_type))?;
1263 } else {
1264 bail!(self.offset, "unknown global: global index out of bounds");
1265 };
1266 Ok(())
1267 }
1268 fn visit_i32_load(&mut self, memarg: MemArg) -> Self::Output {
1269 let ty = self.check_memarg(memarg)?;
1270 self.pop_operand(Some(ty))?;
1271 self.push_operand(ValType::I32)?;
1272 Ok(())
1273 }
1274 fn visit_i64_load(&mut self, memarg: MemArg) -> Self::Output {
1275 let ty = self.check_memarg(memarg)?;
1276 self.pop_operand(Some(ty))?;
1277 self.push_operand(ValType::I64)?;
1278 Ok(())
1279 }
1280 fn visit_f32_load(&mut self, memarg: MemArg) -> Self::Output {
1281 self.check_floats_enabled()?;
1282 let ty = self.check_memarg(memarg)?;
1283 self.pop_operand(Some(ty))?;
1284 self.push_operand(ValType::F32)?;
1285 Ok(())
1286 }
1287 fn visit_f64_load(&mut self, memarg: MemArg) -> Self::Output {
1288 self.check_floats_enabled()?;
1289 let ty = self.check_memarg(memarg)?;
1290 self.pop_operand(Some(ty))?;
1291 self.push_operand(ValType::F64)?;
1292 Ok(())
1293 }
1294 fn visit_i32_load8_s(&mut self, memarg: MemArg) -> Self::Output {
1295 let ty = self.check_memarg(memarg)?;
1296 self.pop_operand(Some(ty))?;
1297 self.push_operand(ValType::I32)?;
1298 Ok(())
1299 }
1300 fn visit_i32_load8_u(&mut self, memarg: MemArg) -> Self::Output {
1301 self.visit_i32_load8_s(memarg)
1302 }
1303 fn visit_i32_load16_s(&mut self, memarg: MemArg) -> Self::Output {
1304 let ty = self.check_memarg(memarg)?;
1305 self.pop_operand(Some(ty))?;
1306 self.push_operand(ValType::I32)?;
1307 Ok(())
1308 }
1309 fn visit_i32_load16_u(&mut self, memarg: MemArg) -> Self::Output {
1310 self.visit_i32_load16_s(memarg)
1311 }
1312 fn visit_i64_load8_s(&mut self, memarg: MemArg) -> Self::Output {
1313 let ty = self.check_memarg(memarg)?;
1314 self.pop_operand(Some(ty))?;
1315 self.push_operand(ValType::I64)?;
1316 Ok(())
1317 }
1318 fn visit_i64_load8_u(&mut self, memarg: MemArg) -> Self::Output {
1319 self.visit_i64_load8_s(memarg)
1320 }
1321 fn visit_i64_load16_s(&mut self, memarg: MemArg) -> Self::Output {
1322 let ty = self.check_memarg(memarg)?;
1323 self.pop_operand(Some(ty))?;
1324 self.push_operand(ValType::I64)?;
1325 Ok(())
1326 }
1327 fn visit_i64_load16_u(&mut self, memarg: MemArg) -> Self::Output {
1328 self.visit_i64_load16_s(memarg)
1329 }
1330 fn visit_i64_load32_s(&mut self, memarg: MemArg) -> Self::Output {
1331 let ty = self.check_memarg(memarg)?;
1332 self.pop_operand(Some(ty))?;
1333 self.push_operand(ValType::I64)?;
1334 Ok(())
1335 }
1336 fn visit_i64_load32_u(&mut self, memarg: MemArg) -> Self::Output {
1337 self.visit_i64_load32_s(memarg)
1338 }
1339 fn visit_i32_store(&mut self, memarg: MemArg) -> Self::Output {
1340 let ty = self.check_memarg(memarg)?;
1341 self.pop_operand(Some(ValType::I32))?;
1342 self.pop_operand(Some(ty))?;
1343 Ok(())
1344 }
1345 fn visit_i64_store(&mut self, memarg: MemArg) -> Self::Output {
1346 let ty = self.check_memarg(memarg)?;
1347 self.pop_operand(Some(ValType::I64))?;
1348 self.pop_operand(Some(ty))?;
1349 Ok(())
1350 }
1351 fn visit_f32_store(&mut self, memarg: MemArg) -> Self::Output {
1352 self.check_floats_enabled()?;
1353 let ty = self.check_memarg(memarg)?;
1354 self.pop_operand(Some(ValType::F32))?;
1355 self.pop_operand(Some(ty))?;
1356 Ok(())
1357 }
1358 fn visit_f64_store(&mut self, memarg: MemArg) -> Self::Output {
1359 self.check_floats_enabled()?;
1360 let ty = self.check_memarg(memarg)?;
1361 self.pop_operand(Some(ValType::F64))?;
1362 self.pop_operand(Some(ty))?;
1363 Ok(())
1364 }
1365 fn visit_i32_store8(&mut self, memarg: MemArg) -> Self::Output {
1366 let ty = self.check_memarg(memarg)?;
1367 self.pop_operand(Some(ValType::I32))?;
1368 self.pop_operand(Some(ty))?;
1369 Ok(())
1370 }
1371 fn visit_i32_store16(&mut self, memarg: MemArg) -> Self::Output {
1372 let ty = self.check_memarg(memarg)?;
1373 self.pop_operand(Some(ValType::I32))?;
1374 self.pop_operand(Some(ty))?;
1375 Ok(())
1376 }
1377 fn visit_i64_store8(&mut self, memarg: MemArg) -> Self::Output {
1378 let ty = self.check_memarg(memarg)?;
1379 self.pop_operand(Some(ValType::I64))?;
1380 self.pop_operand(Some(ty))?;
1381 Ok(())
1382 }
1383 fn visit_i64_store16(&mut self, memarg: MemArg) -> Self::Output {
1384 let ty = self.check_memarg(memarg)?;
1385 self.pop_operand(Some(ValType::I64))?;
1386 self.pop_operand(Some(ty))?;
1387 Ok(())
1388 }
1389 fn visit_i64_store32(&mut self, memarg: MemArg) -> Self::Output {
1390 let ty = self.check_memarg(memarg)?;
1391 self.pop_operand(Some(ValType::I64))?;
1392 self.pop_operand(Some(ty))?;
1393 Ok(())
1394 }
1395 fn visit_memory_size(&mut self, mem: u32, mem_byte: u8) -> Self::Output {
1396 if mem_byte != 0 && !self.features.multi_memory {
1397 bail!(self.offset, "multi-memory not enabled: zero byte expected");
1398 }
1399 let index_ty = self.check_memory_index(mem)?;
1400 self.push_operand(index_ty)?;
1401 Ok(())
1402 }
1403 fn visit_memory_grow(&mut self, mem: u32, mem_byte: u8) -> Self::Output {
1404 if mem_byte != 0 && !self.features.multi_memory {
1405 bail!(self.offset, "multi-memory not enabled: zero byte expected");
1406 }
1407 let index_ty = self.check_memory_index(mem)?;
1408 self.pop_operand(Some(index_ty))?;
1409 self.push_operand(index_ty)?;
1410 Ok(())
1411 }
1412 fn visit_i32_const(&mut self, _value: i32) -> Self::Output {
1413 self.push_operand(ValType::I32)?;
1414 Ok(())
1415 }
1416 fn visit_i64_const(&mut self, _value: i64) -> Self::Output {
1417 self.push_operand(ValType::I64)?;
1418 Ok(())
1419 }
1420 fn visit_f32_const(&mut self, _value: Ieee32) -> Self::Output {
1421 self.check_floats_enabled()?;
1422 self.push_operand(ValType::F32)?;
1423 Ok(())
1424 }
1425 fn visit_f64_const(&mut self, _value: Ieee64) -> Self::Output {
1426 self.check_floats_enabled()?;
1427 self.push_operand(ValType::F64)?;
1428 Ok(())
1429 }
1430 fn visit_i32_eqz(&mut self) -> Self::Output {
1431 self.pop_operand(Some(ValType::I32))?;
1432 self.push_operand(ValType::I32)?;
1433 Ok(())
1434 }
1435 fn visit_i32_eq(&mut self) -> Self::Output {
1436 self.check_cmp_op(ValType::I32)
1437 }
1438 fn visit_i32_ne(&mut self) -> Self::Output {
1439 self.check_cmp_op(ValType::I32)
1440 }
1441 fn visit_i32_lt_s(&mut self) -> Self::Output {
1442 self.check_cmp_op(ValType::I32)
1443 }
1444 fn visit_i32_lt_u(&mut self) -> Self::Output {
1445 self.check_cmp_op(ValType::I32)
1446 }
1447 fn visit_i32_gt_s(&mut self) -> Self::Output {
1448 self.check_cmp_op(ValType::I32)
1449 }
1450 fn visit_i32_gt_u(&mut self) -> Self::Output {
1451 self.check_cmp_op(ValType::I32)
1452 }
1453 fn visit_i32_le_s(&mut self) -> Self::Output {
1454 self.check_cmp_op(ValType::I32)
1455 }
1456 fn visit_i32_le_u(&mut self) -> Self::Output {
1457 self.check_cmp_op(ValType::I32)
1458 }
1459 fn visit_i32_ge_s(&mut self) -> Self::Output {
1460 self.check_cmp_op(ValType::I32)
1461 }
1462 fn visit_i32_ge_u(&mut self) -> Self::Output {
1463 self.check_cmp_op(ValType::I32)
1464 }
1465 fn visit_i64_eqz(&mut self) -> Self::Output {
1466 self.pop_operand(Some(ValType::I64))?;
1467 self.push_operand(ValType::I32)?;
1468 Ok(())
1469 }
1470 fn visit_i64_eq(&mut self) -> Self::Output {
1471 self.check_cmp_op(ValType::I64)
1472 }
1473 fn visit_i64_ne(&mut self) -> Self::Output {
1474 self.check_cmp_op(ValType::I64)
1475 }
1476 fn visit_i64_lt_s(&mut self) -> Self::Output {
1477 self.check_cmp_op(ValType::I64)
1478 }
1479 fn visit_i64_lt_u(&mut self) -> Self::Output {
1480 self.check_cmp_op(ValType::I64)
1481 }
1482 fn visit_i64_gt_s(&mut self) -> Self::Output {
1483 self.check_cmp_op(ValType::I64)
1484 }
1485 fn visit_i64_gt_u(&mut self) -> Self::Output {
1486 self.check_cmp_op(ValType::I64)
1487 }
1488 fn visit_i64_le_s(&mut self) -> Self::Output {
1489 self.check_cmp_op(ValType::I64)
1490 }
1491 fn visit_i64_le_u(&mut self) -> Self::Output {
1492 self.check_cmp_op(ValType::I64)
1493 }
1494 fn visit_i64_ge_s(&mut self) -> Self::Output {
1495 self.check_cmp_op(ValType::I64)
1496 }
1497 fn visit_i64_ge_u(&mut self) -> Self::Output {
1498 self.check_cmp_op(ValType::I64)
1499 }
1500 fn visit_f32_eq(&mut self) -> Self::Output {
1501 self.check_fcmp_op(ValType::F32)
1502 }
1503 fn visit_f32_ne(&mut self) -> Self::Output {
1504 self.check_fcmp_op(ValType::F32)
1505 }
1506 fn visit_f32_lt(&mut self) -> Self::Output {
1507 self.check_fcmp_op(ValType::F32)
1508 }
1509 fn visit_f32_gt(&mut self) -> Self::Output {
1510 self.check_fcmp_op(ValType::F32)
1511 }
1512 fn visit_f32_le(&mut self) -> Self::Output {
1513 self.check_fcmp_op(ValType::F32)
1514 }
1515 fn visit_f32_ge(&mut self) -> Self::Output {
1516 self.check_fcmp_op(ValType::F32)
1517 }
1518 fn visit_f64_eq(&mut self) -> Self::Output {
1519 self.check_fcmp_op(ValType::F64)
1520 }
1521 fn visit_f64_ne(&mut self) -> Self::Output {
1522 self.check_fcmp_op(ValType::F64)
1523 }
1524 fn visit_f64_lt(&mut self) -> Self::Output {
1525 self.check_fcmp_op(ValType::F64)
1526 }
1527 fn visit_f64_gt(&mut self) -> Self::Output {
1528 self.check_fcmp_op(ValType::F64)
1529 }
1530 fn visit_f64_le(&mut self) -> Self::Output {
1531 self.check_fcmp_op(ValType::F64)
1532 }
1533 fn visit_f64_ge(&mut self) -> Self::Output {
1534 self.check_fcmp_op(ValType::F64)
1535 }
1536 fn visit_i32_clz(&mut self) -> Self::Output {
1537 self.check_unary_op(ValType::I32)
1538 }
1539 fn visit_i32_ctz(&mut self) -> Self::Output {
1540 self.check_unary_op(ValType::I32)
1541 }
1542 fn visit_i32_popcnt(&mut self) -> Self::Output {
1543 self.check_unary_op(ValType::I32)
1544 }
1545 fn visit_i32_add(&mut self) -> Self::Output {
1546 self.check_binary_op(ValType::I32)
1547 }
1548 fn visit_i32_sub(&mut self) -> Self::Output {
1549 self.check_binary_op(ValType::I32)
1550 }
1551 fn visit_i32_mul(&mut self) -> Self::Output {
1552 self.check_binary_op(ValType::I32)
1553 }
1554 fn visit_i32_div_s(&mut self) -> Self::Output {
1555 self.check_binary_op(ValType::I32)
1556 }
1557 fn visit_i32_div_u(&mut self) -> Self::Output {
1558 self.check_binary_op(ValType::I32)
1559 }
1560 fn visit_i32_rem_s(&mut self) -> Self::Output {
1561 self.check_binary_op(ValType::I32)
1562 }
1563 fn visit_i32_rem_u(&mut self) -> Self::Output {
1564 self.check_binary_op(ValType::I32)
1565 }
1566 fn visit_i32_and(&mut self) -> Self::Output {
1567 self.check_binary_op(ValType::I32)
1568 }
1569 fn visit_i32_or(&mut self) -> Self::Output {
1570 self.check_binary_op(ValType::I32)
1571 }
1572 fn visit_i32_xor(&mut self) -> Self::Output {
1573 self.check_binary_op(ValType::I32)
1574 }
1575 fn visit_i32_shl(&mut self) -> Self::Output {
1576 self.check_binary_op(ValType::I32)
1577 }
1578 fn visit_i32_shr_s(&mut self) -> Self::Output {
1579 self.check_binary_op(ValType::I32)
1580 }
1581 fn visit_i32_shr_u(&mut self) -> Self::Output {
1582 self.check_binary_op(ValType::I32)
1583 }
1584 fn visit_i32_rotl(&mut self) -> Self::Output {
1585 self.check_binary_op(ValType::I32)
1586 }
1587 fn visit_i32_rotr(&mut self) -> Self::Output {
1588 self.check_binary_op(ValType::I32)
1589 }
1590 fn visit_i64_clz(&mut self) -> Self::Output {
1591 self.check_unary_op(ValType::I64)
1592 }
1593 fn visit_i64_ctz(&mut self) -> Self::Output {
1594 self.check_unary_op(ValType::I64)
1595 }
1596 fn visit_i64_popcnt(&mut self) -> Self::Output {
1597 self.check_unary_op(ValType::I64)
1598 }
1599 fn visit_i64_add(&mut self) -> Self::Output {
1600 self.check_binary_op(ValType::I64)
1601 }
1602 fn visit_i64_sub(&mut self) -> Self::Output {
1603 self.check_binary_op(ValType::I64)
1604 }
1605 fn visit_i64_mul(&mut self) -> Self::Output {
1606 self.check_binary_op(ValType::I64)
1607 }
1608 fn visit_i64_div_s(&mut self) -> Self::Output {
1609 self.check_binary_op(ValType::I64)
1610 }
1611 fn visit_i64_div_u(&mut self) -> Self::Output {
1612 self.check_binary_op(ValType::I64)
1613 }
1614 fn visit_i64_rem_s(&mut self) -> Self::Output {
1615 self.check_binary_op(ValType::I64)
1616 }
1617 fn visit_i64_rem_u(&mut self) -> Self::Output {
1618 self.check_binary_op(ValType::I64)
1619 }
1620 fn visit_i64_and(&mut self) -> Self::Output {
1621 self.check_binary_op(ValType::I64)
1622 }
1623 fn visit_i64_or(&mut self) -> Self::Output {
1624 self.check_binary_op(ValType::I64)
1625 }
1626 fn visit_i64_xor(&mut self) -> Self::Output {
1627 self.check_binary_op(ValType::I64)
1628 }
1629 fn visit_i64_shl(&mut self) -> Self::Output {
1630 self.check_binary_op(ValType::I64)
1631 }
1632 fn visit_i64_shr_s(&mut self) -> Self::Output {
1633 self.check_binary_op(ValType::I64)
1634 }
1635 fn visit_i64_shr_u(&mut self) -> Self::Output {
1636 self.check_binary_op(ValType::I64)
1637 }
1638 fn visit_i64_rotl(&mut self) -> Self::Output {
1639 self.check_binary_op(ValType::I64)
1640 }
1641 fn visit_i64_rotr(&mut self) -> Self::Output {
1642 self.check_binary_op(ValType::I64)
1643 }
1644 fn visit_f32_abs(&mut self) -> Self::Output {
1645 self.check_funary_op(ValType::F32)
1646 }
1647 fn visit_f32_neg(&mut self) -> Self::Output {
1648 self.check_funary_op(ValType::F32)
1649 }
1650 fn visit_f32_ceil(&mut self) -> Self::Output {
1651 self.check_funary_op(ValType::F32)
1652 }
1653 fn visit_f32_floor(&mut self) -> Self::Output {
1654 self.check_funary_op(ValType::F32)
1655 }
1656 fn visit_f32_trunc(&mut self) -> Self::Output {
1657 self.check_funary_op(ValType::F32)
1658 }
1659 fn visit_f32_nearest(&mut self) -> Self::Output {
1660 self.check_funary_op(ValType::F32)
1661 }
1662 fn visit_f32_sqrt(&mut self) -> Self::Output {
1663 self.check_funary_op(ValType::F32)
1664 }
1665 fn visit_f32_add(&mut self) -> Self::Output {
1666 self.check_fbinary_op(ValType::F32)
1667 }
1668 fn visit_f32_sub(&mut self) -> Self::Output {
1669 self.check_fbinary_op(ValType::F32)
1670 }
1671 fn visit_f32_mul(&mut self) -> Self::Output {
1672 self.check_fbinary_op(ValType::F32)
1673 }
1674 fn visit_f32_div(&mut self) -> Self::Output {
1675 self.check_fbinary_op(ValType::F32)
1676 }
1677 fn visit_f32_min(&mut self) -> Self::Output {
1678 self.check_fbinary_op(ValType::F32)
1679 }
1680 fn visit_f32_max(&mut self) -> Self::Output {
1681 self.check_fbinary_op(ValType::F32)
1682 }
1683 fn visit_f32_copysign(&mut self) -> Self::Output {
1684 self.check_fbinary_op(ValType::F32)
1685 }
1686 fn visit_f64_abs(&mut self) -> Self::Output {
1687 self.check_funary_op(ValType::F64)
1688 }
1689 fn visit_f64_neg(&mut self) -> Self::Output {
1690 self.check_funary_op(ValType::F64)
1691 }
1692 fn visit_f64_ceil(&mut self) -> Self::Output {
1693 self.check_funary_op(ValType::F64)
1694 }
1695 fn visit_f64_floor(&mut self) -> Self::Output {
1696 self.check_funary_op(ValType::F64)
1697 }
1698 fn visit_f64_trunc(&mut self) -> Self::Output {
1699 self.check_funary_op(ValType::F64)
1700 }
1701 fn visit_f64_nearest(&mut self) -> Self::Output {
1702 self.check_funary_op(ValType::F64)
1703 }
1704 fn visit_f64_sqrt(&mut self) -> Self::Output {
1705 self.check_funary_op(ValType::F64)
1706 }
1707 fn visit_f64_add(&mut self) -> Self::Output {
1708 self.check_fbinary_op(ValType::F64)
1709 }
1710 fn visit_f64_sub(&mut self) -> Self::Output {
1711 self.check_fbinary_op(ValType::F64)
1712 }
1713 fn visit_f64_mul(&mut self) -> Self::Output {
1714 self.check_fbinary_op(ValType::F64)
1715 }
1716 fn visit_f64_div(&mut self) -> Self::Output {
1717 self.check_fbinary_op(ValType::F64)
1718 }
1719 fn visit_f64_min(&mut self) -> Self::Output {
1720 self.check_fbinary_op(ValType::F64)
1721 }
1722 fn visit_f64_max(&mut self) -> Self::Output {
1723 self.check_fbinary_op(ValType::F64)
1724 }
1725 fn visit_f64_copysign(&mut self) -> Self::Output {
1726 self.check_fbinary_op(ValType::F64)
1727 }
1728 fn visit_i32_wrap_i64(&mut self) -> Self::Output {
1729 self.check_conversion_op(ValType::I32, ValType::I64)
1730 }
1731 fn visit_i32_trunc_f32_s(&mut self) -> Self::Output {
1732 self.check_conversion_op(ValType::I32, ValType::F32)
1733 }
1734 fn visit_i32_trunc_f32_u(&mut self) -> Self::Output {
1735 self.check_conversion_op(ValType::I32, ValType::F32)
1736 }
1737 fn visit_i32_trunc_f64_s(&mut self) -> Self::Output {
1738 self.check_conversion_op(ValType::I32, ValType::F64)
1739 }
1740 fn visit_i32_trunc_f64_u(&mut self) -> Self::Output {
1741 self.check_conversion_op(ValType::I32, ValType::F64)
1742 }
1743 fn visit_i64_extend_i32_s(&mut self) -> Self::Output {
1744 self.check_conversion_op(ValType::I64, ValType::I32)
1745 }
1746 fn visit_i64_extend_i32_u(&mut self) -> Self::Output {
1747 self.check_conversion_op(ValType::I64, ValType::I32)
1748 }
1749 fn visit_i64_trunc_f32_s(&mut self) -> Self::Output {
1750 self.check_conversion_op(ValType::I64, ValType::F32)
1751 }
1752 fn visit_i64_trunc_f32_u(&mut self) -> Self::Output {
1753 self.check_conversion_op(ValType::I64, ValType::F32)
1754 }
1755 fn visit_i64_trunc_f64_s(&mut self) -> Self::Output {
1756 self.check_conversion_op(ValType::I64, ValType::F64)
1757 }
1758 fn visit_i64_trunc_f64_u(&mut self) -> Self::Output {
1759 self.check_conversion_op(ValType::I64, ValType::F64)
1760 }
1761 fn visit_f32_convert_i32_s(&mut self) -> Self::Output {
1762 self.check_fconversion_op(ValType::F32, ValType::I32)
1763 }
1764 fn visit_f32_convert_i32_u(&mut self) -> Self::Output {
1765 self.check_fconversion_op(ValType::F32, ValType::I32)
1766 }
1767 fn visit_f32_convert_i64_s(&mut self) -> Self::Output {
1768 self.check_fconversion_op(ValType::F32, ValType::I64)
1769 }
1770 fn visit_f32_convert_i64_u(&mut self) -> Self::Output {
1771 self.check_fconversion_op(ValType::F32, ValType::I64)
1772 }
1773 fn visit_f32_demote_f64(&mut self) -> Self::Output {
1774 self.check_fconversion_op(ValType::F32, ValType::F64)
1775 }
1776 fn visit_f64_convert_i32_s(&mut self) -> Self::Output {
1777 self.check_fconversion_op(ValType::F64, ValType::I32)
1778 }
1779 fn visit_f64_convert_i32_u(&mut self) -> Self::Output {
1780 self.check_fconversion_op(ValType::F64, ValType::I32)
1781 }
1782 fn visit_f64_convert_i64_s(&mut self) -> Self::Output {
1783 self.check_fconversion_op(ValType::F64, ValType::I64)
1784 }
1785 fn visit_f64_convert_i64_u(&mut self) -> Self::Output {
1786 self.check_fconversion_op(ValType::F64, ValType::I64)
1787 }
1788 fn visit_f64_promote_f32(&mut self) -> Self::Output {
1789 self.check_fconversion_op(ValType::F64, ValType::F32)
1790 }
1791 fn visit_i32_reinterpret_f32(&mut self) -> Self::Output {
1792 self.check_conversion_op(ValType::I32, ValType::F32)
1793 }
1794 fn visit_i64_reinterpret_f64(&mut self) -> Self::Output {
1795 self.check_conversion_op(ValType::I64, ValType::F64)
1796 }
1797 fn visit_f32_reinterpret_i32(&mut self) -> Self::Output {
1798 self.check_fconversion_op(ValType::F32, ValType::I32)
1799 }
1800 fn visit_f64_reinterpret_i64(&mut self) -> Self::Output {
1801 self.check_fconversion_op(ValType::F64, ValType::I64)
1802 }
1803 fn visit_i32_trunc_sat_f32_s(&mut self) -> Self::Output {
1804 self.check_conversion_op(ValType::I32, ValType::F32)
1805 }
1806 fn visit_i32_trunc_sat_f32_u(&mut self) -> Self::Output {
1807 self.check_conversion_op(ValType::I32, ValType::F32)
1808 }
1809 fn visit_i32_trunc_sat_f64_s(&mut self) -> Self::Output {
1810 self.check_conversion_op(ValType::I32, ValType::F64)
1811 }
1812 fn visit_i32_trunc_sat_f64_u(&mut self) -> Self::Output {
1813 self.check_conversion_op(ValType::I32, ValType::F64)
1814 }
1815 fn visit_i64_trunc_sat_f32_s(&mut self) -> Self::Output {
1816 self.check_conversion_op(ValType::I64, ValType::F32)
1817 }
1818 fn visit_i64_trunc_sat_f32_u(&mut self) -> Self::Output {
1819 self.check_conversion_op(ValType::I64, ValType::F32)
1820 }
1821 fn visit_i64_trunc_sat_f64_s(&mut self) -> Self::Output {
1822 self.check_conversion_op(ValType::I64, ValType::F64)
1823 }
1824 fn visit_i64_trunc_sat_f64_u(&mut self) -> Self::Output {
1825 self.check_conversion_op(ValType::I64, ValType::F64)
1826 }
1827 fn visit_i32_extend8_s(&mut self) -> Self::Output {
1828 self.check_unary_op(ValType::I32)
1829 }
1830 fn visit_i32_extend16_s(&mut self) -> Self::Output {
1831 self.check_unary_op(ValType::I32)
1832 }
1833 fn visit_i64_extend8_s(&mut self) -> Self::Output {
1834 self.check_unary_op(ValType::I64)
1835 }
1836 fn visit_i64_extend16_s(&mut self) -> Self::Output {
1837 self.check_unary_op(ValType::I64)
1838 }
1839 fn visit_i64_extend32_s(&mut self) -> Self::Output {
1840 self.check_unary_op(ValType::I64)
1841 }
1842 fn visit_i32_atomic_load(&mut self, memarg: MemArg) -> Self::Output {
1843 self.check_atomic_load(memarg, ValType::I32)
1844 }
1845 fn visit_i32_atomic_load16_u(&mut self, memarg: MemArg) -> Self::Output {
1846 self.check_atomic_load(memarg, ValType::I32)
1847 }
1848 fn visit_i32_atomic_load8_u(&mut self, memarg: MemArg) -> Self::Output {
1849 self.check_atomic_load(memarg, ValType::I32)
1850 }
1851 fn visit_i64_atomic_load(&mut self, memarg: MemArg) -> Self::Output {
1852 self.check_atomic_load(memarg, ValType::I64)
1853 }
1854 fn visit_i64_atomic_load32_u(&mut self, memarg: MemArg) -> Self::Output {
1855 self.check_atomic_load(memarg, ValType::I64)
1856 }
1857 fn visit_i64_atomic_load16_u(&mut self, memarg: MemArg) -> Self::Output {
1858 self.check_atomic_load(memarg, ValType::I64)
1859 }
1860 fn visit_i64_atomic_load8_u(&mut self, memarg: MemArg) -> Self::Output {
1861 self.check_atomic_load(memarg, ValType::I64)
1862 }
1863 fn visit_i32_atomic_store(&mut self, memarg: MemArg) -> Self::Output {
1864 self.check_atomic_store(memarg, ValType::I32)
1865 }
1866 fn visit_i32_atomic_store16(&mut self, memarg: MemArg) -> Self::Output {
1867 self.check_atomic_store(memarg, ValType::I32)
1868 }
1869 fn visit_i32_atomic_store8(&mut self, memarg: MemArg) -> Self::Output {
1870 self.check_atomic_store(memarg, ValType::I32)
1871 }
1872 fn visit_i64_atomic_store(&mut self, memarg: MemArg) -> Self::Output {
1873 self.check_atomic_store(memarg, ValType::I64)
1874 }
1875 fn visit_i64_atomic_store32(&mut self, memarg: MemArg) -> Self::Output {
1876 self.check_atomic_store(memarg, ValType::I64)
1877 }
1878 fn visit_i64_atomic_store16(&mut self, memarg: MemArg) -> Self::Output {
1879 self.check_atomic_store(memarg, ValType::I64)
1880 }
1881 fn visit_i64_atomic_store8(&mut self, memarg: MemArg) -> Self::Output {
1882 self.check_atomic_store(memarg, ValType::I64)
1883 }
1884 fn visit_i32_atomic_rmw_add(&mut self, memarg: MemArg) -> Self::Output {
1885 self.check_atomic_binary_op(memarg, ValType::I32)
1886 }
1887 fn visit_i32_atomic_rmw_sub(&mut self, memarg: MemArg) -> Self::Output {
1888 self.check_atomic_binary_op(memarg, ValType::I32)
1889 }
1890 fn visit_i32_atomic_rmw_and(&mut self, memarg: MemArg) -> Self::Output {
1891 self.check_atomic_binary_op(memarg, ValType::I32)
1892 }
1893 fn visit_i32_atomic_rmw_or(&mut self, memarg: MemArg) -> Self::Output {
1894 self.check_atomic_binary_op(memarg, ValType::I32)
1895 }
1896 fn visit_i32_atomic_rmw_xor(&mut self, memarg: MemArg) -> Self::Output {
1897 self.check_atomic_binary_op(memarg, ValType::I32)
1898 }
1899 fn visit_i32_atomic_rmw16_add_u(&mut self, memarg: MemArg) -> Self::Output {
1900 self.check_atomic_binary_op(memarg, ValType::I32)
1901 }
1902 fn visit_i32_atomic_rmw16_sub_u(&mut self, memarg: MemArg) -> Self::Output {
1903 self.check_atomic_binary_op(memarg, ValType::I32)
1904 }
1905 fn visit_i32_atomic_rmw16_and_u(&mut self, memarg: MemArg) -> Self::Output {
1906 self.check_atomic_binary_op(memarg, ValType::I32)
1907 }
1908 fn visit_i32_atomic_rmw16_or_u(&mut self, memarg: MemArg) -> Self::Output {
1909 self.check_atomic_binary_op(memarg, ValType::I32)
1910 }
1911 fn visit_i32_atomic_rmw16_xor_u(&mut self, memarg: MemArg) -> Self::Output {
1912 self.check_atomic_binary_op(memarg, ValType::I32)
1913 }
1914 fn visit_i32_atomic_rmw8_add_u(&mut self, memarg: MemArg) -> Self::Output {
1915 self.check_atomic_binary_op(memarg, ValType::I32)
1916 }
1917 fn visit_i32_atomic_rmw8_sub_u(&mut self, memarg: MemArg) -> Self::Output {
1918 self.check_atomic_binary_op(memarg, ValType::I32)
1919 }
1920 fn visit_i32_atomic_rmw8_and_u(&mut self, memarg: MemArg) -> Self::Output {
1921 self.check_atomic_binary_op(memarg, ValType::I32)
1922 }
1923 fn visit_i32_atomic_rmw8_or_u(&mut self, memarg: MemArg) -> Self::Output {
1924 self.check_atomic_binary_op(memarg, ValType::I32)
1925 }
1926 fn visit_i32_atomic_rmw8_xor_u(&mut self, memarg: MemArg) -> Self::Output {
1927 self.check_atomic_binary_op(memarg, ValType::I32)
1928 }
1929 fn visit_i64_atomic_rmw_add(&mut self, memarg: MemArg) -> Self::Output {
1930 self.check_atomic_binary_op(memarg, ValType::I64)
1931 }
1932 fn visit_i64_atomic_rmw_sub(&mut self, memarg: MemArg) -> Self::Output {
1933 self.check_atomic_binary_op(memarg, ValType::I64)
1934 }
1935 fn visit_i64_atomic_rmw_and(&mut self, memarg: MemArg) -> Self::Output {
1936 self.check_atomic_binary_op(memarg, ValType::I64)
1937 }
1938 fn visit_i64_atomic_rmw_or(&mut self, memarg: MemArg) -> Self::Output {
1939 self.check_atomic_binary_op(memarg, ValType::I64)
1940 }
1941 fn visit_i64_atomic_rmw_xor(&mut self, memarg: MemArg) -> Self::Output {
1942 self.check_atomic_binary_op(memarg, ValType::I64)
1943 }
1944 fn visit_i64_atomic_rmw32_add_u(&mut self, memarg: MemArg) -> Self::Output {
1945 self.check_atomic_binary_op(memarg, ValType::I64)
1946 }
1947 fn visit_i64_atomic_rmw32_sub_u(&mut self, memarg: MemArg) -> Self::Output {
1948 self.check_atomic_binary_op(memarg, ValType::I64)
1949 }
1950 fn visit_i64_atomic_rmw32_and_u(&mut self, memarg: MemArg) -> Self::Output {
1951 self.check_atomic_binary_op(memarg, ValType::I64)
1952 }
1953 fn visit_i64_atomic_rmw32_or_u(&mut self, memarg: MemArg) -> Self::Output {
1954 self.check_atomic_binary_op(memarg, ValType::I64)
1955 }
1956 fn visit_i64_atomic_rmw32_xor_u(&mut self, memarg: MemArg) -> Self::Output {
1957 self.check_atomic_binary_op(memarg, ValType::I64)
1958 }
1959 fn visit_i64_atomic_rmw16_add_u(&mut self, memarg: MemArg) -> Self::Output {
1960 self.check_atomic_binary_op(memarg, ValType::I64)
1961 }
1962 fn visit_i64_atomic_rmw16_sub_u(&mut self, memarg: MemArg) -> Self::Output {
1963 self.check_atomic_binary_op(memarg, ValType::I64)
1964 }
1965 fn visit_i64_atomic_rmw16_and_u(&mut self, memarg: MemArg) -> Self::Output {
1966 self.check_atomic_binary_op(memarg, ValType::I64)
1967 }
1968 fn visit_i64_atomic_rmw16_or_u(&mut self, memarg: MemArg) -> Self::Output {
1969 self.check_atomic_binary_op(memarg, ValType::I64)
1970 }
1971 fn visit_i64_atomic_rmw16_xor_u(&mut self, memarg: MemArg) -> Self::Output {
1972 self.check_atomic_binary_op(memarg, ValType::I64)
1973 }
1974 fn visit_i64_atomic_rmw8_add_u(&mut self, memarg: MemArg) -> Self::Output {
1975 self.check_atomic_binary_op(memarg, ValType::I64)
1976 }
1977 fn visit_i64_atomic_rmw8_sub_u(&mut self, memarg: MemArg) -> Self::Output {
1978 self.check_atomic_binary_op(memarg, ValType::I64)
1979 }
1980 fn visit_i64_atomic_rmw8_and_u(&mut self, memarg: MemArg) -> Self::Output {
1981 self.check_atomic_binary_op(memarg, ValType::I64)
1982 }
1983 fn visit_i64_atomic_rmw8_or_u(&mut self, memarg: MemArg) -> Self::Output {
1984 self.check_atomic_binary_op(memarg, ValType::I64)
1985 }
1986 fn visit_i64_atomic_rmw8_xor_u(&mut self, memarg: MemArg) -> Self::Output {
1987 self.check_atomic_binary_op(memarg, ValType::I64)
1988 }
1989 fn visit_i32_atomic_rmw_xchg(&mut self, memarg: MemArg) -> Self::Output {
1990 self.check_atomic_binary_op(memarg, ValType::I32)
1991 }
1992 fn visit_i32_atomic_rmw16_xchg_u(&mut self, memarg: MemArg) -> Self::Output {
1993 self.check_atomic_binary_op(memarg, ValType::I32)
1994 }
1995 fn visit_i32_atomic_rmw8_xchg_u(&mut self, memarg: MemArg) -> Self::Output {
1996 self.check_atomic_binary_op(memarg, ValType::I32)
1997 }
1998 fn visit_i32_atomic_rmw_cmpxchg(&mut self, memarg: MemArg) -> Self::Output {
1999 self.check_atomic_binary_cmpxchg(memarg, ValType::I32)
2000 }
2001 fn visit_i32_atomic_rmw16_cmpxchg_u(&mut self, memarg: MemArg) -> Self::Output {
2002 self.check_atomic_binary_cmpxchg(memarg, ValType::I32)
2003 }
2004 fn visit_i32_atomic_rmw8_cmpxchg_u(&mut self, memarg: MemArg) -> Self::Output {
2005 self.check_atomic_binary_cmpxchg(memarg, ValType::I32)
2006 }
2007 fn visit_i64_atomic_rmw_xchg(&mut self, memarg: MemArg) -> Self::Output {
2008 self.check_atomic_binary_op(memarg, ValType::I64)
2009 }
2010 fn visit_i64_atomic_rmw32_xchg_u(&mut self, memarg: MemArg) -> Self::Output {
2011 self.check_atomic_binary_op(memarg, ValType::I64)
2012 }
2013 fn visit_i64_atomic_rmw16_xchg_u(&mut self, memarg: MemArg) -> Self::Output {
2014 self.check_atomic_binary_op(memarg, ValType::I64)
2015 }
2016 fn visit_i64_atomic_rmw8_xchg_u(&mut self, memarg: MemArg) -> Self::Output {
2017 self.check_atomic_binary_op(memarg, ValType::I64)
2018 }
2019 fn visit_i64_atomic_rmw_cmpxchg(&mut self, memarg: MemArg) -> Self::Output {
2020 self.check_atomic_binary_cmpxchg(memarg, ValType::I64)
2021 }
2022 fn visit_i64_atomic_rmw32_cmpxchg_u(&mut self, memarg: MemArg) -> Self::Output {
2023 self.check_atomic_binary_cmpxchg(memarg, ValType::I64)
2024 }
2025 fn visit_i64_atomic_rmw16_cmpxchg_u(&mut self, memarg: MemArg) -> Self::Output {
2026 self.check_atomic_binary_cmpxchg(memarg, ValType::I64)
2027 }
2028 fn visit_i64_atomic_rmw8_cmpxchg_u(&mut self, memarg: MemArg) -> Self::Output {
2029 self.check_atomic_binary_cmpxchg(memarg, ValType::I64)
2030 }
2031 fn visit_memory_atomic_notify(&mut self, memarg: MemArg) -> Self::Output {
2032 self.check_atomic_binary_op(memarg, ValType::I32)
2033 }
2034 fn visit_memory_atomic_wait32(&mut self, memarg: MemArg) -> Self::Output {
2035 let ty = self.check_shared_memarg(memarg)?;
2036 self.pop_operand(Some(ValType::I64))?;
2037 self.pop_operand(Some(ValType::I32))?;
2038 self.pop_operand(Some(ty))?;
2039 self.push_operand(ValType::I32)?;
2040 Ok(())
2041 }
2042 fn visit_memory_atomic_wait64(&mut self, memarg: MemArg) -> Self::Output {
2043 let ty = self.check_shared_memarg(memarg)?;
2044 self.pop_operand(Some(ValType::I64))?;
2045 self.pop_operand(Some(ValType::I64))?;
2046 self.pop_operand(Some(ty))?;
2047 self.push_operand(ValType::I32)?;
2048 Ok(())
2049 }
2050 fn visit_atomic_fence(&mut self) -> Self::Output {
2051 Ok(())
2052 }
2053 fn visit_ref_null(&mut self, ty: ValType) -> Self::Output {
2054 self.features
2055 .check_value_type(ty)
2056 .map_err(|e| BinaryReaderError::new(e, self.offset))?;
2057 if !ty.is_reference_type() {
2058 bail!(self.offset, "invalid non-reference type in ref.null");
2059 }
2060 self.push_operand(ty)?;
2061 Ok(())
2062 }
2063 fn visit_ref_is_null(&mut self) -> Self::Output {
2064 match self.pop_operand(None)? {
2065 None => {}
2066 Some(t) => {
2067 if !t.is_reference_type() {
2068 bail!(
2069 self.offset,
2070 "type mismatch: invalid reference type in ref.is_null"
2071 );
2072 }
2073 }
2074 }
2075 self.push_operand(ValType::I32)?;
2076 Ok(())
2077 }
2078 fn visit_ref_func(&mut self, function_index: u32) -> Self::Output {
2079 if self.resources.type_of_function(function_index).is_none() {
2080 bail!(
2081 self.offset,
2082 "unknown function {}: function index out of bounds",
2083 function_index,
2084 );
2085 }
2086 if !self.resources.is_function_referenced(function_index) {
2087 bail!(self.offset, "undeclared function reference");
2088 }
2089 self.push_operand(ValType::FuncRef)?;
2090 Ok(())
2091 }
2092 fn visit_v128_load(&mut self, memarg: MemArg) -> Self::Output {
2093 let ty = self.check_memarg(memarg)?;
2094 self.pop_operand(Some(ty))?;
2095 self.push_operand(ValType::V128)?;
2096 Ok(())
2097 }
2098 fn visit_v128_store(&mut self, memarg: MemArg) -> Self::Output {
2099 let ty = self.check_memarg(memarg)?;
2100 self.pop_operand(Some(ValType::V128))?;
2101 self.pop_operand(Some(ty))?;
2102 Ok(())
2103 }
2104 fn visit_v128_const(&mut self, _value: V128) -> Self::Output {
2105 self.push_operand(ValType::V128)?;
2106 Ok(())
2107 }
2108 fn visit_i8x16_splat(&mut self) -> Self::Output {
2109 self.check_v128_splat(ValType::I32)
2110 }
2111 fn visit_i16x8_splat(&mut self) -> Self::Output {
2112 self.check_v128_splat(ValType::I32)
2113 }
2114 fn visit_i32x4_splat(&mut self) -> Self::Output {
2115 self.check_v128_splat(ValType::I32)
2116 }
2117 fn visit_i64x2_splat(&mut self) -> Self::Output {
2118 self.check_v128_splat(ValType::I64)
2119 }
2120 fn visit_f32x4_splat(&mut self) -> Self::Output {
2121 self.check_floats_enabled()?;
2122 self.check_v128_splat(ValType::F32)
2123 }
2124 fn visit_f64x2_splat(&mut self) -> Self::Output {
2125 self.check_floats_enabled()?;
2126 self.check_v128_splat(ValType::F64)
2127 }
2128 fn visit_i8x16_extract_lane_s(&mut self, lane: u8) -> Self::Output {
2129 self.check_simd_lane_index(lane, 16)?;
2130 self.pop_operand(Some(ValType::V128))?;
2131 self.push_operand(ValType::I32)?;
2132 Ok(())
2133 }
2134 fn visit_i8x16_extract_lane_u(&mut self, lane: u8) -> Self::Output {
2135 self.visit_i8x16_extract_lane_s(lane)
2136 }
2137 fn visit_i16x8_extract_lane_s(&mut self, lane: u8) -> Self::Output {
2138 self.check_simd_lane_index(lane, 8)?;
2139 self.pop_operand(Some(ValType::V128))?;
2140 self.push_operand(ValType::I32)?;
2141 Ok(())
2142 }
2143 fn visit_i16x8_extract_lane_u(&mut self, lane: u8) -> Self::Output {
2144 self.visit_i16x8_extract_lane_s(lane)
2145 }
2146 fn visit_i32x4_extract_lane(&mut self, lane: u8) -> Self::Output {
2147 self.check_simd_lane_index(lane, 4)?;
2148 self.pop_operand(Some(ValType::V128))?;
2149 self.push_operand(ValType::I32)?;
2150 Ok(())
2151 }
2152 fn visit_i8x16_replace_lane(&mut self, lane: u8) -> Self::Output {
2153 self.check_simd_lane_index(lane, 16)?;
2154 self.pop_operand(Some(ValType::I32))?;
2155 self.pop_operand(Some(ValType::V128))?;
2156 self.push_operand(ValType::V128)?;
2157 Ok(())
2158 }
2159 fn visit_i16x8_replace_lane(&mut self, lane: u8) -> Self::Output {
2160 self.check_simd_lane_index(lane, 8)?;
2161 self.pop_operand(Some(ValType::I32))?;
2162 self.pop_operand(Some(ValType::V128))?;
2163 self.push_operand(ValType::V128)?;
2164 Ok(())
2165 }
2166 fn visit_i32x4_replace_lane(&mut self, lane: u8) -> Self::Output {
2167 self.check_simd_lane_index(lane, 4)?;
2168 self.pop_operand(Some(ValType::I32))?;
2169 self.pop_operand(Some(ValType::V128))?;
2170 self.push_operand(ValType::V128)?;
2171 Ok(())
2172 }
2173 fn visit_i64x2_extract_lane(&mut self, lane: u8) -> Self::Output {
2174 self.check_simd_lane_index(lane, 2)?;
2175 self.pop_operand(Some(ValType::V128))?;
2176 self.push_operand(ValType::I64)?;
2177 Ok(())
2178 }
2179 fn visit_i64x2_replace_lane(&mut self, lane: u8) -> Self::Output {
2180 self.check_simd_lane_index(lane, 2)?;
2181 self.pop_operand(Some(ValType::I64))?;
2182 self.pop_operand(Some(ValType::V128))?;
2183 self.push_operand(ValType::V128)?;
2184 Ok(())
2185 }
2186 fn visit_f32x4_extract_lane(&mut self, lane: u8) -> Self::Output {
2187 self.check_floats_enabled()?;
2188 self.check_simd_lane_index(lane, 4)?;
2189 self.pop_operand(Some(ValType::V128))?;
2190 self.push_operand(ValType::F32)?;
2191 Ok(())
2192 }
2193 fn visit_f32x4_replace_lane(&mut self, lane: u8) -> Self::Output {
2194 self.check_floats_enabled()?;
2195 self.check_simd_lane_index(lane, 4)?;
2196 self.pop_operand(Some(ValType::F32))?;
2197 self.pop_operand(Some(ValType::V128))?;
2198 self.push_operand(ValType::V128)?;
2199 Ok(())
2200 }
2201 fn visit_f64x2_extract_lane(&mut self, lane: u8) -> Self::Output {
2202 self.check_floats_enabled()?;
2203 self.check_simd_lane_index(lane, 2)?;
2204 self.pop_operand(Some(ValType::V128))?;
2205 self.push_operand(ValType::F64)?;
2206 Ok(())
2207 }
2208 fn visit_f64x2_replace_lane(&mut self, lane: u8) -> Self::Output {
2209 self.check_floats_enabled()?;
2210 self.check_simd_lane_index(lane, 2)?;
2211 self.pop_operand(Some(ValType::F64))?;
2212 self.pop_operand(Some(ValType::V128))?;
2213 self.push_operand(ValType::V128)?;
2214 Ok(())
2215 }
2216 fn visit_f32x4_eq(&mut self) -> Self::Output {
2217 self.check_v128_fbinary_op()
2218 }
2219 fn visit_f32x4_ne(&mut self) -> Self::Output {
2220 self.check_v128_fbinary_op()
2221 }
2222 fn visit_f32x4_lt(&mut self) -> Self::Output {
2223 self.check_v128_fbinary_op()
2224 }
2225 fn visit_f32x4_gt(&mut self) -> Self::Output {
2226 self.check_v128_fbinary_op()
2227 }
2228 fn visit_f32x4_le(&mut self) -> Self::Output {
2229 self.check_v128_fbinary_op()
2230 }
2231 fn visit_f32x4_ge(&mut self) -> Self::Output {
2232 self.check_v128_fbinary_op()
2233 }
2234 fn visit_f64x2_eq(&mut self) -> Self::Output {
2235 self.check_v128_fbinary_op()
2236 }
2237 fn visit_f64x2_ne(&mut self) -> Self::Output {
2238 self.check_v128_fbinary_op()
2239 }
2240 fn visit_f64x2_lt(&mut self) -> Self::Output {
2241 self.check_v128_fbinary_op()
2242 }
2243 fn visit_f64x2_gt(&mut self) -> Self::Output {
2244 self.check_v128_fbinary_op()
2245 }
2246 fn visit_f64x2_le(&mut self) -> Self::Output {
2247 self.check_v128_fbinary_op()
2248 }
2249 fn visit_f64x2_ge(&mut self) -> Self::Output {
2250 self.check_v128_fbinary_op()
2251 }
2252 fn visit_f32x4_add(&mut self) -> Self::Output {
2253 self.check_v128_fbinary_op()
2254 }
2255 fn visit_f32x4_sub(&mut self) -> Self::Output {
2256 self.check_v128_fbinary_op()
2257 }
2258 fn visit_f32x4_mul(&mut self) -> Self::Output {
2259 self.check_v128_fbinary_op()
2260 }
2261 fn visit_f32x4_div(&mut self) -> Self::Output {
2262 self.check_v128_fbinary_op()
2263 }
2264 fn visit_f32x4_min(&mut self) -> Self::Output {
2265 self.check_v128_fbinary_op()
2266 }
2267 fn visit_f32x4_max(&mut self) -> Self::Output {
2268 self.check_v128_fbinary_op()
2269 }
2270 fn visit_f32x4_pmin(&mut self) -> Self::Output {
2271 self.check_v128_fbinary_op()
2272 }
2273 fn visit_f32x4_pmax(&mut self) -> Self::Output {
2274 self.check_v128_fbinary_op()
2275 }
2276 fn visit_f64x2_add(&mut self) -> Self::Output {
2277 self.check_v128_fbinary_op()
2278 }
2279 fn visit_f64x2_sub(&mut self) -> Self::Output {
2280 self.check_v128_fbinary_op()
2281 }
2282 fn visit_f64x2_mul(&mut self) -> Self::Output {
2283 self.check_v128_fbinary_op()
2284 }
2285 fn visit_f64x2_div(&mut self) -> Self::Output {
2286 self.check_v128_fbinary_op()
2287 }
2288 fn visit_f64x2_min(&mut self) -> Self::Output {
2289 self.check_v128_fbinary_op()
2290 }
2291 fn visit_f64x2_max(&mut self) -> Self::Output {
2292 self.check_v128_fbinary_op()
2293 }
2294 fn visit_f64x2_pmin(&mut self) -> Self::Output {
2295 self.check_v128_fbinary_op()
2296 }
2297 fn visit_f64x2_pmax(&mut self) -> Self::Output {
2298 self.check_v128_fbinary_op()
2299 }
2300 fn visit_f32x4_relaxed_min(&mut self) -> Self::Output {
2301 self.check_v128_relaxed_binary_op()
2302 }
2303 fn visit_f32x4_relaxed_max(&mut self) -> Self::Output {
2304 self.check_v128_relaxed_binary_op()
2305 }
2306 fn visit_f64x2_relaxed_min(&mut self) -> Self::Output {
2307 self.check_v128_relaxed_binary_op()
2308 }
2309 fn visit_f64x2_relaxed_max(&mut self) -> Self::Output {
2310 self.check_v128_relaxed_binary_op()
2311 }
2312 fn visit_i16x8_relaxed_q15mulr_s(&mut self) -> Self::Output {
2313 self.check_v128_relaxed_binary_op()
2314 }
2315 fn visit_i16x8_dot_i8x16_i7x16_s(&mut self) -> Self::Output {
2316 self.check_v128_relaxed_binary_op()
2317 }
2318 fn visit_i8x16_eq(&mut self) -> Self::Output {
2319 self.check_v128_binary_op()
2320 }
2321 fn visit_i8x16_ne(&mut self) -> Self::Output {
2322 self.check_v128_binary_op()
2323 }
2324 fn visit_i8x16_lt_s(&mut self) -> Self::Output {
2325 self.check_v128_binary_op()
2326 }
2327 fn visit_i8x16_lt_u(&mut self) -> Self::Output {
2328 self.check_v128_binary_op()
2329 }
2330 fn visit_i8x16_gt_s(&mut self) -> Self::Output {
2331 self.check_v128_binary_op()
2332 }
2333 fn visit_i8x16_gt_u(&mut self) -> Self::Output {
2334 self.check_v128_binary_op()
2335 }
2336 fn visit_i8x16_le_s(&mut self) -> Self::Output {
2337 self.check_v128_binary_op()
2338 }
2339 fn visit_i8x16_le_u(&mut self) -> Self::Output {
2340 self.check_v128_binary_op()
2341 }
2342 fn visit_i8x16_ge_s(&mut self) -> Self::Output {
2343 self.check_v128_binary_op()
2344 }
2345 fn visit_i8x16_ge_u(&mut self) -> Self::Output {
2346 self.check_v128_binary_op()
2347 }
2348 fn visit_i16x8_eq(&mut self) -> Self::Output {
2349 self.check_v128_binary_op()
2350 }
2351 fn visit_i16x8_ne(&mut self) -> Self::Output {
2352 self.check_v128_binary_op()
2353 }
2354 fn visit_i16x8_lt_s(&mut self) -> Self::Output {
2355 self.check_v128_binary_op()
2356 }
2357 fn visit_i16x8_lt_u(&mut self) -> Self::Output {
2358 self.check_v128_binary_op()
2359 }
2360 fn visit_i16x8_gt_s(&mut self) -> Self::Output {
2361 self.check_v128_binary_op()
2362 }
2363 fn visit_i16x8_gt_u(&mut self) -> Self::Output {
2364 self.check_v128_binary_op()
2365 }
2366 fn visit_i16x8_le_s(&mut self) -> Self::Output {
2367 self.check_v128_binary_op()
2368 }
2369 fn visit_i16x8_le_u(&mut self) -> Self::Output {
2370 self.check_v128_binary_op()
2371 }
2372 fn visit_i16x8_ge_s(&mut self) -> Self::Output {
2373 self.check_v128_binary_op()
2374 }
2375 fn visit_i16x8_ge_u(&mut self) -> Self::Output {
2376 self.check_v128_binary_op()
2377 }
2378 fn visit_i32x4_eq(&mut self) -> Self::Output {
2379 self.check_v128_binary_op()
2380 }
2381 fn visit_i32x4_ne(&mut self) -> Self::Output {
2382 self.check_v128_binary_op()
2383 }
2384 fn visit_i32x4_lt_s(&mut self) -> Self::Output {
2385 self.check_v128_binary_op()
2386 }
2387 fn visit_i32x4_lt_u(&mut self) -> Self::Output {
2388 self.check_v128_binary_op()
2389 }
2390 fn visit_i32x4_gt_s(&mut self) -> Self::Output {
2391 self.check_v128_binary_op()
2392 }
2393 fn visit_i32x4_gt_u(&mut self) -> Self::Output {
2394 self.check_v128_binary_op()
2395 }
2396 fn visit_i32x4_le_s(&mut self) -> Self::Output {
2397 self.check_v128_binary_op()
2398 }
2399 fn visit_i32x4_le_u(&mut self) -> Self::Output {
2400 self.check_v128_binary_op()
2401 }
2402 fn visit_i32x4_ge_s(&mut self) -> Self::Output {
2403 self.check_v128_binary_op()
2404 }
2405 fn visit_i32x4_ge_u(&mut self) -> Self::Output {
2406 self.check_v128_binary_op()
2407 }
2408 fn visit_i64x2_eq(&mut self) -> Self::Output {
2409 self.check_v128_binary_op()
2410 }
2411 fn visit_i64x2_ne(&mut self) -> Self::Output {
2412 self.check_v128_binary_op()
2413 }
2414 fn visit_i64x2_lt_s(&mut self) -> Self::Output {
2415 self.check_v128_binary_op()
2416 }
2417 fn visit_i64x2_gt_s(&mut self) -> Self::Output {
2418 self.check_v128_binary_op()
2419 }
2420 fn visit_i64x2_le_s(&mut self) -> Self::Output {
2421 self.check_v128_binary_op()
2422 }
2423 fn visit_i64x2_ge_s(&mut self) -> Self::Output {
2424 self.check_v128_binary_op()
2425 }
2426 fn visit_v128_and(&mut self) -> Self::Output {
2427 self.check_v128_binary_op()
2428 }
2429 fn visit_v128_andnot(&mut self) -> Self::Output {
2430 self.check_v128_binary_op()
2431 }
2432 fn visit_v128_or(&mut self) -> Self::Output {
2433 self.check_v128_binary_op()
2434 }
2435 fn visit_v128_xor(&mut self) -> Self::Output {
2436 self.check_v128_binary_op()
2437 }
2438 fn visit_i8x16_add(&mut self) -> Self::Output {
2439 self.check_v128_binary_op()
2440 }
2441 fn visit_i8x16_add_sat_s(&mut self) -> Self::Output {
2442 self.check_v128_binary_op()
2443 }
2444 fn visit_i8x16_add_sat_u(&mut self) -> Self::Output {
2445 self.check_v128_binary_op()
2446 }
2447 fn visit_i8x16_sub(&mut self) -> Self::Output {
2448 self.check_v128_binary_op()
2449 }
2450 fn visit_i8x16_sub_sat_s(&mut self) -> Self::Output {
2451 self.check_v128_binary_op()
2452 }
2453 fn visit_i8x16_sub_sat_u(&mut self) -> Self::Output {
2454 self.check_v128_binary_op()
2455 }
2456 fn visit_i8x16_min_s(&mut self) -> Self::Output {
2457 self.check_v128_binary_op()
2458 }
2459 fn visit_i8x16_min_u(&mut self) -> Self::Output {
2460 self.check_v128_binary_op()
2461 }
2462 fn visit_i8x16_max_s(&mut self) -> Self::Output {
2463 self.check_v128_binary_op()
2464 }
2465 fn visit_i8x16_max_u(&mut self) -> Self::Output {
2466 self.check_v128_binary_op()
2467 }
2468 fn visit_i16x8_add(&mut self) -> Self::Output {
2469 self.check_v128_binary_op()
2470 }
2471 fn visit_i16x8_add_sat_s(&mut self) -> Self::Output {
2472 self.check_v128_binary_op()
2473 }
2474 fn visit_i16x8_add_sat_u(&mut self) -> Self::Output {
2475 self.check_v128_binary_op()
2476 }
2477 fn visit_i16x8_sub(&mut self) -> Self::Output {
2478 self.check_v128_binary_op()
2479 }
2480 fn visit_i16x8_sub_sat_s(&mut self) -> Self::Output {
2481 self.check_v128_binary_op()
2482 }
2483 fn visit_i16x8_sub_sat_u(&mut self) -> Self::Output {
2484 self.check_v128_binary_op()
2485 }
2486 fn visit_i16x8_mul(&mut self) -> Self::Output {
2487 self.check_v128_binary_op()
2488 }
2489 fn visit_i16x8_min_s(&mut self) -> Self::Output {
2490 self.check_v128_binary_op()
2491 }
2492 fn visit_i16x8_min_u(&mut self) -> Self::Output {
2493 self.check_v128_binary_op()
2494 }
2495 fn visit_i16x8_max_s(&mut self) -> Self::Output {
2496 self.check_v128_binary_op()
2497 }
2498 fn visit_i16x8_max_u(&mut self) -> Self::Output {
2499 self.check_v128_binary_op()
2500 }
2501 fn visit_i32x4_add(&mut self) -> Self::Output {
2502 self.check_v128_binary_op()
2503 }
2504 fn visit_i32x4_sub(&mut self) -> Self::Output {
2505 self.check_v128_binary_op()
2506 }
2507 fn visit_i32x4_mul(&mut self) -> Self::Output {
2508 self.check_v128_binary_op()
2509 }
2510 fn visit_i32x4_min_s(&mut self) -> Self::Output {
2511 self.check_v128_binary_op()
2512 }
2513 fn visit_i32x4_min_u(&mut self) -> Self::Output {
2514 self.check_v128_binary_op()
2515 }
2516 fn visit_i32x4_max_s(&mut self) -> Self::Output {
2517 self.check_v128_binary_op()
2518 }
2519 fn visit_i32x4_max_u(&mut self) -> Self::Output {
2520 self.check_v128_binary_op()
2521 }
2522 fn visit_i32x4_dot_i16x8_s(&mut self) -> Self::Output {
2523 self.check_v128_binary_op()
2524 }
2525 fn visit_i64x2_add(&mut self) -> Self::Output {
2526 self.check_v128_binary_op()
2527 }
2528 fn visit_i64x2_sub(&mut self) -> Self::Output {
2529 self.check_v128_binary_op()
2530 }
2531 fn visit_i64x2_mul(&mut self) -> Self::Output {
2532 self.check_v128_binary_op()
2533 }
2534 fn visit_i8x16_avgr_u(&mut self) -> Self::Output {
2535 self.check_v128_binary_op()
2536 }
2537 fn visit_i16x8_avgr_u(&mut self) -> Self::Output {
2538 self.check_v128_binary_op()
2539 }
2540 fn visit_i8x16_narrow_i16x8_s(&mut self) -> Self::Output {
2541 self.check_v128_binary_op()
2542 }
2543 fn visit_i8x16_narrow_i16x8_u(&mut self) -> Self::Output {
2544 self.check_v128_binary_op()
2545 }
2546 fn visit_i16x8_narrow_i32x4_s(&mut self) -> Self::Output {
2547 self.check_v128_binary_op()
2548 }
2549 fn visit_i16x8_narrow_i32x4_u(&mut self) -> Self::Output {
2550 self.check_v128_binary_op()
2551 }
2552 fn visit_i16x8_extmul_low_i8x16_s(&mut self) -> Self::Output {
2553 self.check_v128_binary_op()
2554 }
2555 fn visit_i16x8_extmul_high_i8x16_s(&mut self) -> Self::Output {
2556 self.check_v128_binary_op()
2557 }
2558 fn visit_i16x8_extmul_low_i8x16_u(&mut self) -> Self::Output {
2559 self.check_v128_binary_op()
2560 }
2561 fn visit_i16x8_extmul_high_i8x16_u(&mut self) -> Self::Output {
2562 self.check_v128_binary_op()
2563 }
2564 fn visit_i32x4_extmul_low_i16x8_s(&mut self) -> Self::Output {
2565 self.check_v128_binary_op()
2566 }
2567 fn visit_i32x4_extmul_high_i16x8_s(&mut self) -> Self::Output {
2568 self.check_v128_binary_op()
2569 }
2570 fn visit_i32x4_extmul_low_i16x8_u(&mut self) -> Self::Output {
2571 self.check_v128_binary_op()
2572 }
2573 fn visit_i32x4_extmul_high_i16x8_u(&mut self) -> Self::Output {
2574 self.check_v128_binary_op()
2575 }
2576 fn visit_i64x2_extmul_low_i32x4_s(&mut self) -> Self::Output {
2577 self.check_v128_binary_op()
2578 }
2579 fn visit_i64x2_extmul_high_i32x4_s(&mut self) -> Self::Output {
2580 self.check_v128_binary_op()
2581 }
2582 fn visit_i64x2_extmul_low_i32x4_u(&mut self) -> Self::Output {
2583 self.check_v128_binary_op()
2584 }
2585 fn visit_i64x2_extmul_high_i32x4_u(&mut self) -> Self::Output {
2586 self.check_v128_binary_op()
2587 }
2588 fn visit_i16x8_q15mulr_sat_s(&mut self) -> Self::Output {
2589 self.check_v128_binary_op()
2590 }
2591 fn visit_f32x4_ceil(&mut self) -> Self::Output {
2592 self.check_v128_funary_op()
2593 }
2594 fn visit_f32x4_floor(&mut self) -> Self::Output {
2595 self.check_v128_funary_op()
2596 }
2597 fn visit_f32x4_trunc(&mut self) -> Self::Output {
2598 self.check_v128_funary_op()
2599 }
2600 fn visit_f32x4_nearest(&mut self) -> Self::Output {
2601 self.check_v128_funary_op()
2602 }
2603 fn visit_f64x2_ceil(&mut self) -> Self::Output {
2604 self.check_v128_funary_op()
2605 }
2606 fn visit_f64x2_floor(&mut self) -> Self::Output {
2607 self.check_v128_funary_op()
2608 }
2609 fn visit_f64x2_trunc(&mut self) -> Self::Output {
2610 self.check_v128_funary_op()
2611 }
2612 fn visit_f64x2_nearest(&mut self) -> Self::Output {
2613 self.check_v128_funary_op()
2614 }
2615 fn visit_f32x4_abs(&mut self) -> Self::Output {
2616 self.check_v128_funary_op()
2617 }
2618 fn visit_f32x4_neg(&mut self) -> Self::Output {
2619 self.check_v128_funary_op()
2620 }
2621 fn visit_f32x4_sqrt(&mut self) -> Self::Output {
2622 self.check_v128_funary_op()
2623 }
2624 fn visit_f64x2_abs(&mut self) -> Self::Output {
2625 self.check_v128_funary_op()
2626 }
2627 fn visit_f64x2_neg(&mut self) -> Self::Output {
2628 self.check_v128_funary_op()
2629 }
2630 fn visit_f64x2_sqrt(&mut self) -> Self::Output {
2631 self.check_v128_funary_op()
2632 }
2633 fn visit_f32x4_demote_f64x2_zero(&mut self) -> Self::Output {
2634 self.check_v128_funary_op()
2635 }
2636 fn visit_f64x2_promote_low_f32x4(&mut self) -> Self::Output {
2637 self.check_v128_funary_op()
2638 }
2639 fn visit_f64x2_convert_low_i32x4_s(&mut self) -> Self::Output {
2640 self.check_v128_funary_op()
2641 }
2642 fn visit_f64x2_convert_low_i32x4_u(&mut self) -> Self::Output {
2643 self.check_v128_funary_op()
2644 }
2645 fn visit_i32x4_trunc_sat_f32x4_s(&mut self) -> Self::Output {
2646 self.check_v128_funary_op()
2647 }
2648 fn visit_i32x4_trunc_sat_f32x4_u(&mut self) -> Self::Output {
2649 self.check_v128_funary_op()
2650 }
2651 fn visit_i32x4_trunc_sat_f64x2_s_zero(&mut self) -> Self::Output {
2652 self.check_v128_funary_op()
2653 }
2654 fn visit_i32x4_trunc_sat_f64x2_u_zero(&mut self) -> Self::Output {
2655 self.check_v128_funary_op()
2656 }
2657 fn visit_f32x4_convert_i32x4_s(&mut self) -> Self::Output {
2658 self.check_v128_funary_op()
2659 }
2660 fn visit_f32x4_convert_i32x4_u(&mut self) -> Self::Output {
2661 self.check_v128_funary_op()
2662 }
2663 fn visit_v128_not(&mut self) -> Self::Output {
2664 self.check_v128_unary_op()
2665 }
2666 fn visit_i8x16_abs(&mut self) -> Self::Output {
2667 self.check_v128_unary_op()
2668 }
2669 fn visit_i8x16_neg(&mut self) -> Self::Output {
2670 self.check_v128_unary_op()
2671 }
2672 fn visit_i8x16_popcnt(&mut self) -> Self::Output {
2673 self.check_v128_unary_op()
2674 }
2675 fn visit_i16x8_abs(&mut self) -> Self::Output {
2676 self.check_v128_unary_op()
2677 }
2678 fn visit_i16x8_neg(&mut self) -> Self::Output {
2679 self.check_v128_unary_op()
2680 }
2681 fn visit_i32x4_abs(&mut self) -> Self::Output {
2682 self.check_v128_unary_op()
2683 }
2684 fn visit_i32x4_neg(&mut self) -> Self::Output {
2685 self.check_v128_unary_op()
2686 }
2687 fn visit_i64x2_abs(&mut self) -> Self::Output {
2688 self.check_v128_unary_op()
2689 }
2690 fn visit_i64x2_neg(&mut self) -> Self::Output {
2691 self.check_v128_unary_op()
2692 }
2693 fn visit_i16x8_extend_low_i8x16_s(&mut self) -> Self::Output {
2694 self.check_v128_unary_op()
2695 }
2696 fn visit_i16x8_extend_high_i8x16_s(&mut self) -> Self::Output {
2697 self.check_v128_unary_op()
2698 }
2699 fn visit_i16x8_extend_low_i8x16_u(&mut self) -> Self::Output {
2700 self.check_v128_unary_op()
2701 }
2702 fn visit_i16x8_extend_high_i8x16_u(&mut self) -> Self::Output {
2703 self.check_v128_unary_op()
2704 }
2705 fn visit_i32x4_extend_low_i16x8_s(&mut self) -> Self::Output {
2706 self.check_v128_unary_op()
2707 }
2708 fn visit_i32x4_extend_high_i16x8_s(&mut self) -> Self::Output {
2709 self.check_v128_unary_op()
2710 }
2711 fn visit_i32x4_extend_low_i16x8_u(&mut self) -> Self::Output {
2712 self.check_v128_unary_op()
2713 }
2714 fn visit_i32x4_extend_high_i16x8_u(&mut self) -> Self::Output {
2715 self.check_v128_unary_op()
2716 }
2717 fn visit_i64x2_extend_low_i32x4_s(&mut self) -> Self::Output {
2718 self.check_v128_unary_op()
2719 }
2720 fn visit_i64x2_extend_high_i32x4_s(&mut self) -> Self::Output {
2721 self.check_v128_unary_op()
2722 }
2723 fn visit_i64x2_extend_low_i32x4_u(&mut self) -> Self::Output {
2724 self.check_v128_unary_op()
2725 }
2726 fn visit_i64x2_extend_high_i32x4_u(&mut self) -> Self::Output {
2727 self.check_v128_unary_op()
2728 }
2729 fn visit_i16x8_extadd_pairwise_i8x16_s(&mut self) -> Self::Output {
2730 self.check_v128_unary_op()
2731 }
2732 fn visit_i16x8_extadd_pairwise_i8x16_u(&mut self) -> Self::Output {
2733 self.check_v128_unary_op()
2734 }
2735 fn visit_i32x4_extadd_pairwise_i16x8_s(&mut self) -> Self::Output {
2736 self.check_v128_unary_op()
2737 }
2738 fn visit_i32x4_extadd_pairwise_i16x8_u(&mut self) -> Self::Output {
2739 self.check_v128_unary_op()
2740 }
2741 fn visit_i32x4_relaxed_trunc_sat_f32x4_s(&mut self) -> Self::Output {
2742 self.check_v128_relaxed_unary_op()
2743 }
2744 fn visit_i32x4_relaxed_trunc_sat_f32x4_u(&mut self) -> Self::Output {
2745 self.check_v128_relaxed_unary_op()
2746 }
2747 fn visit_i32x4_relaxed_trunc_sat_f64x2_s_zero(&mut self) -> Self::Output {
2748 self.check_v128_relaxed_unary_op()
2749 }
2750 fn visit_i32x4_relaxed_trunc_sat_f64x2_u_zero(&mut self) -> Self::Output {
2751 self.check_v128_relaxed_unary_op()
2752 }
2753 fn visit_v128_bitselect(&mut self) -> Self::Output {
2754 self.pop_operand(Some(ValType::V128))?;
2755 self.pop_operand(Some(ValType::V128))?;
2756 self.pop_operand(Some(ValType::V128))?;
2757 self.push_operand(ValType::V128)?;
2758 Ok(())
2759 }
2760 fn visit_f32x4_relaxed_fma(&mut self) -> Self::Output {
2761 self.check_v128_relaxed_ternary_op()
2762 }
2763 fn visit_f32x4_relaxed_fnma(&mut self) -> Self::Output {
2764 self.check_v128_relaxed_ternary_op()
2765 }
2766 fn visit_f64x2_relaxed_fma(&mut self) -> Self::Output {
2767 self.check_v128_relaxed_ternary_op()
2768 }
2769 fn visit_f64x2_relaxed_fnma(&mut self) -> Self::Output {
2770 self.check_v128_relaxed_ternary_op()
2771 }
2772 fn visit_i8x16_relaxed_laneselect(&mut self) -> Self::Output {
2773 self.check_v128_relaxed_ternary_op()
2774 }
2775 fn visit_i16x8_relaxed_laneselect(&mut self) -> Self::Output {
2776 self.check_v128_relaxed_ternary_op()
2777 }
2778 fn visit_i32x4_relaxed_laneselect(&mut self) -> Self::Output {
2779 self.check_v128_relaxed_ternary_op()
2780 }
2781 fn visit_i64x2_relaxed_laneselect(&mut self) -> Self::Output {
2782 self.check_v128_relaxed_ternary_op()
2783 }
2784 fn visit_i32x4_dot_i8x16_i7x16_add_s(&mut self) -> Self::Output {
2785 self.check_v128_relaxed_ternary_op()
2786 }
2787 fn visit_f32x4_relaxed_dot_bf16x8_add_f32x4(&mut self) -> Self::Output {
2788 self.check_v128_relaxed_ternary_op()
2789 }
2790 fn visit_v128_any_true(&mut self) -> Self::Output {
2791 self.check_v128_bitmask_op()
2792 }
2793 fn visit_i8x16_all_true(&mut self) -> Self::Output {
2794 self.check_v128_bitmask_op()
2795 }
2796 fn visit_i8x16_bitmask(&mut self) -> Self::Output {
2797 self.check_v128_bitmask_op()
2798 }
2799 fn visit_i16x8_all_true(&mut self) -> Self::Output {
2800 self.check_v128_bitmask_op()
2801 }
2802 fn visit_i16x8_bitmask(&mut self) -> Self::Output {
2803 self.check_v128_bitmask_op()
2804 }
2805 fn visit_i32x4_all_true(&mut self) -> Self::Output {
2806 self.check_v128_bitmask_op()
2807 }
2808 fn visit_i32x4_bitmask(&mut self) -> Self::Output {
2809 self.check_v128_bitmask_op()
2810 }
2811 fn visit_i64x2_all_true(&mut self) -> Self::Output {
2812 self.check_v128_bitmask_op()
2813 }
2814 fn visit_i64x2_bitmask(&mut self) -> Self::Output {
2815 self.check_v128_bitmask_op()
2816 }
2817 fn visit_i8x16_shl(&mut self) -> Self::Output {
2818 self.check_v128_shift_op()
2819 }
2820 fn visit_i8x16_shr_s(&mut self) -> Self::Output {
2821 self.check_v128_shift_op()
2822 }
2823 fn visit_i8x16_shr_u(&mut self) -> Self::Output {
2824 self.check_v128_shift_op()
2825 }
2826 fn visit_i16x8_shl(&mut self) -> Self::Output {
2827 self.check_v128_shift_op()
2828 }
2829 fn visit_i16x8_shr_s(&mut self) -> Self::Output {
2830 self.check_v128_shift_op()
2831 }
2832 fn visit_i16x8_shr_u(&mut self) -> Self::Output {
2833 self.check_v128_shift_op()
2834 }
2835 fn visit_i32x4_shl(&mut self) -> Self::Output {
2836 self.check_v128_shift_op()
2837 }
2838 fn visit_i32x4_shr_s(&mut self) -> Self::Output {
2839 self.check_v128_shift_op()
2840 }
2841 fn visit_i32x4_shr_u(&mut self) -> Self::Output {
2842 self.check_v128_shift_op()
2843 }
2844 fn visit_i64x2_shl(&mut self) -> Self::Output {
2845 self.check_v128_shift_op()
2846 }
2847 fn visit_i64x2_shr_s(&mut self) -> Self::Output {
2848 self.check_v128_shift_op()
2849 }
2850 fn visit_i64x2_shr_u(&mut self) -> Self::Output {
2851 self.check_v128_shift_op()
2852 }
2853 fn visit_i8x16_swizzle(&mut self) -> Self::Output {
2854 self.pop_operand(Some(ValType::V128))?;
2855 self.pop_operand(Some(ValType::V128))?;
2856 self.push_operand(ValType::V128)?;
2857 Ok(())
2858 }
2859 fn visit_i8x16_relaxed_swizzle(&mut self) -> Self::Output {
2860 self.pop_operand(Some(ValType::V128))?;
2861 self.pop_operand(Some(ValType::V128))?;
2862 self.push_operand(ValType::V128)?;
2863 Ok(())
2864 }
2865 fn visit_i8x16_shuffle(&mut self, lanes: [u8; 16]) -> Self::Output {
2866 self.pop_operand(Some(ValType::V128))?;
2867 self.pop_operand(Some(ValType::V128))?;
2868 for i in lanes {
2869 self.check_simd_lane_index(i, 32)?;
2870 }
2871 self.push_operand(ValType::V128)?;
2872 Ok(())
2873 }
2874 fn visit_v128_load8_splat(&mut self, memarg: MemArg) -> Self::Output {
2875 let ty = self.check_memarg(memarg)?;
2876 self.pop_operand(Some(ty))?;
2877 self.push_operand(ValType::V128)?;
2878 Ok(())
2879 }
2880 fn visit_v128_load16_splat(&mut self, memarg: MemArg) -> Self::Output {
2881 let ty = self.check_memarg(memarg)?;
2882 self.pop_operand(Some(ty))?;
2883 self.push_operand(ValType::V128)?;
2884 Ok(())
2885 }
2886 fn visit_v128_load32_splat(&mut self, memarg: MemArg) -> Self::Output {
2887 let ty = self.check_memarg(memarg)?;
2888 self.pop_operand(Some(ty))?;
2889 self.push_operand(ValType::V128)?;
2890 Ok(())
2891 }
2892 fn visit_v128_load32_zero(&mut self, memarg: MemArg) -> Self::Output {
2893 self.visit_v128_load32_splat(memarg)
2894 }
2895 fn visit_v128_load64_splat(&mut self, memarg: MemArg) -> Self::Output {
2896 self.check_v128_load_op(memarg)
2897 }
2898 fn visit_v128_load64_zero(&mut self, memarg: MemArg) -> Self::Output {
2899 self.check_v128_load_op(memarg)
2900 }
2901 fn visit_v128_load8x8_s(&mut self, memarg: MemArg) -> Self::Output {
2902 self.check_v128_load_op(memarg)
2903 }
2904 fn visit_v128_load8x8_u(&mut self, memarg: MemArg) -> Self::Output {
2905 self.check_v128_load_op(memarg)
2906 }
2907 fn visit_v128_load16x4_s(&mut self, memarg: MemArg) -> Self::Output {
2908 self.check_v128_load_op(memarg)
2909 }
2910 fn visit_v128_load16x4_u(&mut self, memarg: MemArg) -> Self::Output {
2911 self.check_v128_load_op(memarg)
2912 }
2913 fn visit_v128_load32x2_s(&mut self, memarg: MemArg) -> Self::Output {
2914 self.check_v128_load_op(memarg)
2915 }
2916 fn visit_v128_load32x2_u(&mut self, memarg: MemArg) -> Self::Output {
2917 self.check_v128_load_op(memarg)
2918 }
2919 fn visit_v128_load8_lane(&mut self, memarg: MemArg, lane: u8) -> Self::Output {
2920 let idx = self.check_memarg(memarg)?;
2921 self.check_simd_lane_index(lane, 16)?;
2922 self.pop_operand(Some(ValType::V128))?;
2923 self.pop_operand(Some(idx))?;
2924 self.push_operand(ValType::V128)?;
2925 Ok(())
2926 }
2927 fn visit_v128_load16_lane(&mut self, memarg: MemArg, lane: u8) -> Self::Output {
2928 let idx = self.check_memarg(memarg)?;
2929 self.check_simd_lane_index(lane, 8)?;
2930 self.pop_operand(Some(ValType::V128))?;
2931 self.pop_operand(Some(idx))?;
2932 self.push_operand(ValType::V128)?;
2933 Ok(())
2934 }
2935 fn visit_v128_load32_lane(&mut self, memarg: MemArg, lane: u8) -> Self::Output {
2936 let idx = self.check_memarg(memarg)?;
2937 self.check_simd_lane_index(lane, 4)?;
2938 self.pop_operand(Some(ValType::V128))?;
2939 self.pop_operand(Some(idx))?;
2940 self.push_operand(ValType::V128)?;
2941 Ok(())
2942 }
2943 fn visit_v128_load64_lane(&mut self, memarg: MemArg, lane: u8) -> Self::Output {
2944 let idx = self.check_memarg(memarg)?;
2945 self.check_simd_lane_index(lane, 2)?;
2946 self.pop_operand(Some(ValType::V128))?;
2947 self.pop_operand(Some(idx))?;
2948 self.push_operand(ValType::V128)?;
2949 Ok(())
2950 }
2951 fn visit_v128_store8_lane(&mut self, memarg: MemArg, lane: u8) -> Self::Output {
2952 let idx = self.check_memarg(memarg)?;
2953 self.check_simd_lane_index(lane, 16)?;
2954 self.pop_operand(Some(ValType::V128))?;
2955 self.pop_operand(Some(idx))?;
2956 Ok(())
2957 }
2958 fn visit_v128_store16_lane(&mut self, memarg: MemArg, lane: u8) -> Self::Output {
2959 let idx = self.check_memarg(memarg)?;
2960 self.check_simd_lane_index(lane, 8)?;
2961 self.pop_operand(Some(ValType::V128))?;
2962 self.pop_operand(Some(idx))?;
2963 Ok(())
2964 }
2965 fn visit_v128_store32_lane(&mut self, memarg: MemArg, lane: u8) -> Self::Output {
2966 let idx = self.check_memarg(memarg)?;
2967 self.check_simd_lane_index(lane, 4)?;
2968 self.pop_operand(Some(ValType::V128))?;
2969 self.pop_operand(Some(idx))?;
2970 Ok(())
2971 }
2972 fn visit_v128_store64_lane(&mut self, memarg: MemArg, lane: u8) -> Self::Output {
2973 let idx = self.check_memarg(memarg)?;
2974 self.check_simd_lane_index(lane, 2)?;
2975 self.pop_operand(Some(ValType::V128))?;
2976 self.pop_operand(Some(idx))?;
2977 Ok(())
2978 }
2979 fn visit_memory_init(&mut self, segment: u32, mem: u32) -> Self::Output {
2980 let ty = self.check_memory_index(mem)?;
2981 match self.resources.data_count() {
2982 None => bail!(self.offset, "data count section required"),
2983 Some(count) if segment < count => {}
2984 Some(_) => bail!(self.offset, "unknown data segment {}", segment),
2985 }
2986 self.pop_operand(Some(ValType::I32))?;
2987 self.pop_operand(Some(ValType::I32))?;
2988 self.pop_operand(Some(ty))?;
2989 Ok(())
2990 }
2991 fn visit_data_drop(&mut self, segment: u32) -> Self::Output {
2992 match self.resources.data_count() {
2993 None => bail!(self.offset, "data count section required"),
2994 Some(count) if segment < count => {}
2995 Some(_) => bail!(self.offset, "unknown data segment {}", segment),
2996 }
2997 Ok(())
2998 }
2999 fn visit_memory_copy(&mut self, dst: u32, src: u32) -> Self::Output {
3000 let dst_ty = self.check_memory_index(dst)?;
3001 let src_ty = self.check_memory_index(src)?;
3002
3003 self.pop_operand(Some(match src_ty {
3006 ValType::I32 => ValType::I32,
3007 _ => dst_ty,
3008 }))?;
3009
3010 self.pop_operand(Some(src_ty))?;
3013 self.pop_operand(Some(dst_ty))?;
3014 Ok(())
3015 }
3016 fn visit_memory_fill(&mut self, mem: u32) -> Self::Output {
3017 let ty = self.check_memory_index(mem)?;
3018 self.pop_operand(Some(ty))?;
3019 self.pop_operand(Some(ValType::I32))?;
3020 self.pop_operand(Some(ty))?;
3021 Ok(())
3022 }
3023 fn visit_memory_discard(&mut self, mem: u32) -> Self::Output {
3024 let ty = self.check_memory_index(mem)?;
3025 self.pop_operand(Some(ty))?;
3026 self.pop_operand(Some(ty))?;
3027 Ok(())
3028 }
3029 fn visit_table_init(&mut self, segment: u32, table: u32) -> Self::Output {
3030 if table > 0 {}
3031 let table = match self.resources.table_at(table) {
3032 Some(table) => table,
3033 None => bail!(
3034 self.offset,
3035 "unknown table {}: table index out of bounds",
3036 table
3037 ),
3038 };
3039 let segment_ty = match self.resources.element_type_at(segment) {
3040 Some(ty) => ty,
3041 None => bail!(
3042 self.offset,
3043 "unknown elem segment {}: segment index out of bounds",
3044 segment
3045 ),
3046 };
3047 if segment_ty != table.element_type {
3048 bail!(self.offset, "type mismatch");
3049 }
3050 self.pop_operand(Some(ValType::I32))?;
3051 self.pop_operand(Some(ValType::I32))?;
3052 self.pop_operand(Some(ValType::I32))?;
3053 Ok(())
3054 }
3055 fn visit_elem_drop(&mut self, segment: u32) -> Self::Output {
3056 if segment >= self.resources.element_count() {
3057 bail!(
3058 self.offset,
3059 "unknown elem segment {}: segment index out of bounds",
3060 segment
3061 );
3062 }
3063 Ok(())
3064 }
3065 fn visit_table_copy(&mut self, dst_table: u32, src_table: u32) -> Self::Output {
3066 if src_table > 0 || dst_table > 0 {}
3067 let (src, dst) = match (
3068 self.resources.table_at(src_table),
3069 self.resources.table_at(dst_table),
3070 ) {
3071 (Some(a), Some(b)) => (a, b),
3072 _ => bail!(self.offset, "table index out of bounds"),
3073 };
3074 if src.element_type != dst.element_type {
3075 bail!(self.offset, "type mismatch");
3076 }
3077 self.pop_operand(Some(ValType::I32))?;
3078 self.pop_operand(Some(ValType::I32))?;
3079 self.pop_operand(Some(ValType::I32))?;
3080 Ok(())
3081 }
3082 fn visit_table_get(&mut self, table: u32) -> Self::Output {
3083 let ty = match self.resources.table_at(table) {
3084 Some(ty) => ty.element_type,
3085 None => bail!(self.offset, "table index out of bounds"),
3086 };
3087 self.pop_operand(Some(ValType::I32))?;
3088 self.push_operand(ty)?;
3089 Ok(())
3090 }
3091 fn visit_table_set(&mut self, table: u32) -> Self::Output {
3092 let ty = match self.resources.table_at(table) {
3093 Some(ty) => ty.element_type,
3094 None => bail!(self.offset, "table index out of bounds"),
3095 };
3096 self.pop_operand(Some(ty))?;
3097 self.pop_operand(Some(ValType::I32))?;
3098 Ok(())
3099 }
3100 fn visit_table_grow(&mut self, table: u32) -> Self::Output {
3101 let ty = match self.resources.table_at(table) {
3102 Some(ty) => ty.element_type,
3103 None => bail!(self.offset, "table index out of bounds"),
3104 };
3105 self.pop_operand(Some(ValType::I32))?;
3106 self.pop_operand(Some(ty))?;
3107 self.push_operand(ValType::I32)?;
3108 Ok(())
3109 }
3110 fn visit_table_size(&mut self, table: u32) -> Self::Output {
3111 if self.resources.table_at(table).is_none() {
3112 bail!(self.offset, "table index out of bounds");
3113 }
3114 self.push_operand(ValType::I32)?;
3115 Ok(())
3116 }
3117 fn visit_table_fill(&mut self, table: u32) -> Self::Output {
3118 let ty = match self.resources.table_at(table) {
3119 Some(ty) => ty.element_type,
3120 None => bail!(self.offset, "table index out of bounds"),
3121 };
3122 self.pop_operand(Some(ValType::I32))?;
3123 self.pop_operand(Some(ty))?;
3124 self.pop_operand(Some(ValType::I32))?;
3125 Ok(())
3126 }
3127}
3128
3129#[derive(Clone)]
3130enum Either<A, B> {
3131 A(A),
3132 B(B),
3133}
3134
3135impl<A, B> Iterator for Either<A, B>
3136where
3137 A: Iterator,
3138 B: Iterator<Item = A::Item>,
3139{
3140 type Item = A::Item;
3141 fn next(&mut self) -> Option<A::Item> {
3142 match self {
3143 Either::A(a) => a.next(),
3144 Either::B(b) => b.next(),
3145 }
3146 }
3147}
3148
3149impl<A, B> DoubleEndedIterator for Either<A, B>
3150where
3151 A: DoubleEndedIterator,
3152 B: DoubleEndedIterator<Item = A::Item>,
3153{
3154 fn next_back(&mut self) -> Option<A::Item> {
3155 match self {
3156 Either::A(a) => a.next_back(),
3157 Either::B(b) => b.next_back(),
3158 }
3159 }
3160}
3161
3162impl<A, B> ExactSizeIterator for Either<A, B>
3163where
3164 A: ExactSizeIterator,
3165 B: ExactSizeIterator<Item = A::Item>,
3166{
3167 fn len(&self) -> usize {
3168 match self {
3169 Either::A(a) => a.len(),
3170 Either::B(b) => b.len(),
3171 }
3172 }
3173}
3174
3175trait PreciseIterator: ExactSizeIterator + DoubleEndedIterator + Clone {}
3176impl<T: ExactSizeIterator + DoubleEndedIterator + Clone> PreciseIterator for T {}
3177
3178impl Locals {
3179 fn define(&mut self, count: u32, ty: ValType) -> bool {
3185 match self.num_locals.checked_add(count) {
3186 Some(n) => self.num_locals = n,
3187 None => return false,
3188 }
3189 if self.num_locals > (MAX_WASM_FUNCTION_LOCALS as u32) {
3190 return false;
3191 }
3192 for _ in 0..count {
3193 if self.first.len() >= MAX_LOCALS_TO_TRACK {
3194 break;
3195 }
3196 self.first.push(ty);
3197 }
3198 self.all.push((self.num_locals - 1, ty));
3199 true
3200 }
3201
3202 pub(super) fn len_locals(&self) -> u32 {
3204 self.num_locals
3205 }
3206
3207 #[inline]
3209 pub(super) fn get(&self, idx: u32) -> Option<ValType> {
3210 match self.first.get(idx as usize) {
3211 Some(ty) => Some(*ty),
3212 None => self.get_bsearch(idx),
3213 }
3214 }
3215
3216 fn get_bsearch(&self, idx: u32) -> Option<ValType> {
3217 match self.all.binary_search_by_key(&idx, |(idx, _)| *idx) {
3218 Err(i) if i == self.all.len() => None,
3221
3222 Ok(i) | Err(i) => Some(self.all[i].1),
3228 }
3229 }
3230}