1use crate::{
40 DefinedGlobalIndex, DefinedMemoryIndex, DefinedTableIndex, DefinedTagIndex, FuncIndex,
41 FuncRefIndex, GlobalIndex, MemoryIndex, Module, OwnedMemoryIndex, RuntimeDataIndex, TableIndex,
42 TagIndex,
43};
44use cranelift_entity::packed_option::ReservedValue;
45
46pub const NUM_COMPONENT_CONTEXT_SLOTS: usize = 2;
49
50#[cfg(target_pointer_width = "32")]
51fn cast_to_u32(sz: usize) -> u32 {
52 u32::try_from(sz).unwrap()
53}
54#[cfg(target_pointer_width = "64")]
55fn cast_to_u32(sz: usize) -> u32 {
56 u32::try_from(sz).expect("overflow in cast from usize to u32")
57}
58
59#[inline]
61fn align(offset: u32, width: u32) -> u32 {
62 (offset + (width - 1)) / width * width
63}
64
65#[derive(Debug, Clone, Copy)]
68pub struct VMOffsets<P> {
69 pub ptr: P,
71 pub num_imported_functions: u32,
73 pub num_imported_tables: u32,
75 pub num_imported_memories: u32,
77 pub num_imported_globals: u32,
79 pub num_imported_tags: u32,
81 pub num_defined_tables: u32,
83 pub num_defined_memories: u32,
85 pub num_owned_memories: u32,
87 pub num_defined_globals: u32,
89 pub num_defined_tags: u32,
91 pub num_escaped_funcs: u32,
94 pub num_runtime_data: u32,
96 pub has_startup_func: bool,
98
99 imported_functions: u32,
101 imported_tables: u32,
102 imported_memories: u32,
103 imported_globals: u32,
104 imported_tags: u32,
105 defined_tables: u32,
106 defined_memories: u32,
107 owned_memories: u32,
108 defined_globals: u32,
109 defined_tags: u32,
110 defined_func_refs: u32,
111 startup_func_ref: u32,
112 runtime_data_bases: u32,
113 runtime_data_lengths: u32,
114 size: u32,
115}
116
117pub trait PtrSize {
119 fn size(&self) -> u8;
121
122 fn vmcontext_store_context(&self) -> u8 {
124 u8::try_from(align(
125 u32::try_from(core::mem::size_of::<u32>()).unwrap(),
126 u32::from(self.size()),
127 ))
128 .unwrap()
129 }
130
131 fn vmcontext_builtin_functions(&self) -> u8 {
133 self.vmcontext_store_context() + self.size()
134 }
135
136 #[inline]
138 fn vm_func_ref_array_call(&self) -> u8 {
139 0 * self.size()
140 }
141
142 #[inline]
144 fn vm_func_ref_wasm_call(&self) -> u8 {
145 1 * self.size()
146 }
147
148 #[inline]
150 fn vm_func_ref_type_index(&self) -> u8 {
151 2 * self.size()
152 }
153
154 #[inline]
156 fn vm_func_ref_vmctx(&self) -> u8 {
157 3 * self.size()
158 }
159
160 #[inline]
162 fn size_of_vm_func_ref(&self) -> u8 {
163 4 * self.size()
164 }
165
166 #[inline]
169 fn size_of_vmglobal_definition(&self) -> u8 {
170 16
171 }
172
173 #[inline]
175 fn size_of_vmtag_definition(&self) -> u8 {
176 4
177 }
178
179 #[inline]
181 fn maximum_value_size(&self) -> u8 {
182 self.size_of_vmglobal_definition()
183 }
184
185 #[inline]
189 fn vmstore_context_fuel_consumed(&self) -> u8 {
190 0
191 }
192
193 #[inline]
195 fn vmstore_context_epoch_deadline(&self) -> u8 {
196 self.vmstore_context_fuel_consumed() + 8
197 }
198
199 #[inline]
202 fn vmstore_context_execution_version(&self) -> u8 {
203 self.vmstore_context_epoch_deadline() + 8
204 }
205
206 #[inline]
208 fn vmstore_context_stack_limit(&self) -> u8 {
209 self.vmstore_context_execution_version() + 8
210 }
211
212 #[inline]
214 fn vmstore_context_gc_heap(&self) -> u8 {
215 self.vmstore_context_stack_limit() + self.size()
216 }
217
218 fn vmstore_context_gc_heap_base(&self) -> u8 {
220 let offset = self.vmstore_context_gc_heap() + self.vmmemory_definition_base();
221 debug_assert!(offset < self.vmstore_context_last_wasm_exit_trampoline_fp());
222 offset
223 }
224
225 fn vmstore_context_gc_heap_current_length(&self) -> u8 {
227 let offset = self.vmstore_context_gc_heap() + self.vmmemory_definition_current_length();
228 debug_assert!(offset < self.vmstore_context_last_wasm_exit_trampoline_fp());
229 offset
230 }
231
232 fn vmstore_context_last_wasm_exit_trampoline_fp(&self) -> u8 {
235 self.vmstore_context_gc_heap() + self.size_of_vmmemory_definition()
236 }
237
238 fn vmstore_context_last_wasm_exit_pc(&self) -> u8 {
240 self.vmstore_context_last_wasm_exit_trampoline_fp() + self.size()
241 }
242
243 fn vmstore_context_last_wasm_entry_sp(&self) -> u8 {
245 self.vmstore_context_last_wasm_exit_pc() + self.size()
246 }
247
248 fn vmstore_context_last_wasm_entry_fp(&self) -> u8 {
250 self.vmstore_context_last_wasm_entry_sp() + self.size()
251 }
252
253 fn vmstore_context_last_wasm_entry_trap_handler(&self) -> u8 {
255 self.vmstore_context_last_wasm_entry_fp() + self.size()
256 }
257
258 fn vmstore_context_stack_chain(&self) -> u8 {
260 self.vmstore_context_last_wasm_entry_trap_handler() + self.size()
261 }
262
263 fn vmstore_context_store_data(&self) -> u8 {
265 self.vmstore_context_stack_chain() + self.size_of_vmstack_chain()
266 }
267
268 fn vmstore_context_async_guard_range(&self) -> u8 {
270 self.vmstore_context_store_data() + self.size()
271 }
272
273 fn vmstore_context_component_context_slot(&self, i: u8) -> u8 {
276 assert!(usize::from(i) < NUM_COMPONENT_CONTEXT_SLOTS);
277 let base = self.vmstore_context_async_guard_range() + 2 * self.size();
278 let slot_size = 4;
279 base + i * slot_size
280 }
281
282 #[inline]
286 fn vmmemory_definition_base(&self) -> u8 {
287 0 * self.size()
288 }
289
290 #[inline]
292 fn vmmemory_definition_current_length(&self) -> u8 {
293 1 * self.size()
294 }
295
296 #[inline]
298 fn size_of_vmmemory_definition(&self) -> u8 {
299 2 * self.size()
300 }
301
302 #[inline]
304 fn size_of_vmmemory_pointer(&self) -> u8 {
305 self.size()
306 }
307
308 fn vmarray_call_host_func_context_func_ref(&self) -> u8 {
312 u8::try_from(align(
313 u32::try_from(core::mem::size_of::<u32>()).unwrap(),
314 u32::from(self.size()),
315 ))
316 .unwrap()
317 }
318
319 fn size_of_vmstack_chain(&self) -> u8 {
321 2 * self.size()
322 }
323
324 fn vmstack_limits_stack_limit(&self) -> u8 {
328 0
329 }
330
331 fn vmstack_limits_last_wasm_entry_fp(&self) -> u8 {
333 self.size()
334 }
335
336 fn vmhostarray_length(&self) -> u8 {
340 0
341 }
342
343 fn vmhostarray_capacity(&self) -> u8 {
345 4
346 }
347
348 fn vmhostarray_data(&self) -> u8 {
350 8
351 }
352
353 fn size_of_vmhostarray(&self) -> u8 {
355 8 + self.size()
356 }
357
358 fn vmcommon_stack_information_limits(&self) -> u8 {
362 0 * self.size()
363 }
364
365 fn vmcommon_stack_information_state(&self) -> u8 {
367 2 * self.size()
368 }
369
370 fn vmcommon_stack_information_handlers(&self) -> u8 {
372 u8::try_from(align(
373 self.vmcommon_stack_information_state() as u32 + 4,
374 u32::from(self.size()),
375 ))
376 .unwrap()
377 }
378
379 fn vmcommon_stack_information_first_switch_handler_index(&self) -> u8 {
381 self.vmcommon_stack_information_handlers() + self.size_of_vmhostarray()
382 }
383
384 fn size_of_vmcommon_stack_information(&self) -> u8 {
386 u8::try_from(align(
387 self.vmcommon_stack_information_first_switch_handler_index() as u32 + 4,
388 u32::from(self.size()),
389 ))
390 .unwrap()
391 }
392
393 fn vmcontobj_contref(&self) -> u8 {
397 0
398 }
399
400 fn vmcontobj_revision(&self) -> u8 {
402 self.size()
403 }
404
405 fn size_of_vmcontobj(&self) -> u8 {
407 u8::try_from(align(
408 u32::from(self.vmcontobj_revision())
409 + u32::try_from(core::mem::size_of::<usize>()).unwrap(),
410 u32::from(self.size()),
411 ))
412 .unwrap()
413 }
414
415 fn vmcontref_common_stack_information(&self) -> u8 {
419 0 * self.size()
420 }
421
422 fn vmcontref_parent_chain(&self) -> u8 {
424 u8::try_from(align(
425 (self.vmcontref_common_stack_information() + self.size_of_vmcommon_stack_information())
426 as u32,
427 u32::from(self.size()),
428 ))
429 .unwrap()
430 }
431
432 fn vmcontref_last_ancestor(&self) -> u8 {
434 self.vmcontref_parent_chain() + 2 * self.size()
435 }
436
437 fn vmcontref_revision(&self) -> u8 {
439 self.vmcontref_last_ancestor() + self.size()
440 }
441
442 fn vmcontref_stack(&self) -> u8 {
444 self.vmcontref_revision() + self.size()
445 }
446
447 fn vmcontref_args(&self) -> u8 {
449 self.vmcontref_stack() + 3 * self.size()
450 }
451
452 fn vmcontref_values(&self) -> u8 {
454 self.vmcontref_args() + self.size_of_vmhostarray()
455 }
456
457 #[inline]
459 fn vmctx_magic(&self) -> u8 {
460 0
464 }
465
466 #[inline]
468 fn vmctx_store_context(&self) -> u8 {
469 self.vmctx_magic() + self.size()
470 }
471
472 #[inline]
474 fn vmctx_builtin_functions(&self) -> u8 {
475 self.vmctx_store_context() + self.size()
476 }
477
478 #[inline]
481 fn vmctx_epoch_ptr(&self) -> u8 {
482 self.vmctx_builtin_functions() + self.size()
483 }
484
485 #[inline]
490 fn vmctx_gc_heap_data(&self) -> u8 {
491 self.vmctx_epoch_ptr() + self.size()
492 }
493
494 #[inline]
497 fn vmdrc_heap_data_over_approximated_stack_roots(&self) -> u8 {
498 0
499 }
500
501 #[inline]
504 fn vmdrc_heap_data_current_over_approximated_stack_roots_len(&self) -> u8 {
505 4
506 }
507
508 #[inline]
512 fn vmdrc_heap_data_over_approximated_stack_roots_len_after_last_gc(&self) -> u8 {
513 8
514 }
515
516 #[inline]
518 fn size_of_vmdrc_heap_data(&self) -> u8 {
519 12
520 }
521
522 #[inline]
524 fn align_of_vmdrc_heap_data(&self) -> u8 {
525 4
526 }
527
528 #[inline]
530 fn vmcopying_heap_data_bump_ptr(&self) -> u8 {
531 0
532 }
533
534 #[inline]
537 fn vmcopying_heap_data_active_space_end(&self) -> u8 {
538 4
539 }
540
541 #[inline]
543 fn size_of_vmcopying_heap_data(&self) -> u8 {
544 8
545 }
546
547 #[inline]
549 fn align_of_vmcopying_heap_data(&self) -> u8 {
550 4
551 }
552
553 #[inline]
555 fn vmctx_type_ids_array(&self) -> u8 {
556 self.vmctx_gc_heap_data() + self.size()
557 }
558
559 #[inline]
563 fn vmctx_dynamic_data_start(&self) -> u8 {
564 self.vmctx_type_ids_array() + self.size()
565 }
566}
567
568pub trait GetPtrSize {
570 type Ptr: PtrSize;
572
573 fn get_ptr_size(&self) -> &Self::Ptr;
575}
576
577impl<P> GetPtrSize for P
578where
579 P: PtrSize,
580{
581 type Ptr = Self;
582
583 #[inline]
584 fn get_ptr_size(&self) -> &Self::Ptr {
585 self
586 }
587}
588
589#[derive(Clone, Copy)]
591pub struct HostPtr;
592
593impl PtrSize for HostPtr {
594 #[inline]
595 fn size(&self) -> u8 {
596 core::mem::size_of::<usize>() as u8
597 }
598}
599
600impl PtrSize for u8 {
601 #[inline]
602 fn size(&self) -> u8 {
603 *self
604 }
605}
606
607#[derive(Debug, Clone, Copy)]
609pub struct VMOffsetsFields<P> {
610 pub ptr: P,
612 pub num_imported_functions: u32,
614 pub num_imported_tables: u32,
616 pub num_imported_memories: u32,
618 pub num_imported_globals: u32,
620 pub num_imported_tags: u32,
622 pub num_defined_tables: u32,
624 pub num_defined_memories: u32,
626 pub num_owned_memories: u32,
628 pub num_defined_globals: u32,
630 pub num_defined_tags: u32,
632 pub num_escaped_funcs: u32,
635 pub num_runtime_data: u32,
637 pub has_startup_func: bool,
639}
640
641impl<P: PtrSize> VMOffsets<P> {
642 pub fn new(ptr: P, module: &Module) -> Self {
644 let num_owned_memories = module
645 .memories
646 .iter()
647 .skip(module.num_imported_memories)
648 .filter(|p| !p.1.shared)
649 .count()
650 .try_into()
651 .unwrap();
652 VMOffsets::from(VMOffsetsFields {
653 ptr,
654 num_imported_functions: cast_to_u32(module.num_imported_funcs),
655 num_imported_tables: cast_to_u32(module.num_imported_tables),
656 num_imported_memories: cast_to_u32(module.num_imported_memories),
657 num_imported_globals: cast_to_u32(module.num_imported_globals),
658 num_imported_tags: cast_to_u32(module.num_imported_tags),
659 num_defined_tables: cast_to_u32(module.num_defined_tables()),
660 num_defined_memories: cast_to_u32(module.num_defined_memories()),
661 num_owned_memories,
662 num_defined_globals: cast_to_u32(module.globals.len() - module.num_imported_globals),
663 num_defined_tags: cast_to_u32(module.tags.len() - module.num_imported_tags),
664 num_escaped_funcs: cast_to_u32(module.num_escaped_funcs),
665 num_runtime_data: cast_to_u32(module.runtime_data.len()),
666 has_startup_func: !module.startup.is_none(),
667 })
668 }
669
670 #[inline]
672 pub fn pointer_size(&self) -> u8 {
673 self.ptr.size()
674 }
675
676 pub fn region_sizes(&self) -> impl Iterator<Item = (&str, u32)> {
681 macro_rules! calculate_sizes {
682 ($($name:ident: $desc:tt,)*) => {{
683 let VMOffsets {
684 ptr: _,
687 num_imported_functions: _,
688 num_imported_tables: _,
689 num_imported_memories: _,
690 num_imported_globals: _,
691 num_imported_tags: _,
692 num_defined_tables: _,
693 num_defined_globals: _,
694 num_defined_memories: _,
695 num_defined_tags: _,
696 num_owned_memories: _,
697 num_escaped_funcs: _,
698 num_runtime_data: _,
699 has_startup_func: _,
700
701 size,
703
704 $($name,)*
707 } = *self;
708
709 let mut last = size;
713 $(
714 assert!($name <= last);
715 let tmp = $name;
716 let $name = last - $name;
717 last = tmp;
718 )*
719 assert_ne!(last, 0);
720 IntoIterator::into_iter([
721 $(($desc, $name),)*
722 ("static vmctx data", last),
723 ])
724 }};
725 }
726
727 calculate_sizes! {
728 runtime_data_lengths: "runtime data lengths",
729 runtime_data_bases: "runtime data base pointers",
730 startup_func_ref: "startup funcref",
731 defined_func_refs: "module functions",
732 defined_tags: "defined tags",
733 defined_globals: "defined globals",
734 defined_tables: "defined tables",
735 imported_tags: "imported tags",
736 imported_globals: "imported globals",
737 imported_tables: "imported tables",
738 imported_functions: "imported functions",
739 owned_memories: "owned memories",
740 defined_memories: "defined memories",
741 imported_memories: "imported memories",
742 }
743 }
744}
745
746impl<P: PtrSize> GetPtrSize for VMOffsets<P> {
747 type Ptr = P;
748
749 #[inline]
750 fn get_ptr_size(&self) -> &Self::Ptr {
751 &self.ptr
752 }
753}
754
755impl<P: PtrSize> From<VMOffsetsFields<P>> for VMOffsets<P> {
756 fn from(fields: VMOffsetsFields<P>) -> VMOffsets<P> {
757 let mut ret = Self {
758 ptr: fields.ptr,
759 num_imported_functions: fields.num_imported_functions,
760 num_imported_tables: fields.num_imported_tables,
761 num_imported_memories: fields.num_imported_memories,
762 num_imported_globals: fields.num_imported_globals,
763 num_imported_tags: fields.num_imported_tags,
764 num_defined_tables: fields.num_defined_tables,
765 num_defined_memories: fields.num_defined_memories,
766 num_owned_memories: fields.num_owned_memories,
767 num_defined_globals: fields.num_defined_globals,
768 num_defined_tags: fields.num_defined_tags,
769 num_escaped_funcs: fields.num_escaped_funcs,
770 num_runtime_data: fields.num_runtime_data,
771 has_startup_func: fields.has_startup_func,
772 imported_functions: 0,
773 imported_tables: 0,
774 imported_memories: 0,
775 imported_globals: 0,
776 imported_tags: 0,
777 defined_tables: 0,
778 defined_memories: 0,
779 owned_memories: 0,
780 defined_globals: 0,
781 defined_tags: 0,
782 defined_func_refs: 0,
783 startup_func_ref: 0,
784 runtime_data_bases: 0,
785 runtime_data_lengths: 0,
786 size: 0,
787 };
788
789 #[inline]
794 fn cadd(count: u32, size: u32) -> u32 {
795 count.checked_add(size).unwrap()
796 }
797
798 #[inline]
799 fn cmul(count: u32, size: u8) -> u32 {
800 count.checked_mul(u32::from(size)).unwrap()
801 }
802
803 let mut next_field_offset = u32::from(ret.ptr.vmctx_dynamic_data_start());
804
805 macro_rules! fields {
806 (size($field:ident) = $size:expr, $($rest:tt)*) => {
807 ret.$field = next_field_offset;
808 next_field_offset = cadd(next_field_offset, u32::from($size));
809 fields!($($rest)*);
810 };
811 (align($align:expr), $($rest:tt)*) => {
812 next_field_offset = align(next_field_offset, $align);
813 fields!($($rest)*);
814 };
815 () => {};
816 }
817
818 fields! {
819 size(imported_memories)
820 = cmul(ret.num_imported_memories, ret.size_of_vmmemory_import()),
821 size(defined_memories)
822 = cmul(ret.num_defined_memories, ret.ptr.size_of_vmmemory_pointer()),
823 size(owned_memories)
824 = cmul(ret.num_owned_memories, ret.ptr.size_of_vmmemory_definition()),
825 size(imported_functions)
826 = cmul(ret.num_imported_functions, ret.size_of_vmfunction_import()),
827 size(imported_tables)
828 = cmul(ret.num_imported_tables, ret.size_of_vmtable_import()),
829 size(imported_globals)
830 = cmul(ret.num_imported_globals, ret.size_of_vmglobal_import()),
831 size(imported_tags)
832 = cmul(ret.num_imported_tags, ret.size_of_vmtag_import()),
833 size(defined_tables)
834 = cmul(ret.num_defined_tables, ret.size_of_vmtable_definition()),
835 align(16),
836 size(defined_globals)
837 = cmul(ret.num_defined_globals, ret.ptr.size_of_vmglobal_definition()),
838 size(defined_tags)
839 = cmul(ret.num_defined_tags, ret.ptr.size_of_vmtag_definition()),
840 size(defined_func_refs) = cmul(
841 ret.num_escaped_funcs,
842 ret.ptr.size_of_vm_func_ref(),
843 ),
844 size(startup_func_ref) = if ret.has_startup_func {
845 ret.ptr.size_of_vm_func_ref()
846 } else {
847 0
848 },
849 size(runtime_data_bases) = cmul(ret.num_runtime_data, ret.ptr.size()),
850 size(runtime_data_lengths) = cmul(ret.num_runtime_data, 4),
851 }
852
853 ret.size = next_field_offset;
854
855 return ret;
856 }
857}
858
859impl<P: PtrSize> VMOffsets<P> {
860 #[inline]
862 pub fn vmfunction_import_array_call(&self) -> u8 {
863 0 * self.pointer_size()
864 }
865
866 #[inline]
868 pub fn vmfunction_import_wasm_call(&self) -> u8 {
869 1 * self.pointer_size()
870 }
871
872 #[inline]
874 pub fn vmfunction_import_type_index(&self) -> u8 {
875 2 * self.pointer_size()
876 }
877
878 #[inline]
880 pub fn vmfunction_import_vmctx(&self) -> u8 {
881 3 * self.pointer_size()
882 }
883
884 #[inline]
886 pub fn size_of_vmfunction_import(&self) -> u8 {
887 4 * self.pointer_size()
888 }
889}
890
891impl<P: PtrSize> VMOffsets<P> {
893 pub fn size_of_vmfunction_body_ptr(&self) -> u8 {
895 1 * self.pointer_size()
896 }
897}
898
899impl<P: PtrSize> VMOffsets<P> {
901 #[inline]
903 pub fn vmtable_import_from(&self) -> u8 {
904 0 * self.pointer_size()
905 }
906
907 #[inline]
909 pub fn vmtable_import_vmctx(&self) -> u8 {
910 1 * self.pointer_size()
911 }
912
913 #[inline]
915 pub fn vmtable_import_index(&self) -> u8 {
916 2 * self.pointer_size()
917 }
918
919 #[inline]
921 pub fn size_of_vmtable_import(&self) -> u8 {
922 3 * self.pointer_size()
923 }
924}
925
926impl<P: PtrSize> VMOffsets<P> {
928 #[inline]
930 pub fn vmtable_definition_base(&self) -> u8 {
931 0 * self.pointer_size()
932 }
933
934 pub fn vmtable_definition_current_elements(&self) -> u8 {
936 1 * self.pointer_size()
937 }
938
939 #[inline]
941 pub fn size_of_vmtable_definition_current_elements(&self) -> u8 {
942 self.pointer_size()
943 }
944
945 #[inline]
947 pub fn size_of_vmtable_definition(&self) -> u8 {
948 2 * self.pointer_size()
949 }
950}
951
952impl<P: PtrSize> VMOffsets<P> {
954 #[inline]
956 pub fn vmmemory_import_from(&self) -> u8 {
957 0 * self.pointer_size()
958 }
959
960 #[inline]
962 pub fn vmmemory_import_vmctx(&self) -> u8 {
963 1 * self.pointer_size()
964 }
965
966 #[inline]
968 pub fn vmmemory_import_index(&self) -> u8 {
969 2 * self.pointer_size()
970 }
971
972 #[inline]
974 pub fn size_of_vmmemory_import(&self) -> u8 {
975 3 * self.pointer_size()
976 }
977}
978
979impl<P: PtrSize> VMOffsets<P> {
981 #[inline]
983 pub fn vmglobal_import_from(&self) -> u8 {
984 0 * self.pointer_size()
985 }
986
987 #[inline]
989 pub fn size_of_vmglobal_import(&self) -> u8 {
990 2 * self.pointer_size() + 8
992 }
993}
994
995impl<P: PtrSize> VMOffsets<P> {
997 #[inline]
999 pub fn size_of_vmshared_type_index(&self) -> u8 {
1000 4
1001 }
1002}
1003
1004impl<P: PtrSize> VMOffsets<P> {
1006 #[inline]
1008 pub fn vmtag_import_from(&self) -> u8 {
1009 0 * self.pointer_size()
1010 }
1011
1012 #[inline]
1014 pub fn vmtag_import_vmctx(&self) -> u8 {
1015 1 * self.pointer_size()
1016 }
1017
1018 #[inline]
1020 pub fn vmtag_import_index(&self) -> u8 {
1021 2 * self.pointer_size()
1022 }
1023
1024 #[inline]
1026 pub fn size_of_vmtag_import(&self) -> u8 {
1027 3 * self.pointer_size()
1028 }
1029}
1030
1031impl<P: PtrSize> VMOffsets<P> {
1033 #[inline]
1035 pub fn vmctx_imported_functions_begin(&self) -> u32 {
1036 self.imported_functions
1037 }
1038
1039 #[inline]
1041 pub fn vmctx_imported_tables_begin(&self) -> u32 {
1042 self.imported_tables
1043 }
1044
1045 #[inline]
1047 pub fn vmctx_imported_memories_begin(&self) -> u32 {
1048 self.imported_memories
1049 }
1050
1051 #[inline]
1053 pub fn vmctx_imported_globals_begin(&self) -> u32 {
1054 self.imported_globals
1055 }
1056
1057 #[inline]
1059 pub fn vmctx_imported_tags_begin(&self) -> u32 {
1060 self.imported_tags
1061 }
1062
1063 #[inline]
1065 pub fn vmctx_tables_begin(&self) -> u32 {
1066 self.defined_tables
1067 }
1068
1069 #[inline]
1071 pub fn vmctx_memories_begin(&self) -> u32 {
1072 self.defined_memories
1073 }
1074
1075 #[inline]
1077 pub fn vmctx_owned_memories_begin(&self) -> u32 {
1078 self.owned_memories
1079 }
1080
1081 #[inline]
1083 pub fn vmctx_globals_begin(&self) -> u32 {
1084 self.defined_globals
1085 }
1086
1087 #[inline]
1089 pub fn vmctx_tags_begin(&self) -> u32 {
1090 self.defined_tags
1091 }
1092
1093 #[inline]
1095 pub fn vmctx_func_refs_begin(&self) -> u32 {
1096 self.defined_func_refs
1097 }
1098
1099 #[inline]
1101 pub fn vmctx_runtime_data_bases_begin(&self) -> u32 {
1102 self.runtime_data_bases
1103 }
1104
1105 #[inline]
1107 pub fn vmctx_runtime_data_lengths_begin(&self) -> u32 {
1108 self.runtime_data_lengths
1109 }
1110
1111 #[inline]
1113 pub fn size_of_vmctx(&self) -> u32 {
1114 self.size
1115 }
1116
1117 #[inline]
1119 pub fn vmctx_vmfunction_import(&self, index: FuncIndex) -> u32 {
1120 assert!(index.as_u32() < self.num_imported_functions);
1121 self.vmctx_imported_functions_begin()
1122 + index.as_u32() * u32::from(self.size_of_vmfunction_import())
1123 }
1124
1125 #[inline]
1127 pub fn vmctx_vmtable_import(&self, index: TableIndex) -> u32 {
1128 assert!(index.as_u32() < self.num_imported_tables);
1129 self.vmctx_imported_tables_begin()
1130 + index.as_u32() * u32::from(self.size_of_vmtable_import())
1131 }
1132
1133 #[inline]
1135 pub fn vmctx_vmmemory_import(&self, index: MemoryIndex) -> u32 {
1136 assert!(index.as_u32() < self.num_imported_memories);
1137 self.vmctx_imported_memories_begin()
1138 + index.as_u32() * u32::from(self.size_of_vmmemory_import())
1139 }
1140
1141 #[inline]
1143 pub fn vmctx_vmglobal_import(&self, index: GlobalIndex) -> u32 {
1144 assert!(index.as_u32() < self.num_imported_globals);
1145 self.vmctx_imported_globals_begin()
1146 + index.as_u32() * u32::from(self.size_of_vmglobal_import())
1147 }
1148
1149 #[inline]
1151 pub fn vmctx_vmtag_import(&self, index: TagIndex) -> u32 {
1152 assert!(index.as_u32() < self.num_imported_tags);
1153 self.vmctx_imported_tags_begin() + index.as_u32() * u32::from(self.size_of_vmtag_import())
1154 }
1155
1156 #[inline]
1158 pub fn vmctx_vmtable_definition(&self, index: DefinedTableIndex) -> u32 {
1159 assert!(index.as_u32() < self.num_defined_tables);
1160 self.vmctx_tables_begin() + index.as_u32() * u32::from(self.size_of_vmtable_definition())
1161 }
1162
1163 #[inline]
1165 pub fn vmctx_vmmemory_pointer(&self, index: DefinedMemoryIndex) -> u32 {
1166 assert!(index.as_u32() < self.num_defined_memories);
1167 self.vmctx_memories_begin()
1168 + index.as_u32() * u32::from(self.ptr.size_of_vmmemory_pointer())
1169 }
1170
1171 #[inline]
1173 pub fn vmctx_vmmemory_definition(&self, index: OwnedMemoryIndex) -> u32 {
1174 assert!(index.as_u32() < self.num_owned_memories);
1175 self.vmctx_owned_memories_begin()
1176 + index.as_u32() * u32::from(self.ptr.size_of_vmmemory_definition())
1177 }
1178
1179 #[inline]
1181 pub fn vmctx_vmglobal_definition(&self, index: DefinedGlobalIndex) -> u32 {
1182 assert!(index.as_u32() < self.num_defined_globals);
1183 self.vmctx_globals_begin()
1184 + index.as_u32() * u32::from(self.ptr.size_of_vmglobal_definition())
1185 }
1186
1187 #[inline]
1189 pub fn vmctx_vmtag_definition(&self, index: DefinedTagIndex) -> u32 {
1190 assert!(index.as_u32() < self.num_defined_tags);
1191 self.vmctx_tags_begin() + index.as_u32() * u32::from(self.ptr.size_of_vmtag_definition())
1192 }
1193
1194 #[inline]
1197 pub fn vmctx_func_ref(&self, index: FuncRefIndex) -> u32 {
1198 assert!(!index.is_reserved_value());
1199 assert!(index.as_u32() < self.num_escaped_funcs);
1200 self.vmctx_func_refs_begin() + index.as_u32() * u32::from(self.ptr.size_of_vm_func_ref())
1201 }
1202
1203 #[inline]
1207 pub fn vmctx_startup_func_ref(&self) -> u32 {
1208 assert!(self.has_startup_func);
1209 self.startup_func_ref
1210 }
1211
1212 #[inline]
1214 pub fn vmctx_runtime_data_base(&self, index: RuntimeDataIndex) -> u32 {
1215 assert!(!index.is_reserved_value());
1216 assert!(index.as_u32() < self.num_runtime_data);
1217 self.vmctx_runtime_data_bases_begin() + index.as_u32() * u32::from(self.ptr.size())
1218 }
1219
1220 #[inline]
1222 pub fn vmctx_runtime_data_length(&self, index: RuntimeDataIndex) -> u32 {
1223 assert!(!index.is_reserved_value());
1224 assert!(index.as_u32() < self.num_runtime_data);
1225 self.vmctx_runtime_data_lengths_begin() + index.as_u32() * 4
1226 }
1227
1228 #[inline]
1230 pub fn vmctx_vmfunction_import_wasm_call(&self, index: FuncIndex) -> u32 {
1231 self.vmctx_vmfunction_import(index) + u32::from(self.vmfunction_import_wasm_call())
1232 }
1233
1234 #[inline]
1236 pub fn vmctx_vmfunction_import_array_call(&self, index: FuncIndex) -> u32 {
1237 self.vmctx_vmfunction_import(index) + u32::from(self.vmfunction_import_array_call())
1238 }
1239
1240 #[inline]
1242 pub fn vmctx_vmfunction_import_vmctx(&self, index: FuncIndex) -> u32 {
1243 self.vmctx_vmfunction_import(index) + u32::from(self.vmfunction_import_vmctx())
1244 }
1245
1246 #[inline]
1249 pub fn vmctx_vmtable_from(&self, index: TableIndex) -> u32 {
1250 self.vmctx_vmtable_import(index) + u32::from(self.vmtable_import_from())
1251 }
1252
1253 #[inline]
1255 pub fn vmctx_vmtable_definition_base(&self, index: DefinedTableIndex) -> u32 {
1256 self.vmctx_vmtable_definition(index) + u32::from(self.vmtable_definition_base())
1257 }
1258
1259 #[inline]
1261 pub fn vmctx_vmtable_definition_current_elements(&self, index: DefinedTableIndex) -> u32 {
1262 self.vmctx_vmtable_definition(index) + u32::from(self.vmtable_definition_current_elements())
1263 }
1264
1265 #[inline]
1267 pub fn vmctx_vmmemory_import_from(&self, index: MemoryIndex) -> u32 {
1268 self.vmctx_vmmemory_import(index) + u32::from(self.vmmemory_import_from())
1269 }
1270
1271 #[inline]
1273 pub fn vmctx_vmmemory_definition_base(&self, index: OwnedMemoryIndex) -> u32 {
1274 self.vmctx_vmmemory_definition(index) + u32::from(self.ptr.vmmemory_definition_base())
1275 }
1276
1277 #[inline]
1279 pub fn vmctx_vmmemory_definition_current_length(&self, index: OwnedMemoryIndex) -> u32 {
1280 self.vmctx_vmmemory_definition(index)
1281 + u32::from(self.ptr.vmmemory_definition_current_length())
1282 }
1283
1284 #[inline]
1286 pub fn vmctx_vmglobal_import_from(&self, index: GlobalIndex) -> u32 {
1287 self.vmctx_vmglobal_import(index) + u32::from(self.vmglobal_import_from())
1288 }
1289
1290 #[inline]
1292 pub fn vmctx_vmtag_import_from(&self, index: TagIndex) -> u32 {
1293 self.vmctx_vmtag_import(index) + u32::from(self.vmtag_import_from())
1294 }
1295
1296 #[inline]
1298 pub fn vmctx_vmtag_import_vmctx(&self, index: TagIndex) -> u32 {
1299 self.vmctx_vmtag_import(index) + u32::from(self.vmtag_import_vmctx())
1300 }
1301
1302 #[inline]
1304 pub fn vmctx_vmtag_import_index(&self, index: TagIndex) -> u32 {
1305 self.vmctx_vmtag_import(index) + u32::from(self.vmtag_import_index())
1306 }
1307}
1308
1309impl<P: PtrSize> VMOffsets<P> {
1311 #[inline]
1313 pub fn vm_gc_header_kind(&self) -> u32 {
1314 0
1315 }
1316
1317 #[inline]
1319 pub fn vm_gc_header_reserved_bits(&self) -> u32 {
1320 self.vm_gc_header_kind()
1322 }
1323
1324 #[inline]
1326 pub fn vm_gc_header_ty(&self) -> u32 {
1327 self.vm_gc_header_kind() + 4
1328 }
1329}
1330
1331impl<P: PtrSize> VMOffsets<P> {
1335 #[inline]
1337 pub fn vm_drc_header_ref_count(&self) -> u32 {
1338 8
1339 }
1340
1341 #[inline]
1343 pub fn vm_drc_header_next_over_approximated_stack_root(&self) -> u32 {
1344 self.vm_drc_header_ref_count() + 8
1345 }
1346}
1347
1348pub const VMCONTEXT_MAGIC: u32 = u32::from_le_bytes(*b"core");
1352
1353pub const VM_ARRAY_CALL_HOST_FUNC_MAGIC: u32 = u32::from_le_bytes(*b"ACHF");
1358
1359#[cfg(test)]
1360mod tests {
1361 use crate::vmoffsets::align;
1362
1363 #[test]
1364 fn alignment() {
1365 fn is_aligned(x: u32) -> bool {
1366 x % 16 == 0
1367 }
1368 assert!(is_aligned(align(0, 16)));
1369 assert!(is_aligned(align(32, 16)));
1370 assert!(is_aligned(align(33, 16)));
1371 assert!(is_aligned(align(31, 16)));
1372 }
1373}