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