1use core::iter;
2
3use alloc::collections::btree_set::BTreeSet;
4use alloc::vec::Vec;
5
6use crate::core::error::DecodingError;
7use crate::core::indices::{
8 read_label_idx, DataIdx, ElemIdx, ExtendedIdxVec, FuncIdx, GlobalIdx, IdxVec, LocalIdx, MemIdx,
9 TableIdx, TypeIdx,
10};
11use crate::core::reader::section_header::{SectionHeader, SectionTy};
12use crate::core::reader::span::Span;
13use crate::core::reader::types::element::ElemType;
14use crate::core::reader::types::global::Global;
15use crate::core::reader::types::memarg::MemArg;
16use crate::core::reader::types::{BlockType, FuncType, MemType, NumType, TableType, ValType};
17use crate::core::reader::WasmReader;
18use crate::core::sidetable::{Sidetable, SidetableEntry};
19use crate::core::utils::ToUsizeExt;
20use crate::validation_stack::{LabelInfo, ValidationStack};
21use crate::{RefType, ValidationError};
22
23#[allow(clippy::too_many_arguments)]
35pub unsafe fn validate_code_section(
36 wasm: &mut WasmReader,
37 section_header: SectionHeader,
38 fn_types: &IdxVec<TypeIdx, FuncType>,
39 c_funcs: &ExtendedIdxVec<FuncIdx, TypeIdx>,
40 c_globals: &IdxVec<GlobalIdx, Global>,
41 c_mems: &IdxVec<MemIdx, MemType>,
42 data_count: Option<u32>,
43 c_tables: &IdxVec<TableIdx, TableType>,
44 c_elems: &IdxVec<ElemIdx, ElemType>,
45 validation_context_refs: &BTreeSet<FuncIdx>,
46 sidetable: &mut Sidetable,
47) -> Result<Vec<(Span, usize)>, ValidationError> {
48 assert_eq!(section_header.ty, SectionTy::Code);
49 let code_block_spans_stps = wasm.read_vec_enumerated(|wasm, idx| {
50 let ty_idx = c_funcs
54 .iter_local_definitions()
55 .nth(idx.into_usize())
56 .ok_or(ValidationError::FunctionAndCodeSectionsHaveDifferentLengths)?;
57
58 let func_ty: FuncType = unsafe { fn_types.get(*ty_idx).clone() };
61
62 let func_size = wasm.read_var_u32()?;
63 let func_block = wasm.make_span(func_size.into_usize())?;
64 let previous_pc = wasm.pc;
65
66 let locals = {
67 let params = func_ty.params.valtypes.iter().cloned();
68 let declared_locals = read_declared_locals(wasm)?;
69 params.chain(declared_locals).collect::<Vec<ValType>>()
70 };
71
72 let mut stack = ValidationStack::new_for_func(func_ty);
73 let stp = sidetable.len();
74
75 unsafe {
78 read_instructions(
79 wasm,
80 &mut stack,
81 sidetable,
82 &locals,
83 c_globals,
84 fn_types,
85 c_funcs.inner(),
86 c_mems,
87 data_count,
88 c_tables,
89 c_elems,
90 validation_context_refs,
91 )
92 }?;
93
94 if previous_pc + func_size.into_usize() != wasm.pc {
96 return Err(ValidationError::CodeExprHasTrailingInstructions);
97 }
98
99 Ok((func_block, stp))
100 })?;
101
102 trace!(
103 "Read code section. Found {} code blocks",
104 code_block_spans_stps.len()
105 );
106
107 Ok(code_block_spans_stps)
108}
109
110pub fn read_declared_locals(wasm: &mut WasmReader) -> Result<Vec<ValType>, DecodingError> {
111 let locals = wasm.read_vec(|wasm| {
112 let n = wasm.read_var_u32()?.into_usize();
113 let valtype = ValType::read(wasm)?;
114
115 Ok((n, valtype))
116 })?;
117
118 let mut total_no_of_locals: u64 = 0;
123 for local in &locals {
124 let temp = local.0 as u64;
125 if temp > u32::MAX.into() {
126 return Err(DecodingError::TooManyLocals(total_no_of_locals));
127 };
128 total_no_of_locals = match total_no_of_locals.checked_add(temp) {
129 None => return Err(DecodingError::TooManyLocals(total_no_of_locals)),
130 Some(n) => n,
131 }
132 }
133
134 if total_no_of_locals > u32::MAX.into() {
135 return Err(DecodingError::TooManyLocals(total_no_of_locals));
136 }
137
138 let locals = locals
140 .into_iter()
141 .flat_map(|entry| iter::repeat_n(entry.1, entry.0))
142 .collect::<Vec<ValType>>();
143
144 Ok(locals)
145}
146
147fn validate_branch_and_generate_sidetable_entry(
150 _wasm: &WasmReader,
151 label_idx: u32,
152 stack: &mut ValidationStack,
153 sidetable: &mut Sidetable,
154 unify_to_expected_types: bool,
155) -> Result<(), ValidationError> {
156 stack.assert_val_types_of_label_jump_types_on_top(label_idx, unify_to_expected_types)?;
157
158 let stack_len = stack.len();
160
161 let index_of_label_in_ctrl_stack = stack
162 .ctrl_stack
163 .len()
164 .checked_sub(label_idx.into_usize())
165 .and_then(|i| i.checked_sub(1));
166
167 let targeted_ctrl_block_entry = index_of_label_in_ctrl_stack
168 .and_then(|idx| stack.ctrl_stack.get_mut(idx))
169 .ok_or(ValidationError::InvalidLabelIdx(label_idx))?;
170
171 let valcnt = targeted_ctrl_block_entry.label_types().len();
172 let popcnt = stack_len - targeted_ctrl_block_entry.height - valcnt;
173
174 let stp_here = sidetable.len();
184 sidetable.push(SidetableEntry {
185 pc: usize::MAX,
186 stp: usize::MAX,
187 popcnt,
188 valcnt,
189 });
190
191 match &mut targeted_ctrl_block_entry.label_info {
192 LabelInfo::Block { stps_to_backpatch } => stps_to_backpatch.push(stp_here),
193 LabelInfo::Loop { ip, stp } => {
194 sidetable[stp_here].pc = *ip;
196 sidetable[stp_here].stp = *stp;
197 }
198 LabelInfo::If {
199 stps_to_backpatch, ..
200 } => stps_to_backpatch.push(stp_here),
201 LabelInfo::Func { stps_to_backpatch } => stps_to_backpatch.push(stp_here),
202 LabelInfo::Untyped => {
203 unreachable!("this label is for untyped wasm sequences")
204 }
205 }
206 Ok(())
207}
208
209#[allow(clippy::too_many_arguments)]
221unsafe fn read_instructions(
222 wasm: &mut WasmReader,
223 stack: &mut ValidationStack,
224 sidetable: &mut Sidetable,
225 locals: &[ValType],
226 c_globals: &IdxVec<GlobalIdx, Global>,
227 fn_types: &IdxVec<TypeIdx, FuncType>,
228 c_funcs: &IdxVec<FuncIdx, TypeIdx>,
229 c_mems: &IdxVec<MemIdx, MemType>,
230 data_count: Option<u32>,
231 c_tables: &IdxVec<TableIdx, TableType>,
232 c_elems: &IdxVec<ElemIdx, ElemType>,
233 validation_context_refs: &BTreeSet<FuncIdx>,
234) -> Result<(), ValidationError> {
235 loop {
236 let Ok(first_instr_byte) = wasm.read_u8() else {
237 return Err(ValidationError::ExprMissingEnd);
239 };
240
241 #[cfg(feature = "log")]
242 crate::core::utils::print_beautiful_instruction_name_1_byte(first_instr_byte, wasm.pc);
243
244 use crate::core::reader::types::opcode::*;
245 match first_instr_byte {
246 NOP => {}
248 BLOCK => {
250 let block_ty = {
251 let block_ty = BlockType::read_and_validate(wasm, fn_types)?;
252 unsafe { block_ty.as_func_type(fn_types) }?
255 };
256 let label_info = LabelInfo::Block {
257 stps_to_backpatch: Vec::new(),
258 };
259 stack.assert_push_ctrl(label_info, block_ty, true)?;
263 }
264 LOOP => {
265 let block_ty = {
266 let block_ty = BlockType::read_and_validate(wasm, fn_types)?;
267 unsafe { block_ty.as_func_type(fn_types) }?
270 };
271 let label_info = LabelInfo::Loop {
272 ip: wasm.pc,
273 stp: sidetable.len(),
274 };
275 stack.assert_push_ctrl(label_info, block_ty, true)?;
279 }
280 IF => {
281 let block_ty = {
282 let block_ty = BlockType::read_and_validate(wasm, fn_types)?;
283 unsafe { block_ty.as_func_type(fn_types) }?
286 };
287
288 stack.assert_pop_val_type(ValType::NumType(NumType::I32))?;
289
290 let stp_here = sidetable.len();
291 sidetable.push(SidetableEntry {
292 pc: usize::MAX,
293 stp: usize::MAX,
294 popcnt: 0,
295 valcnt: block_ty.params.valtypes.len(),
296 });
297
298 let label_info = LabelInfo::If {
299 stp: stp_here,
300 stps_to_backpatch: Vec::new(),
301 };
302 stack.assert_push_ctrl(label_info, block_ty, true)?;
306 }
307 ELSE => {
308 let (mut label_info, block_ty) = stack.assert_pop_ctrl(true)?;
309 if let LabelInfo::If {
310 stp,
311 stps_to_backpatch,
312 } = &mut label_info
313 {
314 if *stp == usize::MAX {
315 return Err(ValidationError::ElseWithoutMatchingIf);
317 }
318 let stp_here = sidetable.len();
319 sidetable.push(SidetableEntry {
320 pc: usize::MAX,
321 stp: usize::MAX,
322 popcnt: 0,
323 valcnt: block_ty.returns.valtypes.len(),
324 });
325 stps_to_backpatch.push(stp_here);
326
327 sidetable[*stp].pc = wasm.pc;
328 sidetable[*stp].stp = sidetable.len();
329
330 *stp = usize::MAX; for valtype in block_ty.returns.valtypes.iter().rev() {
333 stack.assert_pop_val_type(*valtype)?;
334 }
335
336 for valtype in block_ty.params.valtypes.iter() {
337 stack.push_valtype(*valtype);
338 }
339 stack.assert_push_ctrl(label_info, block_ty, true)?;
343 } else {
344 return Err(ValidationError::ElseWithoutMatchingIf);
345 }
346 }
347 BR => {
348 let label_idx = read_label_idx(wasm)?;
349 validate_branch_and_generate_sidetable_entry(
350 wasm, label_idx, stack, sidetable, false,
351 )?;
352 stack.make_unspecified()?;
353 }
354 BR_IF => {
355 let label_idx = read_label_idx(wasm)?;
356 stack.assert_pop_val_type(ValType::NumType(NumType::I32))?;
357 validate_branch_and_generate_sidetable_entry(
361 wasm, label_idx, stack, sidetable, true,
362 )?;
363 }
364 BR_TABLE => {
365 let label_vec = wasm.read_vec(read_label_idx)?;
366 let max_label_idx = read_label_idx(wasm)?;
367 stack.assert_pop_val_type(ValType::NumType(NumType::I32))?;
368 for label_idx in &label_vec {
369 validate_branch_and_generate_sidetable_entry(
370 wasm, *label_idx, stack, sidetable, false,
371 )?;
372 }
373
374 validate_branch_and_generate_sidetable_entry(
375 wasm,
376 max_label_idx,
377 stack,
378 sidetable,
379 false,
380 )?;
381
382 let max_label_idx = max_label_idx.into_usize();
389
390 let max_label_arity = stack
391 .ctrl_stack
392 .get(stack.ctrl_stack.len() - max_label_idx - 1)
393 .unwrap()
394 .label_types()
395 .len();
396 for label_idx in &label_vec {
397 let label_idx_as_usize = label_idx.into_usize();
398 let label_arity = stack
399 .ctrl_stack
400 .get(stack.ctrl_stack.len() - label_idx_as_usize - 1)
401 .unwrap()
402 .label_types()
403 .len();
404 if max_label_arity != label_arity {
405 return Err(ValidationError::InvalidLabelIdx(*label_idx));
406 }
407 }
408
409 stack.make_unspecified()?;
410 }
411 END => {
412 let (label_info, block_ty) = stack.assert_pop_ctrl(true)?;
416 let stp_here = sidetable.len();
417
418 match label_info {
419 LabelInfo::Block { stps_to_backpatch } => {
420 stps_to_backpatch.iter().for_each(|i| {
421 sidetable[*i].pc = wasm.pc;
422 sidetable[*i].stp = stp_here;
423 });
424 }
425 LabelInfo::If {
426 stp,
427 stps_to_backpatch,
428 } => {
429 if stp != usize::MAX {
430 if !(block_ty.params == block_ty.returns) {
435 return Err(ValidationError::IfWithoutMatchingElse);
436 }
437
438 sidetable[stp].pc = wasm.pc;
441 sidetable[stp].stp = stp_here;
442 }
443 stps_to_backpatch.iter().for_each(|i| {
444 sidetable[*i].pc = wasm.pc;
445 sidetable[*i].stp = stp_here;
446 });
447 }
448 LabelInfo::Loop { .. } => (),
449 LabelInfo::Func { stps_to_backpatch } => {
450 stps_to_backpatch.iter().for_each(|i| {
453 sidetable[*i].pc = wasm.pc - 1; sidetable[*i].stp = stp_here;
457 });
458 }
459 LabelInfo::Untyped => unreachable!("this label is for untyped wasm sequences"),
460 }
461
462 if stack.ctrl_stack.is_empty() {
463 return Ok(());
464 }
465 }
466 RETURN => {
467 let label_idx = u32::try_from(stack.ctrl_stack.len() - 1)
474 .expect("that there are never so many nested control blocks that the index to the outermost label exceeds u32::MAX");
475 validate_branch_and_generate_sidetable_entry(
476 wasm, label_idx, stack, sidetable, false,
477 )?;
478 stack.make_unspecified()?;
479 }
480 CALL => {
482 let func_idx = FuncIdx::read_and_validate(wasm, c_funcs)?;
483 let type_idx = *unsafe { c_funcs.get(func_idx) };
486 let func_ty = unsafe { fn_types.get(type_idx) };
490
491 for typ in func_ty.params.valtypes.iter().rev() {
492 stack.assert_pop_val_type(*typ)?;
493 }
494
495 for typ in func_ty.returns.valtypes.iter() {
496 stack.push_valtype(*typ);
497 }
498 }
499 CALL_INDIRECT => {
500 let type_idx = TypeIdx::read_and_validate(wasm, fn_types)?;
501
502 let table_idx = TableIdx::read_and_validate(wasm, c_tables)?;
503
504 let tab = unsafe { c_tables.get(table_idx) };
507
508 if tab.et != RefType::FuncRef {
509 return Err(ValidationError::IndirectCallToNonFuncRefTable(tab.et));
510 }
511
512 let func_ty = unsafe { fn_types.get(type_idx) };
515
516 stack.assert_pop_val_type(ValType::NumType(NumType::I32))?;
517
518 for typ in func_ty.params.valtypes.iter().rev() {
519 stack.assert_pop_val_type(*typ)?;
520 }
521
522 for typ in func_ty.returns.valtypes.iter() {
523 stack.push_valtype(*typ);
524 }
525 }
526 UNREACHABLE => {
528 stack.make_unspecified()?;
529 }
530 DROP => {
531 stack.drop_val()?;
532 }
533 SELECT => {
534 stack.validate_polymorphic_select()?;
535 }
536 SELECT_T => {
537 let type_vec = wasm.read_vec(ValType::read)?;
538 if type_vec.len() != 1 {
539 return Err(ValidationError::InvalidSelectTypeVectorLength(
540 type_vec.len(),
541 ));
542 }
543 stack.assert_pop_val_type(ValType::NumType(NumType::I32))?;
544 stack.assert_pop_val_type(type_vec[0])?;
545 stack.assert_pop_val_type(type_vec[0])?;
546 stack.push_valtype(type_vec[0]);
547 }
548 LOCAL_GET => {
550 let local_idx = LocalIdx::read_and_validate(wasm, locals)?;
551 let local_ty = locals
552 .get(local_idx.into_inner().into_usize())
553 .expect("the local index to be valid as this was just checked");
554 stack.push_valtype(*local_ty);
555 }
556 LOCAL_SET => {
558 let local_idx = LocalIdx::read_and_validate(wasm, locals)?;
559 let local_ty = locals
560 .get(local_idx.into_inner().into_usize())
561 .expect("the local index to be valid as this was just checked");
562 stack.assert_pop_val_type(*local_ty)?;
563 }
564 LOCAL_TEE => {
566 let local_idx = LocalIdx::read_and_validate(wasm, locals)?;
567 let local_ty = locals
568 .get(local_idx.into_inner().into_usize())
569 .expect("the local index to be valid as this was just checked");
570 stack.assert_val_types_on_top(&[*local_ty], true)?;
571 }
572 GLOBAL_GET => {
574 let global_idx = GlobalIdx::read_and_validate(wasm, c_globals)?;
575 let global = unsafe { c_globals.get(global_idx) };
578
579 stack.push_valtype(global.ty.ty);
580 trace!(
581 "Instruction: global.get '{}' [] -> [{:?}]",
582 global_idx,
583 global.ty.ty
585 );
586 }
587 GLOBAL_SET => {
589 let global_idx = GlobalIdx::read_and_validate(wasm, c_globals)?;
590 let global = unsafe { c_globals.get(global_idx) };
593
594 if !global.ty.is_mut {
595 return Err(ValidationError::MutationOfConstGlobal);
596 }
597
598 stack.assert_pop_val_type(global.ty.ty)?;
599 }
600 TABLE_GET => {
601 let table_idx = TableIdx::read_and_validate(wasm, c_tables)?;
602
603 let table = unsafe { c_tables.get(table_idx) };
606 let t = table.et;
607
608 stack.assert_pop_val_type(ValType::NumType(NumType::I32))?;
609 stack.push_valtype(ValType::RefType(t));
610 }
611 TABLE_SET => {
612 let table_idx = TableIdx::read_and_validate(wasm, c_tables)?;
613
614 let table = unsafe { c_tables.get(table_idx) };
617 let t = table.et;
618
619 stack.assert_pop_ref_type(Some(t))?;
620 stack.assert_pop_val_type(ValType::NumType(NumType::I32))?;
621 }
622 I32_LOAD => {
623 let _mem_idx = MemIdx::validate(0, c_mems)?;
624 let memarg = MemArg::read(wasm)?;
625 if memarg.align > 2 {
626 return Err(ValidationError::ErroneousAlignment {
627 alignment: memarg.align,
628 minimum_required_alignment: 2,
629 });
630 }
631 stack.assert_pop_val_type(ValType::NumType(NumType::I32))?;
632 stack.push_valtype(ValType::NumType(NumType::I32));
633 }
634 I64_LOAD => {
635 let _mem_idx = MemIdx::validate(0, c_mems)?;
636 let memarg = MemArg::read(wasm)?;
637 if memarg.align > 3 {
638 return Err(ValidationError::ErroneousAlignment {
639 alignment: memarg.align,
640 minimum_required_alignment: 3,
641 });
642 }
643 stack.assert_pop_val_type(ValType::NumType(NumType::I32))?;
644 stack.push_valtype(ValType::NumType(NumType::I64));
645 }
646 F32_LOAD => {
647 let _mem_idx = MemIdx::validate(0, c_mems)?;
648 let memarg = MemArg::read(wasm)?;
649 if memarg.align > 2 {
650 return Err(ValidationError::ErroneousAlignment {
651 alignment: memarg.align,
652 minimum_required_alignment: 2,
653 });
654 }
655 stack.assert_pop_val_type(ValType::NumType(NumType::I32))?;
656 stack.push_valtype(ValType::NumType(NumType::F32));
657 }
658 F64_LOAD => {
659 let _mem_idx = MemIdx::validate(0, c_mems)?;
660 let memarg = MemArg::read(wasm)?;
661 if memarg.align > 3 {
662 return Err(ValidationError::ErroneousAlignment {
663 alignment: memarg.align,
664 minimum_required_alignment: 3,
665 });
666 }
667 stack.assert_pop_val_type(ValType::NumType(NumType::I32))?;
668 stack.push_valtype(ValType::NumType(NumType::F64));
669 }
670 I32_LOAD8_S => {
671 let _mem_idx = MemIdx::validate(0, c_mems)?;
672 let memarg = MemArg::read(wasm)?;
673 if memarg.align > 0 {
674 return Err(ValidationError::ErroneousAlignment {
675 alignment: memarg.align,
676 minimum_required_alignment: 0,
677 });
678 }
679 stack.assert_pop_val_type(ValType::NumType(NumType::I32))?;
680 stack.push_valtype(ValType::NumType(NumType::I32));
681 }
682 I32_LOAD8_U => {
683 let _mem_idx = MemIdx::validate(0, c_mems)?;
684 let memarg = MemArg::read(wasm)?;
685 if memarg.align > 0 {
686 return Err(ValidationError::ErroneousAlignment {
687 alignment: memarg.align,
688 minimum_required_alignment: 0,
689 });
690 }
691 stack.assert_pop_val_type(ValType::NumType(NumType::I32))?;
692 stack.push_valtype(ValType::NumType(NumType::I32));
693 }
694 I32_LOAD16_S => {
695 let _mem_idx = MemIdx::validate(0, c_mems)?;
696 let memarg = MemArg::read(wasm)?;
697 if memarg.align > 1 {
698 return Err(ValidationError::ErroneousAlignment {
699 alignment: memarg.align,
700 minimum_required_alignment: 1,
701 });
702 }
703 stack.assert_pop_val_type(ValType::NumType(NumType::I32))?;
704 stack.push_valtype(ValType::NumType(NumType::I32));
705 }
706 I32_LOAD16_U => {
707 let _mem_idx = MemIdx::validate(0, c_mems)?;
708 let memarg = MemArg::read(wasm)?;
709 if memarg.align > 1 {
710 return Err(ValidationError::ErroneousAlignment {
711 alignment: memarg.align,
712 minimum_required_alignment: 1,
713 });
714 }
715 stack.assert_pop_val_type(ValType::NumType(NumType::I32))?;
716 stack.push_valtype(ValType::NumType(NumType::I32));
717 }
718 I64_LOAD8_S => {
719 let _mem_idx = MemIdx::validate(0, c_mems)?;
720 let memarg = MemArg::read(wasm)?;
721 if memarg.align > 0 {
722 return Err(ValidationError::ErroneousAlignment {
723 alignment: memarg.align,
724 minimum_required_alignment: 0,
725 });
726 }
727 stack.assert_pop_val_type(ValType::NumType(NumType::I32))?;
728 stack.push_valtype(ValType::NumType(NumType::I64));
729 }
730 I64_LOAD8_U => {
731 let _mem_idx = MemIdx::validate(0, c_mems)?;
732 let memarg = MemArg::read(wasm)?;
733 if memarg.align > 0 {
734 return Err(ValidationError::ErroneousAlignment {
735 alignment: memarg.align,
736 minimum_required_alignment: 0,
737 });
738 }
739 stack.assert_pop_val_type(ValType::NumType(NumType::I32))?;
740 stack.push_valtype(ValType::NumType(NumType::I64));
741 }
742 I64_LOAD16_S => {
743 let _mem_idx = MemIdx::validate(0, c_mems)?;
744 let memarg = MemArg::read(wasm)?;
745 if memarg.align > 1 {
746 return Err(ValidationError::ErroneousAlignment {
747 alignment: memarg.align,
748 minimum_required_alignment: 1,
749 });
750 }
751 stack.assert_pop_val_type(ValType::NumType(NumType::I32))?;
752 stack.push_valtype(ValType::NumType(NumType::I64));
753 }
754 I64_LOAD16_U => {
755 let _mem_idx = MemIdx::validate(0, c_mems)?;
756 let memarg = MemArg::read(wasm)?;
757 if memarg.align > 1 {
758 return Err(ValidationError::ErroneousAlignment {
759 alignment: memarg.align,
760 minimum_required_alignment: 1,
761 });
762 }
763 stack.assert_pop_val_type(ValType::NumType(NumType::I32))?;
764 stack.push_valtype(ValType::NumType(NumType::I64));
765 }
766 I64_LOAD32_S => {
767 let _mem_idx = MemIdx::validate(0, c_mems)?;
768 let memarg = MemArg::read(wasm)?;
769 if memarg.align > 2 {
770 return Err(ValidationError::ErroneousAlignment {
771 alignment: memarg.align,
772 minimum_required_alignment: 2,
773 });
774 }
775 stack.assert_pop_val_type(ValType::NumType(NumType::I32))?;
776 stack.push_valtype(ValType::NumType(NumType::I64));
777 }
778 I64_LOAD32_U => {
779 let _mem_idx = MemIdx::validate(0, c_mems)?;
780 let memarg = MemArg::read(wasm)?;
781 if memarg.align > 2 {
782 return Err(ValidationError::ErroneousAlignment {
783 alignment: memarg.align,
784 minimum_required_alignment: 2,
785 });
786 }
787 stack.assert_pop_val_type(ValType::NumType(NumType::I32))?;
788 stack.push_valtype(ValType::NumType(NumType::I64));
789 }
790 I32_STORE => {
791 let _mem_idx = MemIdx::validate(0, c_mems)?;
792 let memarg = MemArg::read(wasm)?;
793 if memarg.align > 2 {
794 return Err(ValidationError::ErroneousAlignment {
795 alignment: memarg.align,
796 minimum_required_alignment: 2,
797 });
798 }
799 stack.assert_pop_val_type(ValType::NumType(NumType::I32))?;
800 stack.assert_pop_val_type(ValType::NumType(NumType::I32))?;
801 }
802 I64_STORE => {
803 let _mem_idx = MemIdx::validate(0, c_mems)?;
804 let memarg = MemArg::read(wasm)?;
805 if memarg.align > 3 {
806 return Err(ValidationError::ErroneousAlignment {
807 alignment: memarg.align,
808 minimum_required_alignment: 3,
809 });
810 }
811 stack.assert_pop_val_type(ValType::NumType(NumType::I64))?;
812 stack.assert_pop_val_type(ValType::NumType(NumType::I32))?;
813 }
814 F32_STORE => {
815 let _mem_idx = MemIdx::validate(0, c_mems)?;
816 let memarg = MemArg::read(wasm)?;
817 if memarg.align > 2 {
818 return Err(ValidationError::ErroneousAlignment {
819 alignment: memarg.align,
820 minimum_required_alignment: 2,
821 });
822 }
823 stack.assert_pop_val_type(ValType::NumType(NumType::F32))?;
824 stack.assert_pop_val_type(ValType::NumType(NumType::I32))?;
825 }
826 F64_STORE => {
827 let _mem_idx = MemIdx::validate(0, c_mems)?;
828 let memarg = MemArg::read(wasm)?;
829 if memarg.align > 3 {
830 return Err(ValidationError::ErroneousAlignment {
831 alignment: memarg.align,
832 minimum_required_alignment: 3,
833 });
834 }
835 stack.assert_pop_val_type(ValType::NumType(NumType::F64))?;
836 stack.assert_pop_val_type(ValType::NumType(NumType::I32))?;
837 }
838 I32_STORE8 => {
839 let _mem_idx = MemIdx::validate(0, c_mems)?;
840 let memarg = MemArg::read(wasm)?;
841 if memarg.align > 0 {
842 return Err(ValidationError::ErroneousAlignment {
843 alignment: memarg.align,
844 minimum_required_alignment: 0,
845 });
846 }
847 stack.assert_pop_val_type(ValType::NumType(NumType::I32))?;
848 stack.assert_pop_val_type(ValType::NumType(NumType::I32))?;
849 }
850 I32_STORE16 => {
851 let _mem_idx = MemIdx::validate(0, c_mems)?;
852 let memarg = MemArg::read(wasm)?;
853 if memarg.align > 1 {
854 return Err(ValidationError::ErroneousAlignment {
855 alignment: memarg.align,
856 minimum_required_alignment: 1,
857 });
858 }
859 stack.assert_pop_val_type(ValType::NumType(NumType::I32))?;
860 stack.assert_pop_val_type(ValType::NumType(NumType::I32))?;
861 }
862 I64_STORE8 => {
863 let _mem_idx = MemIdx::validate(0, c_mems)?;
864 let memarg = MemArg::read(wasm)?;
865 if memarg.align > 0 {
866 return Err(ValidationError::ErroneousAlignment {
867 alignment: memarg.align,
868 minimum_required_alignment: 0,
869 });
870 }
871 stack.assert_pop_val_type(ValType::NumType(NumType::I64))?;
872 stack.assert_pop_val_type(ValType::NumType(NumType::I32))?;
873 }
874 I64_STORE16 => {
875 let _mem_idx = MemIdx::validate(0, c_mems)?;
876 let memarg = MemArg::read(wasm)?;
877 if memarg.align > 1 {
878 return Err(ValidationError::ErroneousAlignment {
879 alignment: memarg.align,
880 minimum_required_alignment: 1,
881 });
882 }
883 stack.assert_pop_val_type(ValType::NumType(NumType::I64))?;
884 stack.assert_pop_val_type(ValType::NumType(NumType::I32))?;
885 }
886 I64_STORE32 => {
887 let _mem_idx = MemIdx::validate(0, c_mems)?;
888 let memarg = MemArg::read(wasm)?;
889 if memarg.align > 2 {
890 return Err(ValidationError::ErroneousAlignment {
891 alignment: memarg.align,
892 minimum_required_alignment: 2,
893 });
894 }
895 stack.assert_pop_val_type(ValType::NumType(NumType::I64))?;
896 stack.assert_pop_val_type(ValType::NumType(NumType::I32))?;
897 }
898 MEMORY_SIZE => {
899 let zero = wasm.read_u8()?;
902 if zero != 0 {
903 return Err(ValidationError::UnsupportedMultipleMemoriesProposal);
904 }
905 let _mem_idx = MemIdx::validate(0, c_mems)?;
906
907 stack.push_valtype(ValType::NumType(NumType::I32));
908 }
909 MEMORY_GROW => {
910 let zero = wasm.read_u8()?;
913 if zero != 0 {
914 return Err(ValidationError::UnsupportedMultipleMemoriesProposal);
915 }
916 let _mem_idx = MemIdx::validate(0, c_mems)?;
917
918 stack.assert_pop_val_type(ValType::NumType(NumType::I32))?;
919 stack.push_valtype(ValType::NumType(NumType::I32));
920 }
921 I32_CONST => {
923 let _num = wasm.read_var_i32()?;
924 stack.push_valtype(ValType::NumType(NumType::I32));
925 }
926 I64_CONST => {
927 let _num = wasm.read_var_i64()?;
928 stack.push_valtype(ValType::NumType(NumType::I64));
929 }
930 F32_CONST => {
931 let _num = wasm.read_f32()?;
932 stack.push_valtype(ValType::NumType(NumType::F32));
933 }
934 F64_CONST => {
935 let _num = wasm.read_f64()?;
936 stack.push_valtype(ValType::NumType(NumType::F64));
937 }
938 I32_EQZ => {
939 stack.assert_pop_val_type(ValType::NumType(NumType::I32))?;
940
941 stack.push_valtype(ValType::NumType(NumType::I32));
942 }
943 I32_EQ | I32_NE | I32_LT_S | I32_LT_U | I32_GT_S | I32_GT_U | I32_LE_S | I32_LE_U
944 | I32_GE_S | I32_GE_U => {
945 stack.assert_pop_val_type(ValType::NumType(NumType::I32))?;
946 stack.assert_pop_val_type(ValType::NumType(NumType::I32))?;
947
948 stack.push_valtype(ValType::NumType(NumType::I32));
949 }
950 I64_EQZ => {
951 stack.assert_pop_val_type(ValType::NumType(NumType::I64))?;
952
953 stack.push_valtype(ValType::NumType(NumType::I32));
954 }
955 I64_EQ | I64_NE | I64_LT_S | I64_LT_U | I64_GT_S | I64_GT_U | I64_LE_S | I64_LE_U
956 | I64_GE_S | I64_GE_U => {
957 stack.assert_pop_val_type(ValType::NumType(NumType::I64))?;
958 stack.assert_pop_val_type(ValType::NumType(NumType::I64))?;
959
960 stack.push_valtype(ValType::NumType(NumType::I32));
961 }
962 F32_EQ | F32_NE | F32_LT | F32_GT | F32_LE | F32_GE => {
963 stack.assert_pop_val_type(ValType::NumType(NumType::F32))?;
964 stack.assert_pop_val_type(ValType::NumType(NumType::F32))?;
965
966 stack.push_valtype(ValType::NumType(NumType::I32));
967 }
968 F64_EQ | F64_NE | F64_LT | F64_GT | F64_LE | F64_GE => {
969 stack.assert_pop_val_type(ValType::NumType(NumType::F64))?;
970 stack.assert_pop_val_type(ValType::NumType(NumType::F64))?;
971
972 stack.push_valtype(ValType::NumType(NumType::I32));
973 }
974 F32_ABS | F32_NEG | F32_CEIL | F32_FLOOR | F32_TRUNC | F32_NEAREST | F32_SQRT => {
975 stack.assert_pop_val_type(ValType::NumType(NumType::F32))?;
976
977 stack.push_valtype(ValType::NumType(NumType::F32));
978 }
979 F32_ADD | F32_SUB | F32_MUL | F32_DIV | F32_MIN | F32_MAX | F32_COPYSIGN => {
980 stack.assert_pop_val_type(ValType::NumType(NumType::F32))?;
981 stack.assert_pop_val_type(ValType::NumType(NumType::F32))?;
982
983 stack.push_valtype(ValType::NumType(NumType::F32));
984 }
985 F64_ABS | F64_NEG | F64_CEIL | F64_FLOOR | F64_TRUNC | F64_NEAREST | F64_SQRT => {
986 stack.assert_pop_val_type(ValType::NumType(NumType::F64))?;
987
988 stack.push_valtype(ValType::NumType(NumType::F64));
989 }
990 F64_ADD | F64_SUB | F64_MUL | F64_DIV | F64_MIN | F64_MAX | F64_COPYSIGN => {
991 stack.assert_pop_val_type(ValType::NumType(NumType::F64))?;
992 stack.assert_pop_val_type(ValType::NumType(NumType::F64))?;
993
994 stack.push_valtype(ValType::NumType(NumType::F64));
995 }
996 I32_ADD | I32_SUB | I32_MUL | I32_DIV_S | I32_DIV_U | I32_REM_S => {
997 stack.assert_pop_val_type(ValType::NumType(NumType::I32))?;
998 stack.assert_pop_val_type(ValType::NumType(NumType::I32))?;
999
1000 stack.push_valtype(ValType::NumType(NumType::I32));
1001 }
1002 I32_CLZ | I32_CTZ | I32_POPCNT => {
1004 stack.assert_pop_val_type(ValType::NumType(NumType::I32))?;
1005
1006 stack.push_valtype(ValType::NumType(NumType::I32));
1007 }
1008 I32_REM_U | I32_AND | I32_OR | I32_XOR | I32_SHL | I32_SHR_S | I32_SHR_U | I32_ROTL
1009 | I32_ROTR => {
1010 stack.assert_pop_val_type(ValType::NumType(NumType::I32))?;
1011 stack.assert_pop_val_type(ValType::NumType(NumType::I32))?;
1012
1013 stack.push_valtype(ValType::NumType(NumType::I32));
1014 }
1015 I64_CLZ | I64_CTZ | I64_POPCNT => {
1016 stack.assert_pop_val_type(ValType::NumType(NumType::I64))?;
1017
1018 stack.push_valtype(ValType::NumType(NumType::I64));
1019 }
1020
1021 I64_ADD | I64_SUB | I64_MUL | I64_DIV_S | I64_DIV_U | I64_REM_S | I64_REM_U
1022 | I64_AND | I64_OR | I64_XOR | I64_SHL | I64_SHR_S | I64_SHR_U | I64_ROTL
1023 | I64_ROTR => {
1024 stack.assert_pop_val_type(ValType::NumType(NumType::I64))?;
1025 stack.assert_pop_val_type(ValType::NumType(NumType::I64))?;
1026
1027 stack.push_valtype(ValType::NumType(NumType::I64));
1028 }
1029
1030 I32_WRAP_I64 => {
1031 stack.assert_pop_val_type(ValType::NumType(NumType::I64))?;
1032
1033 stack.push_valtype(ValType::NumType(NumType::I32));
1034 }
1035
1036 I32_TRUNC_F32_S | I32_TRUNC_F32_U | I32_REINTERPRET_F32 => {
1037 stack.assert_pop_val_type(ValType::NumType(NumType::F32))?;
1038
1039 stack.push_valtype(ValType::NumType(NumType::I32));
1040 }
1041
1042 I32_TRUNC_F64_S | I32_TRUNC_F64_U => {
1043 stack.assert_pop_val_type(ValType::NumType(NumType::F64))?;
1044
1045 stack.push_valtype(ValType::NumType(NumType::I32));
1046 }
1047
1048 I64_EXTEND_I32_S | I64_EXTEND_I32_U => {
1049 stack.assert_pop_val_type(ValType::NumType(NumType::I32))?;
1050
1051 stack.push_valtype(ValType::NumType(NumType::I64));
1052 }
1053
1054 I64_TRUNC_F32_S | I64_TRUNC_F32_U => {
1055 stack.assert_pop_val_type(ValType::NumType(NumType::F32))?;
1056
1057 stack.push_valtype(ValType::NumType(NumType::I64));
1058 }
1059
1060 I64_TRUNC_F64_S | I64_TRUNC_F64_U | I64_REINTERPRET_F64 => {
1061 stack.assert_pop_val_type(ValType::NumType(NumType::F64))?;
1062
1063 stack.push_valtype(ValType::NumType(NumType::I64));
1064 }
1065
1066 F32_CONVERT_I32_S | F32_CONVERT_I32_U | F32_REINTERPRET_I32 => {
1067 stack.assert_pop_val_type(ValType::NumType(NumType::I32))?;
1068
1069 stack.push_valtype(ValType::NumType(NumType::F32));
1070 }
1071
1072 F32_CONVERT_I64_S | F32_CONVERT_I64_U => {
1073 stack.assert_pop_val_type(ValType::NumType(NumType::I64))?;
1074
1075 stack.push_valtype(ValType::NumType(NumType::F32));
1076 }
1077
1078 F32_DEMOTE_F64 => {
1079 stack.assert_pop_val_type(ValType::NumType(NumType::F64))?;
1080
1081 stack.push_valtype(ValType::NumType(NumType::F32));
1082 }
1083
1084 F64_CONVERT_I32_S | F64_CONVERT_I32_U => {
1085 stack.assert_pop_val_type(ValType::NumType(NumType::I32))?;
1086
1087 stack.push_valtype(ValType::NumType(NumType::F64));
1088 }
1089
1090 F64_CONVERT_I64_S | F64_CONVERT_I64_U | F64_REINTERPRET_I64 => {
1091 stack.assert_pop_val_type(ValType::NumType(NumType::I64))?;
1092
1093 stack.push_valtype(ValType::NumType(NumType::F64));
1094 }
1095
1096 F64_PROMOTE_F32 => {
1097 stack.assert_pop_val_type(ValType::NumType(NumType::F32))?;
1098
1099 stack.push_valtype(ValType::NumType(NumType::F64));
1100 }
1101
1102 REF_NULL => {
1103 let reftype = RefType::read(wasm)?;
1104 stack.push_valtype(ValType::RefType(reftype));
1106 }
1107
1108 REF_IS_NULL => {
1109 stack.assert_pop_ref_type(None)?;
1110 stack.push_valtype(ValType::NumType(NumType::I32));
1111 }
1112
1113 REF_FUNC => {
1114 let func_idx = FuncIdx::read_and_validate(wasm, c_funcs)?;
1115
1116 if !validation_context_refs.contains(&func_idx) {
1119 return Err(ValidationError::ReferencingAnUnreferencedFunction(func_idx));
1120 }
1121
1122 stack.push_valtype(ValType::RefType(RefType::FuncRef));
1123 }
1124
1125 FC_EXTENSIONS => {
1126 let Ok(second_instr) = wasm.read_var_u32() else {
1127 return Err(ValidationError::ExprMissingEnd);
1129 };
1130
1131 #[cfg(feature = "log")]
1132 crate::core::utils::print_beautiful_fc_extension(second_instr, wasm.pc);
1133
1134 #[cfg(feature = "log")]
1135 trace!(
1136 "Read instruction byte {second_instr} at wasm_binary[{}]",
1137 wasm.pc
1138 );
1139
1140 use crate::core::reader::types::opcode::fc_extensions::*;
1141 match second_instr {
1142 I32_TRUNC_SAT_F32_S => {
1143 stack.assert_pop_val_type(ValType::NumType(NumType::F32))?;
1144 stack.push_valtype(ValType::NumType(NumType::I32));
1145 }
1146 I32_TRUNC_SAT_F32_U => {
1147 stack.assert_pop_val_type(ValType::NumType(NumType::F32))?;
1148 stack.push_valtype(ValType::NumType(NumType::I32));
1149 }
1150 I32_TRUNC_SAT_F64_S => {
1151 stack.assert_pop_val_type(ValType::NumType(NumType::F64))?;
1152 stack.push_valtype(ValType::NumType(NumType::I32));
1153 }
1154 I32_TRUNC_SAT_F64_U => {
1155 stack.assert_pop_val_type(ValType::NumType(NumType::F64))?;
1156 stack.push_valtype(ValType::NumType(NumType::I32));
1157 }
1158 I64_TRUNC_SAT_F32_S => {
1159 stack.assert_pop_val_type(ValType::NumType(NumType::F32))?;
1160 stack.push_valtype(ValType::NumType(NumType::I64));
1161 }
1162 I64_TRUNC_SAT_F32_U => {
1163 stack.assert_pop_val_type(ValType::NumType(NumType::F32))?;
1164 stack.push_valtype(ValType::NumType(NumType::I64));
1165 }
1166 I64_TRUNC_SAT_F64_S => {
1167 stack.assert_pop_val_type(ValType::NumType(NumType::F64))?;
1168 stack.push_valtype(ValType::NumType(NumType::I64));
1169 }
1170 I64_TRUNC_SAT_F64_U => {
1171 stack.assert_pop_val_type(ValType::NumType(NumType::F64))?;
1172 stack.push_valtype(ValType::NumType(NumType::I64));
1173 }
1174 MEMORY_INIT => {
1175 let data_idx = DataIdx::read_and_validate(
1176 wasm,
1177 data_count.ok_or(ValidationError::MissingDataCountSection)?,
1178 );
1179 let zero = wasm.read_u8()?;
1182 if zero != 0 {
1183 return Err(ValidationError::UnsupportedMultipleMemoriesProposal);
1184 }
1185 if c_mems.len() == 0 {
1186 return Err(ValidationError::InvalidMemIdx(0));
1187 }
1188 let _data_idx = data_idx?;
1190
1191 stack.assert_pop_val_type(ValType::NumType(NumType::I32))?;
1192 stack.assert_pop_val_type(ValType::NumType(NumType::I32))?;
1193 stack.assert_pop_val_type(ValType::NumType(NumType::I32))?;
1194 }
1195 DATA_DROP => {
1196 let _data_idx = DataIdx::read_and_validate(
1197 wasm,
1198 data_count.ok_or(ValidationError::MissingDataCountSection)?,
1199 )?;
1200 }
1201 MEMORY_COPY => {
1202 let zeros = (wasm.read_u8()?, wasm.read_u8()?);
1205 if zeros != (0, 0) {
1206 return Err(ValidationError::UnsupportedMultipleMemoriesProposal);
1207 }
1208 let _mem_idx = MemIdx::validate(0, c_mems)?;
1209
1210 stack.assert_pop_val_type(ValType::NumType(NumType::I32))?;
1211 stack.assert_pop_val_type(ValType::NumType(NumType::I32))?;
1212 stack.assert_pop_val_type(ValType::NumType(NumType::I32))?;
1213 }
1214 MEMORY_FILL => {
1215 let zero = wasm.read_u8()?;
1218 if zero != 0 {
1219 return Err(ValidationError::UnsupportedMultipleMemoriesProposal);
1220 }
1221 let _mem_idx = MemIdx::validate(0, c_mems)?;
1222
1223 stack.assert_pop_val_type(ValType::NumType(NumType::I32))?;
1224 stack.assert_pop_val_type(ValType::NumType(NumType::I32))?;
1225 stack.assert_pop_val_type(ValType::NumType(NumType::I32))?;
1226 }
1227 TABLE_INIT => {
1228 let elem_idx = ElemIdx::read_and_validate(wasm, c_elems);
1232 let table_idx = TableIdx::read_and_validate(wasm, c_tables);
1233 if let Err(invalid_table_idx @ ValidationError::InvalidTableIdx(_)) =
1234 table_idx
1235 {
1236 return Err(invalid_table_idx);
1237 }
1238 let elem_idx = elem_idx?;
1239 let table_idx = table_idx?;
1240
1241 let table1 = unsafe { c_tables.get(table_idx) };
1244 let table_type = table1.et;
1245
1246 let element = unsafe { c_elems.get(elem_idx) };
1249 let element_type = element.to_ref_type();
1250
1251 if table_type != element_type {
1252 return Err(ValidationError::MismatchedRefTypesDuringTableInit {
1253 table_ty: table_type,
1254 elem_ty: element_type,
1255 });
1256 }
1257 stack.assert_pop_val_type(ValType::NumType(NumType::I32))?;
1258 stack.assert_pop_val_type(ValType::NumType(NumType::I32))?;
1259 stack.assert_pop_val_type(ValType::NumType(NumType::I32))?;
1261 }
1262 ELEM_DROP => {
1263 let _elem_idx = ElemIdx::read_and_validate(wasm, c_elems)?;
1264 }
1265 TABLE_COPY => {
1266 let table_x_idx = TableIdx::read_and_validate(wasm, c_tables)?;
1267 let table_y_idx = TableIdx::read_and_validate(wasm, c_tables)?;
1268
1269 let table1 = unsafe { c_tables.get(table_x_idx) };
1272 let table2 = unsafe { c_tables.get(table_y_idx) };
1275
1276 let t1 = table1.et;
1277 let t2 = table2.et;
1278
1279 if t1 != t2 {
1280 return Err(ValidationError::MismatchedRefTypesDuringTableCopy {
1281 source_table_ty: t2,
1282 destination_table_ty: t1,
1283 });
1284 }
1285
1286 stack.assert_pop_val_type(ValType::NumType(NumType::I32))?;
1287 stack.assert_pop_val_type(ValType::NumType(NumType::I32))?;
1288 stack.assert_pop_val_type(ValType::NumType(NumType::I32))?;
1289 }
1290 TABLE_GROW => {
1291 let table_idx = TableIdx::read_and_validate(wasm, c_tables)?;
1292
1293 let table = unsafe { c_tables.get(table_idx) };
1296 let t = table.et;
1297
1298 stack.assert_pop_val_type(ValType::NumType(NumType::I32))?;
1299 stack.assert_pop_ref_type(Some(t))?;
1300
1301 stack.push_valtype(ValType::NumType(NumType::I32));
1302 }
1303 TABLE_SIZE => {
1304 let _table_idx = TableIdx::read_and_validate(wasm, c_tables)?;
1305
1306 stack.push_valtype(ValType::NumType(NumType::I32));
1307 }
1308 TABLE_FILL => {
1309 let table_idx = TableIdx::read_and_validate(wasm, c_tables)?;
1310
1311 let table = unsafe { c_tables.get(table_idx) };
1314 let t = table.et;
1315
1316 stack.assert_pop_val_type(ValType::NumType(NumType::I32))?;
1317 stack.assert_pop_ref_type(Some(t))?;
1318 stack.assert_pop_val_type(ValType::NumType(NumType::I32))?;
1319 }
1320 _ => {
1321 return Err(ValidationError::InvalidMultiByteInstr(
1322 first_instr_byte,
1323 second_instr,
1324 ))
1325 }
1326 }
1327 }
1328
1329 I32_EXTEND8_S => {
1330 stack.assert_pop_val_type(ValType::NumType(NumType::I32))?;
1331
1332 stack.push_valtype(ValType::NumType(NumType::I32));
1333 }
1334 I32_EXTEND16_S => {
1335 stack.assert_pop_val_type(ValType::NumType(NumType::I32))?;
1336
1337 stack.push_valtype(ValType::NumType(NumType::I32));
1338 }
1339 I64_EXTEND8_S => {
1340 stack.assert_pop_val_type(ValType::NumType(NumType::I64))?;
1341
1342 stack.push_valtype(ValType::NumType(NumType::I64));
1343 }
1344 I64_EXTEND16_S => {
1345 stack.assert_pop_val_type(ValType::NumType(NumType::I64))?;
1346
1347 stack.push_valtype(ValType::NumType(NumType::I64));
1348 }
1349 I64_EXTEND32_S => {
1350 stack.assert_pop_val_type(ValType::NumType(NumType::I64))?;
1351
1352 stack.push_valtype(ValType::NumType(NumType::I64));
1353 }
1354
1355 FD_EXTENSIONS => {
1356 let Ok(second_instr) = wasm.read_var_u32() else {
1357 return Err(ValidationError::ExprMissingEnd);
1359 };
1360
1361 #[cfg(feature = "log")]
1362 crate::core::utils::print_beautiful_fd_extension(second_instr, wasm.pc);
1363
1364 use crate::core::reader::types::opcode::fd_extensions::*;
1365
1366 match second_instr {
1367 V128_LOAD => {
1368 let _mem_idx = MemIdx::validate(0, c_mems)?;
1369 let memarg = MemArg::read(wasm)?;
1370 if memarg.align > 4 {
1371 return Err(ValidationError::ErroneousAlignment {
1372 alignment: memarg.align,
1373 minimum_required_alignment: 4,
1374 });
1375 }
1376 stack.assert_pop_val_type(ValType::NumType(NumType::I32))?;
1377 stack.push_valtype(ValType::VecType);
1378 }
1379 V128_STORE => {
1380 let _mem_idx = MemIdx::validate(0, c_mems)?;
1381 let memarg = MemArg::read(wasm)?;
1382 if memarg.align > 4 {
1383 return Err(ValidationError::ErroneousAlignment { alignment: memarg.align, minimum_required_alignment: 4 });
1384 }
1385 stack.assert_pop_val_type(ValType::VecType)?;
1386 stack.assert_pop_val_type(ValType::NumType(NumType::I32))?;
1387 }
1388
1389 V128_LOAD8X8_S | V128_LOAD8X8_U
1391 | V128_LOAD16X4_S | V128_LOAD16X4_U
1392 | V128_LOAD32X2_S | V128_LOAD32X2_U
1393 => {
1394 let _mem_idx = MemIdx::validate(0, c_mems)?;
1395 let memarg = MemArg::read(wasm)?;
1396 if memarg.align > 3 {
1397 return Err(ValidationError::ErroneousAlignment { alignment: memarg.align, minimum_required_alignment: 3 });
1398 }
1399 stack.assert_pop_val_type(ValType::NumType(NumType::I32))?;
1400 stack.push_valtype(ValType::VecType);
1401 },
1402
1403 V128_LOAD8_SPLAT => {
1405 let _mem_idx = MemIdx::validate(0, c_mems)?;
1406 let memarg = MemArg::read(wasm)?;
1407 if memarg.align > 0 {
1408 return Err(ValidationError::ErroneousAlignment { alignment: memarg.align, minimum_required_alignment: 0 });
1409 }
1410 stack.assert_pop_val_type(ValType::NumType(NumType::I32))?;
1411 stack.push_valtype(ValType::VecType);
1412 }
1413 V128_LOAD16_SPLAT => {
1414 let _mem_idx = MemIdx::validate(0, c_mems)?;
1415 let memarg = MemArg::read(wasm)?;
1416 if memarg.align > 1 {
1417 return Err(ValidationError::ErroneousAlignment { alignment: memarg.align, minimum_required_alignment: 1 });
1418 }
1419 stack.assert_pop_val_type(ValType::NumType(NumType::I32))?;
1420 stack.push_valtype(ValType::VecType);
1421 }
1422 V128_LOAD32_SPLAT | V128_LOAD32_ZERO => {
1423 let _mem_idx = MemIdx::validate(0, c_mems)?;
1424 let memarg = MemArg::read(wasm)?;
1425 if memarg.align > 2 {
1426 return Err(ValidationError::ErroneousAlignment { alignment: memarg.align, minimum_required_alignment: 2 });
1427 }
1428 stack.assert_pop_val_type(ValType::NumType(NumType::I32))?;
1429 stack.push_valtype(ValType::VecType);
1430 }
1431 V128_LOAD64_SPLAT | V128_LOAD64_ZERO => {
1432 let _mem_idx = MemIdx::validate(0, c_mems)?;
1433 let memarg = MemArg::read(wasm)?;
1434 if memarg.align > 3 {
1435 return Err(ValidationError::ErroneousAlignment { alignment: memarg.align, minimum_required_alignment: 3 });
1436 }
1437 stack.assert_pop_val_type(ValType::NumType(NumType::I32))?;
1438 stack.push_valtype(ValType::VecType);
1439 }
1440
1441 V128_LOAD8_LANE => {
1443 let memarg = MemArg::read(wasm)?;
1444 let lane_idx = wasm.read_u8()?;
1445 if lane_idx >= 16 {
1446 return Err(ValidationError::InvalidLaneIdx(lane_idx));
1447 }
1448 let _mem_idx = MemIdx::validate(0, c_mems)?;
1449 if memarg.align > 0 {
1450 return Err(ValidationError::ErroneousAlignment { alignment: memarg.align, minimum_required_alignment: 0 });
1451 }
1452 stack.assert_pop_val_type(ValType::VecType)?;
1453 stack.assert_pop_val_type(ValType::NumType(NumType::I32))?;
1454 stack.push_valtype(ValType::VecType);
1455 }
1456 V128_LOAD16_LANE => {
1457 let memarg = MemArg::read(wasm)?;
1458 let lane_idx = wasm.read_u8()?;
1459 if lane_idx >= 8 {
1460 return Err(ValidationError::InvalidLaneIdx(lane_idx));
1461 }
1462 let _mem_idx = MemIdx::validate(0, c_mems)?;
1463 if memarg.align > 1 {
1464 return Err(ValidationError::ErroneousAlignment { alignment: memarg.align, minimum_required_alignment: 1 });
1465 }
1466 stack.assert_pop_val_type(ValType::VecType)?;
1467 stack.assert_pop_val_type(ValType::NumType(NumType::I32))?;
1468 stack.push_valtype(ValType::VecType);
1469 }
1470 V128_LOAD32_LANE => {
1471 let memarg = MemArg::read(wasm)?;
1472 let lane_idx = wasm.read_u8()?;
1473 if lane_idx >= 4 {
1474 return Err(ValidationError::InvalidLaneIdx(lane_idx));
1475 }
1476 let _mem_idx = MemIdx::validate(0, c_mems)?;
1477 if memarg.align > 2 {
1478 return Err(ValidationError::ErroneousAlignment { alignment: memarg.align, minimum_required_alignment: 2 });
1479 }
1480 stack.assert_pop_val_type(ValType::VecType)?;
1481 stack.assert_pop_val_type(ValType::NumType(NumType::I32))?;
1482 stack.push_valtype(ValType::VecType);
1483 }
1484 V128_LOAD64_LANE => {
1485 let memarg = MemArg::read(wasm)?;
1486 let lane_idx = wasm.read_u8()?;
1487 if lane_idx >= 2 {
1488 return Err(ValidationError::InvalidLaneIdx(lane_idx));
1489 }
1490 let _mem_idx = MemIdx::validate(0, c_mems)?;
1491 if memarg.align > 3 {
1492 return Err(ValidationError::ErroneousAlignment { alignment: memarg.align, minimum_required_alignment: 3 });
1493 }
1494 stack.assert_pop_val_type(ValType::VecType)?;
1495 stack.assert_pop_val_type(ValType::NumType(NumType::I32))?;
1496 stack.push_valtype(ValType::VecType);
1497 }
1498
1499 V128_STORE8_LANE => {
1501 let memarg = MemArg::read(wasm)?;
1502 let lane_idx = wasm.read_u8()?;
1503 if lane_idx >= 16 {
1504 return Err(ValidationError::InvalidLaneIdx(lane_idx));
1505 }
1506 let _mem_idx = MemIdx::validate(0, c_mems)?;
1507 if memarg.align > 0 {
1508 return Err(ValidationError::ErroneousAlignment { alignment: memarg.align, minimum_required_alignment: 0 });
1509 }
1510 stack.assert_pop_val_type(ValType::VecType)?;
1511 stack.assert_pop_val_type(ValType::NumType(NumType::I32))?;
1512 }
1513 V128_STORE16_LANE => {
1514 let memarg = MemArg::read(wasm)?;
1515 let lane_idx = wasm.read_u8()?;
1516 if lane_idx >= 8 {
1517 return Err(ValidationError::InvalidLaneIdx(lane_idx));
1518 }
1519 let _mem_idx = MemIdx::validate(0, c_mems)?;
1520 if memarg.align > 1 {
1521 return Err(ValidationError::ErroneousAlignment { alignment: memarg.align, minimum_required_alignment: 1 });
1522 }
1523 stack.assert_pop_val_type(ValType::VecType)?;
1524 stack.assert_pop_val_type(ValType::NumType(NumType::I32))?;
1525 }
1526 V128_STORE32_LANE => {
1527 let memarg = MemArg::read(wasm)?;
1528 let lane_idx = wasm.read_u8()?;
1529 if lane_idx >= 4 {
1530 return Err(ValidationError::InvalidLaneIdx(lane_idx));
1531 }
1532 let _mem_idx = MemIdx::validate(0, c_mems)?;
1533 if memarg.align > 2 {
1534 return Err(ValidationError::ErroneousAlignment { alignment: memarg.align, minimum_required_alignment: 2 });
1535 }
1536 stack.assert_pop_val_type(ValType::VecType)?;
1537 stack.assert_pop_val_type(ValType::NumType(NumType::I32))?;
1538 }
1539 V128_STORE64_LANE => {
1540 let memarg = MemArg::read(wasm)?;
1541 let lane_idx = wasm.read_u8()?;
1542 if lane_idx >= 2 {
1543 return Err(ValidationError::InvalidLaneIdx(lane_idx));
1544 }
1545 let _mem_idx = MemIdx::validate(0, c_mems)?;
1546 if memarg.align > 3 {
1547 return Err(ValidationError::ErroneousAlignment { alignment: memarg.align, minimum_required_alignment: 3 });
1548 }
1549 stack.assert_pop_val_type(ValType::VecType)?;
1550 stack.assert_pop_val_type(ValType::NumType(NumType::I32))?;
1551 }
1552
1553 V128_CONST => {
1554 for _ in 0..16 {
1555 let _data = wasm.read_u8()?;
1556 }
1557 stack.push_valtype(ValType::VecType);
1558 }
1559
1560 V128_NOT => {
1562 stack.assert_pop_val_type(ValType::VecType)?;
1563 stack.push_valtype(ValType::VecType);
1564 }
1565
1566 V128_AND | V128_ANDNOT | V128_OR | V128_XOR => {
1568 stack.assert_pop_val_type(ValType::VecType)?;
1569 stack.assert_pop_val_type(ValType::VecType)?;
1570 stack.push_valtype(ValType::VecType);
1571 }
1572
1573 V128_BITSELECT => {
1575 stack.assert_pop_val_type(ValType::VecType)?;
1576 stack.assert_pop_val_type(ValType::VecType)?;
1577 stack.assert_pop_val_type(ValType::VecType)?;
1578 stack.push_valtype(ValType::VecType);
1579 }
1580
1581 V128_ANY_TRUE => {
1583 stack.assert_pop_val_type(ValType::VecType)?;
1584 stack.push_valtype(ValType::NumType(NumType::I32));
1585 }
1586 I8X16_SWIZZLE => {
1587 stack.assert_pop_val_type(ValType::VecType)?;
1588 stack.assert_pop_val_type(ValType::VecType)?;
1589 stack.push_valtype(ValType::VecType);
1590 }
1591 I8X16_SHUFFLE => {
1592 for _ in 0..16 {
1593 let lane_idx = wasm.read_u8()?;
1594 if lane_idx >= 32 {
1595 return Err(ValidationError::InvalidLaneIdx(lane_idx));
1596 }
1597 }
1598 stack.assert_pop_val_type(ValType::VecType)?;
1599 stack.assert_pop_val_type(ValType::VecType)?;
1600 stack.push_valtype(ValType::VecType);
1601 }
1602
1603 I8X16_SPLAT | I16X8_SPLAT | I32X4_SPLAT => {
1605 stack.assert_pop_val_type(ValType::NumType(NumType::I32))?;
1606 stack.push_valtype(ValType::VecType);
1607 }
1608 I64X2_SPLAT => {
1609 stack.assert_pop_val_type(ValType::NumType(NumType::I64))?;
1610 stack.push_valtype(ValType::VecType);
1611 }
1612 F32X4_SPLAT => {
1613 stack.assert_pop_val_type(ValType::NumType(NumType::F32))?;
1614 stack.push_valtype(ValType::VecType);
1615 }
1616 F64X2_SPLAT => {
1617 stack.assert_pop_val_type(ValType::NumType(NumType::F64))?;
1618 stack.push_valtype(ValType::VecType);
1619 }
1620
1621 I8X16_EXTRACT_LANE_S | I8X16_EXTRACT_LANE_U => {
1623 let lane_idx = wasm.read_u8()?;
1624 if lane_idx >= 16 {
1625 return Err(ValidationError::InvalidLaneIdx(lane_idx));
1626 }
1627 stack.assert_pop_val_type(ValType::VecType)?;
1628 stack.push_valtype(ValType::NumType(NumType::I32));
1629 }
1630 I16X8_EXTRACT_LANE_S | I16X8_EXTRACT_LANE_U => {
1631 let lane_idx = wasm.read_u8()?;
1632 if lane_idx >= 8 {
1633 return Err(ValidationError::InvalidLaneIdx(lane_idx));
1634 }
1635 stack.assert_pop_val_type(ValType::VecType)?;
1636 stack.push_valtype(ValType::NumType(NumType::I32));
1637 }
1638 I32X4_EXTRACT_LANE => {
1639 let lane_idx = wasm.read_u8()?;
1640 if lane_idx >= 4 {
1641 return Err(ValidationError::InvalidLaneIdx(lane_idx));
1642 }
1643 stack.assert_pop_val_type(ValType::VecType)?;
1644 stack.push_valtype(ValType::NumType(NumType::I32));
1645 }
1646 I64X2_EXTRACT_LANE => {
1647 let lane_idx = wasm.read_u8()?;
1648 if lane_idx >= 2 {
1649 return Err(ValidationError::InvalidLaneIdx(lane_idx));
1650 }
1651 stack.assert_pop_val_type(ValType::VecType)?;
1652 stack.push_valtype(ValType::NumType(NumType::I64));
1653 }
1654 F32X4_EXTRACT_LANE => {
1655 let lane_idx = wasm.read_u8()?;
1656 if lane_idx >= 4 {
1657 return Err(ValidationError::InvalidLaneIdx(lane_idx));
1658 }
1659 stack.assert_pop_val_type(ValType::VecType)?;
1660 stack.push_valtype(ValType::NumType(NumType::F32));
1661 }
1662 F64X2_EXTRACT_LANE => {
1663 let lane_idx = wasm.read_u8()?;
1664 if lane_idx >= 2 {
1665 return Err(ValidationError::InvalidLaneIdx(lane_idx));
1666 }
1667 stack.assert_pop_val_type(ValType::VecType)?;
1668 stack.push_valtype(ValType::NumType(NumType::F64));
1669 }
1670
1671 I8X16_REPLACE_LANE => {
1673 let lane_idx = wasm.read_u8()?;
1674 if lane_idx >= 16 {
1675 return Err(ValidationError::InvalidLaneIdx(lane_idx));
1676 }
1677 stack.assert_pop_val_type(ValType::NumType(NumType::I32))?;
1678 stack.assert_pop_val_type(ValType::VecType)?;
1679 stack.push_valtype(ValType::VecType);
1680 }
1681 I16X8_REPLACE_LANE => {
1682 let lane_idx = wasm.read_u8()?;
1683 if lane_idx >= 8 {
1684 return Err(ValidationError::InvalidLaneIdx(lane_idx));
1685 }
1686 stack.assert_pop_val_type(ValType::NumType(NumType::I32))?;
1687 stack.assert_pop_val_type(ValType::VecType)?;
1688 stack.push_valtype(ValType::VecType);
1689 }
1690 I32X4_REPLACE_LANE => {
1691 let lane_idx = wasm.read_u8()?;
1692 if lane_idx >= 4 {
1693 return Err(ValidationError::InvalidLaneIdx(lane_idx));
1694 }
1695 stack.assert_pop_val_type(ValType::NumType(NumType::I32))?;
1696 stack.assert_pop_val_type(ValType::VecType)?;
1697 stack.push_valtype(ValType::VecType);
1698 }
1699 I64X2_REPLACE_LANE => {
1700 let lane_idx = wasm.read_u8()?;
1701 if lane_idx >= 2 {
1702 return Err(ValidationError::InvalidLaneIdx(lane_idx));
1703 }
1704 stack.assert_pop_val_type(ValType::NumType(NumType::I64))?;
1705 stack.assert_pop_val_type(ValType::VecType)?;
1706 stack.push_valtype(ValType::VecType);
1707 }
1708 F32X4_REPLACE_LANE => {
1709 let lane_idx = wasm.read_u8()?;
1710 if lane_idx >= 4 {
1711 return Err(ValidationError::InvalidLaneIdx(lane_idx));
1712 }
1713 stack.assert_pop_val_type(ValType::NumType(NumType::F32))?;
1714 stack.assert_pop_val_type(ValType::VecType)?;
1715 stack.push_valtype(ValType::VecType);
1716 }
1717 F64X2_REPLACE_LANE => {
1718 let lane_idx = wasm.read_u8()?;
1719 if lane_idx >= 2 {
1720 return Err(ValidationError::InvalidLaneIdx(lane_idx));
1721 }
1722 stack.assert_pop_val_type(ValType::NumType(NumType::F64))?;
1723 stack.assert_pop_val_type(ValType::VecType)?;
1724 stack.push_valtype(ValType::VecType);
1725 }
1726
1727 I8X16_ABS | I16X8_ABS | I32X4_ABS | I64X2_ABS
1730 | I8X16_NEG | I16X8_NEG | I32X4_NEG | I64X2_NEG
1731 | F32X4_ABS | F64X2_ABS
1733 | F32X4_NEG | F64X2_NEG
1734 | F32X4_SQRT | F64X2_SQRT
1735 | F32X4_CEIL | F64X2_CEIL
1736 | F32X4_FLOOR | F64X2_FLOOR
1737 | F32X4_TRUNC | F64X2_TRUNC
1738 | F32X4_NEAREST | F64X2_NEAREST
1739 | I8X16_POPCNT
1741 => {
1742 stack.assert_pop_val_type(ValType::VecType)?;
1743 stack.push_valtype(ValType::VecType);
1744 }
1745
1746 I8X16_ADD | I16X8_ADD | I32X4_ADD | I64X2_ADD
1749 | I8X16_SUB | I16X8_SUB | I32X4_SUB | I64X2_SUB
1750 | F32X4_ADD | F64X2_ADD
1752 | F32X4_SUB | F64X2_SUB
1753 | F32X4_MUL | F64X2_MUL
1754 | F32X4_DIV | F64X2_DIV
1755 | F32X4_MIN | F64X2_MIN
1756 | F32X4_MAX | F64X2_MAX
1757 | F32X4_PMIN | F64X2_PMIN
1758 | F32X4_PMAX | F64X2_PMAX
1759 | I8X16_MIN_S | I16X8_MIN_S | I32X4_MIN_S
1761 | I8X16_MIN_U | I16X8_MIN_U | I32X4_MIN_U
1762 | I8X16_MAX_S | I16X8_MAX_S | I32X4_MAX_S
1763 | I8X16_MAX_U | I16X8_MAX_U | I32X4_MAX_U
1764 | I8X16_ADD_SAT_S | I16X8_ADD_SAT_S
1766 | I8X16_ADD_SAT_U | I16X8_ADD_SAT_U
1767 | I8X16_SUB_SAT_S | I16X8_SUB_SAT_S
1768 | I8X16_SUB_SAT_U | I16X8_SUB_SAT_U
1769 | I16X8_MUL | I32X4_MUL | I64X2_MUL
1771 | I8X16_AVGR_U | I16X8_AVGR_U
1772 | I16X8_Q15MULRSAT_S
1773 => {
1774 stack.assert_pop_val_type(ValType::VecType)?;
1775 stack.assert_pop_val_type(ValType::VecType)?;
1776 stack.push_valtype(ValType::VecType);
1777 }
1778
1779 I8X16_EQ | I16X8_EQ | I32X4_EQ | I64X2_EQ
1782 | I8X16_NE | I16X8_NE | I32X4_NE | I64X2_NE
1783 | I8X16_LT_S | I16X8_LT_S | I32X4_LT_S | I64X2_LT_S
1784 | I8X16_LT_U | I16X8_LT_U | I32X4_LT_U | I8X16_GT_S
1785 | I16X8_GT_S | I32X4_GT_S | I64X2_GT_S
1786 | I8X16_GT_U | I16X8_GT_U | I32X4_GT_U
1787 | I8X16_LE_S | I16X8_LE_S | I32X4_LE_S | I64X2_LE_S
1788 | I8X16_LE_U | I16X8_LE_U | I32X4_LE_U
1789 | I8X16_GE_S | I16X8_GE_S | I32X4_GE_S | I64X2_GE_S
1790 | I8X16_GE_U | I16X8_GE_U | I32X4_GE_U
1791 | F32X4_EQ | F64X2_EQ
1793 | F32X4_NE | F64X2_NE
1794 | F32X4_LT | F64X2_LT
1795 | F32X4_GT | F64X2_GT
1796 | F32X4_LE | F64X2_LE
1797 | F32X4_GE | F64X2_GE
1798 => {
1799 stack.assert_pop_val_type(ValType::VecType)?;
1800 stack.assert_pop_val_type(ValType::VecType)?;
1801 stack.push_valtype(ValType::VecType);
1802 }
1803
1804 I8X16_SHL | I16X8_SHL | I32X4_SHL | I64X2_SHL
1806 | I8X16_SHR_S | I8X16_SHR_U | I16X8_SHR_S | I16X8_SHR_U | I32X4_SHR_S | I32X4_SHR_U | I64X2_SHR_S | I64X2_SHR_U
1807 => {
1808 stack.assert_pop_val_type(ValType::NumType(NumType::I32))?;
1809 stack.assert_pop_val_type(ValType::VecType)?;
1810 stack.push_valtype(ValType::VecType);
1811 }
1812
1813 I8X16_ALL_TRUE | I16X8_ALL_TRUE | I32X4_ALL_TRUE | I64X2_ALL_TRUE
1816 => {
1817 stack.assert_pop_val_type(ValType::VecType)?;
1818 stack.push_valtype(ValType::NumType(NumType::I32));
1819 }
1820
1821 I16X8_EXTEND_HIGH_I8X16_S | I16X8_EXTEND_HIGH_I8X16_U | I16X8_EXTEND_LOW_I8X16_S | I16X8_EXTEND_LOW_I8X16_U
1823 | I32X4_EXTEND_HIGH_I16X8_S | I32X4_EXTEND_HIGH_I16X8_U | I32X4_EXTEND_LOW_I16X8_S | I32X4_EXTEND_LOW_I16X8_U
1824 | I64X2_EXTEND_HIGH_I32X4_S | I64X2_EXTEND_HIGH_I32X4_U | I64X2_EXTEND_LOW_I32X4_S | I64X2_EXTEND_LOW_I32X4_U
1825 | I32X4_TRUNC_SAT_F32X4_S | I32X4_TRUNC_SAT_F32X4_U | I32X4_TRUNC_SAT_F64X2_S_ZERO | I32X4_TRUNC_SAT_F64X2_U_ZERO
1826 | F32X4_CONVERT_I32X4_S | F32X4_CONVERT_I32X4_U | F64X2_CONVERT_LOW_I32X4_S | F64X2_CONVERT_LOW_I32X4_U
1827 | F32X4_DEMOTE_F64X2_ZERO
1828 | F64X2_PROMOTE_LOW_F32X4
1829 => {
1830 stack.assert_pop_val_type(ValType::VecType)?;
1831 stack.push_valtype(ValType::VecType);
1832 }
1833
1834 | I8X16_NARROW_I16X8_S | I8X16_NARROW_I16X8_U
1836 | I16X8_NARROW_I32X4_S | I16X8_NARROW_I32X4_U
1837 => {
1838 stack.assert_pop_val_type(ValType::VecType)?;
1839 stack.assert_pop_val_type(ValType::VecType)?;
1840 stack.push_valtype(ValType::VecType);
1841 }
1842
1843 I8X16_BITMASK | I16X8_BITMASK | I32X4_BITMASK | I64X2_BITMASK
1845 => {
1846 stack.assert_pop_val_type(ValType::VecType)?;
1847 stack.push_valtype(ValType::NumType(NumType::I32));
1848 }
1849
1850 I32X4_DOT_I16X8_S => {
1852 stack.assert_pop_val_type(ValType::VecType)?;
1853 stack.assert_pop_val_type(ValType::VecType)?;
1854 stack.push_valtype(ValType::VecType);
1855 }
1856
1857 I16X8_EXTMUL_HIGH_I8X16_S | I16X8_EXTMUL_HIGH_I8X16_U | I16X8_EXTMUL_LOW_I8X16_S | I16X8_EXTMUL_LOW_I8X16_U
1859 | I32X4_EXTMUL_HIGH_I16X8_S | I32X4_EXTMUL_HIGH_I16X8_U | I32X4_EXTMUL_LOW_I16X8_S | I32X4_EXTMUL_LOW_I16X8_U
1860 | I64X2_EXTMUL_HIGH_I32X4_S | I64X2_EXTMUL_HIGH_I32X4_U | I64X2_EXTMUL_LOW_I32X4_S | I64X2_EXTMUL_LOW_I32X4_U
1861 => {
1862 stack.assert_pop_val_type(ValType::VecType)?;
1863 stack.assert_pop_val_type(ValType::VecType)?;
1864 stack.push_valtype(ValType::VecType);
1865 }
1866
1867 I16X8_EXTADD_PAIRWISE_I8X16_S | I16X8_EXTADD_PAIRWISE_I8X16_U
1869 | I32X4_EXTADD_PAIRWISE_I16X8_S | I32X4_EXTADD_PAIRWISE_I16X8_U
1870 => {
1871 stack.assert_pop_val_type(ValType::VecType)?;
1872 stack.push_valtype(ValType::VecType);
1873 }
1874
1875 F32X4_RELAXED_MADD | F32X4_RELAXED_MAX | F32X4_RELAXED_MIN | F32X4_RELAXED_NMADD
1877 | F64X2_RELAXED_MADD | F64X2_RELAXED_MAX | F64X2_RELAXED_MIN | F64X2_RELAXED_NMADD
1878 | I8X16_RELAXED_LANESELECT | I16X8_RELAXED_LANESELECT | I32X4_RELAXED_LANESELECT | I64X2_RELAXED_LANESELECT
1879 | I32X4_RELAXED_TRUNC_F32X4_S | I32X4_RELAXED_TRUNC_F32X4_U
1880 | I32X4_RELAXED_TRUNC_F64X2_S_ZERO | I32X4_RELAXED_TRUNC_F64X2_U_ZERO
1881 | I8X16_RELAXED_SWIZZLE
1882 | 154 | 187 | 194 | 256.. => return Err(ValidationError::InvalidMultiByteInstr(first_instr_byte, second_instr)),
1883 }
1884 }
1885
1886 0x06..=0x0A
1888 | 0x12..=0x19
1889 | 0x1C..=0x1F
1890 | 0x25..=0x27
1891 | 0xC0..=0xFA
1892 | 0xFB
1893 | 0xFE
1894 | 0xFF => {
1895 return Err(ValidationError::InvalidInstr(first_instr_byte));
1896 }
1897 }
1898 }
1899}