wasmer_types/
vmoffsets.rs

1// This file contains code from external sources.
2// Attributions: https://github.com/wasmerio/wasmer/blob/main/docs/ATTRIBUTIONS.md
3
4//! Offsets and sizes of various structs in wasmer-vm's vmcontext
5//! module.
6
7#![deny(rustdoc::broken_intra_doc_links)]
8
9use crate::{
10    FunctionIndex, GlobalIndex, LocalGlobalIndex, LocalMemoryIndex, LocalTableIndex, MemoryIndex,
11    ModuleInfo, SignatureIndex, TableIndex, TagIndex,
12};
13use more_asserts::assert_lt;
14use std::convert::TryFrom;
15use std::mem::size_of;
16
17/// An index type for builtin functions.
18#[derive(Copy, Clone, Debug)]
19pub struct VMBuiltinFunctionIndex(u32);
20
21impl VMBuiltinFunctionIndex {
22    /// Returns an index for wasm's `memory.grow` builtin function.
23    pub const fn get_memory32_grow_index() -> Self {
24        Self(0)
25    }
26    /// Returns an index for wasm's imported `memory.grow` builtin function.
27    pub const fn get_imported_memory32_grow_index() -> Self {
28        Self(1)
29    }
30    /// Returns an index for wasm's `memory.size` builtin function.
31    pub const fn get_memory32_size_index() -> Self {
32        Self(2)
33    }
34    /// Returns an index for wasm's imported `memory.size` builtin function.
35    pub const fn get_imported_memory32_size_index() -> Self {
36        Self(3)
37    }
38    /// Returns an index for wasm's `table.copy` when both tables are locally
39    /// defined.
40    pub const fn get_table_copy_index() -> Self {
41        Self(4)
42    }
43    /// Returns an index for wasm's `table.init`.
44    pub const fn get_table_init_index() -> Self {
45        Self(5)
46    }
47    /// Returns an index for wasm's `elem.drop`.
48    pub const fn get_elem_drop_index() -> Self {
49        Self(6)
50    }
51    /// Returns an index for wasm's `memory.copy` for locally defined memories.
52    pub const fn get_memory_copy_index() -> Self {
53        Self(7)
54    }
55    /// Returns an index for wasm's `memory.copy` for imported memories.
56    pub const fn get_imported_memory_copy_index() -> Self {
57        Self(8)
58    }
59    /// Returns an index for wasm's `memory.fill` for locally defined memories.
60    pub const fn get_memory_fill_index() -> Self {
61        Self(9)
62    }
63    /// Returns an index for wasm's `memory.fill` for imported memories.
64    pub const fn get_imported_memory_fill_index() -> Self {
65        Self(10)
66    }
67    /// Returns an index for wasm's `memory.init` instruction.
68    pub const fn get_memory_init_index() -> Self {
69        Self(11)
70    }
71    /// Returns an index for wasm's `data.drop` instruction.
72    pub const fn get_data_drop_index() -> Self {
73        Self(12)
74    }
75    /// Returns an index for wasm's `raise_trap` instruction.
76    pub const fn get_raise_trap_index() -> Self {
77        Self(13)
78    }
79    /// Returns an index for wasm's `table.size` instruction for local tables.
80    pub const fn get_table_size_index() -> Self {
81        Self(14)
82    }
83    /// Returns an index for wasm's `table.size` instruction for imported tables.
84    pub const fn get_imported_table_size_index() -> Self {
85        Self(15)
86    }
87    /// Returns an index for wasm's `table.grow` instruction for local tables.
88    pub const fn get_table_grow_index() -> Self {
89        Self(16)
90    }
91    /// Returns an index for wasm's `table.grow` instruction for imported tables.
92    pub const fn get_imported_table_grow_index() -> Self {
93        Self(17)
94    }
95    /// Returns an index for wasm's `table.get` instruction for local tables.
96    pub const fn get_table_get_index() -> Self {
97        Self(18)
98    }
99    /// Returns an index for wasm's `table.get` instruction for imported tables.
100    pub const fn get_imported_table_get_index() -> Self {
101        Self(19)
102    }
103    /// Returns an index for wasm's `table.set` instruction for local tables.
104    pub const fn get_table_set_index() -> Self {
105        Self(20)
106    }
107    /// Returns an index for wasm's `table.set` instruction for imported tables.
108    pub const fn get_imported_table_set_index() -> Self {
109        Self(21)
110    }
111    /// Returns an index for wasm's `func.ref` instruction.
112    pub const fn get_func_ref_index() -> Self {
113        Self(22)
114    }
115    /// Returns an index for wasm's `table.fill` instruction for local tables.
116    pub const fn get_table_fill_index() -> Self {
117        Self(23)
118    }
119    /// Returns an index for wasm's local `memory.atomic.wait32` builtin function.
120    pub const fn get_memory_atomic_wait32_index() -> Self {
121        Self(24)
122    }
123    /// Returns an index for wasm's imported `memory.atomic.wait32` builtin function.
124    pub const fn get_imported_memory_atomic_wait32_index() -> Self {
125        Self(25)
126    }
127    /// Returns an index for wasm's local `memory.atomic.wait64` builtin function.
128    pub const fn get_memory_atomic_wait64_index() -> Self {
129        Self(26)
130    }
131    /// Returns an index for wasm's imported `memory.atomic.wait64` builtin function.
132    pub const fn get_imported_memory_atomic_wait64_index() -> Self {
133        Self(27)
134    }
135    /// Returns an index for wasm's local `memory.atomic.notify` builtin function.
136    pub const fn get_memory_atomic_notify_index() -> Self {
137        Self(28)
138    }
139
140    /// Returns an index for wasm's imported `memory.atomic.notify` builtin function.
141    pub const fn get_imported_memory_atomic_notify_index() -> Self {
142        Self(29)
143    }
144
145    /// Returns an index for wasm's imported `throw` builtin function.
146    pub const fn get_imported_throw_index() -> Self {
147        Self(30)
148    }
149
150    /// Returns an index for wasm's imported `rethrow` builtin function.
151    pub const fn get_imported_rethrow_index() -> Self {
152        Self(31)
153    }
154
155    /// Returns an index for wasm's imported `alloc_exception` builtin function.
156    pub const fn get_imported_alloc_exception_index() -> Self {
157        Self(32)
158    }
159
160    /// Returns an index for wasm's imported `delete_exception` builtin function.
161    pub const fn get_imported_delete_exception_index() -> Self {
162        Self(33)
163    }
164
165    /// Returns an index for wasm's imported `read_exception` builtin function.
166    pub const fn get_imported_read_exception_index() -> Self {
167        Self(34)
168    }
169
170    /// Returns an index for wasm's imported `debug_usize` builtin function.
171    pub const fn get_imported_debug_usize_index() -> Self {
172        Self(35)
173    }
174
175    /// Returns the total number of builtin functions.
176    pub const fn builtin_functions_total_number() -> u32 {
177        36
178    }
179
180    /// Return the index as an u32 number.
181    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/// Align an offset used in this module to a specific byte-width by rounding up
196#[inline]
197const fn align(offset: u32, width: u32) -> u32 {
198    (offset + (width - 1)) / width * width
199}
200
201/// This class computes offsets to fields within VMContext and other
202/// related structs that JIT code accesses directly.
203#[derive(Clone, Debug)]
204pub struct VMOffsets {
205    /// The size in bytes of a pointer on the target.
206    pointer_size: u8,
207    /// The number of signature declarations in the module.
208    num_signature_ids: u32,
209    /// The number of imported functions in the module.
210    num_imported_functions: u32,
211    /// The number of imported tables in the module.
212    num_imported_tables: u32,
213    /// The number of imported memories in the module.
214    num_imported_memories: u32,
215    /// The number of imported tags in the module.
216    num_imported_tags: u32,
217    /// The number of imported globals in the module.
218    num_imported_globals: u32,
219    /// The number of defined tables in the module.
220    num_local_tables: u32,
221    /// The number of defined memories in the module.
222    num_local_memories: u32,
223    /// The number of defined globals in the module.
224    num_local_globals: u32,
225
226    vmctx_signature_ids_begin: u32,
227    vmctx_imported_functions_begin: u32,
228    vmctx_imported_tables_begin: u32,
229    vmctx_imported_memories_begin: u32,
230    vmctx_imported_tags_begin: u32,
231    vmctx_imported_globals_begin: u32,
232    vmctx_tables_begin: u32,
233    vmctx_memories_begin: u32,
234    vmctx_globals_begin: u32,
235    vmctx_builtin_functions_begin: u32,
236    vmctx_trap_handler_begin: u32,
237    vmctx_gas_limiter_pointer: u32,
238    vmctx_stack_limit_begin: u32,
239    vmctx_stack_limit_initial_begin: u32,
240    size_of_vmctx: u32,
241}
242
243impl VMOffsets {
244    /// Return a new `VMOffsets` instance, for a given pointer size.
245    pub fn new(pointer_size: u8, module: &ModuleInfo) -> Self {
246        let mut ret = Self {
247            pointer_size,
248            num_signature_ids: cast_to_u32(module.signatures.len()),
249            num_imported_functions: cast_to_u32(module.num_imported_functions),
250            num_imported_tables: cast_to_u32(module.num_imported_tables),
251            num_imported_memories: cast_to_u32(module.num_imported_memories),
252            num_imported_tags: cast_to_u32(module.num_imported_tags),
253            num_imported_globals: cast_to_u32(module.num_imported_globals),
254            num_local_tables: cast_to_u32(module.tables.len()),
255            num_local_memories: cast_to_u32(module.memories.len()),
256            num_local_globals: cast_to_u32(module.globals.len()),
257            vmctx_signature_ids_begin: 0,
258            vmctx_imported_functions_begin: 0,
259            vmctx_imported_tables_begin: 0,
260            vmctx_imported_memories_begin: 0,
261            vmctx_imported_tags_begin: 0,
262            vmctx_imported_globals_begin: 0,
263            vmctx_tables_begin: 0,
264            vmctx_memories_begin: 0,
265            vmctx_globals_begin: 0,
266            vmctx_builtin_functions_begin: 0,
267            vmctx_trap_handler_begin: 0,
268            vmctx_gas_limiter_pointer: 0,
269            vmctx_stack_limit_begin: 0,
270            vmctx_stack_limit_initial_begin: 0,
271            size_of_vmctx: 0,
272        };
273        ret.precompute();
274        ret
275    }
276
277    /// Return a new `VMOffsets` instance, for a given pointer size
278    /// skipping the `ModuleInfo`.
279    ///
280    /// Note: This should only when generating code for trampolines.
281    pub fn new_for_trampolines(pointer_size: u8) -> Self {
282        Self {
283            pointer_size,
284            num_signature_ids: 0,
285            num_imported_functions: 0,
286            num_imported_tables: 0,
287            num_imported_memories: 0,
288            num_imported_tags: 0,
289            num_imported_globals: 0,
290            num_local_tables: 0,
291            num_local_memories: 0,
292            num_local_globals: 0,
293            vmctx_signature_ids_begin: 0,
294            vmctx_imported_functions_begin: 0,
295            vmctx_imported_tables_begin: 0,
296            vmctx_imported_memories_begin: 0,
297            vmctx_imported_tags_begin: 0,
298            vmctx_imported_globals_begin: 0,
299            vmctx_tables_begin: 0,
300            vmctx_memories_begin: 0,
301            vmctx_globals_begin: 0,
302            vmctx_builtin_functions_begin: 0,
303            vmctx_trap_handler_begin: 0,
304            vmctx_gas_limiter_pointer: 0,
305            vmctx_stack_limit_begin: 0,
306            vmctx_stack_limit_initial_begin: 0,
307            size_of_vmctx: 0,
308        }
309    }
310
311    /// Number of local tables defined in the module
312    pub fn num_local_tables(&self) -> u32 {
313        self.num_local_tables
314    }
315
316    /// Number of local memories defined in the module
317    pub fn num_local_memories(&self) -> u32 {
318        self.num_local_memories
319    }
320
321    fn precompute(&mut self) {
322        /// Offset base by num_items items of size item_size, panicking on overflow
323        fn offset_by(base: u32, num_items: u32, item_size: u32) -> u32 {
324            base.checked_add(num_items.checked_mul(item_size).unwrap())
325                .unwrap()
326        }
327        /// Offset base by num_items items of size item_size, panicking on overflow
328        /// Also, will align the value on pointer size boundary,
329        /// to avoid misalignement issue
330        fn offset_by_aligned(base: u32, num_items: u32, item_size: u32) -> u32 {
331            align(
332                base.checked_add(num_items.checked_mul(item_size).unwrap())
333                    .unwrap(),
334                size_of::<&u32>() as u32,
335            )
336        }
337
338        self.vmctx_signature_ids_begin = 0;
339        self.vmctx_imported_functions_begin = offset_by_aligned(
340            self.vmctx_signature_ids_begin,
341            self.num_signature_ids,
342            u32::from(self.size_of_vmshared_signature_index()),
343        );
344        self.vmctx_imported_tables_begin = offset_by_aligned(
345            self.vmctx_imported_functions_begin,
346            self.num_imported_functions,
347            u32::from(self.size_of_vmfunction_import()),
348        );
349        self.vmctx_imported_memories_begin = offset_by_aligned(
350            self.vmctx_imported_tables_begin,
351            self.num_imported_tables,
352            u32::from(self.size_of_vmtable_import()),
353        );
354
355        self.vmctx_imported_tags_begin = offset_by_aligned(
356            self.vmctx_imported_memories_begin,
357            self.num_imported_memories,
358            u32::from(self.size_of_vmmemory_import()),
359        );
360
361        self.vmctx_imported_globals_begin = offset_by_aligned(
362            self.vmctx_imported_tags_begin,
363            self.num_imported_tags,
364            u32::from(self.size_of_vmtag_import()),
365        );
366
367        self.vmctx_tables_begin = offset_by_aligned(
368            self.vmctx_imported_globals_begin,
369            self.num_imported_globals,
370            u32::from(self.size_of_vmglobal_import()),
371        );
372        self.vmctx_memories_begin = offset_by_aligned(
373            self.vmctx_tables_begin,
374            self.num_local_tables,
375            u32::from(self.size_of_vmtable_definition()),
376        );
377        self.vmctx_globals_begin = align(
378            offset_by(
379                self.vmctx_memories_begin,
380                self.num_local_memories,
381                u32::from(self.size_of_vmmemory_definition()),
382            ),
383            16,
384        );
385        self.vmctx_builtin_functions_begin = offset_by(
386            self.vmctx_globals_begin,
387            self.num_local_globals,
388            u32::from(self.size_of_vmglobal_local()),
389        );
390        self.vmctx_trap_handler_begin = offset_by(
391            self.vmctx_builtin_functions_begin,
392            VMBuiltinFunctionIndex::builtin_functions_total_number(),
393            u32::from(self.pointer_size),
394        );
395        self.vmctx_gas_limiter_pointer = offset_by(
396            self.vmctx_trap_handler_begin,
397            1,
398            u32::from(self.pointer_size),
399        );
400        self.vmctx_stack_limit_begin = offset_by(
401            self.vmctx_gas_limiter_pointer,
402            1,
403            u32::from(self.pointer_size),
404        );
405        self.vmctx_stack_limit_initial_begin = self.vmctx_stack_limit_begin.checked_add(4).unwrap();
406        self.size_of_vmctx = self.vmctx_stack_limit_begin.checked_add(4).unwrap();
407    }
408}
409
410/// Offsets for `VMFunctionImport`.
411impl VMOffsets {
412    /// The offset of the `body` field.
413    #[allow(clippy::erasing_op)]
414    pub const fn vmfunction_import_body(&self) -> u8 {
415        0 * self.pointer_size
416    }
417
418    /// The offset of the `vmctx` field.
419    #[allow(clippy::identity_op)]
420    pub const fn vmfunction_import_vmctx(&self) -> u8 {
421        1 * self.pointer_size
422    }
423
424    /// The offset of the `handle` field.
425    pub const fn vmfunction_import_handle(&self) -> u8 {
426        2 * self.pointer_size
427    }
428
429    /// Return the size of `VMFunctionImport`.
430    pub const fn size_of_vmfunction_import(&self) -> u8 {
431        3 * self.pointer_size
432    }
433}
434
435/// Offsets for `VMDynamicFunctionContext`.
436impl VMOffsets {
437    /// The offset of the `address` field.
438    #[allow(clippy::erasing_op)]
439    pub const fn vmdynamicfunction_import_context_address(&self) -> u8 {
440        0 * self.pointer_size
441    }
442
443    /// The offset of the `ctx` field.
444    #[allow(clippy::identity_op)]
445    pub const fn vmdynamicfunction_import_context_ctx(&self) -> u8 {
446        1 * self.pointer_size
447    }
448
449    /// Return the size of `VMDynamicFunctionContext`.
450    pub const fn size_of_vmdynamicfunction_import_context(&self) -> u8 {
451        2 * self.pointer_size
452    }
453}
454
455/// Offsets for `*const VMFunctionBody`.
456impl VMOffsets {
457    /// The size of the `current_elements` field.
458    #[allow(clippy::identity_op)]
459    pub const fn size_of_vmfunction_body_ptr(&self) -> u8 {
460        1 * self.pointer_size
461    }
462}
463
464/// Offsets for `VMTableImport`.
465impl VMOffsets {
466    /// The offset of the `definition` field.
467    #[allow(clippy::erasing_op)]
468    pub const fn vmtable_import_definition(&self) -> u8 {
469        0 * self.pointer_size
470    }
471
472    /// The offset of the `handle` field.
473    #[allow(clippy::identity_op)]
474    pub const fn vmtable_import_handle(&self) -> u8 {
475        1 * self.pointer_size
476    }
477
478    /// Return the size of `VMTableImport`.
479    pub const fn size_of_vmtable_import(&self) -> u8 {
480        2 * self.pointer_size
481    }
482}
483
484/// Offsets for `VMTableDefinition`.
485impl VMOffsets {
486    /// The offset of the `base` field.
487    #[allow(clippy::erasing_op)]
488    pub const fn vmtable_definition_base(&self) -> u8 {
489        0 * self.pointer_size
490    }
491
492    /// The offset of the `current_elements` field.
493    #[allow(clippy::identity_op)]
494    pub const fn vmtable_definition_current_elements(&self) -> u8 {
495        1 * self.pointer_size
496    }
497
498    /// The size of the `current_elements` field.
499    pub const fn size_of_vmtable_definition_current_elements(&self) -> u8 {
500        4
501    }
502
503    /// Return the size of `VMTableDefinition`.
504    pub const fn size_of_vmtable_definition(&self) -> u8 {
505        2 * self.pointer_size
506    }
507}
508
509/// Offsets for `VMMemoryImport`.
510impl VMOffsets {
511    /// The offset of the `from` field.
512    #[allow(clippy::erasing_op)]
513    pub const fn vmmemory_import_definition(&self) -> u8 {
514        0 * self.pointer_size
515    }
516
517    /// The offset of the `handle` field.
518    #[allow(clippy::identity_op)]
519    pub const fn vmmemory_import_handle(&self) -> u8 {
520        1 * self.pointer_size
521    }
522
523    /// Return the size of `VMMemoryImport`.
524    pub const fn size_of_vmmemory_import(&self) -> u8 {
525        2 * self.pointer_size
526    }
527}
528
529/// Offsets for `VMMemoryDefinition`.
530impl VMOffsets {
531    /// The offset of the `base` field.
532    #[allow(clippy::erasing_op)]
533    pub const fn vmmemory_definition_base(&self) -> u8 {
534        0 * self.pointer_size
535    }
536
537    /// The offset of the `current_length` field.
538    #[allow(clippy::identity_op)]
539    pub const fn vmmemory_definition_current_length(&self) -> u8 {
540        1 * self.pointer_size
541    }
542
543    /// The size of the `current_length` field.
544    pub const fn size_of_vmmemory_definition_current_length(&self) -> u8 {
545        4
546    }
547
548    /// Return the size of `VMMemoryDefinition`.
549    pub const fn size_of_vmmemory_definition(&self) -> u8 {
550        2 * self.pointer_size
551    }
552}
553
554/// Offsets for `VMGlobalImport`.
555impl VMOffsets {
556    /// The offset of the `definition` field.
557    #[allow(clippy::erasing_op)]
558    pub const fn vmglobal_import_definition(&self) -> u8 {
559        0 * self.pointer_size
560    }
561
562    /// The offset of the `handle` field.
563    #[allow(clippy::identity_op)]
564    pub const fn vmglobal_import_handle(&self) -> u8 {
565        1 * self.pointer_size
566    }
567
568    /// Return the size of `VMGlobalImport`.
569    #[allow(clippy::identity_op)]
570    pub const fn size_of_vmglobal_import(&self) -> u8 {
571        2 * self.pointer_size
572    }
573}
574
575/// Offsets for a non-null pointer to a `VMGlobalDefinition` used as a local global.
576impl VMOffsets {
577    /// Return the size of a pointer to a `VMGlobalDefinition`;
578    ///
579    /// The underlying global itself is the size of the largest value type (i.e. a V128),
580    /// however the size of this type is just the size of a pointer.
581    pub const fn size_of_vmglobal_local(&self) -> u8 {
582        self.pointer_size
583    }
584}
585
586/// Offsets for `VMSharedSignatureIndex`.
587impl VMOffsets {
588    /// Return the size of `VMSharedSignatureIndex`.
589    pub const fn size_of_vmshared_signature_index(&self) -> u8 {
590        4
591    }
592}
593
594/// Offsets for `VMCallerCheckedAnyfunc`.
595impl VMOffsets {
596    /// The offset of the `func_ptr` field.
597    #[allow(clippy::erasing_op)]
598    pub const fn vmcaller_checked_anyfunc_func_ptr(&self) -> u8 {
599        0 * self.pointer_size
600    }
601
602    /// The offset of the `type_index` field.
603    #[allow(clippy::identity_op)]
604    pub const fn vmcaller_checked_anyfunc_type_index(&self) -> u8 {
605        1 * self.pointer_size
606    }
607
608    /// The offset of the `vmctx` field.
609    pub const fn vmcaller_checked_anyfunc_vmctx(&self) -> u8 {
610        2 * self.pointer_size
611    }
612
613    /// The offset of the `call_trampoline` field.
614    pub const fn vmcaller_checked_anyfunc_call_trampoline(&self) -> u8 {
615        3 * self.pointer_size
616    }
617
618    /// Return the size of `VMCallerCheckedAnyfunc`.
619    pub const fn size_of_vmcaller_checked_anyfunc(&self) -> u8 {
620        4 * self.pointer_size
621    }
622}
623
624/// Offsets for `VMFuncRef`.
625impl VMOffsets {
626    /// The offset to the pointer to the anyfunc inside the ref.
627    #[allow(clippy::erasing_op)]
628    pub const fn vm_funcref_anyfunc_ptr(&self) -> u8 {
629        0 * self.pointer_size
630    }
631
632    /// Return the size of `VMFuncRef`.
633    #[allow(clippy::identity_op)]
634    pub const fn size_of_vm_funcref(&self) -> u8 {
635        1 * self.pointer_size
636    }
637}
638
639/// Offsets for `VMTag` imports.
640impl VMOffsets {
641    /// Return the size of `VMTagImport`.
642    #[allow(clippy::identity_op)]
643    pub const fn size_of_vmtag_import(&self) -> u8 {
644        1 * self.pointer_size
645    }
646}
647
648/// Offsets for `VMContext`.
649impl VMOffsets {
650    /// The offset of the `signature_ids` array.
651    pub fn vmctx_signature_ids_begin(&self) -> u32 {
652        self.vmctx_signature_ids_begin
653    }
654
655    /// The offset of the `tables` array.
656    #[allow(clippy::erasing_op)]
657    pub fn vmctx_imported_functions_begin(&self) -> u32 {
658        self.vmctx_imported_functions_begin
659    }
660
661    /// The offset of the `tables` array.
662    #[allow(clippy::identity_op)]
663    pub fn vmctx_imported_tables_begin(&self) -> u32 {
664        self.vmctx_imported_tables_begin
665    }
666
667    /// The offset of the `memories` array.
668    pub fn vmctx_imported_memories_begin(&self) -> u32 {
669        self.vmctx_imported_memories_begin
670    }
671
672    /// The offset of the `globals` array.
673    pub fn vmctx_imported_globals_begin(&self) -> u32 {
674        self.vmctx_imported_globals_begin
675    }
676
677    /// The offset of the `globals` array.
678    pub fn vmctx_imported_tags_begin(&self) -> u32 {
679        self.vmctx_imported_tags_begin
680    }
681
682    /// The offset of the `tables` array.
683    pub fn vmctx_tables_begin(&self) -> u32 {
684        self.vmctx_tables_begin
685    }
686
687    /// The offset of the `memories` array.
688    pub fn vmctx_memories_begin(&self) -> u32 {
689        self.vmctx_memories_begin
690    }
691
692    /// The offset of the `globals` array.
693    pub fn vmctx_globals_begin(&self) -> u32 {
694        self.vmctx_globals_begin
695    }
696
697    /// The offset of the builtin functions array.
698    pub fn vmctx_builtin_functions_begin(&self) -> u32 {
699        self.vmctx_builtin_functions_begin
700    }
701
702    /// Return the size of the `VMContext` allocation.
703    pub fn size_of_vmctx(&self) -> u32 {
704        self.size_of_vmctx
705    }
706
707    /// Return the offset to `VMSharedSignatureIndex` index `index`.
708    pub fn vmctx_vmshared_signature_id(&self, index: SignatureIndex) -> u32 {
709        assert_lt!(index.as_u32(), self.num_signature_ids);
710        self.vmctx_signature_ids_begin
711            + index.as_u32() * u32::from(self.size_of_vmshared_signature_index())
712    }
713
714    /// Return the offset to `VMFunctionImport` index `index`.
715    pub fn vmctx_vmfunction_import(&self, index: FunctionIndex) -> u32 {
716        assert_lt!(index.as_u32(), self.num_imported_functions);
717        self.vmctx_imported_functions_begin
718            + index.as_u32() * u32::from(self.size_of_vmfunction_import())
719    }
720
721    /// Return the offset to `VMTableImport` index `index`.
722    pub fn vmctx_vmtable_import(&self, index: TableIndex) -> u32 {
723        assert_lt!(index.as_u32(), self.num_imported_tables);
724        self.vmctx_imported_tables_begin + index.as_u32() * u32::from(self.size_of_vmtable_import())
725    }
726
727    /// Return the offset to `VMMemoryImport` index `index`.
728    pub fn vmctx_vmmemory_import(&self, index: MemoryIndex) -> u32 {
729        assert_lt!(index.as_u32(), self.num_imported_memories);
730        self.vmctx_imported_memories_begin
731            + index.as_u32() * u32::from(self.size_of_vmmemory_import())
732    }
733
734    /// Return the offset to `VMTagImport` index `index`.
735    pub fn vmctx_vmtag_import(&self, index: TagIndex) -> u32 {
736        assert_lt!(index.as_u32(), self.num_imported_tags);
737        self.vmctx_imported_tags_begin + index.as_u32() * u32::from(self.size_of_vmtag_import())
738    }
739
740    /// Return the offset to `VMGlobalImport` index `index`.
741    pub fn vmctx_vmglobal_import(&self, index: GlobalIndex) -> u32 {
742        assert_lt!(index.as_u32(), self.num_imported_globals);
743        self.vmctx_imported_globals_begin
744            + index.as_u32() * u32::from(self.size_of_vmglobal_import())
745    }
746
747    /// Return the offset to `VMTableDefinition` index `index`.
748    pub fn vmctx_vmtable_definition(&self, index: LocalTableIndex) -> u32 {
749        assert_lt!(index.as_u32(), self.num_local_tables);
750        self.vmctx_tables_begin + index.as_u32() * u32::from(self.size_of_vmtable_definition())
751    }
752
753    /// Return the offset to `VMMemoryDefinition` index `index`.
754    pub fn vmctx_vmmemory_definition(&self, index: LocalMemoryIndex) -> u32 {
755        assert_lt!(index.as_u32(), self.num_local_memories);
756        self.vmctx_memories_begin + index.as_u32() * u32::from(self.size_of_vmmemory_definition())
757    }
758
759    /// Return the offset to the `VMGlobalDefinition` index `index`.
760    pub fn vmctx_vmglobal_definition(&self, index: LocalGlobalIndex) -> u32 {
761        assert_lt!(index.as_u32(), self.num_local_globals);
762        self.vmctx_globals_begin + index.as_u32() * u32::from(self.size_of_vmglobal_local())
763    }
764
765    /// Return the offset to the `body` field in `*const VMFunctionBody` index `index`.
766    /// Remember updating precompute upon changes
767    pub fn vmctx_vmfunction_import_body(&self, index: FunctionIndex) -> u32 {
768        self.vmctx_vmfunction_import(index) + u32::from(self.vmfunction_import_body())
769    }
770
771    /// Return the offset to the `vmctx` field in `*const VMFunctionBody` index `index`.
772    /// Remember updating precompute upon changes
773    pub fn vmctx_vmfunction_import_vmctx(&self, index: FunctionIndex) -> u32 {
774        self.vmctx_vmfunction_import(index) + u32::from(self.vmfunction_import_vmctx())
775    }
776
777    /// Return the offset to the `definition` field in `VMTableImport` index `index`.
778    /// Remember updating precompute upon changes
779    pub fn vmctx_vmtable_import_definition(&self, index: TableIndex) -> u32 {
780        self.vmctx_vmtable_import(index) + u32::from(self.vmtable_import_definition())
781    }
782
783    /// Return the offset to the `base` field in `VMTableDefinition` index `index`.
784    /// Remember updating precompute upon changes
785    pub fn vmctx_vmtable_definition_base(&self, index: LocalTableIndex) -> u32 {
786        self.vmctx_vmtable_definition(index) + u32::from(self.vmtable_definition_base())
787    }
788
789    /// Return the offset to the `current_elements` field in `VMTableDefinition` index `index`.
790    /// Remember updating precompute upon changes
791    pub fn vmctx_vmtable_definition_current_elements(&self, index: LocalTableIndex) -> u32 {
792        self.vmctx_vmtable_definition(index) + u32::from(self.vmtable_definition_current_elements())
793    }
794
795    /// Return the offset to the `from` field in `VMMemoryImport` index `index`.
796    /// Remember updating precompute upon changes
797    pub fn vmctx_vmmemory_import_definition(&self, index: MemoryIndex) -> u32 {
798        self.vmctx_vmmemory_import(index) + u32::from(self.vmmemory_import_definition())
799    }
800
801    /// Return the offset to the `vmctx` field in `VMMemoryImport` index `index`.
802    /// Remember updating precompute upon changes
803    pub fn vmctx_vmmemory_import_handle(&self, index: MemoryIndex) -> u32 {
804        self.vmctx_vmmemory_import(index) + u32::from(self.vmmemory_import_handle())
805    }
806
807    /// Return the offset to the `base` field in `VMMemoryDefinition` index `index`.
808    /// Remember updating precompute upon changes
809    pub fn vmctx_vmmemory_definition_base(&self, index: LocalMemoryIndex) -> u32 {
810        self.vmctx_vmmemory_definition(index) + u32::from(self.vmmemory_definition_base())
811    }
812
813    /// Return the offset to the `current_length` field in `VMMemoryDefinition` index `index`.
814    /// Remember updating precompute upon changes
815    pub fn vmctx_vmmemory_definition_current_length(&self, index: LocalMemoryIndex) -> u32 {
816        self.vmctx_vmmemory_definition(index) + u32::from(self.vmmemory_definition_current_length())
817    }
818
819    /// Return the offset to the `from` field in `VMGlobalImport` index `index`.
820    /// Remember updating precompute upon changes
821    pub fn vmctx_vmglobal_import_definition(&self, index: GlobalIndex) -> u32 {
822        self.vmctx_vmglobal_import(index) + u32::from(self.vmglobal_import_definition())
823    }
824
825    /// Return the offset to builtin function in `VMBuiltinFunctionsArray` index `index`.
826    /// Remember updating precompute upon changes
827    pub fn vmctx_builtin_function(&self, index: VMBuiltinFunctionIndex) -> u32 {
828        self.vmctx_builtin_functions_begin + index.index() * u32::from(self.pointer_size)
829    }
830}
831
832/// Target specific type for shared signature index.
833#[derive(Debug, Copy, Clone)]
834pub struct TargetSharedSignatureIndex(u32);
835
836impl TargetSharedSignatureIndex {
837    /// Constructs `TargetSharedSignatureIndex`.
838    pub const fn new(value: u32) -> Self {
839        Self(value)
840    }
841
842    /// Returns index value.
843    pub const fn index(self) -> u32 {
844        self.0
845    }
846}
847
848#[cfg(test)]
849mod tests {
850    use crate::vmoffsets::align;
851
852    #[test]
853    fn alignment() {
854        fn is_aligned(x: u32) -> bool {
855            x % 16 == 0
856        }
857        assert!(is_aligned(align(0, 16)));
858        assert!(is_aligned(align(32, 16)));
859        assert!(is_aligned(align(33, 16)));
860        assert!(is_aligned(align(31, 16)));
861    }
862}