1use crate::{
37 DefinedGlobalIndex, DefinedMemoryIndex, DefinedTableIndex, DefinedTagIndex, FuncIndex,
38 FuncRefIndex, GlobalIndex, MemoryIndex, Module, OwnedMemoryIndex, TableIndex, TagIndex,
39};
40use cranelift_entity::packed_option::ReservedValue;
41
42#[cfg(target_pointer_width = "32")]
43fn cast_to_u32(sz: usize) -> u32 {
44 u32::try_from(sz).unwrap()
45}
46#[cfg(target_pointer_width = "64")]
47fn cast_to_u32(sz: usize) -> u32 {
48 u32::try_from(sz).expect("overflow in cast from usize to u32")
49}
50
51#[inline]
53fn align(offset: u32, width: u32) -> u32 {
54 (offset + (width - 1)) / width * width
55}
56
57#[derive(Debug, Clone, Copy)]
60pub struct VMOffsets<P> {
61 pub ptr: P,
63 pub num_imported_functions: u32,
65 pub num_imported_tables: u32,
67 pub num_imported_memories: u32,
69 pub num_imported_globals: u32,
71 pub num_imported_tags: u32,
73 pub num_defined_tables: u32,
75 pub num_defined_memories: u32,
77 pub num_owned_memories: u32,
79 pub num_defined_globals: u32,
81 pub num_defined_tags: u32,
83 pub num_escaped_funcs: u32,
86
87 imported_functions: u32,
89 imported_tables: u32,
90 imported_memories: u32,
91 imported_globals: u32,
92 imported_tags: u32,
93 defined_tables: u32,
94 defined_memories: u32,
95 owned_memories: u32,
96 defined_globals: u32,
97 defined_tags: u32,
98 defined_func_refs: u32,
99 size: u32,
100}
101
102pub trait PtrSize {
104 fn size(&self) -> u8;
106
107 fn vmcontext_store_context(&self) -> u8 {
109 u8::try_from(align(
110 u32::try_from(core::mem::size_of::<u32>()).unwrap(),
111 u32::from(self.size()),
112 ))
113 .unwrap()
114 }
115
116 fn vmcontext_builtin_functions(&self) -> u8 {
118 self.vmcontext_store_context() + self.size()
119 }
120
121 #[inline]
123 fn vm_func_ref_array_call(&self) -> u8 {
124 0 * self.size()
125 }
126
127 #[inline]
129 fn vm_func_ref_wasm_call(&self) -> u8 {
130 1 * self.size()
131 }
132
133 #[inline]
135 fn vm_func_ref_type_index(&self) -> u8 {
136 2 * self.size()
137 }
138
139 #[inline]
141 fn vm_func_ref_vmctx(&self) -> u8 {
142 3 * self.size()
143 }
144
145 #[inline]
147 fn size_of_vm_func_ref(&self) -> u8 {
148 4 * self.size()
149 }
150
151 #[inline]
154 fn size_of_vmglobal_definition(&self) -> u8 {
155 16
156 }
157
158 #[inline]
160 fn size_of_vmtag_definition(&self) -> u8 {
161 4
162 }
163
164 #[inline]
166 fn maximum_value_size(&self) -> u8 {
167 self.size_of_vmglobal_definition()
168 }
169
170 #[inline]
174 fn vmstore_context_fuel_consumed(&self) -> u8 {
175 0
176 }
177
178 #[inline]
180 fn vmstore_context_epoch_deadline(&self) -> u8 {
181 self.vmstore_context_fuel_consumed() + 8
182 }
183
184 #[inline]
186 fn vmstore_context_stack_limit(&self) -> u8 {
187 self.vmstore_context_epoch_deadline() + 8
188 }
189
190 #[inline]
192 fn vmstore_context_gc_heap(&self) -> u8 {
193 self.vmstore_context_stack_limit() + self.size()
194 }
195
196 fn vmstore_context_gc_heap_base(&self) -> u8 {
198 let offset = self.vmstore_context_gc_heap() + self.vmmemory_definition_base();
199 debug_assert!(offset < self.vmstore_context_last_wasm_exit_trampoline_fp());
200 offset
201 }
202
203 fn vmstore_context_gc_heap_current_length(&self) -> u8 {
205 let offset = self.vmstore_context_gc_heap() + self.vmmemory_definition_current_length();
206 debug_assert!(offset < self.vmstore_context_last_wasm_exit_trampoline_fp());
207 offset
208 }
209
210 fn vmstore_context_last_wasm_exit_trampoline_fp(&self) -> u8 {
213 self.vmstore_context_gc_heap() + self.size_of_vmmemory_definition()
214 }
215
216 fn vmstore_context_last_wasm_exit_pc(&self) -> u8 {
218 self.vmstore_context_last_wasm_exit_trampoline_fp() + self.size()
219 }
220
221 fn vmstore_context_last_wasm_entry_fp(&self) -> u8 {
223 self.vmstore_context_last_wasm_exit_pc() + self.size()
224 }
225
226 fn vmstore_context_stack_chain(&self) -> u8 {
228 self.vmstore_context_last_wasm_entry_fp() + self.size()
229 }
230
231 #[inline]
235 fn vmmemory_definition_base(&self) -> u8 {
236 0 * self.size()
237 }
238
239 #[inline]
241 fn vmmemory_definition_current_length(&self) -> u8 {
242 1 * self.size()
243 }
244
245 #[inline]
247 fn size_of_vmmemory_definition(&self) -> u8 {
248 2 * self.size()
249 }
250
251 #[inline]
253 fn size_of_vmmemory_pointer(&self) -> u8 {
254 self.size()
255 }
256
257 fn vmarray_call_host_func_context_func_ref(&self) -> u8 {
261 u8::try_from(align(
262 u32::try_from(core::mem::size_of::<u32>()).unwrap(),
263 u32::from(self.size()),
264 ))
265 .unwrap()
266 }
267
268 fn size_of_vmstack_chain(&self) -> u8 {
270 2 * self.size()
271 }
272
273 fn vmstack_limits_stack_limit(&self) -> u8 {
277 0
278 }
279
280 fn vmstack_limits_last_wasm_entry_fp(&self) -> u8 {
282 self.size()
283 }
284
285 fn vmhostarray_length(&self) -> u8 {
289 0
290 }
291
292 fn vmhostarray_capacity(&self) -> u8 {
294 4
295 }
296
297 fn vmhostarray_data(&self) -> u8 {
299 8
300 }
301
302 fn size_of_vmhostarray(&self) -> u8 {
304 8 + self.size()
305 }
306
307 fn vmcommon_stack_information_limits(&self) -> u8 {
311 0 * self.size()
312 }
313
314 fn vmcommon_stack_information_state(&self) -> u8 {
316 2 * self.size()
317 }
318
319 fn vmcommon_stack_information_handlers(&self) -> u8 {
321 u8::try_from(align(
322 self.vmcommon_stack_information_state() as u32 + 4,
323 u32::from(self.size()),
324 ))
325 .unwrap()
326 }
327
328 fn vmcommon_stack_information_first_switch_handler_index(&self) -> u8 {
330 self.vmcommon_stack_information_handlers() + self.size_of_vmhostarray()
331 }
332
333 fn size_of_vmcommon_stack_information(&self) -> u8 {
335 u8::try_from(align(
336 self.vmcommon_stack_information_first_switch_handler_index() as u32 + 4,
337 u32::from(self.size()),
338 ))
339 .unwrap()
340 }
341
342 fn vmcontobj_contref(&self) -> u8 {
346 0
347 }
348
349 fn vmcontobj_revision(&self) -> u8 {
351 self.size()
352 }
353
354 fn size_of_vmcontobj(&self) -> u8 {
356 u8::try_from(align(
357 u32::from(self.vmcontobj_revision())
358 + u32::try_from(core::mem::size_of::<usize>()).unwrap(),
359 u32::from(self.size()),
360 ))
361 .unwrap()
362 }
363
364 fn vmcontref_common_stack_information(&self) -> u8 {
368 0 * self.size()
369 }
370
371 fn vmcontref_parent_chain(&self) -> u8 {
373 u8::try_from(align(
374 (self.vmcontref_common_stack_information() + self.size_of_vmcommon_stack_information())
375 as u32,
376 u32::from(self.size()),
377 ))
378 .unwrap()
379 }
380
381 fn vmcontref_last_ancestor(&self) -> u8 {
383 self.vmcontref_parent_chain() + 2 * self.size()
384 }
385
386 fn vmcontref_revision(&self) -> u8 {
388 self.vmcontref_last_ancestor() + self.size()
389 }
390
391 fn vmcontref_stack(&self) -> u8 {
393 self.vmcontref_revision() + self.size()
394 }
395
396 fn vmcontref_args(&self) -> u8 {
398 self.vmcontref_stack() + 3 * self.size()
399 }
400
401 fn vmcontref_values(&self) -> u8 {
403 self.vmcontref_args() + self.size_of_vmhostarray()
404 }
405
406 #[inline]
408 fn vmctx_magic(&self) -> u8 {
409 0
413 }
414
415 #[inline]
417 fn vmctx_store_context(&self) -> u8 {
418 self.vmctx_magic() + self.size()
419 }
420
421 #[inline]
423 fn vmctx_builtin_functions(&self) -> u8 {
424 self.vmctx_store_context() + self.size()
425 }
426
427 #[inline]
430 fn vmctx_epoch_ptr(&self) -> u8 {
431 self.vmctx_builtin_functions() + self.size()
432 }
433
434 #[inline]
439 fn vmctx_gc_heap_data(&self) -> u8 {
440 self.vmctx_epoch_ptr() + self.size()
441 }
442
443 #[inline]
445 fn vmctx_type_ids_array(&self) -> u8 {
446 self.vmctx_gc_heap_data() + self.size()
447 }
448
449 #[inline]
453 fn vmctx_dynamic_data_start(&self) -> u8 {
454 self.vmctx_type_ids_array() + self.size()
455 }
456}
457
458#[derive(Clone, Copy)]
460pub struct HostPtr;
461
462impl PtrSize for HostPtr {
463 #[inline]
464 fn size(&self) -> u8 {
465 core::mem::size_of::<usize>() as u8
466 }
467}
468
469impl PtrSize for u8 {
470 #[inline]
471 fn size(&self) -> u8 {
472 *self
473 }
474}
475
476#[derive(Debug, Clone, Copy)]
478pub struct VMOffsetsFields<P> {
479 pub ptr: P,
481 pub num_imported_functions: u32,
483 pub num_imported_tables: u32,
485 pub num_imported_memories: u32,
487 pub num_imported_globals: u32,
489 pub num_imported_tags: u32,
491 pub num_defined_tables: u32,
493 pub num_defined_memories: u32,
495 pub num_owned_memories: u32,
497 pub num_defined_globals: u32,
499 pub num_defined_tags: u32,
501 pub num_escaped_funcs: u32,
504}
505
506impl<P: PtrSize> VMOffsets<P> {
507 pub fn new(ptr: P, module: &Module) -> Self {
509 let num_owned_memories = module
510 .memories
511 .iter()
512 .skip(module.num_imported_memories)
513 .filter(|p| !p.1.shared)
514 .count()
515 .try_into()
516 .unwrap();
517 VMOffsets::from(VMOffsetsFields {
518 ptr,
519 num_imported_functions: cast_to_u32(module.num_imported_funcs),
520 num_imported_tables: cast_to_u32(module.num_imported_tables),
521 num_imported_memories: cast_to_u32(module.num_imported_memories),
522 num_imported_globals: cast_to_u32(module.num_imported_globals),
523 num_imported_tags: cast_to_u32(module.num_imported_tags),
524 num_defined_tables: cast_to_u32(module.num_defined_tables()),
525 num_defined_memories: cast_to_u32(module.num_defined_memories()),
526 num_owned_memories,
527 num_defined_globals: cast_to_u32(module.globals.len() - module.num_imported_globals),
528 num_defined_tags: cast_to_u32(module.tags.len() - module.num_imported_tags),
529 num_escaped_funcs: cast_to_u32(module.num_escaped_funcs),
530 })
531 }
532
533 #[inline]
535 pub fn pointer_size(&self) -> u8 {
536 self.ptr.size()
537 }
538
539 pub fn region_sizes(&self) -> impl Iterator<Item = (&str, u32)> {
544 macro_rules! calculate_sizes {
545 ($($name:ident: $desc:tt,)*) => {{
546 let VMOffsets {
547 ptr: _,
550 num_imported_functions: _,
551 num_imported_tables: _,
552 num_imported_memories: _,
553 num_imported_globals: _,
554 num_imported_tags: _,
555 num_defined_tables: _,
556 num_defined_globals: _,
557 num_defined_memories: _,
558 num_defined_tags: _,
559 num_owned_memories: _,
560 num_escaped_funcs: _,
561
562 size,
564
565 $($name,)*
568 } = *self;
569
570 let mut last = size;
574 $(
575 assert!($name <= last);
576 let tmp = $name;
577 let $name = last - $name;
578 last = tmp;
579 )*
580 assert_ne!(last, 0);
581 IntoIterator::into_iter([
582 $(($desc, $name),)*
583 ("static vmctx data", last),
584 ])
585 }};
586 }
587
588 calculate_sizes! {
589 defined_func_refs: "module functions",
590 defined_tags: "defined tags",
591 defined_globals: "defined globals",
592 defined_tables: "defined tables",
593 imported_tags: "imported tags",
594 imported_globals: "imported globals",
595 imported_tables: "imported tables",
596 imported_functions: "imported functions",
597 owned_memories: "owned memories",
598 defined_memories: "defined memories",
599 imported_memories: "imported memories",
600 }
601 }
602}
603
604impl<P: PtrSize> From<VMOffsetsFields<P>> for VMOffsets<P> {
605 fn from(fields: VMOffsetsFields<P>) -> VMOffsets<P> {
606 let mut ret = Self {
607 ptr: fields.ptr,
608 num_imported_functions: fields.num_imported_functions,
609 num_imported_tables: fields.num_imported_tables,
610 num_imported_memories: fields.num_imported_memories,
611 num_imported_globals: fields.num_imported_globals,
612 num_imported_tags: fields.num_imported_tags,
613 num_defined_tables: fields.num_defined_tables,
614 num_defined_memories: fields.num_defined_memories,
615 num_owned_memories: fields.num_owned_memories,
616 num_defined_globals: fields.num_defined_globals,
617 num_defined_tags: fields.num_defined_tags,
618 num_escaped_funcs: fields.num_escaped_funcs,
619 imported_functions: 0,
620 imported_tables: 0,
621 imported_memories: 0,
622 imported_globals: 0,
623 imported_tags: 0,
624 defined_tables: 0,
625 defined_memories: 0,
626 owned_memories: 0,
627 defined_globals: 0,
628 defined_tags: 0,
629 defined_func_refs: 0,
630 size: 0,
631 };
632
633 #[inline]
638 fn cadd(count: u32, size: u32) -> u32 {
639 count.checked_add(size).unwrap()
640 }
641
642 #[inline]
643 fn cmul(count: u32, size: u8) -> u32 {
644 count.checked_mul(u32::from(size)).unwrap()
645 }
646
647 let mut next_field_offset = u32::from(ret.ptr.vmctx_dynamic_data_start());
648
649 macro_rules! fields {
650 (size($field:ident) = $size:expr, $($rest:tt)*) => {
651 ret.$field = next_field_offset;
652 next_field_offset = cadd(next_field_offset, u32::from($size));
653 fields!($($rest)*);
654 };
655 (align($align:expr), $($rest:tt)*) => {
656 next_field_offset = align(next_field_offset, $align);
657 fields!($($rest)*);
658 };
659 () => {};
660 }
661
662 fields! {
663 size(imported_memories)
664 = cmul(ret.num_imported_memories, ret.size_of_vmmemory_import()),
665 size(defined_memories)
666 = cmul(ret.num_defined_memories, ret.ptr.size_of_vmmemory_pointer()),
667 size(owned_memories)
668 = cmul(ret.num_owned_memories, ret.ptr.size_of_vmmemory_definition()),
669 size(imported_functions)
670 = cmul(ret.num_imported_functions, ret.size_of_vmfunction_import()),
671 size(imported_tables)
672 = cmul(ret.num_imported_tables, ret.size_of_vmtable_import()),
673 size(imported_globals)
674 = cmul(ret.num_imported_globals, ret.size_of_vmglobal_import()),
675 size(imported_tags)
676 = cmul(ret.num_imported_tags, ret.size_of_vmtag_import()),
677 size(defined_tables)
678 = cmul(ret.num_defined_tables, ret.size_of_vmtable_definition()),
679 align(16),
680 size(defined_globals)
681 = cmul(ret.num_defined_globals, ret.ptr.size_of_vmglobal_definition()),
682 size(defined_tags)
683 = cmul(ret.num_defined_tags, ret.ptr.size_of_vmtag_definition()),
684 size(defined_func_refs) = cmul(
685 ret.num_escaped_funcs,
686 ret.ptr.size_of_vm_func_ref(),
687 ),
688 }
689
690 ret.size = next_field_offset;
691
692 return ret;
693 }
694}
695
696impl<P: PtrSize> VMOffsets<P> {
697 #[inline]
699 pub fn vmfunction_import_wasm_call(&self) -> u8 {
700 0 * self.pointer_size()
701 }
702
703 #[inline]
705 pub fn vmfunction_import_array_call(&self) -> u8 {
706 1 * self.pointer_size()
707 }
708
709 #[inline]
711 pub fn vmfunction_import_vmctx(&self) -> u8 {
712 2 * self.pointer_size()
713 }
714
715 #[inline]
717 pub fn size_of_vmfunction_import(&self) -> u8 {
718 3 * self.pointer_size()
719 }
720}
721
722impl<P: PtrSize> VMOffsets<P> {
724 pub fn size_of_vmfunction_body_ptr(&self) -> u8 {
726 1 * self.pointer_size()
727 }
728}
729
730impl<P: PtrSize> VMOffsets<P> {
732 #[inline]
734 pub fn vmtable_import_from(&self) -> u8 {
735 0 * self.pointer_size()
736 }
737
738 #[inline]
740 pub fn vmtable_import_vmctx(&self) -> u8 {
741 1 * self.pointer_size()
742 }
743
744 #[inline]
746 pub fn vmtable_import_index(&self) -> u8 {
747 2 * self.pointer_size()
748 }
749
750 #[inline]
752 pub fn size_of_vmtable_import(&self) -> u8 {
753 3 * self.pointer_size()
754 }
755}
756
757impl<P: PtrSize> VMOffsets<P> {
759 #[inline]
761 pub fn vmtable_definition_base(&self) -> u8 {
762 0 * self.pointer_size()
763 }
764
765 pub fn vmtable_definition_current_elements(&self) -> u8 {
767 1 * self.pointer_size()
768 }
769
770 #[inline]
772 pub fn size_of_vmtable_definition_current_elements(&self) -> u8 {
773 self.pointer_size()
774 }
775
776 #[inline]
778 pub fn size_of_vmtable_definition(&self) -> u8 {
779 2 * self.pointer_size()
780 }
781}
782
783impl<P: PtrSize> VMOffsets<P> {
785 #[inline]
787 pub fn vmmemory_import_from(&self) -> u8 {
788 0 * self.pointer_size()
789 }
790
791 #[inline]
793 pub fn vmmemory_import_vmctx(&self) -> u8 {
794 1 * self.pointer_size()
795 }
796
797 #[inline]
799 pub fn vmmemory_import_index(&self) -> u8 {
800 2 * self.pointer_size()
801 }
802
803 #[inline]
805 pub fn size_of_vmmemory_import(&self) -> u8 {
806 3 * self.pointer_size()
807 }
808}
809
810impl<P: PtrSize> VMOffsets<P> {
812 #[inline]
814 pub fn vmglobal_import_from(&self) -> u8 {
815 0 * self.pointer_size()
816 }
817
818 #[inline]
820 pub fn size_of_vmglobal_import(&self) -> u8 {
821 2 * self.pointer_size() + 8
823 }
824}
825
826impl<P: PtrSize> VMOffsets<P> {
828 #[inline]
830 pub fn size_of_vmshared_type_index(&self) -> u8 {
831 4
832 }
833}
834
835impl<P: PtrSize> VMOffsets<P> {
837 #[inline]
839 pub fn vmtag_import_from(&self) -> u8 {
840 0 * self.pointer_size()
841 }
842
843 #[inline]
845 pub fn vmtag_import_vmctx(&self) -> u8 {
846 1 * self.pointer_size()
847 }
848
849 #[inline]
851 pub fn vmtag_import_index(&self) -> u8 {
852 2 * self.pointer_size()
853 }
854
855 #[inline]
857 pub fn size_of_vmtag_import(&self) -> u8 {
858 3 * self.pointer_size()
859 }
860}
861
862impl<P: PtrSize> VMOffsets<P> {
864 #[inline]
866 pub fn vmctx_imported_functions_begin(&self) -> u32 {
867 self.imported_functions
868 }
869
870 #[inline]
872 pub fn vmctx_imported_tables_begin(&self) -> u32 {
873 self.imported_tables
874 }
875
876 #[inline]
878 pub fn vmctx_imported_memories_begin(&self) -> u32 {
879 self.imported_memories
880 }
881
882 #[inline]
884 pub fn vmctx_imported_globals_begin(&self) -> u32 {
885 self.imported_globals
886 }
887
888 #[inline]
890 pub fn vmctx_imported_tags_begin(&self) -> u32 {
891 self.imported_tags
892 }
893
894 #[inline]
896 pub fn vmctx_tables_begin(&self) -> u32 {
897 self.defined_tables
898 }
899
900 #[inline]
902 pub fn vmctx_memories_begin(&self) -> u32 {
903 self.defined_memories
904 }
905
906 #[inline]
908 pub fn vmctx_owned_memories_begin(&self) -> u32 {
909 self.owned_memories
910 }
911
912 #[inline]
914 pub fn vmctx_globals_begin(&self) -> u32 {
915 self.defined_globals
916 }
917
918 #[inline]
920 pub fn vmctx_tags_begin(&self) -> u32 {
921 self.defined_tags
922 }
923
924 #[inline]
926 pub fn vmctx_func_refs_begin(&self) -> u32 {
927 self.defined_func_refs
928 }
929
930 #[inline]
932 pub fn size_of_vmctx(&self) -> u32 {
933 self.size
934 }
935
936 #[inline]
938 pub fn vmctx_vmfunction_import(&self, index: FuncIndex) -> u32 {
939 assert!(index.as_u32() < self.num_imported_functions);
940 self.vmctx_imported_functions_begin()
941 + index.as_u32() * u32::from(self.size_of_vmfunction_import())
942 }
943
944 #[inline]
946 pub fn vmctx_vmtable_import(&self, index: TableIndex) -> u32 {
947 assert!(index.as_u32() < self.num_imported_tables);
948 self.vmctx_imported_tables_begin()
949 + index.as_u32() * u32::from(self.size_of_vmtable_import())
950 }
951
952 #[inline]
954 pub fn vmctx_vmmemory_import(&self, index: MemoryIndex) -> u32 {
955 assert!(index.as_u32() < self.num_imported_memories);
956 self.vmctx_imported_memories_begin()
957 + index.as_u32() * u32::from(self.size_of_vmmemory_import())
958 }
959
960 #[inline]
962 pub fn vmctx_vmglobal_import(&self, index: GlobalIndex) -> u32 {
963 assert!(index.as_u32() < self.num_imported_globals);
964 self.vmctx_imported_globals_begin()
965 + index.as_u32() * u32::from(self.size_of_vmglobal_import())
966 }
967
968 #[inline]
970 pub fn vmctx_vmtag_import(&self, index: TagIndex) -> u32 {
971 assert!(index.as_u32() < self.num_imported_tags);
972 self.vmctx_imported_tags_begin() + index.as_u32() * u32::from(self.size_of_vmtag_import())
973 }
974
975 #[inline]
977 pub fn vmctx_vmtable_definition(&self, index: DefinedTableIndex) -> u32 {
978 assert!(index.as_u32() < self.num_defined_tables);
979 self.vmctx_tables_begin() + index.as_u32() * u32::from(self.size_of_vmtable_definition())
980 }
981
982 #[inline]
984 pub fn vmctx_vmmemory_pointer(&self, index: DefinedMemoryIndex) -> u32 {
985 assert!(index.as_u32() < self.num_defined_memories);
986 self.vmctx_memories_begin()
987 + index.as_u32() * u32::from(self.ptr.size_of_vmmemory_pointer())
988 }
989
990 #[inline]
992 pub fn vmctx_vmmemory_definition(&self, index: OwnedMemoryIndex) -> u32 {
993 assert!(index.as_u32() < self.num_owned_memories);
994 self.vmctx_owned_memories_begin()
995 + index.as_u32() * u32::from(self.ptr.size_of_vmmemory_definition())
996 }
997
998 #[inline]
1000 pub fn vmctx_vmglobal_definition(&self, index: DefinedGlobalIndex) -> u32 {
1001 assert!(index.as_u32() < self.num_defined_globals);
1002 self.vmctx_globals_begin()
1003 + index.as_u32() * u32::from(self.ptr.size_of_vmglobal_definition())
1004 }
1005
1006 #[inline]
1008 pub fn vmctx_vmtag_definition(&self, index: DefinedTagIndex) -> u32 {
1009 assert!(index.as_u32() < self.num_defined_tags);
1010 self.vmctx_tags_begin() + index.as_u32() * u32::from(self.ptr.size_of_vmtag_definition())
1011 }
1012
1013 #[inline]
1016 pub fn vmctx_func_ref(&self, index: FuncRefIndex) -> u32 {
1017 assert!(!index.is_reserved_value());
1018 assert!(index.as_u32() < self.num_escaped_funcs);
1019 self.vmctx_func_refs_begin() + index.as_u32() * u32::from(self.ptr.size_of_vm_func_ref())
1020 }
1021
1022 #[inline]
1024 pub fn vmctx_vmfunction_import_wasm_call(&self, index: FuncIndex) -> u32 {
1025 self.vmctx_vmfunction_import(index) + u32::from(self.vmfunction_import_wasm_call())
1026 }
1027
1028 #[inline]
1030 pub fn vmctx_vmfunction_import_array_call(&self, index: FuncIndex) -> u32 {
1031 self.vmctx_vmfunction_import(index) + u32::from(self.vmfunction_import_array_call())
1032 }
1033
1034 #[inline]
1036 pub fn vmctx_vmfunction_import_vmctx(&self, index: FuncIndex) -> u32 {
1037 self.vmctx_vmfunction_import(index) + u32::from(self.vmfunction_import_vmctx())
1038 }
1039
1040 #[inline]
1043 pub fn vmctx_vmtable_from(&self, index: TableIndex) -> u32 {
1044 self.vmctx_vmtable_import(index) + u32::from(self.vmtable_import_from())
1045 }
1046
1047 #[inline]
1049 pub fn vmctx_vmtable_definition_base(&self, index: DefinedTableIndex) -> u32 {
1050 self.vmctx_vmtable_definition(index) + u32::from(self.vmtable_definition_base())
1051 }
1052
1053 #[inline]
1055 pub fn vmctx_vmtable_definition_current_elements(&self, index: DefinedTableIndex) -> u32 {
1056 self.vmctx_vmtable_definition(index) + u32::from(self.vmtable_definition_current_elements())
1057 }
1058
1059 #[inline]
1061 pub fn vmctx_vmmemory_import_from(&self, index: MemoryIndex) -> u32 {
1062 self.vmctx_vmmemory_import(index) + u32::from(self.vmmemory_import_from())
1063 }
1064
1065 #[inline]
1067 pub fn vmctx_vmmemory_definition_base(&self, index: OwnedMemoryIndex) -> u32 {
1068 self.vmctx_vmmemory_definition(index) + u32::from(self.ptr.vmmemory_definition_base())
1069 }
1070
1071 #[inline]
1073 pub fn vmctx_vmmemory_definition_current_length(&self, index: OwnedMemoryIndex) -> u32 {
1074 self.vmctx_vmmemory_definition(index)
1075 + u32::from(self.ptr.vmmemory_definition_current_length())
1076 }
1077
1078 #[inline]
1080 pub fn vmctx_vmglobal_import_from(&self, index: GlobalIndex) -> u32 {
1081 self.vmctx_vmglobal_import(index) + u32::from(self.vmglobal_import_from())
1082 }
1083
1084 #[inline]
1086 pub fn vmctx_vmtag_import_from(&self, index: TagIndex) -> u32 {
1087 self.vmctx_vmtag_import(index) + u32::from(self.vmtag_import_from())
1088 }
1089
1090 #[inline]
1092 pub fn vmctx_vmtag_import_vmctx(&self, index: TagIndex) -> u32 {
1093 self.vmctx_vmtag_import(index) + u32::from(self.vmtag_import_vmctx())
1094 }
1095
1096 #[inline]
1098 pub fn vmctx_vmtag_import_index(&self, index: TagIndex) -> u32 {
1099 self.vmctx_vmtag_import(index) + u32::from(self.vmtag_import_index())
1100 }
1101}
1102
1103impl<P: PtrSize> VMOffsets<P> {
1105 #[inline]
1107 pub fn vm_gc_header_kind(&self) -> u32 {
1108 0
1109 }
1110
1111 #[inline]
1113 pub fn vm_gc_header_reserved_bits(&self) -> u32 {
1114 self.vm_gc_header_kind()
1116 }
1117
1118 #[inline]
1120 pub fn vm_gc_header_ty(&self) -> u32 {
1121 self.vm_gc_header_kind() + 4
1122 }
1123}
1124
1125impl<P: PtrSize> VMOffsets<P> {
1129 #[inline]
1131 pub fn vm_drc_header_ref_count(&self) -> u32 {
1132 8
1133 }
1134
1135 #[inline]
1137 pub fn vm_drc_header_next_over_approximated_stack_root(&self) -> u32 {
1138 self.vm_drc_header_ref_count() + 8
1139 }
1140}
1141
1142pub const VMCONTEXT_MAGIC: u32 = u32::from_le_bytes(*b"core");
1146
1147pub const VM_ARRAY_CALL_HOST_FUNC_MAGIC: u32 = u32::from_le_bytes(*b"ACHF");
1152
1153#[cfg(test)]
1154mod tests {
1155 use crate::vmoffsets::align;
1156
1157 #[test]
1158 fn alignment() {
1159 fn is_aligned(x: u32) -> bool {
1160 x % 16 == 0
1161 }
1162 assert!(is_aligned(align(0, 16)));
1163 assert!(is_aligned(align(32, 16)));
1164 assert!(is_aligned(align(33, 16)));
1165 assert!(is_aligned(align(31, 16)));
1166 }
1167}