1use crate::{
10 DefinedGlobalIndex, DefinedMemoryIndex, DefinedTableIndex, DefinedTagIndex, FuncIndex,
11 FuncRefIndex, GlobalIndex, MemoryIndex, Module, OwnedMemoryIndex, RuntimeDataIndex, TableIndex,
12 TagIndex,
13};
14
15pub const NUM_COMPONENT_CONTEXT_SLOTS: usize = 2;
18
19#[cfg(target_pointer_width = "32")]
20fn cast_to_u32(sz: usize) -> u32 {
21 u32::try_from(sz).unwrap()
22}
23#[cfg(target_pointer_width = "64")]
24fn cast_to_u32(sz: usize) -> u32 {
25 u32::try_from(sz).expect("overflow in cast from usize to u32")
26}
27
28#[inline]
30fn align(offset: u32, width: u32) -> u32 {
31 (offset + (width - 1)) / width * width
32}
33
34macro_rules! define_vm_type_offsets {
38 (@size ($p:expr) UnsafeCell < $inner:tt >) => { define_vm_type_offsets!(@size ($p) $inner) };
41
42 (@size ($p:expr) VmPtr < $g:ty >) => { u32::from($p) };
48 (@size ($p:expr) Option < VmPtr < $g:ty >>) => { u32::from($p) };
49 (@size ($p:expr) AtomicUsize) => { u32::from($p) };
50 (@size ($p:expr) usize) => { u32::from($p) };
51 (@size ($p:expr) i64) => { 8u32 };
52 (@size ($p:expr) u64) => { 8u32 };
53 (@size ($p:expr) u32) => { 4u32 };
54 (@size ($p:expr) [u8; 16]) => { 16u32 };
55 (@size ($p:expr) [u32; $n:expr]) => { 4u32 * u32::try_from($n).unwrap() };
56 (@size ($p:expr) VMSharedTypeIndex) => { u32::from(($p).size_of_vmshared_type_index()) };
57 (@size ($p:expr) DefinedTableIndex) => { 4u32 };
58 (@size ($p:expr) DefinedMemoryIndex) => { 4u32 };
59 (@size ($p:expr) DefinedTagIndex) => { 4u32 };
60 (@size ($p:expr) VMGlobalKind) => { 8u32 };
61 (@size ($p:expr) Range < *mut u8 >) => { 2u32 * u32::from($p) };
63 (@size ($p:expr) VMMemoryDefinition) => { u32::from(($p).vm_memory_definition().size()) };
66 (@size ($p:expr) VMLazyThread) => { u32::from(($p).vm_lazy_thread().size()) };
67 (@size ($p:expr) VMStackChain) => { u32::from(($p).size_of_vmstack_chain()) };
70
71 (@align ($p:expr) UnsafeCell < $inner:tt >) => { define_vm_type_offsets!(@align ($p) $inner) };
73
74 (@align ($p:expr) VmPtr < $g:ty >) => { u32::from($p) };
82 (@align ($p:expr) Option < VmPtr < $g:ty >>) => { u32::from($p) };
83 (@align ($p:expr) AtomicUsize) => { u32::from($p) };
84 (@align ($p:expr) usize) => { u32::from($p) };
85 (@align ($p:expr) i64) => { 8u32 };
86 (@align ($p:expr) u64) => { 8u32 };
87 (@align ($p:expr) u32) => { 4u32 };
88 (@align ($p:expr) [u8; 16]) => { 16u32 };
89 (@align ($p:expr) [u32; $n:expr]) => { 4u32 };
90 (@align ($p:expr) VMSharedTypeIndex) => { u32::from(($p).align_of_vmshared_type_index()) };
91 (@align ($p:expr) DefinedTableIndex) => { 4u32 };
92 (@align ($p:expr) DefinedMemoryIndex) => { 4u32 };
93 (@align ($p:expr) DefinedTagIndex) => { 4u32 };
94 (@align ($p:expr) VMGlobalKind) => { 4u32 };
95 (@align ($p:expr) Range < *mut u8 >) => { u32::from($p) };
96 (@align ($p:expr) VMMemoryDefinition) => { u32::from(($p).vm_memory_definition().align()) };
97 (@align ($p:expr) VMLazyThread) => { u32::from(($p).vm_lazy_thread().align()) };
98 (@align ($p:expr) VMStackChain) => { u32::from($p) };
99
100 (@repr_align C) => { 1u32 };
102 (@repr_align transparent) => { 1u32 };
103 (@repr_align C, align($n:literal)) => {{ let align: u32 = $n; align }};
104
105 (@fields $Name:ident ($p:ident, $o:ident) prefix( $($prefix:tt)* )) => {};
115 (@fields $Name:ident ($p:ident, $o:ident) prefix( $($prefix:tt)* )
116 [ $fname:ident : $($fty:tt)* ]
117 $($rest:tt)*
118 ) => {
119 #[doc = concat!(
120 "The offset of the `", stringify!($fname),
121 "` field of `", stringify!($Name), "`."
122 )]
123 #[inline]
124 pub fn $fname(&self) -> u8 {
125 let $p = self.0.size();
126 let $o: u32 = 0;
127 $($prefix)*
128 let $o = align($o, define_vm_type_offsets!(@align ($p) $($fty)*));
129 let _ = $p;
130 u8::try_from($o).unwrap()
131 }
132 define_vm_type_offsets!(@fields $Name ($p, $o)
133 prefix(
134 $($prefix)*
135 let $o = align($o, define_vm_type_offsets!(@align ($p) $($fty)*));
136 let $o = $o + define_vm_type_offsets!(@size ($p) $($fty)*);
137 )
138 $($rest)*
139 );
140 };
141
142 (@impl $Name:ident [$($repr:tt)*] { $( [ $fname:ident : $($fty:tt)* ] )* }) => {
152 impl<P: PtrSize> $Name<P> {
153 define_vm_type_offsets!(@fields $Name (p, o) prefix()
154 $( [ $fname : $($fty)* ] )*
155 );
156
157 #[doc = concat!("The alignment of the `", stringify!($Name), "` type.")]
158 #[inline]
159 pub fn align(&self) -> u8 {
160 let p = self.0.size();
161 let a: u32 = define_vm_type_offsets!(@repr_align $($repr)*);
162 $(
163 let a = core::cmp::max(
164 a,
165 define_vm_type_offsets!(@align (p) $($fty)*),
166 );
167 )*
168 let _ = p;
169 u8::try_from(a).unwrap()
170 }
171
172 #[doc = concat!("The size of the `", stringify!($Name), "` type.")]
173 #[inline]
174 pub fn size(&self) -> u8 {
175 let p = self.0.size();
176 let o: u32 = 0;
177 $(
178 let o = align(o, define_vm_type_offsets!(@align (p) $($fty)*));
179 let o = o + define_vm_type_offsets!(@size (p) $($fty)*);
180 )*
181 let o = align(o, u32::from(self.align()));
182 let _ = p;
183 u8::try_from(o).unwrap()
184 }
185 }
186 };
187 (@impl $Name:ident $repr:tt { $($groups:tt)* }
192 $(#[$($attr:tt)*])* $fvis:vis $fname:ident : $($rest:tt)*
193 ) => {
194 define_vm_type_offsets!(@impl_ty $Name $repr { $($groups)* } $fname [] $($rest)*);
195 };
196 (@impl_ty $Name:ident $repr:tt { $($groups:tt)* } $fname:ident [ $($fty:tt)* ] , $($rest:tt)*) => {
199 define_vm_type_offsets!(@impl $Name $repr { $($groups)* [ $fname : $($fty)* ] } $($rest)*);
200 };
201 (@impl_ty $Name:ident $repr:tt { $($groups:tt)* } $fname:ident [ $($fty:tt)* ] $tok:tt $($rest:tt)*) => {
202 define_vm_type_offsets!(@impl_ty $Name $repr { $($groups)* } $fname [ $($fty)* $tok ] $($rest)*);
203 };
204
205 ( $(
207 $(#[doc = $sdoc:literal])*
208 $(#[derive($($d:ident),*)])?
209 #[repr($($repr:tt)*)]
210 #[snake_name = $snake:ident]
211 $svis:vis struct $Name:ident {
212 $($body:tt)*
213 }
214 )* ) => {
215 $(
216 #[doc = concat!("Offsets of fields within the `", stringify!($Name), "` type.")]
217 pub struct $Name<P: PtrSize>(pub P);
218
219 define_vm_type_offsets!(@impl $Name [$($repr)*] {} $($body)*);
220 )*
221 };
222}
223
224macro_rules! define_vmctx_static_offsets {
228 (@chain $p:ident [ $($prev:tt)* ] []) => {
231 #[inline]
235 pub fn end_of_static_fields(&self) -> u8 {
236 let $p = self.0.size();
237 let _ = $p;
238 u8::try_from($($prev)*).unwrap()
239 }
240 };
241 (@chain $p:ident [ $($prev:tt)* ] [ align { $al:tt } $($rest:tt)* ]) => {
242 define_vmctx_static_offsets!(
243 @chain $p
244 [ crate::vmctxtypes::align_up($($prev)*, vmctx_align_value!(($p) $al)) ]
245 [ $($rest)* ]
246 );
247 };
248 (@chain $p:ident [ $($prev:tt)* ] [
249 field { $(# $fattr:tt)* $fname:ident : $($fty:tt)* } $($rest:tt)*
250 ]) => {
251 #[doc = concat!("The offset of the `", stringify!($fname), "` field.")]
252 #[inline]
253 pub fn $fname(&self) -> u8 {
254 let $p = self.0.size();
255 let _ = $p;
256 u8::try_from($($prev)*).unwrap()
257 }
258 define_vmctx_static_offsets!(
259 @chain $p
260 [ $($prev)* + vmctx_field_size!(($p) $($fty)*) ]
261 [ $($rest)* ]
262 );
263 };
264
265 ( $(
266 {
267 $Name:ident $snake:ident
268 static { $($stat:tt)* }
269 dynamic { $($dyn:tt)* }
270 }
271 )* ) => {
272 $(
273 #[doc = concat!("Offsets of the statically-positioned fields within the `",
274 stringify!($Name), "` type.")]
275 pub struct $Name<P: PtrSize>(pub P);
276
277 impl<P: PtrSize> $Name<P> {
278 define_vmctx_static_offsets!(@chain ptr [ 0u32 ] [ $($stat)* ]);
279 }
280 )*
281 };
282}
283
284pub mod offsets {
291 use super::{NUM_COMPONENT_CONTEXT_SLOTS, PtrSize, align};
292
293 for_each_vm_type!(define_vm_type_offsets);
294 for_each_vmctx_type!(define_vmctx_static_offsets);
295}
296
297const COMPONENT_CONTEXT_SLOT_SIZE: u8 = 4;
301
302impl<P: PtrSize> offsets::VMStoreContext<P> {
305 pub fn gc_heap_base(&self) -> u8 {
307 let offset = self.gc_heap() + self.0.vm_memory_definition().base();
308 debug_assert!(offset < self.last_wasm_exit_trampoline_fp());
309 offset
310 }
311
312 pub fn gc_heap_current_length(&self) -> u8 {
315 let offset = self.gc_heap() + self.0.vm_memory_definition().current_length();
316 debug_assert!(offset < self.last_wasm_exit_trampoline_fp());
317 offset
318 }
319
320 pub fn component_context_slot(&self, i: u8) -> u8 {
322 assert!(usize::from(i) < NUM_COMPONENT_CONTEXT_SLOTS);
323 self.component_context() + i * COMPONENT_CONTEXT_SLOT_SIZE
324 }
325}
326
327impl<P: PtrSize> offsets::VMDeferredThread<P> {
330 pub fn saved_context_slot(&self, i: u8) -> u8 {
332 assert!(usize::from(i) < NUM_COMPONENT_CONTEXT_SLOTS);
333 self.saved_context() + i * COMPONENT_CONTEXT_SLOT_SIZE
334 }
335}
336
337macro_rules! define_ptr_size_vm_type_accessors {
340 ( $(
341 $(#[doc = $sdoc:literal])*
342 $(#[derive($($d:ident),*)])?
343 #[repr($($repr:tt)*)]
344 #[snake_name = $snake:ident]
345 $svis:vis struct $Name:ident {
346 $($body:tt)*
347 }
348 )* ) => {
349 $(
350 #[doc = concat!("Get the [`offsets::", stringify!($Name), "`] offsets for this pointer size.")]
351 #[inline]
352 fn $snake(&self) -> offsets::$Name<&Self> {
353 offsets::$Name(self)
354 }
355 )*
356 };
357}
358
359macro_rules! define_ptr_size_vmctx_type_accessors {
362 ( $(
363 {
364 $Name:ident $snake:ident
365 static { $($stat:tt)* }
366 dynamic { $($dyn:tt)* }
367 }
368 )* ) => {
369 $(
370 #[doc = concat!("Get the [`offsets::", stringify!($Name),
371 "`] offsets for this pointer size.")]
372 #[inline]
373 fn $snake(&self) -> offsets::$Name<&Self> {
374 offsets::$Name(self)
375 }
376 )*
377 };
378}
379
380#[derive(Debug, Clone, Copy)]
383pub struct VMOffsets<P> {
384 pub ptr: P,
386 pub num_imported_functions: u32,
388 pub num_imported_tables: u32,
390 pub num_imported_memories: u32,
392 pub num_imported_globals: u32,
394 pub num_imported_tags: u32,
396 pub num_defined_tables: u32,
398 pub num_defined_memories: u32,
400 pub num_owned_memories: u32,
402 pub num_defined_globals: u32,
404 pub num_defined_tags: u32,
406 pub num_escaped_funcs: u32,
409 pub num_runtime_data: u32,
411 pub has_startup_func: bool,
413
414 imported_memories: u32,
416 memories: u32,
417 owned_memories: u32,
418 imported_functions: u32,
419 imported_tables: u32,
420 imported_globals: u32,
421 imported_tags: u32,
422 tables: u32,
423 globals: u32,
424 tags: u32,
425 func_refs: u32,
426 startup_func_ref: u32,
427 runtime_data_bases: u32,
428 runtime_data_lengths: u32,
429 size: u32,
430}
431
432pub trait PtrSize {
434 fn size(&self) -> u8;
436
437 for_each_vm_type!(define_ptr_size_vm_type_accessors);
440
441 for_each_vmctx_type!(define_ptr_size_vmctx_type_accessors);
444
445 #[inline]
447 fn size_of_vmshared_type_index(&self) -> u8 {
448 4
449 }
450
451 #[inline]
453 fn align_of_vmshared_type_index(&self) -> u8 {
454 4
455 }
456
457 #[inline]
459 fn maximum_value_size(&self) -> u8 {
460 self.vm_global_definition().size()
461 }
462
463 #[inline]
465 fn size_of_vmmemory_pointer(&self) -> u8 {
466 self.size()
467 }
468
469 fn vmarray_call_host_func_context_func_ref(&self) -> u8 {
473 u8::try_from(align(
474 u32::try_from(core::mem::size_of::<u32>()).unwrap(),
475 u32::from(self.size()),
476 ))
477 .unwrap()
478 }
479
480 fn size_of_vmstack_chain(&self) -> u8 {
482 2 * self.size()
483 }
484
485 fn vmstack_limits_stack_limit(&self) -> u8 {
489 0
490 }
491
492 fn vmstack_limits_last_wasm_entry_fp(&self) -> u8 {
494 self.size()
495 }
496
497 fn vmstack_limits_last_wasm_entry_sp(&self) -> u8 {
499 self.vmstack_limits_last_wasm_entry_fp() + self.size()
500 }
501
502 fn vmstack_limits_last_wasm_entry_trap_handler(&self) -> u8 {
504 self.vmstack_limits_last_wasm_entry_sp() + self.size()
505 }
506
507 fn vmhostarray_length(&self) -> u8 {
511 0
512 }
513
514 fn vmhostarray_capacity(&self) -> u8 {
516 4
517 }
518
519 fn vmhostarray_data(&self) -> u8 {
521 8
522 }
523
524 fn size_of_vmhostarray(&self) -> u8 {
526 8 + self.size()
527 }
528
529 fn vmcommon_stack_information_limits(&self) -> u8 {
533 0 * self.size()
534 }
535
536 fn vmcommon_stack_information_state(&self) -> u8 {
538 4 * self.size()
539 }
540
541 fn vmcommon_stack_information_handlers(&self) -> u8 {
543 u8::try_from(align(
544 self.vmcommon_stack_information_state() as u32 + 4,
545 u32::from(self.size()),
546 ))
547 .unwrap()
548 }
549
550 fn vmcommon_stack_information_first_switch_handler_index(&self) -> u8 {
552 self.vmcommon_stack_information_handlers() + self.size_of_vmhostarray()
553 }
554
555 fn size_of_vmcommon_stack_information(&self) -> u8 {
557 u8::try_from(align(
558 self.vmcommon_stack_information_first_switch_handler_index() as u32 + 4,
559 u32::from(self.size()),
560 ))
561 .unwrap()
562 }
563
564 fn vmcontobj_contref(&self) -> u8 {
568 0
569 }
570
571 fn vmcontobj_revision(&self) -> u8 {
573 self.size()
574 }
575
576 fn size_of_vmcontobj(&self) -> u8 {
578 u8::try_from(align(
579 u32::from(self.vmcontobj_revision())
580 + u32::try_from(core::mem::size_of::<usize>()).unwrap(),
581 u32::from(self.size()),
582 ))
583 .unwrap()
584 }
585
586 fn vmcontref_common_stack_information(&self) -> u8 {
590 0 * self.size()
591 }
592
593 fn vmcontref_parent_chain(&self) -> u8 {
595 u8::try_from(align(
596 (self.vmcontref_common_stack_information() + self.size_of_vmcommon_stack_information())
597 as u32,
598 u32::from(self.size()),
599 ))
600 .unwrap()
601 }
602
603 fn vmcontref_last_ancestor(&self) -> u8 {
605 self.vmcontref_parent_chain() + 2 * self.size()
606 }
607
608 fn vmcontref_revision(&self) -> u8 {
610 self.vmcontref_last_ancestor() + self.size()
611 }
612
613 fn vmcontref_stack(&self) -> u8 {
615 self.vmcontref_revision() + self.size()
616 }
617
618 fn vmcontref_args(&self) -> u8 {
620 self.vmcontref_stack() + 3 * self.size()
621 }
622
623 fn vmcontref_values(&self) -> u8 {
625 self.vmcontref_args() + self.size_of_vmhostarray()
626 }
627
628 #[inline]
631 fn vmdrc_heap_data_over_approximated_stack_roots(&self) -> u8 {
632 0
633 }
634
635 #[inline]
638 fn vmdrc_heap_data_current_over_approximated_stack_roots_len(&self) -> u8 {
639 4
640 }
641
642 #[inline]
646 fn vmdrc_heap_data_over_approximated_stack_roots_len_after_last_gc(&self) -> u8 {
647 8
648 }
649
650 #[inline]
652 fn size_of_vmdrc_heap_data(&self) -> u8 {
653 12
654 }
655
656 #[inline]
658 fn align_of_vmdrc_heap_data(&self) -> u8 {
659 4
660 }
661
662 #[inline]
664 fn vmcopying_heap_data_bump_ptr(&self) -> u8 {
665 0
666 }
667
668 #[inline]
671 fn vmcopying_heap_data_active_space_end(&self) -> u8 {
672 4
673 }
674
675 #[inline]
677 fn size_of_vmcopying_heap_data(&self) -> u8 {
678 8
679 }
680
681 #[inline]
683 fn align_of_vmcopying_heap_data(&self) -> u8 {
684 4
685 }
686}
687
688pub trait GetPtrSize {
690 type Ptr: PtrSize;
692
693 fn get_ptr_size(&self) -> &Self::Ptr;
695}
696
697impl<P> GetPtrSize for P
698where
699 P: PtrSize,
700{
701 type Ptr = Self;
702
703 #[inline]
704 fn get_ptr_size(&self) -> &Self::Ptr {
705 self
706 }
707}
708
709#[derive(Clone, Copy)]
711pub struct HostPtr;
712
713impl PtrSize for HostPtr {
714 #[inline]
715 fn size(&self) -> u8 {
716 core::mem::size_of::<usize>() as u8
717 }
718}
719
720impl PtrSize for u8 {
721 #[inline]
722 fn size(&self) -> u8 {
723 *self
724 }
725}
726
727impl<P> PtrSize for &'_ P
728where
729 P: PtrSize + ?Sized,
730{
731 #[inline]
732 fn size(&self) -> u8 {
733 (**self).size()
734 }
735}
736
737#[derive(Debug, Clone, Copy)]
739pub struct VMOffsetsFields<P> {
740 pub ptr: P,
742 pub num_imported_functions: u32,
744 pub num_imported_tables: u32,
746 pub num_imported_memories: u32,
748 pub num_imported_globals: u32,
750 pub num_imported_tags: u32,
752 pub num_defined_tables: u32,
754 pub num_defined_memories: u32,
756 pub num_owned_memories: u32,
758 pub num_defined_globals: u32,
760 pub num_defined_tags: u32,
762 pub num_escaped_funcs: u32,
765 pub num_runtime_data: u32,
767 pub has_startup_func: bool,
769}
770
771impl<P: PtrSize> VMOffsets<P> {
772 pub fn new(ptr: P, module: &Module) -> Self {
774 let num_owned_memories = module
775 .memories
776 .iter()
777 .skip(module.num_imported_memories)
778 .filter(|p| !p.1.shared)
779 .count()
780 .try_into()
781 .unwrap();
782 VMOffsets::from(VMOffsetsFields {
783 ptr,
784 num_imported_functions: cast_to_u32(module.num_imported_funcs),
785 num_imported_tables: cast_to_u32(module.num_imported_tables),
786 num_imported_memories: cast_to_u32(module.num_imported_memories),
787 num_imported_globals: cast_to_u32(module.num_imported_globals),
788 num_imported_tags: cast_to_u32(module.num_imported_tags),
789 num_defined_tables: cast_to_u32(module.num_defined_tables()),
790 num_defined_memories: cast_to_u32(module.num_defined_memories()),
791 num_owned_memories,
792 num_defined_globals: cast_to_u32(module.globals.len() - module.num_imported_globals),
793 num_defined_tags: cast_to_u32(module.tags.len() - module.num_imported_tags),
794 num_escaped_funcs: cast_to_u32(module.num_escaped_funcs),
795 num_runtime_data: cast_to_u32(module.runtime_data.len()),
796 has_startup_func: !module.startup.is_none(),
797 })
798 }
799
800 #[inline]
802 pub fn pointer_size(&self) -> u8 {
803 self.ptr.size()
804 }
805
806 pub fn region_sizes(&self) -> impl Iterator<Item = (&str, u32)> {
811 macro_rules! calculate_sizes {
812 ($($name:ident: $desc:tt,)*) => {{
813 let VMOffsets {
814 ptr: _,
817 num_imported_functions: _,
818 num_imported_tables: _,
819 num_imported_memories: _,
820 num_imported_globals: _,
821 num_imported_tags: _,
822 num_defined_tables: _,
823 num_defined_globals: _,
824 num_defined_memories: _,
825 num_defined_tags: _,
826 num_owned_memories: _,
827 num_escaped_funcs: _,
828 num_runtime_data: _,
829 has_startup_func: _,
830
831 size,
833
834 $($name,)*
837 } = *self;
838
839 let mut last = size;
843 $(
844 assert!($name <= last);
845 let tmp = $name;
846 let $name = last - $name;
847 last = tmp;
848 )*
849 assert_ne!(last, 0);
850 IntoIterator::into_iter([
851 $(($desc, $name),)*
852 ("static vmctx data", last),
853 ])
854 }};
855 }
856
857 calculate_sizes! {
858 runtime_data_lengths: "runtime data lengths",
859 runtime_data_bases: "runtime data base pointers",
860 startup_func_ref: "startup funcref",
861 func_refs: "module functions",
862 tags: "defined tags",
863 globals: "defined globals",
864 tables: "defined tables",
865 imported_tags: "imported tags",
866 imported_globals: "imported globals",
867 imported_tables: "imported tables",
868 imported_functions: "imported functions",
869 owned_memories: "owned memories",
870 memories: "defined memories",
871 imported_memories: "imported memories",
872 }
873 }
874}
875
876impl<P: PtrSize> GetPtrSize for VMOffsets<P> {
877 type Ptr = P;
878
879 #[inline]
880 fn get_ptr_size(&self) -> &Self::Ptr {
881 &self.ptr
882 }
883}
884
885impl<P: PtrSize> From<VMOffsetsFields<P>> for VMOffsets<P> {
886 fn from(fields: VMOffsetsFields<P>) -> VMOffsets<P> {
887 let mut ret = Self {
888 ptr: fields.ptr,
889 num_imported_functions: fields.num_imported_functions,
890 num_imported_tables: fields.num_imported_tables,
891 num_imported_memories: fields.num_imported_memories,
892 num_imported_globals: fields.num_imported_globals,
893 num_imported_tags: fields.num_imported_tags,
894 num_defined_tables: fields.num_defined_tables,
895 num_defined_memories: fields.num_defined_memories,
896 num_owned_memories: fields.num_owned_memories,
897 num_defined_globals: fields.num_defined_globals,
898 num_defined_tags: fields.num_defined_tags,
899 num_escaped_funcs: fields.num_escaped_funcs,
900 num_runtime_data: fields.num_runtime_data,
901 has_startup_func: fields.has_startup_func,
902 imported_memories: 0,
903 memories: 0,
904 owned_memories: 0,
905 imported_functions: 0,
906 imported_tables: 0,
907 imported_globals: 0,
908 imported_tags: 0,
909 tables: 0,
910 globals: 0,
911 tags: 0,
912 func_refs: 0,
913 startup_func_ref: 0,
914 runtime_data_bases: 0,
915 runtime_data_lengths: 0,
916 size: 0,
917 };
918 ret.compute_field_offsets();
919 ret
920 }
921}
922
923impl<P: PtrSize> VMOffsets<P> {
925 pub fn size_of_vmfunction_body_ptr(&self) -> u8 {
927 1 * self.pointer_size()
928 }
929}
930
931impl<P: PtrSize> VMOffsets<P> {
933 #[inline]
935 pub fn size_of_vmtable_definition_current_elements(&self) -> u8 {
936 self.pointer_size()
937 }
938}
939
940impl<P: PtrSize> VMOffsets<P> {
942 #[inline]
944 pub fn size_of_vmshared_type_index(&self) -> u8 {
945 self.ptr.size_of_vmshared_type_index()
946 }
947}
948
949impl_vmctx_array_index! {
950 MemoryIndex,
951 DefinedMemoryIndex,
952 OwnedMemoryIndex,
953 FuncIndex,
954 TableIndex,
955 DefinedTableIndex,
956 GlobalIndex,
957 DefinedGlobalIndex,
958 TagIndex,
959 DefinedTagIndex,
960 FuncRefIndex,
961 RuntimeDataIndex,
962}
963
964macro_rules! define_vmoffsets_dynamic_offsets {
967 (@one VMContext $snake:ident { $($dyn:tt)* }) => {
968 impl<P: PtrSize> VMOffsets<P> {
970 define_vmctx_dynamic_offsets!(@accessors (self) [ $($dyn)* ]);
971 define_vmctx_dynamic_offsets!(@compute_fn (self, next) $snake [ $($dyn)* ]);
972
973 #[inline]
975 pub fn size_of_vmctx(&self) -> u32 {
976 self.size
977 }
978 }
979 };
980 (@one $other:ident $snake:ident { $($dyn:tt)* }) => {};
981
982 ( $(
983 {
984 $Name:ident $snake:ident
985 static { $($stat:tt)* }
986 dynamic { $($dyn:tt)* }
987 }
988 )* ) => {
989 $( define_vmoffsets_dynamic_offsets!(@one $Name $snake { $($dyn)* }); )*
990 };
991}
992for_each_vmctx_type!(define_vmoffsets_dynamic_offsets);
993
994impl<P: PtrSize> VMOffsets<P> {
996 #[inline]
998 pub fn vm_gc_header_kind(&self) -> u32 {
999 0
1000 }
1001
1002 #[inline]
1004 pub fn vm_gc_header_reserved_bits(&self) -> u32 {
1005 self.vm_gc_header_kind()
1007 }
1008
1009 #[inline]
1011 pub fn vm_gc_header_ty(&self) -> u32 {
1012 self.vm_gc_header_kind() + 4
1013 }
1014}
1015
1016impl<P: PtrSize> VMOffsets<P> {
1020 #[inline]
1022 pub fn vm_drc_header_ref_count(&self) -> u32 {
1023 8
1024 }
1025
1026 #[inline]
1028 pub fn vm_drc_header_next_over_approximated_stack_root(&self) -> u32 {
1029 self.vm_drc_header_ref_count() + 8
1030 }
1031}
1032
1033pub const VMCONTEXT_MAGIC: u32 = u32::from_le_bytes(*b"core");
1037
1038pub const VM_ARRAY_CALL_HOST_FUNC_MAGIC: u32 = u32::from_le_bytes(*b"ACHF");
1043
1044#[cfg(test)]
1045mod tests {
1046 use crate::vmoffsets::align;
1047
1048 #[test]
1049 fn alignment() {
1050 fn is_aligned(x: u32) -> bool {
1051 x % 16 == 0
1052 }
1053 assert!(is_aligned(align(0, 16)));
1054 assert!(is_aligned(align(32, 16)));
1055 assert!(is_aligned(align(33, 16)));
1056 assert!(is_aligned(align(31, 16)));
1057 }
1058}
1059
1060pub const VM_LAZY_THREAD_FORCED: u64 = 1;