1use crate::{
10 DefinedGlobalIndex, DefinedMemoryIndex, DefinedTableIndex, DefinedTagIndex, FuncIndex,
11 FuncRefIndex, GlobalIndex, MemoryIndex, Module, ModuleInternedTypeIndex, OwnedMemoryIndex,
12 RuntimeDataIndex, TableIndex, 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) * mut $g:ty) => { u32::from($p) };
52 (@size ($p:expr) i64) => { 8u32 };
53 (@size ($p:expr) u64) => { 8u32 };
54 (@size ($p:expr) u32) => { 4u32 };
55 (@size ($p:expr) NonZeroU32) => { 4u32 };
58 (@size ($p:expr) Option < VMGcRef >) => { 4u32 };
59 (@size ($p:expr) [u8; 16]) => { 16u32 };
60 (@size ($p:expr) [u32; $n:expr]) => { 4u32 * u32::try_from($n).unwrap() };
61 (@size ($p:expr) VMSharedTypeIndex) => { u32::from(($p).size_of_vmshared_type_index()) };
62 (@size ($p:expr) DefinedTableIndex) => { 4u32 };
63 (@size ($p:expr) DefinedMemoryIndex) => { 4u32 };
64 (@size ($p:expr) DefinedTagIndex) => { 4u32 };
65 (@size ($p:expr) VMGlobalKind) => { 8u32 };
66 (@size ($p:expr) Range < *mut u8 >) => { 2u32 * u32::from($p) };
68 (@size ($p:expr) VMMemoryDefinition) => { u32::from(($p).vm_memory_definition().size()) };
71 (@size ($p:expr) VMLazyThread) => { u32::from(($p).vm_lazy_thread().size()) };
72 (@size ($p:expr) VMStackLimits) => { u32::from(($p).vm_stack_limits().size()) };
73 (@size ($p:expr) VMHostArray) => { u32::from(($p).vm_host_array().size()) };
74 (@size ($p:expr) VMCommonStackInformation) => {
75 u32::from(($p).vm_common_stack_information().size())
76 };
77 (@size ($p:expr) VMStackChain) => { u32::from(($p).size_of_vmstack_chain()) };
80 (@size ($p:expr) VMStackState) => { 4u32 };
81 (@size ($p:expr) VMContinuationStack) => { 3u32 * u32::from($p) };
85 (@size ($p:expr) PhantomPinned) => { 0u32 };
86
87 (@align ($p:expr) UnsafeCell < $inner:tt >) => { define_vm_type_offsets!(@align ($p) $inner) };
89
90 (@align ($p:expr) VmPtr < $g:ty >) => { u32::from($p) };
98 (@align ($p:expr) Option < VmPtr < $g:ty >>) => { u32::from($p) };
99 (@align ($p:expr) AtomicUsize) => { u32::from($p) };
100 (@align ($p:expr) usize) => { u32::from($p) };
101 (@align ($p:expr) * mut $g:ty) => { u32::from($p) };
102 (@align ($p:expr) i64) => { 8u32 };
103 (@align ($p:expr) u64) => { 8u32 };
104 (@align ($p:expr) u32) => { 4u32 };
105 (@align ($p:expr) NonZeroU32) => { 4u32 };
106 (@align ($p:expr) Option < VMGcRef >) => { 4u32 };
107 (@align ($p:expr) [u8; 16]) => { 16u32 };
108 (@align ($p:expr) [u32; $n:expr]) => { 4u32 };
109 (@align ($p:expr) VMSharedTypeIndex) => { u32::from(($p).align_of_vmshared_type_index()) };
110 (@align ($p:expr) DefinedTableIndex) => { 4u32 };
111 (@align ($p:expr) DefinedMemoryIndex) => { 4u32 };
112 (@align ($p:expr) DefinedTagIndex) => { 4u32 };
113 (@align ($p:expr) VMGlobalKind) => { 4u32 };
114 (@align ($p:expr) Range < *mut u8 >) => { u32::from($p) };
115 (@align ($p:expr) VMMemoryDefinition) => { u32::from(($p).vm_memory_definition().align()) };
116 (@align ($p:expr) VMLazyThread) => { u32::from(($p).vm_lazy_thread().align()) };
117 (@align ($p:expr) VMStackLimits) => { u32::from(($p).vm_stack_limits().align()) };
118 (@align ($p:expr) VMHostArray) => { u32::from(($p).vm_host_array().align()) };
119 (@align ($p:expr) VMCommonStackInformation) => {
120 u32::from(($p).vm_common_stack_information().align())
121 };
122 (@align ($p:expr) VMStackChain) => { u32::from($p) };
123 (@align ($p:expr) VMStackState) => { 4u32 };
124 (@align ($p:expr) VMContinuationStack) => { u32::from($p) };
125 (@align ($p:expr) PhantomPinned) => { 1u32 };
126
127 (@repr_align C) => { 1u32 };
129 (@repr_align transparent) => { 1u32 };
130 (@repr_align C, align($n:literal)) => {{ let align: u32 = $n; align }};
131
132 (@fields $Name:ident ($p:ident, $o:ident) prefix( $($prefix:tt)* )) => {};
142 (@fields $Name:ident ($p:ident, $o:ident) prefix( $($prefix:tt)* )
143 [ $fname:ident : $($fty:tt)* ]
144 $($rest:tt)*
145 ) => {
146 #[doc = concat!(
147 "The offset of the `", stringify!($fname),
148 "` field of `", stringify!($Name), "`."
149 )]
150 #[inline]
151 pub fn $fname(&self) -> u8 {
152 let $p = self.0.size();
153 let $o: u32 = 0;
154 $($prefix)*
155 let $o = align($o, define_vm_type_offsets!(@align ($p) $($fty)*));
156 let _ = $p;
157 u8::try_from($o).unwrap()
158 }
159 define_vm_type_offsets!(@fields $Name ($p, $o)
160 prefix(
161 $($prefix)*
162 let $o = align($o, define_vm_type_offsets!(@align ($p) $($fty)*));
163 let $o = $o + define_vm_type_offsets!(@size ($p) $($fty)*);
164 )
165 $($rest)*
166 );
167 };
168
169 (@impl $Name:ident [$($repr:tt)*] { $( [ $fname:ident : $($fty:tt)* ] )* }) => {
179 impl<P: PtrSize> $Name<P> {
180 define_vm_type_offsets!(@fields $Name (p, o) prefix()
181 $( [ $fname : $($fty)* ] )*
182 );
183
184 #[doc = concat!("The alignment of the `", stringify!($Name), "` type.")]
185 #[inline]
186 pub fn align(&self) -> u8 {
187 let p = self.0.size();
188 let a: u32 = define_vm_type_offsets!(@repr_align $($repr)*);
189 $(
190 let a = core::cmp::max(
191 a,
192 define_vm_type_offsets!(@align (p) $($fty)*),
193 );
194 )*
195 let _ = p;
196 u8::try_from(a).unwrap()
197 }
198
199 #[doc = concat!("The size of the `", stringify!($Name), "` type.")]
200 #[inline]
201 pub fn size(&self) -> u8 {
202 let p = self.0.size();
203 let o: u32 = 0;
204 $(
205 let o = align(o, define_vm_type_offsets!(@align (p) $($fty)*));
206 let o = o + define_vm_type_offsets!(@size (p) $($fty)*);
207 )*
208 let o = align(o, u32::from(self.align()));
209 let _ = p;
210 u8::try_from(o).unwrap()
211 }
212 }
213 };
214 (@impl $Name:ident $repr:tt { $($groups:tt)* }
219 $(#[$($attr:tt)*])* $fvis:vis $fname:ident : $($rest:tt)*
220 ) => {
221 define_vm_type_offsets!(@impl_ty $Name $repr { $($groups)* } $fname [] $($rest)*);
222 };
223 (@impl_ty $Name:ident $repr:tt { $($groups:tt)* } $fname:ident [ $($fty:tt)* ] , $($rest:tt)*) => {
226 define_vm_type_offsets!(@impl $Name $repr { $($groups)* [ $fname : $($fty)* ] } $($rest)*);
227 };
228 (@impl_ty $Name:ident $repr:tt { $($groups:tt)* } $fname:ident [ $($fty:tt)* ] $tok:tt $($rest:tt)*) => {
229 define_vm_type_offsets!(@impl_ty $Name $repr { $($groups)* } $fname [ $($fty)* $tok ] $($rest)*);
230 };
231
232 ( $(
234 $(#[doc = $sdoc:literal])*
235 $(#[cfg($($scfg:tt)*)])?
236 $(#[derive($($d:ident),*)])?
237 #[repr($($repr:tt)*)]
238 #[snake_name = $snake:ident]
239 $svis:vis struct $Name:ident {
240 $($body:tt)*
241 }
242 )* ) => {
243 $(
244 #[doc = concat!("Offsets of fields within the `", stringify!($Name), "` type.")]
245 pub struct $Name<P: PtrSize>(pub P);
246
247 define_vm_type_offsets!(@impl $Name [$($repr)*] {} $($body)*);
248 )*
249 };
250}
251
252#[allow(
256 unused_macro_rules,
257 reason = "only `VMComponentContext` has a `#[ptr_size_offset]` prefix in its \
258 `dynamic` section, so those arms go unused for `VMContext`"
259)]
260macro_rules! define_vmctx_static_offsets {
261 (@chain $p:ident [ $($prev:tt)* ] [] [ $($dyn:tt)* ]) => {
265 #[inline]
269 pub fn end_of_static_fields(&self) -> u8 {
270 let $p = self.0.size();
271 let _ = $p;
272 u8::try_from($($prev)*).unwrap()
273 }
274
275 define_vmctx_static_offsets!(@dyn_chain $p [ $($prev)* ] [ $($dyn)* ]);
276 };
277 (@chain $p:ident [ $($prev:tt)* ] [ align { $al:tt } $($rest:tt)* ] $dyn:tt) => {
278 define_vmctx_static_offsets!(
279 @chain $p
280 [ crate::vmctxtypes::align_up($($prev)*, vmctx_align_value!(($p) $al)) ]
281 [ $($rest)* ]
282 $dyn
283 );
284 };
285 (@chain $p:ident [ $($prev:tt)* ] [
286 field { $(# $fattr:tt)* $fname:ident : $($fty:tt)* } $($rest:tt)*
287 ] $dyn:tt) => {
288 #[doc = concat!("The offset of the `", stringify!($fname), "` field.")]
289 #[inline]
290 pub fn $fname(&self) -> u8 {
291 let $p = self.0.size();
292 let _ = $p;
293 u8::try_from($($prev)*).unwrap()
294 }
295 define_vmctx_static_offsets!(
296 @chain $p
297 [ $($prev)* + vmctx_field_size!(($p) $($fty)*) ]
298 [ $($rest)* ]
299 $dyn
300 );
301 };
302
303 (@dyn_chain $p:ident [ $($prev:tt)* ] [ align { $al:tt } $($rest:tt)* ]) => {
306 define_vmctx_static_offsets!(
307 @dyn_chain $p
308 [ crate::vmctxtypes::align_up($($prev)*, vmctx_align_value!(($p) $al)) ]
309 [ $($rest)* ]
310 );
311 };
312 (@dyn_chain $p:ident [ $($prev:tt)* ] [
313 field { #[ptr_size_offset] $(# $fattr:tt)* $fname:ident : $($fty:tt)* } $($rest:tt)*
314 ]) => {
315 #[doc = concat!("The offset of the `", stringify!($fname), "` field.")]
316 #[inline]
317 pub fn $fname(&self) -> u32 {
318 let $p = self.0.size();
319 let _ = $p;
320 $($prev)*
321 }
322 define_vmctx_static_offsets!(
323 @dyn_chain $p
324 [ $($prev)* + vmctx_field_size!(($p) $($fty)*) ]
325 [ $($rest)* ]
326 );
327 };
328 (@dyn_chain $p:ident [ $($prev:tt)* ] [
329 array {
330 #[ptr_size_offset] $(# $fattr:tt)*
331 $fname:ident [ $count:ident ; $Index:ident ] : $($fty:tt)*
332 } $($rest:tt)*
333 ]) => {
334 #[doc = concat!(
338 "The offset of the `index`th element of the `", stringify!($fname),
339 "` array.\n\nThis is not bounds checked: the array's length is a \
340 property of the particular module or component being compiled, which \
341 is exactly what this wrapper does not know."
342 )]
343 #[inline]
344 pub fn $fname(&self, index: impl crate::VmctxArrayIndex) -> u32 {
345 let $p = self.0.size();
346 let _ = $p;
347 let index = index.vmctx_array_index();
348 ($($prev)*) + vmctx_field_size!(($p) $($fty)*) * index
349 }
350 };
354 (@dyn_chain $p:ident [ $($prev:tt)* ] [ $($rest:tt)* ]) => {};
356
357 ( $(
358 {
359 $Name:ident $snake:ident
360 static { $($stat:tt)* }
361 dynamic { $($dyn:tt)* }
362 }
363 )* ) => {
364 $(
365 #[doc = concat!("Offsets of the statically-positioned fields within the `",
366 stringify!($Name), "` type.")]
367 pub struct $Name<P: PtrSize>(pub P);
368
369 impl<P: PtrSize> $Name<P> {
370 define_vmctx_static_offsets!(@chain ptr [ 0u32 ] [ $($stat)* ] [ $($dyn)* ]);
371 }
372 )*
373 };
374}
375
376pub mod offsets {
383 use super::{NUM_COMPONENT_CONTEXT_SLOTS, PtrSize, align};
384
385 for_each_vm_type!(define_vm_type_offsets);
386 for_each_vmctx_type!(define_vmctx_static_offsets);
387}
388
389impl<P: PtrSize> offsets::VMStoreContext<P> {
392 pub fn gc_heap_base(&self) -> u8 {
394 let offset = self.gc_heap() + self.0.vm_memory_definition().base();
395 debug_assert!(offset < self.last_wasm_exit_trampoline_fp());
396 offset
397 }
398
399 pub fn gc_heap_current_length(&self) -> u8 {
402 let offset = self.gc_heap() + self.0.vm_memory_definition().current_length();
403 debug_assert!(offset < self.last_wasm_exit_trampoline_fp());
404 offset
405 }
406}
407
408macro_rules! define_ptr_size_vm_type_accessors {
411 ( $(
412 $(#[doc = $sdoc:literal])*
413 $(#[cfg($($scfg:tt)*)])?
414 $(#[derive($($d:ident),*)])?
415 #[repr($($repr:tt)*)]
416 #[snake_name = $snake:ident]
417 $svis:vis struct $Name:ident {
418 $($body:tt)*
419 }
420 )* ) => {
421 $(
422 #[doc = concat!("Get the [`offsets::", stringify!($Name), "`] offsets for this pointer size.")]
423 #[inline]
424 fn $snake(&self) -> offsets::$Name<&Self> {
425 offsets::$Name(self)
426 }
427 )*
428 };
429}
430
431macro_rules! define_ptr_size_vmctx_type_accessors {
434 ( $(
435 {
436 $Name:ident $snake:ident
437 static { $($stat:tt)* }
438 dynamic { $($dyn:tt)* }
439 }
440 )* ) => {
441 $(
442 #[doc = concat!("Get the [`offsets::", stringify!($Name),
443 "`] offsets for this pointer size.")]
444 #[inline]
445 fn $snake(&self) -> offsets::$Name<&Self> {
446 offsets::$Name(self)
447 }
448 )*
449 };
450}
451
452#[derive(Debug, Clone, Copy)]
455pub struct VMOffsets<P> {
456 pub ptr: P,
458 pub num_imported_functions: u32,
460 pub num_imported_tables: u32,
462 pub num_imported_memories: u32,
464 pub num_imported_globals: u32,
466 pub num_imported_tags: u32,
468 pub num_defined_tables: u32,
470 pub num_defined_memories: u32,
472 pub num_owned_memories: u32,
474 pub num_defined_globals: u32,
476 pub num_defined_tags: u32,
478 pub num_escaped_funcs: u32,
481 pub num_runtime_data: u32,
483 pub has_startup_func: bool,
485
486 imported_memories: u32,
488 memories: u32,
489 owned_memories: u32,
490 imported_functions: u32,
491 imported_tables: u32,
492 imported_globals: u32,
493 imported_tags: u32,
494 tables: u32,
495 globals: u32,
496 tags: u32,
497 func_refs: u32,
498 startup_func_ref: u32,
499 runtime_data_bases: u32,
500 runtime_data_lengths: u32,
501 size: u32,
502}
503
504pub trait PtrSize {
506 fn size(&self) -> u8;
508
509 for_each_vm_type!(define_ptr_size_vm_type_accessors);
512
513 for_each_vmctx_type!(define_ptr_size_vmctx_type_accessors);
516
517 #[inline]
519 fn size_of_vmshared_type_index(&self) -> u8 {
520 4
521 }
522
523 #[inline]
525 fn align_of_vmshared_type_index(&self) -> u8 {
526 4
527 }
528
529 #[inline]
531 fn maximum_value_size(&self) -> u8 {
532 self.vm_global_definition().size()
533 }
534
535 #[inline]
537 fn size_of_vmmemory_pointer(&self) -> u8 {
538 self.size()
539 }
540
541 fn vmarray_call_host_func_context_func_ref(&self) -> u8 {
545 u8::try_from(align(
546 u32::try_from(core::mem::size_of::<u32>()).unwrap(),
547 u32::from(self.size()),
548 ))
549 .unwrap()
550 }
551
552 fn size_of_vmstack_chain(&self) -> u8 {
554 2 * self.size()
555 }
556
557 fn vmcontobj_contref(&self) -> u8 {
561 0
562 }
563
564 fn vmcontobj_revision(&self) -> u8 {
566 self.size()
567 }
568
569 fn size_of_vmcontobj(&self) -> u8 {
571 u8::try_from(align(
572 u32::from(self.vmcontobj_revision())
573 + u32::try_from(core::mem::size_of::<usize>()).unwrap(),
574 u32::from(self.size()),
575 ))
576 .unwrap()
577 }
578}
579
580pub trait GetPtrSize {
582 type Ptr: PtrSize;
584
585 fn get_ptr_size(&self) -> &Self::Ptr;
587}
588
589impl<P> GetPtrSize for P
590where
591 P: PtrSize,
592{
593 type Ptr = Self;
594
595 #[inline]
596 fn get_ptr_size(&self) -> &Self::Ptr {
597 self
598 }
599}
600
601#[derive(Clone, Copy)]
603pub struct HostPtr;
604
605impl PtrSize for HostPtr {
606 #[inline]
607 fn size(&self) -> u8 {
608 core::mem::size_of::<usize>() as u8
609 }
610}
611
612impl PtrSize for u8 {
613 #[inline]
614 fn size(&self) -> u8 {
615 *self
616 }
617}
618
619impl<P> PtrSize for &'_ P
620where
621 P: PtrSize + ?Sized,
622{
623 #[inline]
624 fn size(&self) -> u8 {
625 (**self).size()
626 }
627}
628
629#[derive(Debug, Clone, Copy)]
631pub struct VMOffsetsFields<P> {
632 pub ptr: P,
634 pub num_imported_functions: u32,
636 pub num_imported_tables: u32,
638 pub num_imported_memories: u32,
640 pub num_imported_globals: u32,
642 pub num_imported_tags: u32,
644 pub num_defined_tables: u32,
646 pub num_defined_memories: u32,
648 pub num_owned_memories: u32,
650 pub num_defined_globals: u32,
652 pub num_defined_tags: u32,
654 pub num_escaped_funcs: u32,
657 pub num_runtime_data: u32,
659 pub has_startup_func: bool,
661}
662
663impl<P: PtrSize> VMOffsets<P> {
664 pub fn new(ptr: P, module: &Module) -> Self {
666 let num_owned_memories = module
667 .memories
668 .iter()
669 .skip(module.num_imported_memories)
670 .filter(|p| !p.1.shared)
671 .count()
672 .try_into()
673 .unwrap();
674 VMOffsets::from(VMOffsetsFields {
675 ptr,
676 num_imported_functions: cast_to_u32(module.num_imported_funcs),
677 num_imported_tables: cast_to_u32(module.num_imported_tables),
678 num_imported_memories: cast_to_u32(module.num_imported_memories),
679 num_imported_globals: cast_to_u32(module.num_imported_globals),
680 num_imported_tags: cast_to_u32(module.num_imported_tags),
681 num_defined_tables: cast_to_u32(module.num_defined_tables()),
682 num_defined_memories: cast_to_u32(module.num_defined_memories()),
683 num_owned_memories,
684 num_defined_globals: cast_to_u32(module.globals.len() - module.num_imported_globals),
685 num_defined_tags: cast_to_u32(module.tags.len() - module.num_imported_tags),
686 num_escaped_funcs: cast_to_u32(module.num_escaped_funcs),
687 num_runtime_data: cast_to_u32(module.runtime_data.len()),
688 has_startup_func: !module.startup.is_none(),
689 })
690 }
691
692 #[inline]
694 pub fn pointer_size(&self) -> u8 {
695 self.ptr.size()
696 }
697
698 pub fn region_sizes(&self) -> impl Iterator<Item = (&str, u32)> {
703 macro_rules! calculate_sizes {
704 ($($name:ident: $desc:tt,)*) => {{
705 let VMOffsets {
706 ptr: _,
709 num_imported_functions: _,
710 num_imported_tables: _,
711 num_imported_memories: _,
712 num_imported_globals: _,
713 num_imported_tags: _,
714 num_defined_tables: _,
715 num_defined_globals: _,
716 num_defined_memories: _,
717 num_defined_tags: _,
718 num_owned_memories: _,
719 num_escaped_funcs: _,
720 num_runtime_data: _,
721 has_startup_func: _,
722
723 size,
725
726 $($name,)*
729 } = *self;
730
731 let mut last = size;
735 $(
736 assert!($name <= last);
737 let tmp = $name;
738 let $name = last - $name;
739 last = tmp;
740 )*
741 assert_ne!(last, 0);
742 IntoIterator::into_iter([
743 $(($desc, $name),)*
744 ("static vmctx data", last),
745 ])
746 }};
747 }
748
749 calculate_sizes! {
750 runtime_data_lengths: "runtime data lengths",
751 runtime_data_bases: "runtime data base pointers",
752 startup_func_ref: "startup funcref",
753 func_refs: "module functions",
754 tags: "defined tags",
755 globals: "defined globals",
756 tables: "defined tables",
757 imported_tags: "imported tags",
758 imported_globals: "imported globals",
759 imported_tables: "imported tables",
760 imported_functions: "imported functions",
761 owned_memories: "owned memories",
762 memories: "defined memories",
763 imported_memories: "imported memories",
764 }
765 }
766}
767
768impl<P: PtrSize> GetPtrSize for VMOffsets<P> {
769 type Ptr = P;
770
771 #[inline]
772 fn get_ptr_size(&self) -> &Self::Ptr {
773 &self.ptr
774 }
775}
776
777impl<P: PtrSize> From<VMOffsetsFields<P>> for VMOffsets<P> {
778 fn from(fields: VMOffsetsFields<P>) -> VMOffsets<P> {
779 let mut ret = Self {
780 ptr: fields.ptr,
781 num_imported_functions: fields.num_imported_functions,
782 num_imported_tables: fields.num_imported_tables,
783 num_imported_memories: fields.num_imported_memories,
784 num_imported_globals: fields.num_imported_globals,
785 num_imported_tags: fields.num_imported_tags,
786 num_defined_tables: fields.num_defined_tables,
787 num_defined_memories: fields.num_defined_memories,
788 num_owned_memories: fields.num_owned_memories,
789 num_defined_globals: fields.num_defined_globals,
790 num_defined_tags: fields.num_defined_tags,
791 num_escaped_funcs: fields.num_escaped_funcs,
792 num_runtime_data: fields.num_runtime_data,
793 has_startup_func: fields.has_startup_func,
794 imported_memories: 0,
795 memories: 0,
796 owned_memories: 0,
797 imported_functions: 0,
798 imported_tables: 0,
799 imported_globals: 0,
800 imported_tags: 0,
801 tables: 0,
802 globals: 0,
803 tags: 0,
804 func_refs: 0,
805 startup_func_ref: 0,
806 runtime_data_bases: 0,
807 runtime_data_lengths: 0,
808 size: 0,
809 };
810 ret.compute_field_offsets();
811 ret
812 }
813}
814
815impl<P: PtrSize> VMOffsets<P> {
817 pub fn size_of_vmfunction_body_ptr(&self) -> u8 {
819 1 * self.pointer_size()
820 }
821}
822
823impl<P: PtrSize> VMOffsets<P> {
825 #[inline]
827 pub fn size_of_vmtable_definition_current_elements(&self) -> u8 {
828 self.pointer_size()
829 }
830}
831
832impl<P: PtrSize> VMOffsets<P> {
834 #[inline]
836 pub fn size_of_vmshared_type_index(&self) -> u8 {
837 self.ptr.size_of_vmshared_type_index()
838 }
839}
840
841impl_vmctx_array_index! {
842 MemoryIndex,
843 DefinedMemoryIndex,
844 OwnedMemoryIndex,
845 FuncIndex,
846 TableIndex,
847 DefinedTableIndex,
848 GlobalIndex,
849 DefinedGlobalIndex,
850 TagIndex,
851 DefinedTagIndex,
852 FuncRefIndex,
853 RuntimeDataIndex,
854 ModuleInternedTypeIndex,
855}
856
857macro_rules! define_vmoffsets_dynamic_offsets {
860 (@one VMContext $snake:ident { $($dyn:tt)* }) => {
861 impl<P: PtrSize> VMOffsets<P> {
863 define_vmctx_dynamic_offsets!(@accessors (self) [ $($dyn)* ]);
864 define_vmctx_dynamic_offsets!(@compute_fn (self, next) $snake [ $($dyn)* ]);
865
866 #[inline]
868 pub fn size_of_vmctx(&self) -> u32 {
869 self.size
870 }
871 }
872 };
873 (@one $other:ident $snake:ident { $($dyn:tt)* }) => {};
874
875 ( $(
876 {
877 $Name:ident $snake:ident
878 static { $($stat:tt)* }
879 dynamic { $($dyn:tt)* }
880 }
881 )* ) => {
882 $( define_vmoffsets_dynamic_offsets!(@one $Name $snake { $($dyn)* }); )*
883 };
884}
885for_each_vmctx_type!(define_vmoffsets_dynamic_offsets);
886
887impl<P: PtrSize> VMOffsets<P> {
889 #[inline]
891 pub fn vm_gc_header_kind(&self) -> u32 {
892 0
893 }
894
895 #[inline]
897 pub fn vm_gc_header_reserved_bits(&self) -> u32 {
898 self.vm_gc_header_kind()
900 }
901
902 #[inline]
904 pub fn vm_gc_header_ty(&self) -> u32 {
905 self.vm_gc_header_kind() + 4
906 }
907}
908
909impl<P: PtrSize> VMOffsets<P> {
913 #[inline]
915 pub fn vm_drc_header_ref_count(&self) -> u32 {
916 8
917 }
918
919 #[inline]
921 pub fn vm_drc_header_next_over_approximated_stack_root(&self) -> u32 {
922 self.vm_drc_header_ref_count() + 8
923 }
924}
925
926pub const VMCONTEXT_MAGIC: u32 = u32::from_le_bytes(*b"core");
930
931pub const VM_ARRAY_CALL_HOST_FUNC_MAGIC: u32 = u32::from_le_bytes(*b"ACHF");
936
937#[cfg(test)]
938mod tests {
939 use crate::vmoffsets::align;
940
941 #[test]
942 fn alignment() {
943 fn is_aligned(x: u32) -> bool {
944 x % 16 == 0
945 }
946 assert!(is_aligned(align(0, 16)));
947 assert!(is_aligned(align(32, 16)));
948 assert!(is_aligned(align(33, 16)));
949 assert!(is_aligned(align(31, 16)));
950 }
951}
952
953pub const VM_LAZY_THREAD_FORCED: u64 = 1;