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}
1488
1489impl ConstOp {
1490 pub fn from_wasmparser(op: wasmparser::Operator<'_>, offset: usize) -> WasmResult<Self> {
1492 use wasmparser::Operator as O;
1493 Ok(match op {
1494 O::I32Const { value } => Self::I32Const(value),
1495 O::I64Const { value } => Self::I64Const(value),
1496 O::F32Const { value } => Self::F32Const(value.bits()),
1497 O::F64Const { value } => Self::F64Const(value.bits()),
1498 O::V128Const { value } => Self::V128Const(u128::from_le_bytes(*value.bytes())),
1499 O::RefNull { hty: _ } => Self::RefNull,
1500 O::RefFunc { function_index } => Self::RefFunc(FuncIndex::from_u32(function_index)),
1501 O::GlobalGet { global_index } => Self::GlobalGet(GlobalIndex::from_u32(global_index)),
1502 O::RefI31 => Self::RefI31,
1503 op => {
1504 return Err(wasm_unsupported!(
1505 "unsupported opcode in const expression at offset {offset:#x}: {op:?}",
1506 ));
1507 }
1508 })
1509 }
1510}
1511
1512#[derive(Debug, Clone, Copy, Hash, Eq, PartialEq, Serialize, Deserialize)]
1514pub struct Table {
1515 pub wasm_ty: WasmRefType,
1517 pub minimum: u32,
1519 pub maximum: Option<u32>,
1521}
1522
1523impl TypeTrace for Table {
1524 fn trace<F, E>(&self, func: &mut F) -> Result<(), E>
1525 where
1526 F: FnMut(EngineOrModuleTypeIndex) -> Result<(), E>,
1527 {
1528 let Table {
1529 wasm_ty,
1530 minimum: _,
1531 maximum: _,
1532 } = self;
1533 wasm_ty.trace(func)
1534 }
1535
1536 fn trace_mut<F, E>(&mut self, func: &mut F) -> Result<(), E>
1537 where
1538 F: FnMut(&mut EngineOrModuleTypeIndex) -> Result<(), E>,
1539 {
1540 let Table {
1541 wasm_ty,
1542 minimum: _,
1543 maximum: _,
1544 } = self;
1545 wasm_ty.trace_mut(func)
1546 }
1547}
1548
1549#[derive(Debug, Clone, Copy, Hash, Eq, PartialEq, Serialize, Deserialize)]
1551pub struct Memory {
1552 pub minimum: u64,
1554 pub maximum: Option<u64>,
1556 pub shared: bool,
1558 pub memory64: bool,
1560 pub page_size_log2: u8,
1565}
1566
1567pub const WASM32_MAX_SIZE: u64 = 1 << 32;
1569
1570impl Memory {
1571 pub const DEFAULT_PAGE_SIZE: u32 = 0x10000;
1573
1574 pub const DEFAULT_PAGE_SIZE_LOG2: u8 = {
1576 let log2 = 16;
1577 assert!(1 << log2 == Memory::DEFAULT_PAGE_SIZE);
1578 log2
1579 };
1580
1581 pub fn minimum_byte_size(&self) -> Result<u64, SizeOverflow> {
1589 self.minimum
1590 .checked_mul(self.page_size())
1591 .ok_or(SizeOverflow)
1592 }
1593
1594 pub fn maximum_byte_size(&self) -> Result<u64, SizeOverflow> {
1609 match self.maximum {
1610 Some(max) => max.checked_mul(self.page_size()).ok_or(SizeOverflow),
1611 None => {
1612 let min = self.minimum_byte_size()?;
1613 Ok(min.max(self.max_size_based_on_index_type()))
1614 }
1615 }
1616 }
1617
1618 pub fn page_size(&self) -> u64 {
1620 debug_assert!(
1621 self.page_size_log2 == 16 || self.page_size_log2 == 0,
1622 "invalid page_size_log2: {}; must be 16 or 0",
1623 self.page_size_log2
1624 );
1625 1 << self.page_size_log2
1626 }
1627
1628 pub fn max_size_based_on_index_type(&self) -> u64 {
1633 if self.memory64 {
1634 0_u64.wrapping_sub(self.page_size())
1642 } else {
1643 WASM32_MAX_SIZE
1644 }
1645 }
1646}
1647
1648#[derive(Copy, Clone, Debug)]
1649pub struct SizeOverflow;
1650
1651impl fmt::Display for SizeOverflow {
1652 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1653 f.write_str("size overflow calculating memory size")
1654 }
1655}
1656
1657#[cfg(feature = "std")]
1658impl std::error::Error for SizeOverflow {}
1659
1660impl From<wasmparser::MemoryType> for Memory {
1661 fn from(ty: wasmparser::MemoryType) -> Memory {
1662 let page_size_log2 = u8::try_from(ty.page_size_log2.unwrap_or(16)).unwrap();
1663 debug_assert!(
1664 page_size_log2 == 16 || page_size_log2 == 0,
1665 "invalid page_size_log2: {}; must be 16 or 0",
1666 page_size_log2
1667 );
1668 Memory {
1669 minimum: ty.initial,
1670 maximum: ty.maximum,
1671 shared: ty.shared,
1672 memory64: ty.memory64,
1673 page_size_log2,
1674 }
1675 }
1676}
1677
1678#[derive(Debug, Clone, Copy, Hash, Eq, PartialEq, Serialize, Deserialize)]
1680pub struct Tag {
1681 pub ty: TypeIndex,
1683}
1684
1685impl From<wasmparser::TagType> for Tag {
1686 fn from(ty: wasmparser::TagType) -> Tag {
1687 match ty.kind {
1688 wasmparser::TagKind::Exception => Tag {
1689 ty: TypeIndex::from_u32(ty.func_type_idx),
1690 },
1691 }
1692 }
1693}
1694
1695pub trait TypeConvert {
1697 fn convert_global_type(&self, ty: &wasmparser::GlobalType) -> Global {
1699 Global {
1700 wasm_ty: self.convert_valtype(ty.content_type),
1701 mutability: ty.mutable,
1702 }
1703 }
1704
1705 fn convert_table_type(&self, ty: &wasmparser::TableType) -> WasmResult<Table> {
1707 if ty.table64 {
1708 return Err(wasm_unsupported!("wasm memory64: 64-bit table type"));
1709 }
1710 Ok(Table {
1711 wasm_ty: self.convert_ref_type(ty.element_type),
1712 minimum: ty.initial.try_into().unwrap(),
1713 maximum: ty.maximum.map(|i| i.try_into().unwrap()),
1714 })
1715 }
1716
1717 fn convert_sub_type(&self, ty: &wasmparser::SubType) -> WasmSubType {
1718 WasmSubType {
1719 is_final: ty.is_final,
1720 supertype: ty.supertype_idx.map(|i| self.lookup_type_index(i.unpack())),
1721 composite_type: self.convert_composite_type(&ty.composite_type),
1722 }
1723 }
1724
1725 fn convert_composite_type(&self, ty: &wasmparser::CompositeType) -> WasmCompositeType {
1726 assert!(!ty.shared);
1727 match &ty.inner {
1728 wasmparser::CompositeInnerType::Func(f) => {
1729 WasmCompositeType::Func(self.convert_func_type(f))
1730 }
1731 wasmparser::CompositeInnerType::Array(a) => {
1732 WasmCompositeType::Array(self.convert_array_type(a))
1733 }
1734 wasmparser::CompositeInnerType::Struct(s) => {
1735 WasmCompositeType::Struct(self.convert_struct_type(s))
1736 }
1737 }
1738 }
1739
1740 fn convert_struct_type(&self, ty: &wasmparser::StructType) -> WasmStructType {
1741 WasmStructType {
1742 fields: ty
1743 .fields
1744 .iter()
1745 .map(|f| self.convert_field_type(f))
1746 .collect(),
1747 }
1748 }
1749
1750 fn convert_array_type(&self, ty: &wasmparser::ArrayType) -> WasmArrayType {
1751 WasmArrayType(self.convert_field_type(&ty.0))
1752 }
1753
1754 fn convert_field_type(&self, ty: &wasmparser::FieldType) -> WasmFieldType {
1755 WasmFieldType {
1756 element_type: self.convert_storage_type(&ty.element_type),
1757 mutable: ty.mutable,
1758 }
1759 }
1760
1761 fn convert_storage_type(&self, ty: &wasmparser::StorageType) -> WasmStorageType {
1762 match ty {
1763 wasmparser::StorageType::I8 => WasmStorageType::I8,
1764 wasmparser::StorageType::I16 => WasmStorageType::I16,
1765 wasmparser::StorageType::Val(v) => WasmStorageType::Val(self.convert_valtype(*v)),
1766 }
1767 }
1768
1769 fn convert_func_type(&self, ty: &wasmparser::FuncType) -> WasmFuncType {
1771 let params = ty
1772 .params()
1773 .iter()
1774 .map(|t| self.convert_valtype(*t))
1775 .collect();
1776 let results = ty
1777 .results()
1778 .iter()
1779 .map(|t| self.convert_valtype(*t))
1780 .collect();
1781 WasmFuncType::new(params, results)
1782 }
1783
1784 fn convert_valtype(&self, ty: wasmparser::ValType) -> WasmValType {
1786 match ty {
1787 wasmparser::ValType::I32 => WasmValType::I32,
1788 wasmparser::ValType::I64 => WasmValType::I64,
1789 wasmparser::ValType::F32 => WasmValType::F32,
1790 wasmparser::ValType::F64 => WasmValType::F64,
1791 wasmparser::ValType::V128 => WasmValType::V128,
1792 wasmparser::ValType::Ref(t) => WasmValType::Ref(self.convert_ref_type(t)),
1793 }
1794 }
1795
1796 fn convert_ref_type(&self, ty: wasmparser::RefType) -> WasmRefType {
1798 WasmRefType {
1799 nullable: ty.is_nullable(),
1800 heap_type: self.convert_heap_type(ty.heap_type()),
1801 }
1802 }
1803
1804 fn convert_heap_type(&self, ty: wasmparser::HeapType) -> WasmHeapType {
1806 match ty {
1807 wasmparser::HeapType::Concrete(i) => self.lookup_heap_type(i),
1808 wasmparser::HeapType::Abstract { ty, shared: false } => match ty {
1809 wasmparser::AbstractHeapType::Extern => WasmHeapType::Extern,
1810 wasmparser::AbstractHeapType::NoExtern => WasmHeapType::NoExtern,
1811 wasmparser::AbstractHeapType::Func => WasmHeapType::Func,
1812 wasmparser::AbstractHeapType::NoFunc => WasmHeapType::NoFunc,
1813 wasmparser::AbstractHeapType::Any => WasmHeapType::Any,
1814 wasmparser::AbstractHeapType::Eq => WasmHeapType::Eq,
1815 wasmparser::AbstractHeapType::I31 => WasmHeapType::I31,
1816 wasmparser::AbstractHeapType::Array => WasmHeapType::Array,
1817 wasmparser::AbstractHeapType::Struct => WasmHeapType::Struct,
1818 wasmparser::AbstractHeapType::None => WasmHeapType::None,
1819
1820 wasmparser::AbstractHeapType::Exn | wasmparser::AbstractHeapType::NoExn => {
1821 unimplemented!("unsupported heap type {ty:?}");
1822 }
1823 },
1824 _ => unimplemented!("unsupported heap type {ty:?}"),
1825 }
1826 }
1827
1828 fn lookup_heap_type(&self, index: wasmparser::UnpackedIndex) -> WasmHeapType;
1831
1832 fn lookup_type_index(&self, index: wasmparser::UnpackedIndex) -> EngineOrModuleTypeIndex;
1835}