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) i64) => { 8u32 };
52 (@size ($p:expr) u64) => { 8u32 };
53 (@size ($p:expr) u32) => { 4u32 };
54 (@size ($p:expr) NonZeroU32) => { 4u32 };
57 (@size ($p:expr) Option < VMGcRef >) => { 4u32 };
58 (@size ($p:expr) [u8; 16]) => { 16u32 };
59 (@size ($p:expr) [u32; $n:expr]) => { 4u32 * u32::try_from($n).unwrap() };
60 (@size ($p:expr) VMSharedTypeIndex) => { u32::from(($p).size_of_vmshared_type_index()) };
61 (@size ($p:expr) DefinedTableIndex) => { 4u32 };
62 (@size ($p:expr) DefinedMemoryIndex) => { 4u32 };
63 (@size ($p:expr) DefinedTagIndex) => { 4u32 };
64 (@size ($p:expr) VMGlobalKind) => { 8u32 };
65 (@size ($p:expr) Range < *mut u8 >) => { 2u32 * u32::from($p) };
67 (@size ($p:expr) VMMemoryDefinition) => { u32::from(($p).vm_memory_definition().size()) };
70 (@size ($p:expr) VMLazyThread) => { u32::from(($p).vm_lazy_thread().size()) };
71 (@size ($p:expr) VMStackLimits) => { u32::from(($p).vm_stack_limits().size()) };
72 (@size ($p:expr) VMHostArray) => { u32::from(($p).vm_host_array().size()) };
73 (@size ($p:expr) VMPayloads) => { u32::from(($p).vm_payloads().size()) };
74 (@size ($p:expr) VMCommonStackInformation) => {
75 u32::from(($p).vm_common_stack_information().size())
76 };
77 (@size ($p:expr) VMGcHeader) => { u32::from(($p).vm_gc_header().size()) };
78 (@size ($p:expr) VMStackChain) => { u32::from(($p).size_of_vmstack_chain()) };
81 (@size ($p:expr) VMStackState) => { 4u32 };
82 (@size ($p:expr) VMContinuationStack) => { 3u32 * u32::from($p) };
86 (@size ($p:expr) PhantomPinned) => { 0u32 };
87
88 (@align ($p:expr) UnsafeCell < $inner:tt >) => { define_vm_type_offsets!(@align ($p) $inner) };
90
91 (@align ($p:expr) VmPtr < $g:ty >) => { u32::from($p) };
99 (@align ($p:expr) Option < VmPtr < $g:ty >>) => { u32::from($p) };
100 (@align ($p:expr) AtomicUsize) => { u32::from($p) };
101 (@align ($p:expr) usize) => { 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) VMPayloads) => { u32::from(($p).vm_payloads().align()) };
120 (@align ($p:expr) VMCommonStackInformation) => {
121 u32::from(($p).vm_common_stack_information().align())
122 };
123 (@align ($p:expr) VMGcHeader) => { u32::from(($p).vm_gc_header().align()) };
124 (@align ($p:expr) VMStackChain) => { u32::from($p) };
125 (@align ($p:expr) VMStackState) => { 4u32 };
126 (@align ($p:expr) VMContinuationStack) => { u32::from($p) };
127 (@align ($p:expr) PhantomPinned) => { 1u32 };
128
129 (@repr_align C) => { 1u32 };
131 (@repr_align transparent) => { 1u32 };
132 (@repr_align C, align($n:literal)) => {{ let align: u32 = $n; align }};
133
134 (@fields $Name:ident ($p:ident, $o:ident) prefix( $($prefix:tt)* )) => {};
144 (@fields $Name:ident ($p:ident, $o:ident) prefix( $($prefix:tt)* )
145 [ $fname:ident : $($fty:tt)* ]
146 $($rest:tt)*
147 ) => {
148 #[doc = concat!(
149 "The offset of the `", stringify!($fname),
150 "` field of `", stringify!($Name), "`."
151 )]
152 #[inline]
153 pub fn $fname(&self) -> u8 {
154 let $p = self.0.size();
155 let $o: u32 = 0;
156 $($prefix)*
157 let $o = align($o, define_vm_type_offsets!(@align ($p) $($fty)*));
158 let _ = $p;
159 u8::try_from($o).unwrap()
160 }
161 define_vm_type_offsets!(@fields $Name ($p, $o)
162 prefix(
163 $($prefix)*
164 let $o = align($o, define_vm_type_offsets!(@align ($p) $($fty)*));
165 let $o = $o + define_vm_type_offsets!(@size ($p) $($fty)*);
166 )
167 $($rest)*
168 );
169 };
170
171 (@impl $Name:ident [$($repr:tt)*] { $( [ $fname:ident : $($fty:tt)* ] )* }) => {
181 impl<P: PtrSize> $Name<P> {
182 define_vm_type_offsets!(@fields $Name (p, o) prefix()
183 $( [ $fname : $($fty)* ] )*
184 );
185
186 #[doc = concat!("The alignment of the `", stringify!($Name), "` type.")]
187 #[inline]
188 pub fn align(&self) -> u8 {
189 let p = self.0.size();
190 let a: u32 = define_vm_type_offsets!(@repr_align $($repr)*);
191 $(
192 let a = core::cmp::max(
193 a,
194 define_vm_type_offsets!(@align (p) $($fty)*),
195 );
196 )*
197 let _ = p;
198 u8::try_from(a).unwrap()
199 }
200
201 #[doc = concat!("The size of the `", stringify!($Name), "` type.")]
202 #[inline]
203 pub fn size(&self) -> u8 {
204 let p = self.0.size();
205 let o: u32 = 0;
206 $(
207 let o = align(o, define_vm_type_offsets!(@align (p) $($fty)*));
208 let o = o + define_vm_type_offsets!(@size (p) $($fty)*);
209 )*
210 let o = align(o, u32::from(self.align()));
211 let _ = p;
212 u8::try_from(o).unwrap()
213 }
214 }
215 };
216 (@impl $Name:ident $repr:tt { $($groups:tt)* }
221 $(#[$($attr:tt)*])* $fvis:vis $fname:ident : $($rest:tt)*
222 ) => {
223 define_vm_type_offsets!(@impl_ty $Name $repr { $($groups)* } $fname [] $($rest)*);
224 };
225 (@impl_ty $Name:ident $repr:tt { $($groups:tt)* } $fname:ident [ $($fty:tt)* ] , $($rest:tt)*) => {
228 define_vm_type_offsets!(@impl $Name $repr { $($groups)* [ $fname : $($fty)* ] } $($rest)*);
229 };
230 (@impl_ty $Name:ident $repr:tt { $($groups:tt)* } $fname:ident [ $($fty:tt)* ] $tok:tt $($rest:tt)*) => {
231 define_vm_type_offsets!(@impl_ty $Name $repr { $($groups)* } $fname [ $($fty)* $tok ] $($rest)*);
232 };
233
234 ( $(
236 $(#[doc = $sdoc:literal])*
237 $(#[cfg($($scfg:tt)*)])?
238 $(#[derive($($d:ident),*)])?
239 #[repr($($repr:tt)*)]
240 #[snake_name = $snake:ident]
241 $svis:vis struct $Name:ident {
242 $($body:tt)*
243 }
244 )* ) => {
245 $(
246 #[doc = concat!("Offsets of fields within the `", stringify!($Name), "` type.")]
247 pub struct $Name<P: PtrSize>(pub P);
248
249 define_vm_type_offsets!(@impl $Name [$($repr)*] {} $($body)*);
250 )*
251 };
252}
253
254#[allow(
258 unused_macro_rules,
259 reason = "only `VMComponentContext` has a `#[ptr_size_offset]` prefix in its \
260 `dynamic` section, so those arms go unused for `VMContext`"
261)]
262macro_rules! define_vmctx_static_offsets {
263 (@chain $p:ident [ $($prev:tt)* ] [] [ $($dyn:tt)* ]) => {
267 #[inline]
271 pub fn end_of_static_fields(&self) -> u8 {
272 let $p = self.0.size();
273 let _ = $p;
274 u8::try_from($($prev)*).unwrap()
275 }
276
277 define_vmctx_static_offsets!(@dyn_chain $p [ $($prev)* ] [ $($dyn)* ]);
278 };
279 (@chain $p:ident [ $($prev:tt)* ] [ align { $al:tt } $($rest:tt)* ] $dyn:tt) => {
280 define_vmctx_static_offsets!(
281 @chain $p
282 [ crate::vmctxtypes::align_up($($prev)*, vmctx_align_value!(($p) $al)) ]
283 [ $($rest)* ]
284 $dyn
285 );
286 };
287 (@chain $p:ident [ $($prev:tt)* ] [
288 field { $(# $fattr:tt)* $fname:ident : $($fty:tt)* } $($rest:tt)*
289 ] $dyn:tt) => {
290 #[doc = concat!("The offset of the `", stringify!($fname), "` field.")]
291 #[inline]
292 pub fn $fname(&self) -> u8 {
293 let $p = self.0.size();
294 let _ = $p;
295 u8::try_from($($prev)*).unwrap()
296 }
297 define_vmctx_static_offsets!(
298 @chain $p
299 [ $($prev)* + vmctx_field_size!(($p) $($fty)*) ]
300 [ $($rest)* ]
301 $dyn
302 );
303 };
304
305 (@dyn_chain $p:ident [ $($prev:tt)* ] [ align { $al:tt } $($rest:tt)* ]) => {
308 define_vmctx_static_offsets!(
309 @dyn_chain $p
310 [ crate::vmctxtypes::align_up($($prev)*, vmctx_align_value!(($p) $al)) ]
311 [ $($rest)* ]
312 );
313 };
314 (@dyn_chain $p:ident [ $($prev:tt)* ] [
315 field { #[ptr_size_offset] $(# $fattr:tt)* $fname:ident : $($fty:tt)* } $($rest:tt)*
316 ]) => {
317 #[doc = concat!("The offset of the `", stringify!($fname), "` field.")]
318 #[inline]
319 pub fn $fname(&self) -> u32 {
320 let $p = self.0.size();
321 let _ = $p;
322 $($prev)*
323 }
324 define_vmctx_static_offsets!(
325 @dyn_chain $p
326 [ $($prev)* + vmctx_field_size!(($p) $($fty)*) ]
327 [ $($rest)* ]
328 );
329 };
330 (@dyn_chain $p:ident [ $($prev:tt)* ] [
331 array {
332 #[ptr_size_offset] $(# $fattr:tt)*
333 $fname:ident [ $count:ident ; $Index:ident ] : $($fty:tt)*
334 } $($rest:tt)*
335 ]) => {
336 #[doc = concat!(
340 "The offset of the `index`th element of the `", stringify!($fname),
341 "` array.\n\nThis is not bounds checked: the array's length is a \
342 property of the particular module or component being compiled, which \
343 is exactly what this wrapper does not know."
344 )]
345 #[inline]
346 pub fn $fname(&self, index: impl crate::VmctxArrayIndex) -> u32 {
347 let $p = self.0.size();
348 let _ = $p;
349 let index = index.vmctx_array_index();
350 ($($prev)*) + vmctx_field_size!(($p) $($fty)*) * index
351 }
352 };
356 (@dyn_chain $p:ident [ $($prev:tt)* ] [ $($rest:tt)* ]) => {};
358
359 ( $(
360 {
361 $Name:ident $snake:ident
362 static { $($stat:tt)* }
363 dynamic { $($dyn:tt)* }
364 }
365 )* ) => {
366 $(
367 #[doc = concat!("Offsets of the statically-positioned fields within the `",
368 stringify!($Name), "` type.")]
369 pub struct $Name<P: PtrSize>(pub P);
370
371 impl<P: PtrSize> $Name<P> {
372 define_vmctx_static_offsets!(@chain ptr [ 0u32 ] [ $($stat)* ] [ $($dyn)* ]);
373 }
374 )*
375 };
376}
377
378pub mod offsets {
385 use super::{NUM_COMPONENT_CONTEXT_SLOTS, PtrSize, align};
386
387 for_each_vm_type!(define_vm_type_offsets);
388 for_each_vmctx_type!(define_vmctx_static_offsets);
389}
390
391impl<P: PtrSize> offsets::VMStoreContext<P> {
394 pub fn gc_heap_base(&self) -> u8 {
396 let offset = self.gc_heap() + self.0.vm_memory_definition().base();
397 debug_assert!(offset < self.last_wasm_exit_trampoline_fp());
398 offset
399 }
400
401 pub fn gc_heap_current_length(&self) -> u8 {
404 let offset = self.gc_heap() + self.0.vm_memory_definition().current_length();
405 debug_assert!(offset < self.last_wasm_exit_trampoline_fp());
406 offset
407 }
408}
409
410macro_rules! define_ptr_size_vm_type_accessors {
413 ( $(
414 $(#[doc = $sdoc:literal])*
415 $(#[cfg($($scfg:tt)*)])?
416 $(#[derive($($d:ident),*)])?
417 #[repr($($repr:tt)*)]
418 #[snake_name = $snake:ident]
419 $svis:vis struct $Name:ident {
420 $($body:tt)*
421 }
422 )* ) => {
423 $(
424 #[doc = concat!("Get the [`offsets::", stringify!($Name), "`] offsets for this pointer size.")]
425 #[inline]
426 fn $snake(&self) -> offsets::$Name<&Self> {
427 offsets::$Name(self)
428 }
429 )*
430 };
431}
432
433macro_rules! define_ptr_size_vmctx_type_accessors {
436 ( $(
437 {
438 $Name:ident $snake:ident
439 static { $($stat:tt)* }
440 dynamic { $($dyn:tt)* }
441 }
442 )* ) => {
443 $(
444 #[doc = concat!("Get the [`offsets::", stringify!($Name),
445 "`] offsets for this pointer size.")]
446 #[inline]
447 fn $snake(&self) -> offsets::$Name<&Self> {
448 offsets::$Name(self)
449 }
450 )*
451 };
452}
453
454#[derive(Debug, Clone, Copy)]
457pub struct VMOffsets<P> {
458 pub ptr: P,
460 pub num_imported_functions: u32,
462 pub num_imported_tables: u32,
464 pub num_imported_memories: u32,
466 pub num_imported_globals: u32,
468 pub num_imported_tags: u32,
470 pub num_defined_tables: u32,
472 pub num_defined_memories: u32,
474 pub num_owned_memories: u32,
476 pub num_defined_globals: u32,
478 pub num_defined_tags: u32,
480 pub num_escaped_funcs: u32,
483 pub num_runtime_data: u32,
485 pub has_startup_func: bool,
487
488 imported_memories: u32,
490 memories: u32,
491 owned_memories: u32,
492 imported_functions: u32,
493 imported_tables: u32,
494 imported_globals: u32,
495 imported_tags: u32,
496 tables: u32,
497 globals: u32,
498 tags: u32,
499 func_refs: u32,
500 startup_func_ref: u32,
501 runtime_data_bases: u32,
502 runtime_data_lengths: u32,
503 size: u32,
504}
505
506pub trait PtrSize {
508 fn size(&self) -> u8;
510
511 for_each_vm_type!(define_ptr_size_vm_type_accessors);
514
515 for_each_vmctx_type!(define_ptr_size_vmctx_type_accessors);
518
519 #[inline]
521 fn size_of_vmshared_type_index(&self) -> u8 {
522 4
523 }
524
525 #[inline]
527 fn align_of_vmshared_type_index(&self) -> u8 {
528 4
529 }
530
531 #[inline]
533 fn maximum_value_size(&self) -> u8 {
534 self.vm_global_definition().size()
535 }
536
537 #[inline]
539 fn size_of_vmmemory_pointer(&self) -> u8 {
540 self.size()
541 }
542
543 fn vmarray_call_host_func_context_func_ref(&self) -> u8 {
547 u8::try_from(align(
548 u32::try_from(core::mem::size_of::<u32>()).unwrap(),
549 u32::from(self.size()),
550 ))
551 .unwrap()
552 }
553
554 fn size_of_vmstack_chain(&self) -> u8 {
556 2 * self.size()
557 }
558
559 fn vmcontobj_contref(&self) -> u8 {
563 0
564 }
565
566 fn vmcontobj_revision(&self) -> u8 {
568 self.size()
569 }
570
571 fn size_of_vmcontobj(&self) -> u8 {
573 u8::try_from(align(
574 u32::from(self.vmcontobj_revision())
575 + u32::try_from(core::mem::size_of::<usize>()).unwrap(),
576 u32::from(self.size()),
577 ))
578 .unwrap()
579 }
580}
581
582pub trait GetPtrSize {
584 type Ptr: PtrSize;
586
587 fn get_ptr_size(&self) -> &Self::Ptr;
589}
590
591impl<P> GetPtrSize for P
592where
593 P: PtrSize,
594{
595 type Ptr = Self;
596
597 #[inline]
598 fn get_ptr_size(&self) -> &Self::Ptr {
599 self
600 }
601}
602
603#[derive(Clone, Copy)]
605pub struct HostPtr;
606
607impl PtrSize for HostPtr {
608 #[inline]
609 fn size(&self) -> u8 {
610 core::mem::size_of::<usize>() as u8
611 }
612}
613
614impl PtrSize for u8 {
615 #[inline]
616 fn size(&self) -> u8 {
617 *self
618 }
619}
620
621impl<P> PtrSize for &'_ P
622where
623 P: PtrSize + ?Sized,
624{
625 #[inline]
626 fn size(&self) -> u8 {
627 (**self).size()
628 }
629}
630
631#[derive(Debug, Clone, Copy)]
633pub struct VMOffsetsFields<P> {
634 pub ptr: P,
636 pub num_imported_functions: u32,
638 pub num_imported_tables: u32,
640 pub num_imported_memories: u32,
642 pub num_imported_globals: u32,
644 pub num_imported_tags: u32,
646 pub num_defined_tables: u32,
648 pub num_defined_memories: u32,
650 pub num_owned_memories: u32,
652 pub num_defined_globals: u32,
654 pub num_defined_tags: u32,
656 pub num_escaped_funcs: u32,
659 pub num_runtime_data: u32,
661 pub has_startup_func: bool,
663}
664
665impl<P: PtrSize> VMOffsets<P> {
666 pub fn new(ptr: P, module: &Module) -> Self {
668 let num_owned_memories = module
669 .memories
670 .iter()
671 .skip(module.num_imported_memories)
672 .filter(|p| !p.1.shared)
673 .count()
674 .try_into()
675 .unwrap();
676 VMOffsets::from(VMOffsetsFields {
677 ptr,
678 num_imported_functions: cast_to_u32(module.num_imported_funcs),
679 num_imported_tables: cast_to_u32(module.num_imported_tables),
680 num_imported_memories: cast_to_u32(module.num_imported_memories),
681 num_imported_globals: cast_to_u32(module.num_imported_globals),
682 num_imported_tags: cast_to_u32(module.num_imported_tags),
683 num_defined_tables: cast_to_u32(module.num_defined_tables()),
684 num_defined_memories: cast_to_u32(module.num_defined_memories()),
685 num_owned_memories,
686 num_defined_globals: cast_to_u32(module.globals.len() - module.num_imported_globals),
687 num_defined_tags: cast_to_u32(module.tags.len() - module.num_imported_tags),
688 num_escaped_funcs: cast_to_u32(module.num_escaped_funcs),
689 num_runtime_data: cast_to_u32(module.runtime_data.len()),
690 has_startup_func: !module.startup.is_none(),
691 })
692 }
693
694 #[inline]
696 pub fn pointer_size(&self) -> u8 {
697 self.ptr.size()
698 }
699
700 pub fn region_sizes(&self) -> impl Iterator<Item = (&str, u32)> {
705 macro_rules! calculate_sizes {
706 ($($name:ident: $desc:tt,)*) => {{
707 let VMOffsets {
708 ptr: _,
711 num_imported_functions: _,
712 num_imported_tables: _,
713 num_imported_memories: _,
714 num_imported_globals: _,
715 num_imported_tags: _,
716 num_defined_tables: _,
717 num_defined_globals: _,
718 num_defined_memories: _,
719 num_defined_tags: _,
720 num_owned_memories: _,
721 num_escaped_funcs: _,
722 num_runtime_data: _,
723 has_startup_func: _,
724
725 size,
727
728 $($name,)*
731 } = *self;
732
733 let mut last = size;
737 $(
738 assert!($name <= last);
739 let tmp = $name;
740 let $name = last - $name;
741 last = tmp;
742 )*
743 assert_ne!(last, 0);
744 IntoIterator::into_iter([
745 $(($desc, $name),)*
746 ("static vmctx data", last),
747 ])
748 }};
749 }
750
751 calculate_sizes! {
752 runtime_data_lengths: "runtime data lengths",
753 runtime_data_bases: "runtime data base pointers",
754 startup_func_ref: "startup funcref",
755 func_refs: "module functions",
756 tags: "defined tags",
757 globals: "defined globals",
758 tables: "defined tables",
759 imported_tags: "imported tags",
760 imported_globals: "imported globals",
761 imported_tables: "imported tables",
762 imported_functions: "imported functions",
763 owned_memories: "owned memories",
764 memories: "defined memories",
765 imported_memories: "imported memories",
766 }
767 }
768}
769
770impl<P: PtrSize> GetPtrSize for VMOffsets<P> {
771 type Ptr = P;
772
773 #[inline]
774 fn get_ptr_size(&self) -> &Self::Ptr {
775 &self.ptr
776 }
777}
778
779impl<P: PtrSize> From<VMOffsetsFields<P>> for VMOffsets<P> {
780 fn from(fields: VMOffsetsFields<P>) -> VMOffsets<P> {
781 let mut ret = Self {
782 ptr: fields.ptr,
783 num_imported_functions: fields.num_imported_functions,
784 num_imported_tables: fields.num_imported_tables,
785 num_imported_memories: fields.num_imported_memories,
786 num_imported_globals: fields.num_imported_globals,
787 num_imported_tags: fields.num_imported_tags,
788 num_defined_tables: fields.num_defined_tables,
789 num_defined_memories: fields.num_defined_memories,
790 num_owned_memories: fields.num_owned_memories,
791 num_defined_globals: fields.num_defined_globals,
792 num_defined_tags: fields.num_defined_tags,
793 num_escaped_funcs: fields.num_escaped_funcs,
794 num_runtime_data: fields.num_runtime_data,
795 has_startup_func: fields.has_startup_func,
796 imported_memories: 0,
797 memories: 0,
798 owned_memories: 0,
799 imported_functions: 0,
800 imported_tables: 0,
801 imported_globals: 0,
802 imported_tags: 0,
803 tables: 0,
804 globals: 0,
805 tags: 0,
806 func_refs: 0,
807 startup_func_ref: 0,
808 runtime_data_bases: 0,
809 runtime_data_lengths: 0,
810 size: 0,
811 };
812 ret.compute_field_offsets();
813 ret
814 }
815}
816
817impl<P: PtrSize> VMOffsets<P> {
819 pub fn size_of_vmfunction_body_ptr(&self) -> u8 {
821 1 * self.pointer_size()
822 }
823}
824
825impl<P: PtrSize> VMOffsets<P> {
827 #[inline]
829 pub fn size_of_vmtable_definition_current_elements(&self) -> u8 {
830 self.pointer_size()
831 }
832}
833
834impl<P: PtrSize> VMOffsets<P> {
836 #[inline]
838 pub fn size_of_vmshared_type_index(&self) -> u8 {
839 self.ptr.size_of_vmshared_type_index()
840 }
841}
842
843impl_vmctx_array_index! {
844 MemoryIndex,
845 DefinedMemoryIndex,
846 OwnedMemoryIndex,
847 FuncIndex,
848 TableIndex,
849 DefinedTableIndex,
850 GlobalIndex,
851 DefinedGlobalIndex,
852 TagIndex,
853 DefinedTagIndex,
854 FuncRefIndex,
855 RuntimeDataIndex,
856 ModuleInternedTypeIndex,
857}
858
859macro_rules! define_vmoffsets_dynamic_offsets {
862 (@one VMContext $snake:ident { $($dyn:tt)* }) => {
863 impl<P: PtrSize> VMOffsets<P> {
865 define_vmctx_dynamic_offsets!(@accessors (self) [ $($dyn)* ]);
866 define_vmctx_dynamic_offsets!(@compute_fn (self, next) $snake [ $($dyn)* ]);
867
868 #[inline]
870 pub fn size_of_vmctx(&self) -> u32 {
871 self.size
872 }
873 }
874 };
875 (@one $other:ident $snake:ident { $($dyn:tt)* }) => {};
876
877 ( $(
878 {
879 $Name:ident $snake:ident
880 static { $($stat:tt)* }
881 dynamic { $($dyn:tt)* }
882 }
883 )* ) => {
884 $( define_vmoffsets_dynamic_offsets!(@one $Name $snake { $($dyn)* }); )*
885 };
886}
887for_each_vmctx_type!(define_vmoffsets_dynamic_offsets);
888
889pub const VMCONTEXT_MAGIC: u32 = u32::from_le_bytes(*b"core");
893
894pub const VM_ARRAY_CALL_HOST_FUNC_MAGIC: u32 = u32::from_le_bytes(*b"ACHF");
899
900#[cfg(test)]
901mod tests {
902 use crate::vmoffsets::align;
903
904 #[test]
905 fn alignment() {
906 fn is_aligned(x: u32) -> bool {
907 x % 16 == 0
908 }
909 assert!(is_aligned(align(0, 16)));
910 assert!(is_aligned(align(32, 16)));
911 assert!(is_aligned(align(33, 16)));
912 assert!(is_aligned(align(31, 16)));
913 }
914}
915
916pub const VM_LAZY_THREAD_FORCED: u64 = 1;