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