1#![deny(rustdoc::broken_intra_doc_links)]
8
9use crate::{
10 FunctionIndex, GlobalIndex, LocalGlobalIndex, LocalMemoryIndex, LocalTableIndex, MemoryIndex,
11 ModuleInfo, TableIndex, TableType, WasmError, WasmResult, entity::EntityRef,
12};
13use more_asserts::assert_lt;
14use std::convert::TryFrom;
15
16#[derive(Copy, Clone, Debug)]
18pub struct VMBuiltinFunctionIndex(u32);
19
20impl VMBuiltinFunctionIndex {
21 pub const fn get_memory32_grow_index() -> Self {
23 Self(0)
24 }
25 pub const fn get_imported_memory32_grow_index() -> Self {
27 Self(1)
28 }
29 pub const fn get_memory32_size_index() -> Self {
31 Self(2)
32 }
33 pub const fn get_imported_memory32_size_index() -> Self {
35 Self(3)
36 }
37 pub const fn get_table_copy_index() -> Self {
40 Self(4)
41 }
42 pub const fn get_table_init_index() -> Self {
44 Self(5)
45 }
46 pub const fn get_elem_drop_index() -> Self {
48 Self(6)
49 }
50 pub const fn get_memory_copy_index() -> Self {
52 Self(7)
53 }
54 pub const fn get_memory_fill_index() -> Self {
56 Self(8)
57 }
58 pub const fn get_imported_memory_fill_index() -> Self {
60 Self(9)
61 }
62 pub const fn get_memory_init_index() -> Self {
64 Self(10)
65 }
66 pub const fn get_data_drop_index() -> Self {
68 Self(11)
69 }
70 pub const fn get_raise_trap_index() -> Self {
72 Self(12)
73 }
74 pub const fn get_table_size_index() -> Self {
76 Self(13)
77 }
78 pub const fn get_imported_table_size_index() -> Self {
80 Self(14)
81 }
82 pub const fn get_table_grow_index() -> Self {
84 Self(15)
85 }
86 pub const fn get_imported_table_grow_index() -> Self {
88 Self(16)
89 }
90 pub const fn get_table_get_index() -> Self {
92 Self(17)
93 }
94 pub const fn get_imported_table_get_index() -> Self {
96 Self(18)
97 }
98 pub const fn get_table_set_index() -> Self {
100 Self(19)
101 }
102 pub const fn get_imported_table_set_index() -> Self {
104 Self(20)
105 }
106 pub const fn get_func_ref_index() -> Self {
108 Self(21)
109 }
110 pub const fn get_table_fill_index() -> Self {
112 Self(22)
113 }
114 pub const fn get_memory_atomic_wait32_index() -> Self {
116 Self(23)
117 }
118 pub const fn get_imported_memory_atomic_wait32_index() -> Self {
120 Self(24)
121 }
122 pub const fn get_memory_atomic_wait64_index() -> Self {
124 Self(25)
125 }
126 pub const fn get_imported_memory_atomic_wait64_index() -> Self {
128 Self(26)
129 }
130 pub const fn get_memory_atomic_notify_index() -> Self {
132 Self(27)
133 }
134
135 pub const fn get_imported_memory_atomic_notify_index() -> Self {
137 Self(28)
138 }
139
140 pub const fn get_imported_debug_usize_index() -> Self {
142 Self(29)
143 }
144
145 pub const fn get_imported_debug_str_index() -> Self {
147 Self(30)
148 }
149
150 pub const fn get_imported_personality2_index() -> Self {
152 Self(31)
153 }
154
155 pub const fn get_imported_alloc_exception_index() -> Self {
157 Self(32)
158 }
159
160 pub const fn get_imported_throw_index() -> Self {
162 Self(33)
163 }
164
165 pub const fn get_imported_read_exnref_index() -> Self {
167 Self(34)
168 }
169
170 pub const fn get_imported_exception_into_exnref_index() -> Self {
172 Self(35)
173 }
174
175 pub const fn builtin_functions_total_number() -> u32 {
177 36
178 }
179
180 pub const fn index(self) -> u32 {
182 self.0
183 }
184}
185
186#[cfg(target_pointer_width = "32")]
187fn cast_to_u32(sz: usize) -> u32 {
188 u32::try_from(sz).unwrap()
189}
190#[cfg(target_pointer_width = "64")]
191fn cast_to_u32(sz: usize) -> u32 {
192 u32::try_from(sz).expect("overflow in cast from usize to u32")
193}
194
195#[inline]
197const fn align(offset: u32, width: u32) -> u32 {
198 offset.div_ceil(width) * width
199}
200
201#[derive(Clone, Debug)]
204pub struct VMOffsets {
205 pointer_size: u8,
207 num_imported_functions: u32,
209 num_imported_tables: u32,
211 num_imported_memories: u32,
213 num_tag_ids: u32,
215 num_imported_globals: u32,
217 num_local_tables: u32,
219 num_local_memories: u32,
221 num_local_globals: u32,
223 local_fixed_funcref_table_offsets: Vec<Option<u32>>,
226 size_of_local_fixed_funcref_tables: u32,
228
229 vmctx_imported_functions_begin: u32,
230 vmctx_imported_tables_begin: u32,
231 vmctx_imported_memories_begin: u32,
232 vmctx_tag_ids_begin: u32,
233 vmctx_imported_globals_begin: u32,
234 vmctx_tables_begin: u32,
235 vmctx_fixed_funcref_tables_begin: u32,
236 vmctx_memories_begin: u32,
237 vmctx_globals_begin: u32,
238 vmctx_builtin_functions_begin: u32,
239 vmctx_trap_handler_begin: u32,
240 vmctx_gas_limiter_pointer: u32,
241 vmctx_stack_limit_begin: u32,
242 vmctx_stack_limit_initial_begin: u32,
243 size_of_vmctx: u32,
244}
245
246impl VMOffsets {
247 #[deprecated(note = "Use try_new function instead")]
248 pub fn new(pointer_size: u8, module: &ModuleInfo) -> Self {
251 Self::try_new(pointer_size, module).unwrap()
252 }
253
254 pub fn try_new(pointer_size: u8, module: &ModuleInfo) -> Result<Self, String> {
256 let mut local_fixed_funcref_table_offsets =
257 vec![None; module.tables.len() - module.num_imported_tables];
258 let mut size_of_local_fixed_funcref_tables: u32 = 0;
259 let size_of_vmcaller_checked_anyfunc = 4 * u32::from(pointer_size);
261
262 let fixed_table_err = |table: &TableType| {
263 format!(
264 "cannot allocate fixed Table with {} elements",
265 table.minimum,
266 )
267 };
268 for (table_index, table) in module.tables.iter() {
269 if let Some(local_table_index) = module.local_table_index(table_index)
270 && table.is_fixed_funcref_table()
271 {
272 local_fixed_funcref_table_offsets[local_table_index.index()] =
273 Some(size_of_local_fixed_funcref_tables);
274 size_of_local_fixed_funcref_tables = size_of_local_fixed_funcref_tables
275 .checked_add(
276 table
277 .minimum
278 .checked_mul(size_of_vmcaller_checked_anyfunc)
279 .ok_or_else(|| fixed_table_err(table))?,
280 )
281 .ok_or_else(|| fixed_table_err(table))?;
282 }
283 }
284
285 let mut ret = Self {
286 pointer_size,
287 num_imported_functions: cast_to_u32(module.num_imported_functions),
288 num_imported_tables: cast_to_u32(module.num_imported_tables),
289 num_imported_memories: cast_to_u32(module.num_imported_memories),
290 num_tag_ids: cast_to_u32(module.tags.len()),
291 num_imported_globals: cast_to_u32(module.num_imported_globals),
292 num_local_tables: cast_to_u32(module.tables.len()),
293 num_local_memories: cast_to_u32(module.memories.len()),
294 num_local_globals: cast_to_u32(module.globals.len()),
295 local_fixed_funcref_table_offsets,
296 size_of_local_fixed_funcref_tables,
297 vmctx_imported_functions_begin: 0,
298 vmctx_imported_tables_begin: 0,
299 vmctx_imported_memories_begin: 0,
300 vmctx_tag_ids_begin: 0,
301 vmctx_imported_globals_begin: 0,
302 vmctx_tables_begin: 0,
303 vmctx_fixed_funcref_tables_begin: 0,
304 vmctx_memories_begin: 0,
305 vmctx_globals_begin: 0,
306 vmctx_builtin_functions_begin: 0,
307 vmctx_trap_handler_begin: 0,
308 vmctx_gas_limiter_pointer: 0,
309 vmctx_stack_limit_begin: 0,
310 vmctx_stack_limit_initial_begin: 0,
311 size_of_vmctx: 0,
312 };
313 ret.precompute()?;
314 Ok(ret)
315 }
316
317 pub fn new_for_trampolines(pointer_size: u8) -> Self {
322 Self {
323 pointer_size,
324 num_imported_functions: 0,
325 num_imported_tables: 0,
326 num_imported_memories: 0,
327 num_tag_ids: 0,
328 num_imported_globals: 0,
329 num_local_tables: 0,
330 num_local_memories: 0,
331 num_local_globals: 0,
332 local_fixed_funcref_table_offsets: Vec::new(),
333 size_of_local_fixed_funcref_tables: 0,
334 vmctx_imported_functions_begin: 0,
335 vmctx_imported_tables_begin: 0,
336 vmctx_imported_memories_begin: 0,
337 vmctx_tag_ids_begin: 0,
338 vmctx_imported_globals_begin: 0,
339 vmctx_tables_begin: 0,
340 vmctx_fixed_funcref_tables_begin: 0,
341 vmctx_memories_begin: 0,
342 vmctx_globals_begin: 0,
343 vmctx_builtin_functions_begin: 0,
344 vmctx_trap_handler_begin: 0,
345 vmctx_gas_limiter_pointer: 0,
346 vmctx_stack_limit_begin: 0,
347 vmctx_stack_limit_initial_begin: 0,
348 size_of_vmctx: 0,
349 }
350 }
351
352 pub fn num_local_tables(&self) -> u32 {
354 self.num_local_tables
355 }
356
357 pub fn num_local_memories(&self) -> u32 {
359 self.num_local_memories
360 }
361
362 pub fn num_local_globals(&self) -> u32 {
364 self.num_local_globals
365 }
366
367 fn precompute(&mut self) -> Result<(), &'static str> {
368 const ERR_MESSAGE: &str = "precompute exceeds u32 type";
369
370 fn offset_by(base: u32, num_items: u32, item_size: u32) -> Result<u32, &'static str> {
372 base.checked_add(num_items.checked_mul(item_size).ok_or(ERR_MESSAGE)?)
373 .ok_or(ERR_MESSAGE)
374 }
375 let pointer_size = self.pointer_size as u32;
379 let offset_by_aligned =
380 |base: u32, num_items: u32, item_size: u32| -> Result<u32, &'static str> {
381 Ok(align(
382 base.checked_add(num_items.checked_mul(item_size).ok_or(ERR_MESSAGE)?)
383 .ok_or(ERR_MESSAGE)?,
384 pointer_size,
385 ))
386 };
387
388 self.vmctx_imported_functions_begin = 0;
389 self.vmctx_imported_tables_begin = offset_by_aligned(
390 self.vmctx_imported_functions_begin,
391 self.num_imported_functions,
392 u32::from(self.size_of_vmfunction_import()),
393 )?;
394 self.vmctx_imported_memories_begin = offset_by_aligned(
395 self.vmctx_imported_tables_begin,
396 self.num_imported_tables,
397 u32::from(self.size_of_vmtable_import()),
398 )?;
399
400 self.vmctx_tag_ids_begin = offset_by_aligned(
401 self.vmctx_imported_memories_begin,
402 self.num_imported_memories,
403 u32::from(self.size_of_vmmemory_import()),
404 )?;
405
406 self.vmctx_imported_globals_begin = offset_by_aligned(
407 self.vmctx_tag_ids_begin,
408 self.num_tag_ids,
409 u32::from(self.size_of_vmshared_tag_index()),
410 )?;
411
412 self.vmctx_tables_begin = offset_by_aligned(
413 self.vmctx_imported_globals_begin,
414 self.num_imported_globals,
415 u32::from(self.size_of_vmglobal_import()),
416 )?;
417 self.vmctx_fixed_funcref_tables_begin = offset_by_aligned(
418 self.vmctx_tables_begin,
419 self.num_local_tables,
420 u32::from(self.size_of_vmtable_definition()),
421 )?;
422 self.vmctx_memories_begin = align(
423 self.vmctx_fixed_funcref_tables_begin
424 .checked_add(self.size_of_local_fixed_funcref_tables)
425 .ok_or(ERR_MESSAGE)?,
426 pointer_size,
427 );
428 self.vmctx_globals_begin = align(
429 offset_by(
430 self.vmctx_memories_begin,
431 self.num_local_memories,
432 u32::from(self.size_of_vmmemory_definition()),
433 )?,
434 16,
435 );
436 self.vmctx_builtin_functions_begin = offset_by(
437 self.vmctx_globals_begin,
438 self.num_local_globals,
439 u32::from(self.size_of_vmglobal_local()),
440 )?;
441 self.vmctx_trap_handler_begin = offset_by(
442 self.vmctx_builtin_functions_begin,
443 VMBuiltinFunctionIndex::builtin_functions_total_number(),
444 u32::from(self.pointer_size),
445 )?;
446 self.vmctx_gas_limiter_pointer = offset_by(
447 self.vmctx_trap_handler_begin,
448 1,
449 u32::from(self.pointer_size),
450 )?;
451 self.vmctx_stack_limit_begin = offset_by(
452 self.vmctx_gas_limiter_pointer,
453 1,
454 u32::from(self.pointer_size),
455 )?;
456 self.vmctx_stack_limit_initial_begin = self
457 .vmctx_stack_limit_begin
458 .checked_add(4)
459 .ok_or(ERR_MESSAGE)?;
460 self.size_of_vmctx = self
461 .vmctx_stack_limit_begin
462 .checked_add(4)
463 .ok_or(ERR_MESSAGE)?;
464
465 Ok(())
466 }
467}
468
469impl VMOffsets {
471 #[allow(clippy::erasing_op)]
473 pub const fn vmfunction_import_body(&self) -> u8 {
474 0 * self.pointer_size
475 }
476
477 #[allow(clippy::identity_op)]
479 pub const fn vmfunction_import_vmctx(&self) -> u8 {
480 1 * self.pointer_size
481 }
482
483 pub const fn vmfunction_import_handle(&self) -> u8 {
485 2 * self.pointer_size
486 }
487
488 pub const fn vmfunction_import_include_m0_param(&self) -> u8 {
490 3 * self.pointer_size
491 }
492
493 pub const fn size_of_vmfunction_import(&self) -> u8 {
495 4 * self.pointer_size
496 }
497}
498
499impl VMOffsets {
501 #[allow(clippy::erasing_op)]
503 pub const fn vmdynamicfunction_import_context_address(&self) -> u8 {
504 0 * self.pointer_size
505 }
506
507 #[allow(clippy::identity_op)]
509 pub const fn vmdynamicfunction_import_context_ctx(&self) -> u8 {
510 1 * self.pointer_size
511 }
512
513 pub const fn size_of_vmdynamicfunction_import_context(&self) -> u8 {
515 2 * self.pointer_size
516 }
517}
518
519impl VMOffsets {
521 #[allow(clippy::identity_op)]
523 pub const fn size_of_vmfunction_body_ptr(&self) -> u8 {
524 1 * self.pointer_size
525 }
526}
527
528impl VMOffsets {
530 #[allow(clippy::erasing_op)]
532 pub const fn vmtable_import_definition(&self) -> u8 {
533 0 * self.pointer_size
534 }
535
536 #[allow(clippy::identity_op)]
538 pub const fn vmtable_import_handle(&self) -> u8 {
539 1 * self.pointer_size
540 }
541
542 pub const fn size_of_vmtable_import(&self) -> u8 {
544 2 * self.pointer_size
545 }
546}
547
548impl VMOffsets {
550 #[allow(clippy::erasing_op)]
552 pub const fn vmtable_definition_base(&self) -> u8 {
553 0 * self.pointer_size
554 }
555
556 #[allow(clippy::identity_op)]
558 pub const fn vmtable_definition_current_elements(&self) -> u8 {
559 1 * self.pointer_size
560 }
561
562 pub const fn size_of_vmtable_definition_current_elements(&self) -> u8 {
564 4
565 }
566
567 pub const fn size_of_vmtable_definition(&self) -> u8 {
569 2 * self.pointer_size
570 }
571}
572
573impl VMOffsets {
575 #[allow(clippy::erasing_op)]
577 pub const fn vmmemory_import_definition(&self) -> u8 {
578 0 * self.pointer_size
579 }
580
581 #[allow(clippy::identity_op)]
583 pub const fn vmmemory_import_handle(&self) -> u8 {
584 1 * self.pointer_size
585 }
586
587 pub const fn size_of_vmmemory_import(&self) -> u8 {
589 2 * self.pointer_size
590 }
591}
592
593impl VMOffsets {
595 #[allow(clippy::erasing_op)]
597 pub const fn vmmemory_definition_base(&self) -> u8 {
598 0 * self.pointer_size
599 }
600
601 #[allow(clippy::identity_op)]
603 pub const fn vmmemory_definition_current_length(&self) -> u8 {
604 1 * self.pointer_size
605 }
606
607 pub const fn size_of_vmmemory_definition_current_length(&self) -> u8 {
609 4
610 }
611
612 pub const fn size_of_vmmemory_definition(&self) -> u8 {
614 2 * self.pointer_size
615 }
616}
617
618impl VMOffsets {
620 #[allow(clippy::erasing_op)]
622 pub const fn vmglobal_import_definition(&self) -> u8 {
623 0 * self.pointer_size
624 }
625
626 #[allow(clippy::identity_op)]
628 pub const fn vmglobal_import_handle(&self) -> u8 {
629 1 * self.pointer_size
630 }
631
632 #[allow(clippy::identity_op)]
634 pub const fn size_of_vmglobal_import(&self) -> u8 {
635 2 * self.pointer_size
636 }
637}
638
639impl VMOffsets {
641 pub const fn size_of_vmglobal_local(&self) -> u8 {
646 16
647 }
648}
649
650impl VMOffsets {
652 #[allow(clippy::erasing_op)]
654 pub const fn vmcaller_checked_anyfunc_func_ptr(&self) -> u8 {
655 0 * self.pointer_size
656 }
657
658 #[allow(clippy::identity_op)]
660 pub const fn vmcaller_checked_anyfunc_signature_hash(&self) -> u8 {
661 1 * self.pointer_size
662 }
663
664 pub const fn vmcaller_checked_anyfunc_vmctx(&self) -> u8 {
666 2 * self.pointer_size
667 }
668
669 pub const fn vmcaller_checked_anyfunc_call_trampoline(&self) -> u8 {
671 3 * self.pointer_size
672 }
673
674 pub const fn size_of_vmcaller_checked_anyfunc(&self) -> u8 {
676 4 * self.pointer_size
677 }
678}
679
680impl VMOffsets {
682 #[allow(clippy::erasing_op)]
684 pub const fn vm_funcref_anyfunc_ptr(&self) -> u8 {
685 0 * self.pointer_size
686 }
687
688 #[allow(clippy::identity_op)]
690 pub const fn size_of_vm_funcref(&self) -> u8 {
691 1 * self.pointer_size
692 }
693}
694
695impl VMOffsets {
697 pub const fn size_of_vmshared_tag_index(&self) -> u8 {
699 4
700 }
701}
702
703pub fn vmctx_offset(offset: u32) -> WasmResult<i32> {
705 i32::try_from(offset)
706 .map_err(|_| WasmError::Generic(format!("VMContext offset {offset} exceeds i32::MAX")))
707}
708
709impl VMOffsets {
713 #[allow(clippy::erasing_op)]
715 pub fn vmctx_imported_functions_begin(&self) -> u32 {
716 self.vmctx_imported_functions_begin
717 }
718
719 #[allow(clippy::identity_op)]
721 pub fn vmctx_imported_tables_begin(&self) -> u32 {
722 self.vmctx_imported_tables_begin
723 }
724
725 pub fn vmctx_imported_memories_begin(&self) -> u32 {
727 self.vmctx_imported_memories_begin
728 }
729
730 pub fn vmctx_imported_globals_begin(&self) -> u32 {
732 self.vmctx_imported_globals_begin
733 }
734
735 pub fn vmctx_tag_ids_begin(&self) -> u32 {
737 self.vmctx_tag_ids_begin
738 }
739
740 pub fn vmctx_tables_begin(&self) -> u32 {
742 self.vmctx_tables_begin
743 }
744
745 pub fn vmctx_fixed_funcref_tables_begin(&self) -> u32 {
747 self.vmctx_fixed_funcref_tables_begin
748 }
749
750 pub fn vmctx_memories_begin(&self) -> u32 {
752 self.vmctx_memories_begin
753 }
754
755 pub fn vmctx_globals_begin(&self) -> u32 {
757 self.vmctx_globals_begin
758 }
759
760 pub fn vmctx_builtin_functions_begin(&self) -> u32 {
762 self.vmctx_builtin_functions_begin
763 }
764
765 pub fn size_of_vmctx(&self) -> u32 {
767 self.size_of_vmctx
768 }
769
770 pub fn vmctx_vmfunction_import(&self, index: FunctionIndex) -> u32 {
772 assert_lt!(index.as_u32(), self.num_imported_functions);
773 self.vmctx_imported_functions_begin
774 + index.as_u32() * u32::from(self.size_of_vmfunction_import())
775 }
776
777 pub fn vmctx_vmtable_import(&self, index: TableIndex) -> u32 {
779 assert_lt!(index.as_u32(), self.num_imported_tables);
780 self.vmctx_imported_tables_begin + index.as_u32() * u32::from(self.size_of_vmtable_import())
781 }
782
783 pub fn vmctx_vmmemory_import(&self, index: MemoryIndex) -> u32 {
785 assert_lt!(index.as_u32(), self.num_imported_memories);
786 self.vmctx_imported_memories_begin
787 + index.as_u32() * u32::from(self.size_of_vmmemory_import())
788 }
789
790 pub fn vmctx_vmglobal_import(&self, index: GlobalIndex) -> u32 {
792 assert_lt!(index.as_u32(), self.num_imported_globals);
793 self.vmctx_imported_globals_begin
794 + index.as_u32() * u32::from(self.size_of_vmglobal_import())
795 }
796
797 pub fn vmctx_vmtable_definition(&self, index: LocalTableIndex) -> u32 {
799 assert_lt!(index.as_u32(), self.num_local_tables);
800 self.vmctx_tables_begin + index.as_u32() * u32::from(self.size_of_vmtable_definition())
801 }
802
803 pub fn vmctx_vmmemory_definition(&self, index: LocalMemoryIndex) -> u32 {
805 assert_lt!(index.as_u32(), self.num_local_memories);
806 self.vmctx_memories_begin + index.as_u32() * u32::from(self.size_of_vmmemory_definition())
807 }
808
809 pub fn vmctx_vmglobal_definition(&self, index: LocalGlobalIndex) -> u32 {
811 assert_lt!(index.as_u32(), self.num_local_globals);
812 self.vmctx_globals_begin + index.as_u32() * u32::from(self.size_of_vmglobal_local())
813 }
814
815 pub fn vmctx_vmfunction_import_body(&self, index: FunctionIndex) -> u32 {
818 self.vmctx_vmfunction_import(index) + u32::from(self.vmfunction_import_body())
819 }
820
821 pub fn vmctx_vmfunction_import_vmctx(&self, index: FunctionIndex) -> u32 {
824 self.vmctx_vmfunction_import(index) + u32::from(self.vmfunction_import_vmctx())
825 }
826
827 pub fn vmctx_vmtable_import_definition(&self, index: TableIndex) -> u32 {
830 self.vmctx_vmtable_import(index) + u32::from(self.vmtable_import_definition())
831 }
832
833 pub fn vmctx_vmtable_definition_base(&self, index: LocalTableIndex) -> u32 {
836 self.vmctx_vmtable_definition(index) + u32::from(self.vmtable_definition_base())
837 }
838
839 pub fn vmctx_vmtable_definition_current_elements(&self, index: LocalTableIndex) -> u32 {
842 self.vmctx_vmtable_definition(index) + u32::from(self.vmtable_definition_current_elements())
843 }
844
845 pub fn vmctx_fixed_funcref_table_anyfuncs(&self, index: LocalTableIndex) -> Option<u32> {
848 assert_lt!(index.as_u32(), self.num_local_tables);
849 self.local_fixed_funcref_table_offsets[index.index()]
850 .map(|offset| self.vmctx_fixed_funcref_tables_begin + offset)
851 }
852
853 pub fn vmctx_vmmemory_import_definition(&self, index: MemoryIndex) -> u32 {
856 self.vmctx_vmmemory_import(index) + u32::from(self.vmmemory_import_definition())
857 }
858
859 pub fn vmctx_vmmemory_import_handle(&self, index: MemoryIndex) -> u32 {
862 self.vmctx_vmmemory_import(index) + u32::from(self.vmmemory_import_handle())
863 }
864
865 pub fn vmctx_vmmemory_definition_base(&self, index: LocalMemoryIndex) -> u32 {
868 self.vmctx_vmmemory_definition(index) + u32::from(self.vmmemory_definition_base())
869 }
870
871 pub fn vmctx_vmmemory_definition_current_length(&self, index: LocalMemoryIndex) -> u32 {
874 self.vmctx_vmmemory_definition(index) + u32::from(self.vmmemory_definition_current_length())
875 }
876
877 pub fn vmctx_vmglobal_import_definition(&self, index: GlobalIndex) -> u32 {
880 self.vmctx_vmglobal_import(index) + u32::from(self.vmglobal_import_definition())
881 }
882
883 pub fn vmctx_builtin_function(&self, index: VMBuiltinFunctionIndex) -> u32 {
886 self.vmctx_builtin_functions_begin + index.index() * u32::from(self.pointer_size)
887 }
888}
889
890#[cfg(test)]
891mod tests {
892 use crate::vmoffsets::align;
893
894 #[test]
895 fn alignment() {
896 fn is_aligned(x: u32) -> bool {
897 x.is_multiple_of(16)
898 }
899 assert!(is_aligned(align(0, 16)));
900 assert!(is_aligned(align(32, 16)));
901 assert!(is_aligned(align(33, 16)));
902 assert!(is_aligned(align(31, 16)));
903 }
904}