1#![no_std]
5
6extern crate alloc;
7#[cfg(feature = "std")]
8extern crate std;
9
10pub use wasmparser;
11
12#[doc(hidden)]
13pub use alloc::format as __format;
14
15pub mod prelude;
16
17use alloc::borrow::Cow;
18use alloc::boxed::Box;
19use core::{fmt, ops::Range};
20use cranelift_entity::entity_impl;
21use serde_derive::{Deserialize, Serialize};
22use smallvec::SmallVec;
23
24mod error;
25pub use error::*;
26
27pub trait TypeTrace {
30 fn trace<F, E>(&self, func: &mut F) -> Result<(), E>
34 where
35 F: FnMut(EngineOrModuleTypeIndex) -> Result<(), E>;
36
37 fn trace_mut<F, E>(&mut self, func: &mut F) -> Result<(), E>
43 where
44 F: FnMut(&mut EngineOrModuleTypeIndex) -> Result<(), E>;
45
46 fn trace_engine_indices<F, E>(&self, func: &mut F) -> Result<(), E>
48 where
49 F: FnMut(VMSharedTypeIndex) -> Result<(), E>,
50 {
51 self.trace(&mut |idx| match idx {
52 EngineOrModuleTypeIndex::Engine(idx) => func(idx),
53 EngineOrModuleTypeIndex::Module(_) | EngineOrModuleTypeIndex::RecGroup(_) => Ok(()),
54 })
55 }
56
57 fn canonicalize_for_runtime_usage<F>(&mut self, module_to_engine: &mut F)
68 where
69 F: FnMut(ModuleInternedTypeIndex) -> VMSharedTypeIndex,
70 {
71 self.trace_mut::<_, ()>(&mut |idx| match idx {
72 EngineOrModuleTypeIndex::Engine(_) => Ok(()),
73 EngineOrModuleTypeIndex::Module(module_index) => {
74 let engine_index = module_to_engine(*module_index);
75 *idx = EngineOrModuleTypeIndex::Engine(engine_index);
76 Ok(())
77 }
78 EngineOrModuleTypeIndex::RecGroup(_) => {
79 panic!("should not already be canonicalized for hash consing")
80 }
81 })
82 .unwrap()
83 }
84
85 fn is_canonicalized_for_runtime_usage(&self) -> bool {
87 self.trace(&mut |idx| match idx {
88 EngineOrModuleTypeIndex::Engine(_) => Ok(()),
89 EngineOrModuleTypeIndex::Module(_) | EngineOrModuleTypeIndex::RecGroup(_) => Err(()),
90 })
91 .is_ok()
92 }
93
94 fn canonicalize_for_hash_consing<F>(
105 &mut self,
106 rec_group_range: Range<ModuleInternedTypeIndex>,
107 module_to_engine: &mut F,
108 ) where
109 F: FnMut(ModuleInternedTypeIndex) -> VMSharedTypeIndex,
110 {
111 self.trace_mut::<_, ()>(&mut |idx| match *idx {
112 EngineOrModuleTypeIndex::Engine(_) => Ok(()),
113 EngineOrModuleTypeIndex::Module(module_index) => {
114 *idx = if rec_group_range.start <= module_index {
115 debug_assert!(module_index < rec_group_range.end);
118 let relative = module_index.as_u32() - rec_group_range.start.as_u32();
119 let relative = RecGroupRelativeTypeIndex::from_u32(relative);
120 EngineOrModuleTypeIndex::RecGroup(relative)
121 } else {
122 debug_assert!(module_index < rec_group_range.start);
125 EngineOrModuleTypeIndex::Engine(module_to_engine(module_index))
126 };
127 Ok(())
128 }
129 EngineOrModuleTypeIndex::RecGroup(_) => {
130 panic!("should not already be canonicalized for hash consing")
131 }
132 })
133 .unwrap()
134 }
135
136 fn is_canonicalized_for_hash_consing(&self) -> bool {
138 self.trace(&mut |idx| match idx {
139 EngineOrModuleTypeIndex::Engine(_) | EngineOrModuleTypeIndex::RecGroup(_) => Ok(()),
140 EngineOrModuleTypeIndex::Module(_) => Err(()),
141 })
142 .is_ok()
143 }
144}
145
146#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash, Serialize, Deserialize)]
148pub enum WasmValType {
149 I32,
151 I64,
153 F32,
155 F64,
157 V128,
159 Ref(WasmRefType),
161}
162
163impl fmt::Display for WasmValType {
164 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
165 match self {
166 WasmValType::I32 => write!(f, "i32"),
167 WasmValType::I64 => write!(f, "i64"),
168 WasmValType::F32 => write!(f, "f32"),
169 WasmValType::F64 => write!(f, "f64"),
170 WasmValType::V128 => write!(f, "v128"),
171 WasmValType::Ref(rt) => write!(f, "{rt}"),
172 }
173 }
174}
175
176impl TypeTrace for WasmValType {
177 fn trace<F, E>(&self, func: &mut F) -> Result<(), E>
178 where
179 F: FnMut(EngineOrModuleTypeIndex) -> Result<(), E>,
180 {
181 match self {
182 WasmValType::Ref(r) => r.trace(func),
183 WasmValType::I32
184 | WasmValType::I64
185 | WasmValType::F32
186 | WasmValType::F64
187 | WasmValType::V128 => Ok(()),
188 }
189 }
190
191 fn trace_mut<F, E>(&mut self, func: &mut F) -> Result<(), E>
192 where
193 F: FnMut(&mut EngineOrModuleTypeIndex) -> Result<(), E>,
194 {
195 match self {
196 WasmValType::Ref(r) => r.trace_mut(func),
197 WasmValType::I32
198 | WasmValType::I64
199 | WasmValType::F32
200 | WasmValType::F64
201 | WasmValType::V128 => Ok(()),
202 }
203 }
204}
205
206impl WasmValType {
207 #[inline]
209 pub fn is_vmgcref_type(&self) -> bool {
210 match self {
211 WasmValType::Ref(r) => r.is_vmgcref_type(),
212 _ => false,
213 }
214 }
215
216 #[inline]
222 pub fn is_vmgcref_type_and_not_i31(&self) -> bool {
223 match self {
224 WasmValType::Ref(r) => r.is_vmgcref_type_and_not_i31(),
225 _ => false,
226 }
227 }
228
229 fn trampoline_type(&self) -> Self {
230 match self {
231 WasmValType::Ref(r) => WasmValType::Ref(WasmRefType {
232 nullable: true,
233 heap_type: r.heap_type.top().into(),
234 }),
235 WasmValType::I32
236 | WasmValType::I64
237 | WasmValType::F32
238 | WasmValType::F64
239 | WasmValType::V128 => *self,
240 }
241 }
242}
243
244#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash, Serialize, Deserialize)]
246pub struct WasmRefType {
247 pub nullable: bool,
248 pub heap_type: WasmHeapType,
249}
250
251impl TypeTrace for WasmRefType {
252 fn trace<F, E>(&self, func: &mut F) -> Result<(), E>
253 where
254 F: FnMut(EngineOrModuleTypeIndex) -> Result<(), E>,
255 {
256 self.heap_type.trace(func)
257 }
258
259 fn trace_mut<F, E>(&mut self, func: &mut F) -> Result<(), E>
260 where
261 F: FnMut(&mut EngineOrModuleTypeIndex) -> Result<(), E>,
262 {
263 self.heap_type.trace_mut(func)
264 }
265}
266
267impl WasmRefType {
268 pub const EXTERNREF: WasmRefType = WasmRefType {
269 nullable: true,
270 heap_type: WasmHeapType::Extern,
271 };
272 pub const FUNCREF: WasmRefType = WasmRefType {
273 nullable: true,
274 heap_type: WasmHeapType::Func,
275 };
276
277 #[inline]
279 pub fn is_vmgcref_type(&self) -> bool {
280 self.heap_type.is_vmgcref_type()
281 }
282
283 #[inline]
289 pub fn is_vmgcref_type_and_not_i31(&self) -> bool {
290 self.heap_type.is_vmgcref_type_and_not_i31()
291 }
292}
293
294impl fmt::Display for WasmRefType {
295 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
296 match *self {
297 Self::FUNCREF => write!(f, "funcref"),
298 Self::EXTERNREF => write!(f, "externref"),
299 _ => {
300 if self.nullable {
301 write!(f, "(ref null {})", self.heap_type)
302 } else {
303 write!(f, "(ref {})", self.heap_type)
304 }
305 }
306 }
307 }
308}
309
310#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash, Serialize, Deserialize)]
315pub enum EngineOrModuleTypeIndex {
316 Engine(VMSharedTypeIndex),
319
320 Module(ModuleInternedTypeIndex),
323
324 RecGroup(RecGroupRelativeTypeIndex),
328}
329
330impl From<ModuleInternedTypeIndex> for EngineOrModuleTypeIndex {
331 #[inline]
332 fn from(i: ModuleInternedTypeIndex) -> Self {
333 Self::Module(i)
334 }
335}
336
337impl From<VMSharedTypeIndex> for EngineOrModuleTypeIndex {
338 #[inline]
339 fn from(i: VMSharedTypeIndex) -> Self {
340 Self::Engine(i)
341 }
342}
343
344impl From<RecGroupRelativeTypeIndex> for EngineOrModuleTypeIndex {
345 #[inline]
346 fn from(i: RecGroupRelativeTypeIndex) -> Self {
347 Self::RecGroup(i)
348 }
349}
350
351impl fmt::Display for EngineOrModuleTypeIndex {
352 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
353 match self {
354 Self::Engine(i) => write!(f, "(engine {})", i.bits()),
355 Self::Module(i) => write!(f, "(module {})", i.as_u32()),
356 Self::RecGroup(i) => write!(f, "(recgroup {})", i.as_u32()),
357 }
358 }
359}
360
361impl EngineOrModuleTypeIndex {
362 pub fn is_engine_type_index(self) -> bool {
364 matches!(self, Self::Engine(_))
365 }
366
367 pub fn as_engine_type_index(self) -> Option<VMSharedTypeIndex> {
369 match self {
370 Self::Engine(e) => Some(e),
371 Self::RecGroup(_) | Self::Module(_) => None,
372 }
373 }
374
375 pub fn unwrap_engine_type_index(self) -> VMSharedTypeIndex {
377 self.as_engine_type_index()
378 .unwrap_or_else(|| panic!("`unwrap_engine_type_index` on {self:?}"))
379 }
380
381 pub fn is_module_type_index(self) -> bool {
383 matches!(self, Self::Module(_))
384 }
385
386 pub fn as_module_type_index(self) -> Option<ModuleInternedTypeIndex> {
388 match self {
389 Self::Module(e) => Some(e),
390 Self::RecGroup(_) | Self::Engine(_) => None,
391 }
392 }
393
394 pub fn unwrap_module_type_index(self) -> ModuleInternedTypeIndex {
396 self.as_module_type_index()
397 .unwrap_or_else(|| panic!("`unwrap_module_type_index` on {self:?}"))
398 }
399
400 pub fn is_rec_group_type_index(self) -> bool {
402 matches!(self, Self::RecGroup(_))
403 }
404
405 pub fn as_rec_group_type_index(self) -> Option<RecGroupRelativeTypeIndex> {
407 match self {
408 Self::RecGroup(r) => Some(r),
409 Self::Module(_) | Self::Engine(_) => None,
410 }
411 }
412
413 pub fn unwrap_rec_group_type_index(self) -> RecGroupRelativeTypeIndex {
415 self.as_rec_group_type_index()
416 .unwrap_or_else(|| panic!("`unwrap_rec_group_type_index` on {self:?}"))
417 }
418}
419
420#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash, Serialize, Deserialize)]
422pub enum WasmHeapType {
423 Extern,
425 NoExtern,
426
427 Func,
429 ConcreteFunc(EngineOrModuleTypeIndex),
430 NoFunc,
431
432 Any,
434 Eq,
435 I31,
436 Array,
437 ConcreteArray(EngineOrModuleTypeIndex),
438 Struct,
439 ConcreteStruct(EngineOrModuleTypeIndex),
440 None,
441}
442
443impl From<WasmHeapTopType> for WasmHeapType {
444 #[inline]
445 fn from(value: WasmHeapTopType) -> Self {
446 match value {
447 WasmHeapTopType::Extern => Self::Extern,
448 WasmHeapTopType::Any => Self::Any,
449 WasmHeapTopType::Func => Self::Func,
450 }
451 }
452}
453
454impl fmt::Display for WasmHeapType {
455 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
456 match self {
457 Self::Extern => write!(f, "extern"),
458 Self::NoExtern => write!(f, "noextern"),
459 Self::Func => write!(f, "func"),
460 Self::ConcreteFunc(i) => write!(f, "func {i}"),
461 Self::NoFunc => write!(f, "nofunc"),
462 Self::Any => write!(f, "any"),
463 Self::Eq => write!(f, "eq"),
464 Self::I31 => write!(f, "i31"),
465 Self::Array => write!(f, "array"),
466 Self::ConcreteArray(i) => write!(f, "array {i}"),
467 Self::Struct => write!(f, "struct"),
468 Self::ConcreteStruct(i) => write!(f, "struct {i}"),
469 Self::None => write!(f, "none"),
470 }
471 }
472}
473
474impl TypeTrace for WasmHeapType {
475 fn trace<F, E>(&self, func: &mut F) -> Result<(), E>
476 where
477 F: FnMut(EngineOrModuleTypeIndex) -> Result<(), E>,
478 {
479 match *self {
480 Self::ConcreteArray(i) => func(i),
481 Self::ConcreteFunc(i) => func(i),
482 Self::ConcreteStruct(i) => func(i),
483 _ => Ok(()),
484 }
485 }
486
487 fn trace_mut<F, E>(&mut self, func: &mut F) -> Result<(), E>
488 where
489 F: FnMut(&mut EngineOrModuleTypeIndex) -> Result<(), E>,
490 {
491 match self {
492 Self::ConcreteArray(i) => func(i),
493 Self::ConcreteFunc(i) => func(i),
494 Self::ConcreteStruct(i) => func(i),
495 _ => Ok(()),
496 }
497 }
498}
499
500impl WasmHeapType {
501 #[inline]
503 pub fn is_vmgcref_type(&self) -> bool {
504 match self.top() {
505 WasmHeapTopType::Any | WasmHeapTopType::Extern => true,
508
509 WasmHeapTopType::Func => false,
511 }
512 }
513
514 #[inline]
520 pub fn is_vmgcref_type_and_not_i31(&self) -> bool {
521 self.is_vmgcref_type() && *self != Self::I31
522 }
523
524 #[inline]
526 pub fn top(&self) -> WasmHeapTopType {
527 match self {
528 WasmHeapType::Extern | WasmHeapType::NoExtern => WasmHeapTopType::Extern,
529
530 WasmHeapType::Func | WasmHeapType::ConcreteFunc(_) | WasmHeapType::NoFunc => {
531 WasmHeapTopType::Func
532 }
533
534 WasmHeapType::Any
535 | WasmHeapType::Eq
536 | WasmHeapType::I31
537 | WasmHeapType::Array
538 | WasmHeapType::ConcreteArray(_)
539 | WasmHeapType::Struct
540 | WasmHeapType::ConcreteStruct(_)
541 | WasmHeapType::None => WasmHeapTopType::Any,
542 }
543 }
544}
545
546#[derive(Debug, Clone, Copy, Eq, PartialEq)]
548pub enum WasmHeapTopType {
549 Extern,
551 Any,
553 Func,
555}
556
557#[derive(Debug, Clone, Eq, PartialEq, Hash, Serialize, Deserialize)]
559pub struct WasmFuncType {
560 params: Box<[WasmValType]>,
561 non_i31_gc_ref_params_count: usize,
562 returns: Box<[WasmValType]>,
563 non_i31_gc_ref_returns_count: usize,
564}
565
566impl fmt::Display for WasmFuncType {
567 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
568 write!(f, "(func")?;
569 if !self.params.is_empty() {
570 write!(f, " (param")?;
571 for p in self.params.iter() {
572 write!(f, " {p}")?;
573 }
574 write!(f, ")")?;
575 }
576 if !self.returns.is_empty() {
577 write!(f, " (result")?;
578 for r in self.returns.iter() {
579 write!(f, " {r}")?;
580 }
581 write!(f, ")")?;
582 }
583 write!(f, ")")
584 }
585}
586
587impl TypeTrace for WasmFuncType {
588 fn trace<F, E>(&self, func: &mut F) -> Result<(), E>
589 where
590 F: FnMut(EngineOrModuleTypeIndex) -> Result<(), E>,
591 {
592 for p in self.params.iter() {
593 p.trace(func)?;
594 }
595 for r in self.returns.iter() {
596 r.trace(func)?;
597 }
598 Ok(())
599 }
600
601 fn trace_mut<F, E>(&mut self, func: &mut F) -> Result<(), E>
602 where
603 F: FnMut(&mut EngineOrModuleTypeIndex) -> Result<(), E>,
604 {
605 for p in self.params.iter_mut() {
606 p.trace_mut(func)?;
607 }
608 for r in self.returns.iter_mut() {
609 r.trace_mut(func)?;
610 }
611 Ok(())
612 }
613}
614
615impl WasmFuncType {
616 #[inline]
617 pub fn new(params: Box<[WasmValType]>, returns: Box<[WasmValType]>) -> Self {
618 let non_i31_gc_ref_params_count = params
619 .iter()
620 .filter(|p| p.is_vmgcref_type_and_not_i31())
621 .count();
622 let non_i31_gc_ref_returns_count = returns
623 .iter()
624 .filter(|r| r.is_vmgcref_type_and_not_i31())
625 .count();
626 WasmFuncType {
627 params,
628 non_i31_gc_ref_params_count,
629 returns,
630 non_i31_gc_ref_returns_count,
631 }
632 }
633
634 #[inline]
636 pub fn params(&self) -> &[WasmValType] {
637 &self.params
638 }
639
640 #[inline]
642 pub fn non_i31_gc_ref_params_count(&self) -> usize {
643 self.non_i31_gc_ref_params_count
644 }
645
646 #[inline]
648 pub fn returns(&self) -> &[WasmValType] {
649 &self.returns
650 }
651
652 #[inline]
654 pub fn non_i31_gc_ref_returns_count(&self) -> usize {
655 self.non_i31_gc_ref_returns_count
656 }
657
658 pub fn is_trampoline_type(&self) -> bool {
660 self.params().iter().all(|p| *p == p.trampoline_type())
661 && self.returns().iter().all(|r| *r == r.trampoline_type())
662 }
663
664 pub fn trampoline_type(&self) -> Cow<'_, Self> {
690 if self.is_trampoline_type() {
691 return Cow::Borrowed(self);
692 }
693
694 Cow::Owned(Self::new(
695 self.params().iter().map(|p| p.trampoline_type()).collect(),
696 self.returns().iter().map(|r| r.trampoline_type()).collect(),
697 ))
698 }
699}
700
701#[derive(Debug, Clone, Eq, PartialEq, Hash, Serialize, Deserialize)]
703pub enum WasmStorageType {
704 I8,
706 I16,
708 Val(WasmValType),
710}
711
712impl fmt::Display for WasmStorageType {
713 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
714 match self {
715 WasmStorageType::I8 => write!(f, "i8"),
716 WasmStorageType::I16 => write!(f, "i16"),
717 WasmStorageType::Val(v) => fmt::Display::fmt(v, f),
718 }
719 }
720}
721
722impl TypeTrace for WasmStorageType {
723 fn trace<F, E>(&self, func: &mut F) -> Result<(), E>
724 where
725 F: FnMut(EngineOrModuleTypeIndex) -> Result<(), E>,
726 {
727 match self {
728 WasmStorageType::I8 | WasmStorageType::I16 => Ok(()),
729 WasmStorageType::Val(v) => v.trace(func),
730 }
731 }
732
733 fn trace_mut<F, E>(&mut self, func: &mut F) -> Result<(), E>
734 where
735 F: FnMut(&mut EngineOrModuleTypeIndex) -> Result<(), E>,
736 {
737 match self {
738 WasmStorageType::I8 | WasmStorageType::I16 => Ok(()),
739 WasmStorageType::Val(v) => v.trace_mut(func),
740 }
741 }
742}
743
744#[derive(Debug, Clone, Eq, PartialEq, Hash, Serialize, Deserialize)]
746pub struct WasmFieldType {
747 pub element_type: WasmStorageType,
749
750 pub mutable: bool,
752}
753
754impl fmt::Display for WasmFieldType {
755 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
756 if self.mutable {
757 write!(f, "(mut {})", self.element_type)
758 } else {
759 fmt::Display::fmt(&self.element_type, f)
760 }
761 }
762}
763
764impl TypeTrace for WasmFieldType {
765 fn trace<F, E>(&self, func: &mut F) -> Result<(), E>
766 where
767 F: FnMut(EngineOrModuleTypeIndex) -> Result<(), E>,
768 {
769 self.element_type.trace(func)
770 }
771
772 fn trace_mut<F, E>(&mut self, func: &mut F) -> Result<(), E>
773 where
774 F: FnMut(&mut EngineOrModuleTypeIndex) -> Result<(), E>,
775 {
776 self.element_type.trace_mut(func)
777 }
778}
779
780#[derive(Debug, Clone, Eq, PartialEq, Hash, Serialize, Deserialize)]
782pub struct WasmArrayType(pub WasmFieldType);
783
784impl fmt::Display for WasmArrayType {
785 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
786 write!(f, "(array {})", self.0)
787 }
788}
789
790impl TypeTrace for WasmArrayType {
791 fn trace<F, E>(&self, func: &mut F) -> Result<(), E>
792 where
793 F: FnMut(EngineOrModuleTypeIndex) -> Result<(), E>,
794 {
795 self.0.trace(func)
796 }
797
798 fn trace_mut<F, E>(&mut self, func: &mut F) -> Result<(), E>
799 where
800 F: FnMut(&mut EngineOrModuleTypeIndex) -> Result<(), E>,
801 {
802 self.0.trace_mut(func)
803 }
804}
805
806#[derive(Debug, Clone, Eq, PartialEq, Hash, Serialize, Deserialize)]
808pub struct WasmStructType {
809 pub fields: Box<[WasmFieldType]>,
810}
811
812impl fmt::Display for WasmStructType {
813 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
814 write!(f, "(struct")?;
815 for ty in self.fields.iter() {
816 write!(f, " {ty}")?;
817 }
818 write!(f, ")")
819 }
820}
821
822impl TypeTrace for WasmStructType {
823 fn trace<F, E>(&self, func: &mut F) -> Result<(), E>
824 where
825 F: FnMut(EngineOrModuleTypeIndex) -> Result<(), E>,
826 {
827 for f in self.fields.iter() {
828 f.trace(func)?;
829 }
830 Ok(())
831 }
832
833 fn trace_mut<F, E>(&mut self, func: &mut F) -> Result<(), E>
834 where
835 F: FnMut(&mut EngineOrModuleTypeIndex) -> Result<(), E>,
836 {
837 for f in self.fields.iter_mut() {
838 f.trace_mut(func)?;
839 }
840 Ok(())
841 }
842}
843
844#[derive(Debug, Clone, Eq, PartialEq, Hash, Serialize, Deserialize)]
846pub enum WasmCompositeType {
847 Array(WasmArrayType),
848 Func(WasmFuncType),
849 Struct(WasmStructType),
850}
851
852impl fmt::Display for WasmCompositeType {
853 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
854 match self {
855 WasmCompositeType::Array(ty) => fmt::Display::fmt(ty, f),
856 WasmCompositeType::Func(ty) => fmt::Display::fmt(ty, f),
857 WasmCompositeType::Struct(ty) => fmt::Display::fmt(ty, f),
858 }
859 }
860}
861
862impl WasmCompositeType {
863 #[inline]
864 pub fn is_array(&self) -> bool {
865 matches!(self, Self::Array(_))
866 }
867
868 #[inline]
869 pub fn as_array(&self) -> Option<&WasmArrayType> {
870 match self {
871 WasmCompositeType::Array(f) => Some(f),
872 _ => None,
873 }
874 }
875
876 #[inline]
877 pub fn unwrap_array(&self) -> &WasmArrayType {
878 self.as_array().unwrap()
879 }
880
881 #[inline]
882 pub fn is_func(&self) -> bool {
883 matches!(self, Self::Func(_))
884 }
885
886 #[inline]
887 pub fn as_func(&self) -> Option<&WasmFuncType> {
888 match self {
889 WasmCompositeType::Func(f) => Some(f),
890 _ => None,
891 }
892 }
893
894 #[inline]
895 pub fn unwrap_func(&self) -> &WasmFuncType {
896 self.as_func().unwrap()
897 }
898
899 #[inline]
900 pub fn is_struct(&self) -> bool {
901 matches!(self, Self::Struct(_))
902 }
903
904 #[inline]
905 pub fn as_struct(&self) -> Option<&WasmStructType> {
906 match self {
907 WasmCompositeType::Struct(f) => Some(f),
908 _ => None,
909 }
910 }
911
912 #[inline]
913 pub fn unwrap_struct(&self) -> &WasmStructType {
914 self.as_struct().unwrap()
915 }
916}
917
918impl TypeTrace for WasmCompositeType {
919 fn trace<F, E>(&self, func: &mut F) -> Result<(), E>
920 where
921 F: FnMut(EngineOrModuleTypeIndex) -> Result<(), E>,
922 {
923 match self {
924 WasmCompositeType::Array(a) => a.trace(func),
925 WasmCompositeType::Func(f) => f.trace(func),
926 WasmCompositeType::Struct(a) => a.trace(func),
927 }
928 }
929
930 fn trace_mut<F, E>(&mut self, func: &mut F) -> Result<(), E>
931 where
932 F: FnMut(&mut EngineOrModuleTypeIndex) -> Result<(), E>,
933 {
934 match self {
935 WasmCompositeType::Array(a) => a.trace_mut(func),
936 WasmCompositeType::Func(f) => f.trace_mut(func),
937 WasmCompositeType::Struct(a) => a.trace_mut(func),
938 }
939 }
940}
941
942#[derive(Debug, Clone, Eq, PartialEq, Hash, Serialize, Deserialize)]
944pub struct WasmSubType {
945 pub is_final: bool,
948
949 pub supertype: Option<EngineOrModuleTypeIndex>,
951
952 pub composite_type: WasmCompositeType,
954}
955
956impl fmt::Display for WasmSubType {
957 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
958 if self.is_final && self.supertype.is_none() {
959 fmt::Display::fmt(&self.composite_type, f)
960 } else {
961 write!(f, "(sub")?;
962 if self.is_final {
963 write!(f, " final")?;
964 }
965 if let Some(sup) = self.supertype {
966 write!(f, " {sup}")?;
967 }
968 write!(f, " {})", self.composite_type)
969 }
970 }
971}
972
973impl WasmSubType {
974 #[inline]
975 pub fn is_func(&self) -> bool {
976 self.composite_type.is_func()
977 }
978
979 #[inline]
980 pub fn as_func(&self) -> Option<&WasmFuncType> {
981 self.composite_type.as_func()
982 }
983
984 #[inline]
985 pub fn unwrap_func(&self) -> &WasmFuncType {
986 self.composite_type.unwrap_func()
987 }
988
989 #[inline]
990 pub fn is_array(&self) -> bool {
991 self.composite_type.is_array()
992 }
993
994 #[inline]
995 pub fn as_array(&self) -> Option<&WasmArrayType> {
996 self.composite_type.as_array()
997 }
998
999 #[inline]
1000 pub fn unwrap_array(&self) -> &WasmArrayType {
1001 self.composite_type.unwrap_array()
1002 }
1003
1004 #[inline]
1005 pub fn is_struct(&self) -> bool {
1006 self.composite_type.is_struct()
1007 }
1008
1009 #[inline]
1010 pub fn as_struct(&self) -> Option<&WasmStructType> {
1011 self.composite_type.as_struct()
1012 }
1013
1014 #[inline]
1015 pub fn unwrap_struct(&self) -> &WasmStructType {
1016 self.composite_type.unwrap_struct()
1017 }
1018}
1019
1020impl TypeTrace for WasmSubType {
1021 fn trace<F, E>(&self, func: &mut F) -> Result<(), E>
1022 where
1023 F: FnMut(EngineOrModuleTypeIndex) -> Result<(), E>,
1024 {
1025 if let Some(sup) = self.supertype {
1026 func(sup)?;
1027 }
1028 self.composite_type.trace(func)
1029 }
1030
1031 fn trace_mut<F, E>(&mut self, func: &mut F) -> Result<(), E>
1032 where
1033 F: FnMut(&mut EngineOrModuleTypeIndex) -> Result<(), E>,
1034 {
1035 if let Some(sup) = self.supertype.as_mut() {
1036 func(sup)?;
1037 }
1038 self.composite_type.trace_mut(func)
1039 }
1040}
1041
1042#[derive(Debug, Clone, Eq, PartialEq, Hash, Serialize, Deserialize)]
1053pub struct WasmRecGroup {
1054 pub types: Box<[WasmSubType]>,
1056}
1057
1058impl TypeTrace for WasmRecGroup {
1059 fn trace<F, E>(&self, func: &mut F) -> Result<(), E>
1060 where
1061 F: FnMut(EngineOrModuleTypeIndex) -> Result<(), E>,
1062 {
1063 for ty in self.types.iter() {
1064 ty.trace(func)?;
1065 }
1066 Ok(())
1067 }
1068
1069 fn trace_mut<F, E>(&mut self, func: &mut F) -> Result<(), E>
1070 where
1071 F: FnMut(&mut EngineOrModuleTypeIndex) -> Result<(), E>,
1072 {
1073 for ty in self.types.iter_mut() {
1074 ty.trace_mut(func)?;
1075 }
1076 Ok(())
1077 }
1078}
1079
1080#[derive(Copy, Clone, PartialEq, Eq, Hash, PartialOrd, Ord, Debug, Serialize, Deserialize)]
1082pub struct FuncIndex(u32);
1083entity_impl!(FuncIndex);
1084
1085#[derive(Copy, Clone, PartialEq, Eq, Hash, PartialOrd, Ord, Debug, Serialize, Deserialize)]
1087pub struct DefinedFuncIndex(u32);
1088entity_impl!(DefinedFuncIndex);
1089
1090#[derive(Copy, Clone, PartialEq, Eq, Hash, PartialOrd, Ord, Debug, Serialize, Deserialize)]
1092pub struct DefinedTableIndex(u32);
1093entity_impl!(DefinedTableIndex);
1094
1095#[derive(Copy, Clone, PartialEq, Eq, Hash, PartialOrd, Ord, Debug, Serialize, Deserialize)]
1097pub struct DefinedMemoryIndex(u32);
1098entity_impl!(DefinedMemoryIndex);
1099
1100#[derive(Copy, Clone, PartialEq, Eq, Hash, PartialOrd, Ord, Debug, Serialize, Deserialize)]
1102pub struct OwnedMemoryIndex(u32);
1103entity_impl!(OwnedMemoryIndex);
1104
1105#[derive(Copy, Clone, PartialEq, Eq, Hash, PartialOrd, Ord, Debug, Serialize, Deserialize)]
1107pub struct DefinedGlobalIndex(u32);
1108entity_impl!(DefinedGlobalIndex);
1109
1110#[derive(Copy, Clone, PartialEq, Eq, Hash, PartialOrd, Ord, Debug, Serialize, Deserialize)]
1112pub struct TableIndex(u32);
1113entity_impl!(TableIndex);
1114
1115#[derive(Copy, Clone, PartialEq, Eq, Hash, PartialOrd, Ord, Debug, Serialize, Deserialize)]
1117pub struct GlobalIndex(u32);
1118entity_impl!(GlobalIndex);
1119
1120#[derive(Copy, Clone, PartialEq, Eq, Hash, PartialOrd, Ord, Debug, Serialize, Deserialize)]
1122pub struct MemoryIndex(u32);
1123entity_impl!(MemoryIndex);
1124
1125#[derive(Copy, Clone, PartialEq, Eq, Hash, PartialOrd, Ord, Debug, Serialize, Deserialize)]
1128pub struct ModuleInternedRecGroupIndex(u32);
1129entity_impl!(ModuleInternedRecGroupIndex);
1130
1131#[derive(Copy, Clone, PartialEq, Eq, Hash, PartialOrd, Ord, Debug, Serialize, Deserialize)]
1134pub struct EngineInternedRecGroupIndex(u32);
1135entity_impl!(EngineInternedRecGroupIndex);
1136
1137#[derive(Copy, Clone, PartialEq, Eq, Hash, PartialOrd, Ord, Debug, Serialize, Deserialize)]
1139pub struct TypeIndex(u32);
1140entity_impl!(TypeIndex);
1141
1142#[derive(Copy, Clone, PartialEq, Eq, Hash, PartialOrd, Ord, Debug, Serialize, Deserialize)]
1148pub struct RecGroupRelativeTypeIndex(u32);
1149entity_impl!(RecGroupRelativeTypeIndex);
1150
1151#[derive(Copy, Clone, PartialEq, Eq, Hash, PartialOrd, Ord, Debug, Serialize, Deserialize)]
1159pub struct ModuleInternedTypeIndex(u32);
1160entity_impl!(ModuleInternedTypeIndex);
1161
1162#[repr(transparent)] #[derive(Copy, Clone, PartialEq, Eq, Hash, PartialOrd, Ord, Debug, Serialize, Deserialize)]
1171pub struct VMSharedTypeIndex(u32);
1172entity_impl!(VMSharedTypeIndex);
1173
1174impl VMSharedTypeIndex {
1175 #[inline]
1177 pub fn new(value: u32) -> Self {
1178 assert_ne!(
1179 value,
1180 u32::MAX,
1181 "u32::MAX is reserved for the default value"
1182 );
1183 Self(value)
1184 }
1185
1186 #[inline]
1188 pub fn bits(&self) -> u32 {
1189 self.0
1190 }
1191}
1192
1193impl Default for VMSharedTypeIndex {
1194 #[inline]
1195 fn default() -> Self {
1196 Self(u32::MAX)
1197 }
1198}
1199
1200#[derive(Copy, Clone, PartialEq, Eq, Hash, PartialOrd, Ord, Debug, Serialize, Deserialize)]
1202pub struct DataIndex(u32);
1203entity_impl!(DataIndex);
1204
1205#[derive(Copy, Clone, PartialEq, Eq, Hash, PartialOrd, Ord, Debug, Serialize, Deserialize)]
1207pub struct ElemIndex(u32);
1208entity_impl!(ElemIndex);
1209
1210#[derive(Copy, Clone, PartialEq, Eq, Hash, PartialOrd, Ord, Debug, Serialize, Deserialize)]
1212pub struct TagIndex(u32);
1213entity_impl!(TagIndex);
1214
1215#[derive(Copy, Clone, PartialEq, Eq, Hash, PartialOrd, Ord, Debug, Serialize, Deserialize)]
1220pub struct StaticModuleIndex(u32);
1221entity_impl!(StaticModuleIndex);
1222
1223#[derive(Copy, Clone, PartialEq, Eq, Hash, PartialOrd, Ord, Debug, Serialize, Deserialize)]
1225pub enum EntityIndex {
1226 Function(FuncIndex),
1228 Table(TableIndex),
1230 Memory(MemoryIndex),
1232 Global(GlobalIndex),
1234}
1235
1236impl From<FuncIndex> for EntityIndex {
1237 fn from(idx: FuncIndex) -> EntityIndex {
1238 EntityIndex::Function(idx)
1239 }
1240}
1241
1242impl From<TableIndex> for EntityIndex {
1243 fn from(idx: TableIndex) -> EntityIndex {
1244 EntityIndex::Table(idx)
1245 }
1246}
1247
1248impl From<MemoryIndex> for EntityIndex {
1249 fn from(idx: MemoryIndex) -> EntityIndex {
1250 EntityIndex::Memory(idx)
1251 }
1252}
1253
1254impl From<GlobalIndex> for EntityIndex {
1255 fn from(idx: GlobalIndex) -> EntityIndex {
1256 EntityIndex::Global(idx)
1257 }
1258}
1259
1260#[allow(missing_docs)]
1263#[derive(Clone, Debug, Serialize, Deserialize)]
1264pub enum EntityType {
1265 Global(Global),
1267 Memory(Memory),
1269 Tag(Tag),
1271 Table(Table),
1273 Function(EngineOrModuleTypeIndex),
1276}
1277
1278impl TypeTrace for EntityType {
1279 fn trace<F, E>(&self, func: &mut F) -> Result<(), E>
1280 where
1281 F: FnMut(EngineOrModuleTypeIndex) -> Result<(), E>,
1282 {
1283 match self {
1284 Self::Global(g) => g.trace(func),
1285 Self::Table(t) => t.trace(func),
1286 Self::Function(idx) => func(*idx),
1287 Self::Memory(_) | Self::Tag(_) => Ok(()),
1288 }
1289 }
1290
1291 fn trace_mut<F, E>(&mut self, func: &mut F) -> Result<(), E>
1292 where
1293 F: FnMut(&mut EngineOrModuleTypeIndex) -> Result<(), E>,
1294 {
1295 match self {
1296 Self::Global(g) => g.trace_mut(func),
1297 Self::Table(t) => t.trace_mut(func),
1298 Self::Function(idx) => func(idx),
1299 Self::Memory(_) | Self::Tag(_) => Ok(()),
1300 }
1301 }
1302}
1303
1304impl EntityType {
1305 pub fn unwrap_global(&self) -> &Global {
1307 match self {
1308 EntityType::Global(g) => g,
1309 _ => panic!("not a global"),
1310 }
1311 }
1312
1313 pub fn unwrap_memory(&self) -> &Memory {
1315 match self {
1316 EntityType::Memory(g) => g,
1317 _ => panic!("not a memory"),
1318 }
1319 }
1320
1321 pub fn unwrap_tag(&self) -> &Tag {
1323 match self {
1324 EntityType::Tag(g) => g,
1325 _ => panic!("not a tag"),
1326 }
1327 }
1328
1329 pub fn unwrap_table(&self) -> &Table {
1331 match self {
1332 EntityType::Table(g) => g,
1333 _ => panic!("not a table"),
1334 }
1335 }
1336
1337 pub fn unwrap_func(&self) -> EngineOrModuleTypeIndex {
1339 match self {
1340 EntityType::Function(g) => *g,
1341 _ => panic!("not a func"),
1342 }
1343 }
1344}
1345
1346#[derive(Debug, Clone, Copy, Hash, Eq, PartialEq, Serialize, Deserialize)]
1354pub struct Global {
1355 pub wasm_ty: crate::WasmValType,
1357 pub mutability: bool,
1359}
1360
1361impl TypeTrace for Global {
1362 fn trace<F, E>(&self, func: &mut F) -> Result<(), E>
1363 where
1364 F: FnMut(EngineOrModuleTypeIndex) -> Result<(), E>,
1365 {
1366 let Global {
1367 wasm_ty,
1368 mutability: _,
1369 } = self;
1370 wasm_ty.trace(func)
1371 }
1372
1373 fn trace_mut<F, E>(&mut self, func: &mut F) -> Result<(), E>
1374 where
1375 F: FnMut(&mut EngineOrModuleTypeIndex) -> Result<(), E>,
1376 {
1377 let Global {
1378 wasm_ty,
1379 mutability: _,
1380 } = self;
1381 wasm_ty.trace_mut(func)
1382 }
1383}
1384
1385#[derive(Clone, Debug, Eq, PartialEq, Hash, Serialize, Deserialize)]
1389pub struct ConstExpr {
1390 ops: SmallVec<[ConstOp; 2]>,
1391}
1392
1393impl ConstExpr {
1394 pub fn new(ops: impl IntoIterator<Item = ConstOp>) -> Self {
1400 let ops = ops.into_iter().collect::<SmallVec<[ConstOp; 2]>>();
1401 assert!(!ops.is_empty());
1402 ConstExpr { ops }
1403 }
1404
1405 pub fn from_wasmparser(
1410 expr: wasmparser::ConstExpr<'_>,
1411 ) -> WasmResult<(Self, SmallVec<[FuncIndex; 1]>)> {
1412 let mut iter = expr
1413 .get_operators_reader()
1414 .into_iter_with_offsets()
1415 .peekable();
1416
1417 let mut ops = SmallVec::<[ConstOp; 2]>::new();
1418 let mut escaped = SmallVec::<[FuncIndex; 1]>::new();
1419 while let Some(res) = iter.next() {
1420 let (op, offset) = res?;
1421
1422 if matches!(op, wasmparser::Operator::End) && iter.peek().is_none() {
1426 break;
1427 }
1428
1429 if let wasmparser::Operator::RefFunc { function_index } = &op {
1432 escaped.push(FuncIndex::from_u32(*function_index));
1433 }
1434
1435 ops.push(ConstOp::from_wasmparser(op, offset)?);
1436 }
1437 Ok((Self { ops }, escaped))
1438 }
1439
1440 pub fn ops(&self) -> &[ConstOp] {
1442 &self.ops
1443 }
1444
1445 pub fn provably_nonzero_i32(&self) -> bool {
1455 assert!(self.ops.len() > 0);
1456 if self.ops.len() > 1 {
1457 return false;
1460 }
1461 match self.ops[0] {
1463 ConstOp::I32Const(0) => false,
1465 ConstOp::I32Const(_) => true,
1468 _ => false,
1470 }
1471 }
1472}
1473
1474#[allow(missing_docs)]
1476#[derive(Clone, Copy, Debug, Eq, PartialEq, Hash, Serialize, Deserialize)]
1477pub enum ConstOp {
1478 I32Const(i32),
1479 I64Const(i64),
1480 F32Const(u32),
1481 F64Const(u64),
1482 V128Const(u128),
1483 GlobalGet(GlobalIndex),
1484 RefI31,
1485 RefNull,
1486 RefFunc(FuncIndex),
1487 I32Add,
1488 I32Sub,
1489 I32Mul,
1490 I64Add,
1491 I64Sub,
1492 I64Mul,
1493}
1494
1495impl ConstOp {
1496 pub fn from_wasmparser(op: wasmparser::Operator<'_>, offset: usize) -> WasmResult<Self> {
1498 use wasmparser::Operator as O;
1499 Ok(match op {
1500 O::I32Const { value } => Self::I32Const(value),
1501 O::I64Const { value } => Self::I64Const(value),
1502 O::F32Const { value } => Self::F32Const(value.bits()),
1503 O::F64Const { value } => Self::F64Const(value.bits()),
1504 O::V128Const { value } => Self::V128Const(u128::from_le_bytes(*value.bytes())),
1505 O::RefNull { hty: _ } => Self::RefNull,
1506 O::RefFunc { function_index } => Self::RefFunc(FuncIndex::from_u32(function_index)),
1507 O::GlobalGet { global_index } => Self::GlobalGet(GlobalIndex::from_u32(global_index)),
1508 O::RefI31 => Self::RefI31,
1509 O::I32Add => Self::I32Add,
1510 O::I32Sub => Self::I32Sub,
1511 O::I32Mul => Self::I32Mul,
1512 O::I64Add => Self::I64Add,
1513 O::I64Sub => Self::I64Sub,
1514 O::I64Mul => Self::I64Mul,
1515 op => {
1516 return Err(wasm_unsupported!(
1517 "unsupported opcode in const expression at offset {offset:#x}: {op:?}",
1518 ));
1519 }
1520 })
1521 }
1522}
1523
1524#[derive(Debug, Clone, Copy, Hash, Eq, PartialEq, Serialize, Deserialize)]
1526pub struct Table {
1527 pub wasm_ty: WasmRefType,
1529 pub minimum: u32,
1531 pub maximum: Option<u32>,
1533}
1534
1535impl TypeTrace for Table {
1536 fn trace<F, E>(&self, func: &mut F) -> Result<(), E>
1537 where
1538 F: FnMut(EngineOrModuleTypeIndex) -> Result<(), E>,
1539 {
1540 let Table {
1541 wasm_ty,
1542 minimum: _,
1543 maximum: _,
1544 } = self;
1545 wasm_ty.trace(func)
1546 }
1547
1548 fn trace_mut<F, E>(&mut self, func: &mut F) -> Result<(), E>
1549 where
1550 F: FnMut(&mut EngineOrModuleTypeIndex) -> Result<(), E>,
1551 {
1552 let Table {
1553 wasm_ty,
1554 minimum: _,
1555 maximum: _,
1556 } = self;
1557 wasm_ty.trace_mut(func)
1558 }
1559}
1560
1561#[derive(Debug, Clone, Copy, Hash, Eq, PartialEq, Serialize, Deserialize)]
1563pub struct Memory {
1564 pub minimum: u64,
1566 pub maximum: Option<u64>,
1568 pub shared: bool,
1570 pub memory64: bool,
1572 pub page_size_log2: u8,
1577}
1578
1579pub const WASM32_MAX_SIZE: u64 = 1 << 32;
1581
1582impl Memory {
1583 pub const DEFAULT_PAGE_SIZE: u32 = 0x10000;
1585
1586 pub const DEFAULT_PAGE_SIZE_LOG2: u8 = {
1588 let log2 = 16;
1589 assert!(1 << log2 == Memory::DEFAULT_PAGE_SIZE);
1590 log2
1591 };
1592
1593 pub fn minimum_byte_size(&self) -> Result<u64, SizeOverflow> {
1601 self.minimum
1602 .checked_mul(self.page_size())
1603 .ok_or(SizeOverflow)
1604 }
1605
1606 pub fn maximum_byte_size(&self) -> Result<u64, SizeOverflow> {
1621 match self.maximum {
1622 Some(max) => max.checked_mul(self.page_size()).ok_or(SizeOverflow),
1623 None => {
1624 let min = self.minimum_byte_size()?;
1625 Ok(min.max(self.max_size_based_on_index_type()))
1626 }
1627 }
1628 }
1629
1630 pub fn page_size(&self) -> u64 {
1632 debug_assert!(
1633 self.page_size_log2 == 16 || self.page_size_log2 == 0,
1634 "invalid page_size_log2: {}; must be 16 or 0",
1635 self.page_size_log2
1636 );
1637 1 << self.page_size_log2
1638 }
1639
1640 pub fn max_size_based_on_index_type(&self) -> u64 {
1645 if self.memory64 {
1646 0_u64.wrapping_sub(self.page_size())
1654 } else {
1655 WASM32_MAX_SIZE
1656 }
1657 }
1658}
1659
1660#[derive(Copy, Clone, Debug)]
1661pub struct SizeOverflow;
1662
1663impl fmt::Display for SizeOverflow {
1664 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1665 f.write_str("size overflow calculating memory size")
1666 }
1667}
1668
1669#[cfg(feature = "std")]
1670impl std::error::Error for SizeOverflow {}
1671
1672impl From<wasmparser::MemoryType> for Memory {
1673 fn from(ty: wasmparser::MemoryType) -> Memory {
1674 let page_size_log2 = u8::try_from(ty.page_size_log2.unwrap_or(16)).unwrap();
1675 debug_assert!(
1676 page_size_log2 == 16 || page_size_log2 == 0,
1677 "invalid page_size_log2: {page_size_log2}; must be 16 or 0"
1678 );
1679 Memory {
1680 minimum: ty.initial,
1681 maximum: ty.maximum,
1682 shared: ty.shared,
1683 memory64: ty.memory64,
1684 page_size_log2,
1685 }
1686 }
1687}
1688
1689#[derive(Debug, Clone, Copy, Hash, Eq, PartialEq, Serialize, Deserialize)]
1691pub struct Tag {
1692 pub ty: TypeIndex,
1694}
1695
1696impl From<wasmparser::TagType> for Tag {
1697 fn from(ty: wasmparser::TagType) -> Tag {
1698 match ty.kind {
1699 wasmparser::TagKind::Exception => Tag {
1700 ty: TypeIndex::from_u32(ty.func_type_idx),
1701 },
1702 }
1703 }
1704}
1705
1706pub trait TypeConvert {
1708 fn convert_global_type(&self, ty: &wasmparser::GlobalType) -> Global {
1710 Global {
1711 wasm_ty: self.convert_valtype(ty.content_type),
1712 mutability: ty.mutable,
1713 }
1714 }
1715
1716 fn convert_table_type(&self, ty: &wasmparser::TableType) -> WasmResult<Table> {
1718 if ty.table64 {
1719 return Err(wasm_unsupported!("wasm memory64: 64-bit table type"));
1720 }
1721 Ok(Table {
1722 wasm_ty: self.convert_ref_type(ty.element_type),
1723 minimum: ty.initial.try_into().unwrap(),
1724 maximum: ty.maximum.map(|i| i.try_into().unwrap()),
1725 })
1726 }
1727
1728 fn convert_sub_type(&self, ty: &wasmparser::SubType) -> WasmSubType {
1729 WasmSubType {
1730 is_final: ty.is_final,
1731 supertype: ty.supertype_idx.map(|i| self.lookup_type_index(i.unpack())),
1732 composite_type: self.convert_composite_type(&ty.composite_type),
1733 }
1734 }
1735
1736 fn convert_composite_type(&self, ty: &wasmparser::CompositeType) -> WasmCompositeType {
1737 assert!(!ty.shared);
1738 match &ty.inner {
1739 wasmparser::CompositeInnerType::Func(f) => {
1740 WasmCompositeType::Func(self.convert_func_type(f))
1741 }
1742 wasmparser::CompositeInnerType::Array(a) => {
1743 WasmCompositeType::Array(self.convert_array_type(a))
1744 }
1745 wasmparser::CompositeInnerType::Struct(s) => {
1746 WasmCompositeType::Struct(self.convert_struct_type(s))
1747 }
1748 }
1749 }
1750
1751 fn convert_struct_type(&self, ty: &wasmparser::StructType) -> WasmStructType {
1752 WasmStructType {
1753 fields: ty
1754 .fields
1755 .iter()
1756 .map(|f| self.convert_field_type(f))
1757 .collect(),
1758 }
1759 }
1760
1761 fn convert_array_type(&self, ty: &wasmparser::ArrayType) -> WasmArrayType {
1762 WasmArrayType(self.convert_field_type(&ty.0))
1763 }
1764
1765 fn convert_field_type(&self, ty: &wasmparser::FieldType) -> WasmFieldType {
1766 WasmFieldType {
1767 element_type: self.convert_storage_type(&ty.element_type),
1768 mutable: ty.mutable,
1769 }
1770 }
1771
1772 fn convert_storage_type(&self, ty: &wasmparser::StorageType) -> WasmStorageType {
1773 match ty {
1774 wasmparser::StorageType::I8 => WasmStorageType::I8,
1775 wasmparser::StorageType::I16 => WasmStorageType::I16,
1776 wasmparser::StorageType::Val(v) => WasmStorageType::Val(self.convert_valtype(*v)),
1777 }
1778 }
1779
1780 fn convert_func_type(&self, ty: &wasmparser::FuncType) -> WasmFuncType {
1782 let params = ty
1783 .params()
1784 .iter()
1785 .map(|t| self.convert_valtype(*t))
1786 .collect();
1787 let results = ty
1788 .results()
1789 .iter()
1790 .map(|t| self.convert_valtype(*t))
1791 .collect();
1792 WasmFuncType::new(params, results)
1793 }
1794
1795 fn convert_valtype(&self, ty: wasmparser::ValType) -> WasmValType {
1797 match ty {
1798 wasmparser::ValType::I32 => WasmValType::I32,
1799 wasmparser::ValType::I64 => WasmValType::I64,
1800 wasmparser::ValType::F32 => WasmValType::F32,
1801 wasmparser::ValType::F64 => WasmValType::F64,
1802 wasmparser::ValType::V128 => WasmValType::V128,
1803 wasmparser::ValType::Ref(t) => WasmValType::Ref(self.convert_ref_type(t)),
1804 }
1805 }
1806
1807 fn convert_ref_type(&self, ty: wasmparser::RefType) -> WasmRefType {
1809 WasmRefType {
1810 nullable: ty.is_nullable(),
1811 heap_type: self.convert_heap_type(ty.heap_type()),
1812 }
1813 }
1814
1815 fn convert_heap_type(&self, ty: wasmparser::HeapType) -> WasmHeapType {
1817 match ty {
1818 wasmparser::HeapType::Concrete(i) => self.lookup_heap_type(i),
1819 wasmparser::HeapType::Abstract { ty, shared: false } => match ty {
1820 wasmparser::AbstractHeapType::Extern => WasmHeapType::Extern,
1821 wasmparser::AbstractHeapType::NoExtern => WasmHeapType::NoExtern,
1822 wasmparser::AbstractHeapType::Func => WasmHeapType::Func,
1823 wasmparser::AbstractHeapType::NoFunc => WasmHeapType::NoFunc,
1824 wasmparser::AbstractHeapType::Any => WasmHeapType::Any,
1825 wasmparser::AbstractHeapType::Eq => WasmHeapType::Eq,
1826 wasmparser::AbstractHeapType::I31 => WasmHeapType::I31,
1827 wasmparser::AbstractHeapType::Array => WasmHeapType::Array,
1828 wasmparser::AbstractHeapType::Struct => WasmHeapType::Struct,
1829 wasmparser::AbstractHeapType::None => WasmHeapType::None,
1830
1831 wasmparser::AbstractHeapType::Exn | wasmparser::AbstractHeapType::NoExn => {
1832 unimplemented!("unsupported heap type {ty:?}");
1833 }
1834 },
1835 _ => unimplemented!("unsupported heap type {ty:?}"),
1836 }
1837 }
1838
1839 fn lookup_heap_type(&self, index: wasmparser::UnpackedIndex) -> WasmHeapType;
1842
1843 fn lookup_type_index(&self, index: wasmparser::UnpackedIndex) -> EngineOrModuleTypeIndex;
1846}