1use core::iter;
2
3use alloc::vec;
4use alloc::vec::Vec;
5
6use crate::{
7 core::reader::types::{FuncType, ResultType},
8 NumType, RefType, ValType, ValidationError,
9};
10
11#[derive(Debug, PartialEq, Eq)]
12pub struct ValidationStack {
13 stack: Vec<ValidationStackEntry>,
14 pub ctrl_stack: Vec<CtrlStackEntry>,
16}
17
18impl ValidationStack {
19 pub fn new() -> Self {
21 Self {
22 stack: Vec::new(),
23 ctrl_stack: vec![CtrlStackEntry {
24 label_info: LabelInfo::Untyped,
25 block_ty: FuncType {
26 params: ResultType {
27 valtypes: Vec::new(),
28 },
29 returns: ResultType {
30 valtypes: Vec::new(),
31 },
32 },
33 height: 0,
34 unreachable: false,
35 }],
36 }
37 }
38
39 pub(super) fn new_for_func(block_ty: FuncType) -> Self {
41 Self {
42 stack: Vec::new(),
43 ctrl_stack: vec![CtrlStackEntry {
44 label_info: LabelInfo::Func {
45 stps_to_backpatch: Vec::new(),
46 },
47 block_ty,
48 height: 0,
49 unreachable: false,
50 }],
51 }
52 }
53
54 pub fn len(&self) -> usize {
55 self.stack.len()
56 }
57
58 pub fn push_valtype(&mut self, valtype: ValType) {
59 self.stack.push(ValidationStackEntry::Val(valtype));
60 }
61
62 pub(super) fn drop_val(&mut self) -> Result<(), ValidationError> {
65 self.pop_valtype()
66 .map_err(|_| ValidationError::ExpectedAnOperand)?;
67 Ok(())
68 }
69
70 pub(super) fn make_unspecified(&mut self) -> Result<(), ValidationError> {
77 let last_ctrl_stack_entry = self
78 .ctrl_stack
79 .last_mut()
80 .ok_or(ValidationError::ValidationCtrlStackEmpty)?;
81 last_ctrl_stack_entry.unreachable = true;
82 self.stack.truncate(last_ctrl_stack_entry.height);
83 Ok(())
84 }
85
86 fn pop_valtype(&mut self) -> Result<ValidationStackEntry, ValidationError> {
95 let last_ctrl_stack_entry = self.ctrl_stack.last().unwrap();
99 assert!(self.stack.len() >= last_ctrl_stack_entry.height);
100 if last_ctrl_stack_entry.height == self.stack.len() {
101 if last_ctrl_stack_entry.unreachable {
102 Ok(ValidationStackEntry::Bottom)
103 } else {
104 Err(ValidationError::EndInvalidValueStack)
105 }
106 } else {
107 self.stack
109 .pop()
110 .ok_or(ValidationError::EndInvalidValueStack)
111 }
112 }
113
114 pub fn assert_pop_ref_type(
120 &mut self,
121 expected_ty: Option<RefType>,
122 ) -> Result<(), ValidationError> {
123 match self.pop_valtype()? {
124 ValidationStackEntry::Val(ValType::RefType(ref_type)) => {
125 expected_ty.map_or(Ok(()), |ty| {
126 (ty == ref_type).then_some(()).ok_or(
127 ValidationError::MismatchedRefTypesOnValidationStack {
128 expected: ty,
129 actual: ref_type,
130 },
131 )
132 })
133 }
134 ValidationStackEntry::Val(v) => Err(ValidationError::ExpectedReferenceTypeOnStack(v)),
135 ValidationStackEntry::Bottom => Ok(()),
136 }
137 }
138
139 pub fn assert_pop_val_type(&mut self, expected_ty: ValType) -> Result<(), ValidationError> {
145 match self.pop_valtype()? {
146 ValidationStackEntry::Val(ty) => (ty == expected_ty)
147 .then_some(())
148 .ok_or(ValidationError::InvalidValidationStackValType(Some(ty))),
149 ValidationStackEntry::Bottom => Ok(()),
150 }
151 }
152
153 fn assert_val_types_on_top_with_custom_stacks(
156 stack: &mut Vec<ValidationStackEntry>,
157 ctrl_stack: &[CtrlStackEntry],
158 expected_val_types: &[ValType],
159 unify_to_expected_types: bool,
160 ) -> Result<(), ValidationError> {
161 let last_ctrl_stack_entry = ctrl_stack
162 .last()
163 .ok_or(ValidationError::ValidationCtrlStackEmpty)?;
164 let stack_len = stack.len();
165
166 let rev_iterator = expected_val_types.iter().rev().enumerate();
167 for (i, expected_ty) in rev_iterator {
168 if stack_len - last_ctrl_stack_entry.height <= i {
169 if last_ctrl_stack_entry.unreachable {
170 if unify_to_expected_types {
171 stack.splice(
173 stack_len - i..stack_len - i,
174 expected_val_types[..expected_val_types.len() - i]
175 .iter()
176 .map(|ty| ValidationStackEntry::Val(*ty)),
177 );
178 } else {
179 stack.splice(
180 stack_len - i..stack_len - i,
181 iter::repeat(ValidationStackEntry::Bottom)
182 .take(expected_val_types.len() - i),
183 );
184 }
185 return Ok(());
186 } else {
187 return Err(ValidationError::EndInvalidValueStack);
188 }
189 }
190
191 let actual_ty = &mut stack[stack_len - i - 1];
193
194 match actual_ty {
195 ValidationStackEntry::Val(actual_val_ty) => {
196 if *actual_val_ty != *expected_ty {
197 return Err(ValidationError::EndInvalidValueStack);
198 }
199 }
200 ValidationStackEntry::Bottom => {
201 if unify_to_expected_types {
203 *actual_ty = ValidationStackEntry::Val(*expected_ty);
204 }
205 }
206 }
207 }
208
209 Ok(())
210 }
211
212 fn assert_val_types_with_custom_stacks(
213 stack: &mut Vec<ValidationStackEntry>,
214 ctrl_stack: &[CtrlStackEntry],
215 expected_val_types: &[ValType],
216 unify_to_expected_types: bool,
217 ) -> Result<(), ValidationError> {
218 ValidationStack::assert_val_types_on_top_with_custom_stacks(
219 stack,
220 ctrl_stack,
221 expected_val_types,
222 unify_to_expected_types,
223 )?;
224 let last_ctrl_stack_entry = &ctrl_stack[ctrl_stack.len() - 1];
226 if stack.len() == last_ctrl_stack_entry.height + expected_val_types.len() {
227 Ok(())
228 } else {
229 Err(ValidationError::EndInvalidValueStack)
230 }
231 }
232
233 pub(super) fn assert_val_types_on_top(
244 &mut self,
245 expected_val_types: &[ValType],
246 unify_to_expected_types: bool,
247 ) -> Result<(), ValidationError> {
248 ValidationStack::assert_val_types_on_top_with_custom_stacks(
249 &mut self.stack,
250 &self.ctrl_stack,
251 expected_val_types,
252 unify_to_expected_types,
253 )
254 }
255
256 pub fn assert_val_types(
266 &mut self,
267 expected_val_types: &[ValType],
268 unify_to_expected_types: bool,
269 ) -> Result<(), ValidationError> {
270 ValidationStack::assert_val_types_with_custom_stacks(
271 &mut self.stack,
272 &self.ctrl_stack,
273 expected_val_types,
274 unify_to_expected_types,
275 )
276 }
277
278 pub fn assert_val_types_of_label_jump_types_on_top(
288 &mut self,
289 label_idx: usize,
290 unify_to_expected_types: bool,
291 ) -> Result<(), ValidationError> {
292 let index_of_label_in_ctrl_stack = self
293 .ctrl_stack
294 .len()
295 .checked_sub(label_idx)
296 .and_then(|i| i.checked_sub(1));
297
298 let label_types = index_of_label_in_ctrl_stack
299 .and_then(|index_of_label_in_ctrl_stack| {
300 self.ctrl_stack.get(index_of_label_in_ctrl_stack)
301 })
302 .ok_or(ValidationError::InvalidLabelIdx(label_idx))?
303 .label_types();
304 ValidationStack::assert_val_types_on_top_with_custom_stacks(
305 &mut self.stack,
306 &self.ctrl_stack,
307 label_types,
308 unify_to_expected_types,
309 )
310 }
311
312 pub fn assert_push_ctrl(
321 &mut self,
322 label_info: LabelInfo,
323 block_ty: FuncType,
324 unify_to_expected_types: bool,
325 ) -> Result<(), ValidationError> {
326 self.assert_val_types_on_top(&block_ty.params.valtypes, unify_to_expected_types)?;
327 let height = self.stack.len() - block_ty.params.valtypes.len();
328 self.ctrl_stack.push(CtrlStackEntry {
329 label_info,
330 block_ty,
331 height,
332 unreachable: false,
333 });
334 Ok(())
335 }
336
337 pub fn assert_pop_ctrl(
346 &mut self,
347 unify_to_expected_types: bool,
348 ) -> Result<(LabelInfo, FuncType), ValidationError> {
349 let return_types = &self
350 .ctrl_stack
351 .last()
352 .ok_or(ValidationError::ValidationCtrlStackEmpty)?
353 .block_ty
354 .returns
355 .valtypes;
356 ValidationStack::assert_val_types_with_custom_stacks(
357 &mut self.stack,
358 &self.ctrl_stack,
359 return_types,
360 unify_to_expected_types,
361 )?;
362
363 let last_ctrl_stack_entry = self.ctrl_stack.pop().unwrap();
365 Ok((
366 last_ctrl_stack_entry.label_info,
367 last_ctrl_stack_entry.block_ty,
368 ))
369 }
370
371 pub fn validate_polymorphic_select(&mut self) -> Result<(), ValidationError> {
373 self.assert_pop_val_type(ValType::NumType(crate::NumType::I32))?;
377
378 let first_arg = self.pop_valtype()?;
379 let second_arg = self.pop_valtype()?;
380
381 let unified_type = second_arg
382 .unify(&first_arg)
383 .ok_or(ValidationError::InvalidValidationStackValType(None))?;
384
385 if !(unified_type.unifies_to(&ValidationStackEntry::Val(ValType::NumType(NumType::I32)))
387 || unified_type.unifies_to(&ValidationStackEntry::Val(ValType::NumType(NumType::F32)))
388 || unified_type.unifies_to(&ValidationStackEntry::Val(ValType::NumType(NumType::I64)))
389 || unified_type.unifies_to(&ValidationStackEntry::Val(ValType::NumType(NumType::F64)))
390 || unified_type.unifies_to(&ValidationStackEntry::Val(ValType::VecType)))
391 {
392 return Err(ValidationError::InvalidValidationStackValType(None));
393 }
394
395 self.stack.push(unified_type);
396 Ok(())
397 }
398}
399
400#[derive(Clone, Debug, PartialEq, Eq)]
402pub enum ValidationStackEntry {
403 Val(ValType),
404 Bottom,
405}
406
407impl ValidationStackEntry {
408 fn unifies_to(&self, other: &ValidationStackEntry) -> bool {
410 match self {
411 ValidationStackEntry::Bottom => true,
412 ValidationStackEntry::Val(_) => self == other,
413 }
414 }
415
416 fn unify(&self, other: &ValidationStackEntry) -> Option<Self> {
418 self.unifies_to(other).then(|| other.clone())
419 }
420}
421
422#[derive(Clone, Debug, PartialEq, Eq)]
424pub struct CtrlStackEntry {
425 pub label_info: LabelInfo,
426 pub block_ty: FuncType,
427 pub height: usize,
428 pub unreachable: bool,
429}
430
431impl CtrlStackEntry {
432 pub fn label_types(&self) -> &[ValType] {
433 if matches!(self.label_info, LabelInfo::Loop { .. }) {
434 &self.block_ty.params.valtypes
435 } else {
436 &self.block_ty.returns.valtypes
437 }
438 }
439}
440
441#[derive(Clone, Debug, PartialEq, Eq)]
445pub enum LabelInfo {
446 Block {
447 stps_to_backpatch: Vec<usize>,
448 },
449 Loop {
450 ip: usize,
451 stp: usize,
452 },
453 If {
454 stps_to_backpatch: Vec<usize>,
455 stp: usize,
456 },
457 Func {
458 stps_to_backpatch: Vec<usize>,
459 },
460 Untyped,
461}
462
463#[cfg(test)]
464mod tests {
465 use crate::{NumType, RefType, ValType};
466
467 use super::{CtrlStackEntry, FuncType, LabelInfo, ResultType, ValidationStack, Vec};
468
469 fn push_dummy_untyped_label(validation_stack: &mut ValidationStack) {
470 validation_stack.ctrl_stack.push(CtrlStackEntry {
471 label_info: LabelInfo::Untyped,
472 block_ty: FuncType {
473 params: ResultType {
474 valtypes: Vec::new(),
475 },
476 returns: ResultType {
477 valtypes: Vec::new(),
478 },
479 },
480 height: validation_stack.len(),
481 unreachable: false,
482 })
483 }
484
485 #[test]
486 fn push_then_pop() {
487 let mut stack = ValidationStack::new();
488
489 stack.push_valtype(ValType::NumType(NumType::F64));
490 stack.push_valtype(ValType::NumType(NumType::I32));
491 stack.push_valtype(ValType::VecType);
492 stack.push_valtype(ValType::RefType(RefType::ExternRef));
493
494 stack
495 .assert_pop_val_type(ValType::RefType(RefType::ExternRef))
496 .unwrap();
497 stack.assert_pop_val_type(ValType::VecType).unwrap();
498 stack
499 .assert_pop_val_type(ValType::NumType(NumType::I32))
500 .unwrap();
501 stack
502 .assert_pop_val_type(ValType::NumType(NumType::F64))
503 .unwrap();
504 }
505
506 #[test]
540 fn assert_valtypes() {
541 let mut stack = ValidationStack::new();
542
543 stack.push_valtype(ValType::NumType(NumType::F64));
544 stack.push_valtype(ValType::NumType(NumType::I32));
545 stack.push_valtype(ValType::NumType(NumType::F32));
546
547 stack
548 .assert_val_types(
549 &[
550 ValType::NumType(NumType::F64),
551 ValType::NumType(NumType::I32),
552 ValType::NumType(NumType::F32),
553 ],
554 true,
555 )
556 .unwrap();
557
558 push_dummy_untyped_label(&mut stack);
559
560 stack.push_valtype(ValType::NumType(NumType::I32));
561
562 stack
563 .assert_val_types(&[ValType::NumType(NumType::I32)], true)
564 .unwrap();
565 }
566
567 #[test]
568 fn assert_emtpy_valtypes() {
569 let mut stack = ValidationStack::new();
570
571 stack.assert_val_types(&[], true).unwrap();
572
573 stack.push_valtype(ValType::NumType(NumType::I32));
574 push_dummy_untyped_label(&mut stack);
575
576 stack.assert_val_types(&[], true).unwrap();
578 }
579
580 #[test]
581 fn assert_valtypes_on_top() {
582 let mut stack = ValidationStack::new();
583
584 stack.assert_val_types_on_top(&[], true).unwrap();
585
586 stack.push_valtype(ValType::NumType(NumType::I32));
587 stack.push_valtype(ValType::NumType(NumType::F32));
588 stack.push_valtype(ValType::NumType(NumType::I64));
589
590 stack.assert_val_types_on_top(&[], true).unwrap();
592
593 stack
594 .assert_val_types_on_top(&[ValType::NumType(NumType::I64)], true)
595 .unwrap();
596
597 stack
598 .assert_val_types_on_top(
599 &[
600 ValType::NumType(NumType::F32),
601 ValType::NumType(NumType::I64),
602 ],
603 true,
604 )
605 .unwrap();
606
607 stack
608 .assert_val_types_on_top(
609 &[
610 ValType::NumType(NumType::I32),
611 ValType::NumType(NumType::F32),
612 ValType::NumType(NumType::I64),
613 ],
614 true,
615 )
616 .unwrap();
617 }
618
619 #[test]
620 fn unspecified() {
621 let mut stack = ValidationStack::new();
622 push_dummy_untyped_label(&mut stack);
623
624 stack.make_unspecified().unwrap();
625
626 stack
628 .assert_pop_val_type(ValType::NumType(NumType::I32))
629 .unwrap();
630
631 stack
632 .assert_pop_val_type(ValType::RefType(RefType::ExternRef))
633 .unwrap();
634
635 stack.ctrl_stack.pop();
639
640 assert_eq!(stack.assert_val_types(&[], true), Ok(()));
642 }
643
644 #[test]
645 fn unspecified2() {
646 let mut stack = ValidationStack::new();
647 push_dummy_untyped_label(&mut stack);
648
649 stack.make_unspecified().unwrap();
650
651 stack
653 .assert_val_types(
654 &[
655 ValType::NumType(NumType::I64),
656 ValType::NumType(NumType::F32),
657 ValType::NumType(NumType::I32),
658 ],
659 true,
660 )
661 .unwrap();
662
663 stack.ctrl_stack.pop();
664
665 assert_eq!(
666 stack.assert_pop_val_type(ValType::NumType(NumType::I32)),
667 Ok(())
668 );
669 assert_eq!(
670 stack.assert_pop_val_type(ValType::NumType(NumType::F32)),
671 Ok(())
672 );
673 assert_eq!(
674 stack.assert_pop_val_type(ValType::NumType(NumType::I64)),
675 Ok(())
676 );
677 }
678
679 #[test]
680 fn unspecified3() {
681 let mut stack = ValidationStack::new();
682 push_dummy_untyped_label(&mut stack);
683
684 stack.make_unspecified().unwrap();
685
686 stack.push_valtype(ValType::NumType(NumType::I32));
687
688 stack
691 .assert_val_types(
692 &[
693 ValType::NumType(NumType::I64),
694 ValType::NumType(NumType::F32),
695 ValType::NumType(NumType::I32),
696 ],
697 true,
698 )
699 .unwrap();
700
701 stack.ctrl_stack.pop();
702
703 assert_eq!(
704 stack.assert_pop_val_type(ValType::NumType(NumType::I32)),
705 Ok(())
706 );
707 assert_eq!(
708 stack.assert_pop_val_type(ValType::NumType(NumType::F32)),
709 Ok(())
710 );
711 assert_eq!(
712 stack.assert_pop_val_type(ValType::NumType(NumType::I64)),
713 Ok(())
714 );
715 }
716
717 #[test]
718 fn unspecified4() {
719 let mut stack = ValidationStack::new();
720
721 stack.push_valtype(ValType::VecType);
722 stack.push_valtype(ValType::NumType(NumType::I32));
723
724 push_dummy_untyped_label(&mut stack);
725
726 stack.make_unspecified().unwrap();
727
728 stack.push_valtype(ValType::VecType);
729 stack.push_valtype(ValType::RefType(RefType::FuncRef));
730
731 stack
734 .assert_val_types(
735 &[
736 ValType::NumType(NumType::I64),
737 ValType::NumType(NumType::F32),
738 ValType::VecType,
739 ValType::RefType(RefType::FuncRef),
740 ],
741 true,
742 )
743 .unwrap();
744
745 stack.ctrl_stack.pop();
746
747 assert_eq!(
748 stack.assert_pop_val_type(ValType::RefType(RefType::FuncRef)),
749 Ok(())
750 );
751 assert_eq!(stack.assert_pop_val_type(ValType::VecType), Ok(()));
752 assert_eq!(
753 stack.assert_pop_val_type(ValType::NumType(NumType::F32)),
754 Ok(())
755 );
756 assert_eq!(
757 stack.assert_pop_val_type(ValType::NumType(NumType::I64)),
758 Ok(())
759 );
760 assert_eq!(
761 stack.assert_pop_val_type(ValType::NumType(NumType::I32)),
762 Ok(())
763 );
764 assert_eq!(stack.assert_pop_val_type(ValType::VecType), Ok(()));
765 }
766}