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
568#[derive(Clone, Copy)]
570pub struct HostPtr;
571
572impl PtrSize for HostPtr {
573 #[inline]
574 fn size(&self) -> u8 {
575 core::mem::size_of::<usize>() as u8
576 }
577}
578
579impl PtrSize for u8 {
580 #[inline]
581 fn size(&self) -> u8 {
582 *self
583 }
584}
585
586#[derive(Debug, Clone, Copy)]
588pub struct VMOffsetsFields<P> {
589 pub ptr: P,
591 pub num_imported_functions: u32,
593 pub num_imported_tables: u32,
595 pub num_imported_memories: u32,
597 pub num_imported_globals: u32,
599 pub num_imported_tags: u32,
601 pub num_defined_tables: u32,
603 pub num_defined_memories: u32,
605 pub num_owned_memories: u32,
607 pub num_defined_globals: u32,
609 pub num_defined_tags: u32,
611 pub num_escaped_funcs: u32,
614 pub num_runtime_data: u32,
616 pub has_startup_func: bool,
618}
619
620impl<P: PtrSize> VMOffsets<P> {
621 pub fn new(ptr: P, module: &Module) -> Self {
623 let num_owned_memories = module
624 .memories
625 .iter()
626 .skip(module.num_imported_memories)
627 .filter(|p| !p.1.shared)
628 .count()
629 .try_into()
630 .unwrap();
631 VMOffsets::from(VMOffsetsFields {
632 ptr,
633 num_imported_functions: cast_to_u32(module.num_imported_funcs),
634 num_imported_tables: cast_to_u32(module.num_imported_tables),
635 num_imported_memories: cast_to_u32(module.num_imported_memories),
636 num_imported_globals: cast_to_u32(module.num_imported_globals),
637 num_imported_tags: cast_to_u32(module.num_imported_tags),
638 num_defined_tables: cast_to_u32(module.num_defined_tables()),
639 num_defined_memories: cast_to_u32(module.num_defined_memories()),
640 num_owned_memories,
641 num_defined_globals: cast_to_u32(module.globals.len() - module.num_imported_globals),
642 num_defined_tags: cast_to_u32(module.tags.len() - module.num_imported_tags),
643 num_escaped_funcs: cast_to_u32(module.num_escaped_funcs),
644 num_runtime_data: cast_to_u32(module.runtime_data.len()),
645 has_startup_func: !module.startup.is_none(),
646 })
647 }
648
649 #[inline]
651 pub fn pointer_size(&self) -> u8 {
652 self.ptr.size()
653 }
654
655 pub fn region_sizes(&self) -> impl Iterator<Item = (&str, u32)> {
660 macro_rules! calculate_sizes {
661 ($($name:ident: $desc:tt,)*) => {{
662 let VMOffsets {
663 ptr: _,
666 num_imported_functions: _,
667 num_imported_tables: _,
668 num_imported_memories: _,
669 num_imported_globals: _,
670 num_imported_tags: _,
671 num_defined_tables: _,
672 num_defined_globals: _,
673 num_defined_memories: _,
674 num_defined_tags: _,
675 num_owned_memories: _,
676 num_escaped_funcs: _,
677 num_runtime_data: _,
678 has_startup_func: _,
679
680 size,
682
683 $($name,)*
686 } = *self;
687
688 let mut last = size;
692 $(
693 assert!($name <= last);
694 let tmp = $name;
695 let $name = last - $name;
696 last = tmp;
697 )*
698 assert_ne!(last, 0);
699 IntoIterator::into_iter([
700 $(($desc, $name),)*
701 ("static vmctx data", last),
702 ])
703 }};
704 }
705
706 calculate_sizes! {
707 runtime_data_lengths: "runtime data lengths",
708 runtime_data_bases: "runtime data base pointers",
709 startup_func_ref: "startup funcref",
710 defined_func_refs: "module functions",
711 defined_tags: "defined tags",
712 defined_globals: "defined globals",
713 defined_tables: "defined tables",
714 imported_tags: "imported tags",
715 imported_globals: "imported globals",
716 imported_tables: "imported tables",
717 imported_functions: "imported functions",
718 owned_memories: "owned memories",
719 defined_memories: "defined memories",
720 imported_memories: "imported memories",
721 }
722 }
723}
724
725impl<P: PtrSize> From<VMOffsetsFields<P>> for VMOffsets<P> {
726 fn from(fields: VMOffsetsFields<P>) -> VMOffsets<P> {
727 let mut ret = Self {
728 ptr: fields.ptr,
729 num_imported_functions: fields.num_imported_functions,
730 num_imported_tables: fields.num_imported_tables,
731 num_imported_memories: fields.num_imported_memories,
732 num_imported_globals: fields.num_imported_globals,
733 num_imported_tags: fields.num_imported_tags,
734 num_defined_tables: fields.num_defined_tables,
735 num_defined_memories: fields.num_defined_memories,
736 num_owned_memories: fields.num_owned_memories,
737 num_defined_globals: fields.num_defined_globals,
738 num_defined_tags: fields.num_defined_tags,
739 num_escaped_funcs: fields.num_escaped_funcs,
740 num_runtime_data: fields.num_runtime_data,
741 has_startup_func: fields.has_startup_func,
742 imported_functions: 0,
743 imported_tables: 0,
744 imported_memories: 0,
745 imported_globals: 0,
746 imported_tags: 0,
747 defined_tables: 0,
748 defined_memories: 0,
749 owned_memories: 0,
750 defined_globals: 0,
751 defined_tags: 0,
752 defined_func_refs: 0,
753 startup_func_ref: 0,
754 runtime_data_bases: 0,
755 runtime_data_lengths: 0,
756 size: 0,
757 };
758
759 #[inline]
764 fn cadd(count: u32, size: u32) -> u32 {
765 count.checked_add(size).unwrap()
766 }
767
768 #[inline]
769 fn cmul(count: u32, size: u8) -> u32 {
770 count.checked_mul(u32::from(size)).unwrap()
771 }
772
773 let mut next_field_offset = u32::from(ret.ptr.vmctx_dynamic_data_start());
774
775 macro_rules! fields {
776 (size($field:ident) = $size:expr, $($rest:tt)*) => {
777 ret.$field = next_field_offset;
778 next_field_offset = cadd(next_field_offset, u32::from($size));
779 fields!($($rest)*);
780 };
781 (align($align:expr), $($rest:tt)*) => {
782 next_field_offset = align(next_field_offset, $align);
783 fields!($($rest)*);
784 };
785 () => {};
786 }
787
788 fields! {
789 size(imported_memories)
790 = cmul(ret.num_imported_memories, ret.size_of_vmmemory_import()),
791 size(defined_memories)
792 = cmul(ret.num_defined_memories, ret.ptr.size_of_vmmemory_pointer()),
793 size(owned_memories)
794 = cmul(ret.num_owned_memories, ret.ptr.size_of_vmmemory_definition()),
795 size(imported_functions)
796 = cmul(ret.num_imported_functions, ret.size_of_vmfunction_import()),
797 size(imported_tables)
798 = cmul(ret.num_imported_tables, ret.size_of_vmtable_import()),
799 size(imported_globals)
800 = cmul(ret.num_imported_globals, ret.size_of_vmglobal_import()),
801 size(imported_tags)
802 = cmul(ret.num_imported_tags, ret.size_of_vmtag_import()),
803 size(defined_tables)
804 = cmul(ret.num_defined_tables, ret.size_of_vmtable_definition()),
805 align(16),
806 size(defined_globals)
807 = cmul(ret.num_defined_globals, ret.ptr.size_of_vmglobal_definition()),
808 size(defined_tags)
809 = cmul(ret.num_defined_tags, ret.ptr.size_of_vmtag_definition()),
810 size(defined_func_refs) = cmul(
811 ret.num_escaped_funcs,
812 ret.ptr.size_of_vm_func_ref(),
813 ),
814 size(startup_func_ref) = if ret.has_startup_func {
815 ret.ptr.size_of_vm_func_ref()
816 } else {
817 0
818 },
819 size(runtime_data_bases) = cmul(ret.num_runtime_data, ret.ptr.size()),
820 size(runtime_data_lengths) = cmul(ret.num_runtime_data, 4),
821 }
822
823 ret.size = next_field_offset;
824
825 return ret;
826 }
827}
828
829impl<P: PtrSize> VMOffsets<P> {
830 #[inline]
832 pub fn vmfunction_import_array_call(&self) -> u8 {
833 0 * self.pointer_size()
834 }
835
836 #[inline]
838 pub fn vmfunction_import_wasm_call(&self) -> u8 {
839 1 * self.pointer_size()
840 }
841
842 #[inline]
844 pub fn vmfunction_import_type_index(&self) -> u8 {
845 2 * self.pointer_size()
846 }
847
848 #[inline]
850 pub fn vmfunction_import_vmctx(&self) -> u8 {
851 3 * self.pointer_size()
852 }
853
854 #[inline]
856 pub fn size_of_vmfunction_import(&self) -> u8 {
857 4 * self.pointer_size()
858 }
859}
860
861impl<P: PtrSize> VMOffsets<P> {
863 pub fn size_of_vmfunction_body_ptr(&self) -> u8 {
865 1 * self.pointer_size()
866 }
867}
868
869impl<P: PtrSize> VMOffsets<P> {
871 #[inline]
873 pub fn vmtable_import_from(&self) -> u8 {
874 0 * self.pointer_size()
875 }
876
877 #[inline]
879 pub fn vmtable_import_vmctx(&self) -> u8 {
880 1 * self.pointer_size()
881 }
882
883 #[inline]
885 pub fn vmtable_import_index(&self) -> u8 {
886 2 * self.pointer_size()
887 }
888
889 #[inline]
891 pub fn size_of_vmtable_import(&self) -> u8 {
892 3 * self.pointer_size()
893 }
894}
895
896impl<P: PtrSize> VMOffsets<P> {
898 #[inline]
900 pub fn vmtable_definition_base(&self) -> u8 {
901 0 * self.pointer_size()
902 }
903
904 pub fn vmtable_definition_current_elements(&self) -> u8 {
906 1 * self.pointer_size()
907 }
908
909 #[inline]
911 pub fn size_of_vmtable_definition_current_elements(&self) -> u8 {
912 self.pointer_size()
913 }
914
915 #[inline]
917 pub fn size_of_vmtable_definition(&self) -> u8 {
918 2 * self.pointer_size()
919 }
920}
921
922impl<P: PtrSize> VMOffsets<P> {
924 #[inline]
926 pub fn vmmemory_import_from(&self) -> u8 {
927 0 * self.pointer_size()
928 }
929
930 #[inline]
932 pub fn vmmemory_import_vmctx(&self) -> u8 {
933 1 * self.pointer_size()
934 }
935
936 #[inline]
938 pub fn vmmemory_import_index(&self) -> u8 {
939 2 * self.pointer_size()
940 }
941
942 #[inline]
944 pub fn size_of_vmmemory_import(&self) -> u8 {
945 3 * self.pointer_size()
946 }
947}
948
949impl<P: PtrSize> VMOffsets<P> {
951 #[inline]
953 pub fn vmglobal_import_from(&self) -> u8 {
954 0 * self.pointer_size()
955 }
956
957 #[inline]
959 pub fn size_of_vmglobal_import(&self) -> u8 {
960 2 * self.pointer_size() + 8
962 }
963}
964
965impl<P: PtrSize> VMOffsets<P> {
967 #[inline]
969 pub fn size_of_vmshared_type_index(&self) -> u8 {
970 4
971 }
972}
973
974impl<P: PtrSize> VMOffsets<P> {
976 #[inline]
978 pub fn vmtag_import_from(&self) -> u8 {
979 0 * self.pointer_size()
980 }
981
982 #[inline]
984 pub fn vmtag_import_vmctx(&self) -> u8 {
985 1 * self.pointer_size()
986 }
987
988 #[inline]
990 pub fn vmtag_import_index(&self) -> u8 {
991 2 * self.pointer_size()
992 }
993
994 #[inline]
996 pub fn size_of_vmtag_import(&self) -> u8 {
997 3 * self.pointer_size()
998 }
999}
1000
1001impl<P: PtrSize> VMOffsets<P> {
1003 #[inline]
1005 pub fn vmctx_imported_functions_begin(&self) -> u32 {
1006 self.imported_functions
1007 }
1008
1009 #[inline]
1011 pub fn vmctx_imported_tables_begin(&self) -> u32 {
1012 self.imported_tables
1013 }
1014
1015 #[inline]
1017 pub fn vmctx_imported_memories_begin(&self) -> u32 {
1018 self.imported_memories
1019 }
1020
1021 #[inline]
1023 pub fn vmctx_imported_globals_begin(&self) -> u32 {
1024 self.imported_globals
1025 }
1026
1027 #[inline]
1029 pub fn vmctx_imported_tags_begin(&self) -> u32 {
1030 self.imported_tags
1031 }
1032
1033 #[inline]
1035 pub fn vmctx_tables_begin(&self) -> u32 {
1036 self.defined_tables
1037 }
1038
1039 #[inline]
1041 pub fn vmctx_memories_begin(&self) -> u32 {
1042 self.defined_memories
1043 }
1044
1045 #[inline]
1047 pub fn vmctx_owned_memories_begin(&self) -> u32 {
1048 self.owned_memories
1049 }
1050
1051 #[inline]
1053 pub fn vmctx_globals_begin(&self) -> u32 {
1054 self.defined_globals
1055 }
1056
1057 #[inline]
1059 pub fn vmctx_tags_begin(&self) -> u32 {
1060 self.defined_tags
1061 }
1062
1063 #[inline]
1065 pub fn vmctx_func_refs_begin(&self) -> u32 {
1066 self.defined_func_refs
1067 }
1068
1069 #[inline]
1071 pub fn vmctx_runtime_data_bases_begin(&self) -> u32 {
1072 self.runtime_data_bases
1073 }
1074
1075 #[inline]
1077 pub fn vmctx_runtime_data_lengths_begin(&self) -> u32 {
1078 self.runtime_data_lengths
1079 }
1080
1081 #[inline]
1083 pub fn size_of_vmctx(&self) -> u32 {
1084 self.size
1085 }
1086
1087 #[inline]
1089 pub fn vmctx_vmfunction_import(&self, index: FuncIndex) -> u32 {
1090 assert!(index.as_u32() < self.num_imported_functions);
1091 self.vmctx_imported_functions_begin()
1092 + index.as_u32() * u32::from(self.size_of_vmfunction_import())
1093 }
1094
1095 #[inline]
1097 pub fn vmctx_vmtable_import(&self, index: TableIndex) -> u32 {
1098 assert!(index.as_u32() < self.num_imported_tables);
1099 self.vmctx_imported_tables_begin()
1100 + index.as_u32() * u32::from(self.size_of_vmtable_import())
1101 }
1102
1103 #[inline]
1105 pub fn vmctx_vmmemory_import(&self, index: MemoryIndex) -> u32 {
1106 assert!(index.as_u32() < self.num_imported_memories);
1107 self.vmctx_imported_memories_begin()
1108 + index.as_u32() * u32::from(self.size_of_vmmemory_import())
1109 }
1110
1111 #[inline]
1113 pub fn vmctx_vmglobal_import(&self, index: GlobalIndex) -> u32 {
1114 assert!(index.as_u32() < self.num_imported_globals);
1115 self.vmctx_imported_globals_begin()
1116 + index.as_u32() * u32::from(self.size_of_vmglobal_import())
1117 }
1118
1119 #[inline]
1121 pub fn vmctx_vmtag_import(&self, index: TagIndex) -> u32 {
1122 assert!(index.as_u32() < self.num_imported_tags);
1123 self.vmctx_imported_tags_begin() + index.as_u32() * u32::from(self.size_of_vmtag_import())
1124 }
1125
1126 #[inline]
1128 pub fn vmctx_vmtable_definition(&self, index: DefinedTableIndex) -> u32 {
1129 assert!(index.as_u32() < self.num_defined_tables);
1130 self.vmctx_tables_begin() + index.as_u32() * u32::from(self.size_of_vmtable_definition())
1131 }
1132
1133 #[inline]
1135 pub fn vmctx_vmmemory_pointer(&self, index: DefinedMemoryIndex) -> u32 {
1136 assert!(index.as_u32() < self.num_defined_memories);
1137 self.vmctx_memories_begin()
1138 + index.as_u32() * u32::from(self.ptr.size_of_vmmemory_pointer())
1139 }
1140
1141 #[inline]
1143 pub fn vmctx_vmmemory_definition(&self, index: OwnedMemoryIndex) -> u32 {
1144 assert!(index.as_u32() < self.num_owned_memories);
1145 self.vmctx_owned_memories_begin()
1146 + index.as_u32() * u32::from(self.ptr.size_of_vmmemory_definition())
1147 }
1148
1149 #[inline]
1151 pub fn vmctx_vmglobal_definition(&self, index: DefinedGlobalIndex) -> u32 {
1152 assert!(index.as_u32() < self.num_defined_globals);
1153 self.vmctx_globals_begin()
1154 + index.as_u32() * u32::from(self.ptr.size_of_vmglobal_definition())
1155 }
1156
1157 #[inline]
1159 pub fn vmctx_vmtag_definition(&self, index: DefinedTagIndex) -> u32 {
1160 assert!(index.as_u32() < self.num_defined_tags);
1161 self.vmctx_tags_begin() + index.as_u32() * u32::from(self.ptr.size_of_vmtag_definition())
1162 }
1163
1164 #[inline]
1167 pub fn vmctx_func_ref(&self, index: FuncRefIndex) -> u32 {
1168 assert!(!index.is_reserved_value());
1169 assert!(index.as_u32() < self.num_escaped_funcs);
1170 self.vmctx_func_refs_begin() + index.as_u32() * u32::from(self.ptr.size_of_vm_func_ref())
1171 }
1172
1173 #[inline]
1177 pub fn vmctx_startup_func_ref(&self) -> u32 {
1178 assert!(self.has_startup_func);
1179 self.startup_func_ref
1180 }
1181
1182 #[inline]
1184 pub fn vmctx_runtime_data_base(&self, index: RuntimeDataIndex) -> u32 {
1185 assert!(!index.is_reserved_value());
1186 assert!(index.as_u32() < self.num_runtime_data);
1187 self.vmctx_runtime_data_bases_begin() + index.as_u32() * u32::from(self.ptr.size())
1188 }
1189
1190 #[inline]
1192 pub fn vmctx_runtime_data_length(&self, index: RuntimeDataIndex) -> u32 {
1193 assert!(!index.is_reserved_value());
1194 assert!(index.as_u32() < self.num_runtime_data);
1195 self.vmctx_runtime_data_lengths_begin() + index.as_u32() * 4
1196 }
1197
1198 #[inline]
1200 pub fn vmctx_vmfunction_import_wasm_call(&self, index: FuncIndex) -> u32 {
1201 self.vmctx_vmfunction_import(index) + u32::from(self.vmfunction_import_wasm_call())
1202 }
1203
1204 #[inline]
1206 pub fn vmctx_vmfunction_import_array_call(&self, index: FuncIndex) -> u32 {
1207 self.vmctx_vmfunction_import(index) + u32::from(self.vmfunction_import_array_call())
1208 }
1209
1210 #[inline]
1212 pub fn vmctx_vmfunction_import_vmctx(&self, index: FuncIndex) -> u32 {
1213 self.vmctx_vmfunction_import(index) + u32::from(self.vmfunction_import_vmctx())
1214 }
1215
1216 #[inline]
1219 pub fn vmctx_vmtable_from(&self, index: TableIndex) -> u32 {
1220 self.vmctx_vmtable_import(index) + u32::from(self.vmtable_import_from())
1221 }
1222
1223 #[inline]
1225 pub fn vmctx_vmtable_definition_base(&self, index: DefinedTableIndex) -> u32 {
1226 self.vmctx_vmtable_definition(index) + u32::from(self.vmtable_definition_base())
1227 }
1228
1229 #[inline]
1231 pub fn vmctx_vmtable_definition_current_elements(&self, index: DefinedTableIndex) -> u32 {
1232 self.vmctx_vmtable_definition(index) + u32::from(self.vmtable_definition_current_elements())
1233 }
1234
1235 #[inline]
1237 pub fn vmctx_vmmemory_import_from(&self, index: MemoryIndex) -> u32 {
1238 self.vmctx_vmmemory_import(index) + u32::from(self.vmmemory_import_from())
1239 }
1240
1241 #[inline]
1243 pub fn vmctx_vmmemory_definition_base(&self, index: OwnedMemoryIndex) -> u32 {
1244 self.vmctx_vmmemory_definition(index) + u32::from(self.ptr.vmmemory_definition_base())
1245 }
1246
1247 #[inline]
1249 pub fn vmctx_vmmemory_definition_current_length(&self, index: OwnedMemoryIndex) -> u32 {
1250 self.vmctx_vmmemory_definition(index)
1251 + u32::from(self.ptr.vmmemory_definition_current_length())
1252 }
1253
1254 #[inline]
1256 pub fn vmctx_vmglobal_import_from(&self, index: GlobalIndex) -> u32 {
1257 self.vmctx_vmglobal_import(index) + u32::from(self.vmglobal_import_from())
1258 }
1259
1260 #[inline]
1262 pub fn vmctx_vmtag_import_from(&self, index: TagIndex) -> u32 {
1263 self.vmctx_vmtag_import(index) + u32::from(self.vmtag_import_from())
1264 }
1265
1266 #[inline]
1268 pub fn vmctx_vmtag_import_vmctx(&self, index: TagIndex) -> u32 {
1269 self.vmctx_vmtag_import(index) + u32::from(self.vmtag_import_vmctx())
1270 }
1271
1272 #[inline]
1274 pub fn vmctx_vmtag_import_index(&self, index: TagIndex) -> u32 {
1275 self.vmctx_vmtag_import(index) + u32::from(self.vmtag_import_index())
1276 }
1277}
1278
1279impl<P: PtrSize> VMOffsets<P> {
1281 #[inline]
1283 pub fn vm_gc_header_kind(&self) -> u32 {
1284 0
1285 }
1286
1287 #[inline]
1289 pub fn vm_gc_header_reserved_bits(&self) -> u32 {
1290 self.vm_gc_header_kind()
1292 }
1293
1294 #[inline]
1296 pub fn vm_gc_header_ty(&self) -> u32 {
1297 self.vm_gc_header_kind() + 4
1298 }
1299}
1300
1301impl<P: PtrSize> VMOffsets<P> {
1305 #[inline]
1307 pub fn vm_drc_header_ref_count(&self) -> u32 {
1308 8
1309 }
1310
1311 #[inline]
1313 pub fn vm_drc_header_next_over_approximated_stack_root(&self) -> u32 {
1314 self.vm_drc_header_ref_count() + 8
1315 }
1316}
1317
1318pub const VMCONTEXT_MAGIC: u32 = u32::from_le_bytes(*b"core");
1322
1323pub const VM_ARRAY_CALL_HOST_FUNC_MAGIC: u32 = u32::from_le_bytes(*b"ACHF");
1328
1329#[cfg(test)]
1330mod tests {
1331 use crate::vmoffsets::align;
1332
1333 #[test]
1334 fn alignment() {
1335 fn is_aligned(x: u32) -> bool {
1336 x % 16 == 0
1337 }
1338 assert!(is_aligned(align(0, 16)));
1339 assert!(is_aligned(align(32, 16)));
1340 assert!(is_aligned(align(33, 16)));
1341 assert!(is_aligned(align(31, 16)));
1342 }
1343}