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