1use crate::VMFunctionBody;
8use crate::VMTable;
9use crate::global::VMGlobal;
10use crate::instance::Instance;
11use crate::memory::VMMemory;
12use crate::store::InternalStoreHandle;
13use crate::trap::{Trap, TrapCode};
14use crate::{VMBuiltinFunctionIndex, VMFunction};
15use std::convert::TryFrom;
16use std::hash::{Hash, Hasher};
17use std::ptr::{self, NonNull};
18use std::sync::atomic::{AtomicU32, AtomicU64, Ordering};
19use wasmer_types::RawValue;
20
21#[derive(Copy, Clone, Eq)]
26#[repr(C)]
27pub union VMFunctionContext {
28 pub vmctx: *mut VMContext,
30 pub host_env: *mut std::ffi::c_void,
32}
33
34impl VMFunctionContext {
35 pub fn is_null(&self) -> bool {
37 unsafe { self.host_env.is_null() }
38 }
39}
40
41impl std::fmt::Debug for VMFunctionContext {
42 fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
43 f.debug_struct("VMFunctionContext")
44 .field("vmctx_or_hostenv", unsafe { &self.host_env })
45 .finish()
46 }
47}
48
49impl std::cmp::PartialEq for VMFunctionContext {
50 fn eq(&self, rhs: &Self) -> bool {
51 unsafe { std::ptr::eq(self.host_env, rhs.host_env) }
52 }
53}
54
55impl std::hash::Hash for VMFunctionContext {
56 fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
57 unsafe {
58 self.vmctx.hash(state);
59 }
60 }
61}
62
63#[derive(Debug, Copy, Clone)]
65#[repr(C)]
66pub struct VMFunctionImport {
67 pub body: *const VMFunctionBody,
69
70 pub environment: VMFunctionContext,
72
73 pub handle: InternalStoreHandle<VMFunction>,
75
76 pub include_m0_param: bool,
78}
79
80#[cfg(test)]
81mod test_vmfunction_import {
82 use super::VMFunctionImport;
83 use core::mem::offset_of;
84 use std::mem::size_of;
85 use wasmer_types::ModuleInfo;
86 use wasmer_types::VMOffsets;
87
88 #[test]
89 fn check_vmfunction_import_offsets() {
90 let module = ModuleInfo::new();
91 let offsets = VMOffsets::new(size_of::<*mut u8>() as u8, &module);
92 assert_eq!(
93 size_of::<VMFunctionImport>(),
94 usize::from(offsets.size_of_vmfunction_import())
95 );
96 assert_eq!(
97 offset_of!(VMFunctionImport, body),
98 usize::from(offsets.vmfunction_import_body())
99 );
100 assert_eq!(
101 offset_of!(VMFunctionImport, environment),
102 usize::from(offsets.vmfunction_import_vmctx())
103 );
104 }
105}
106
107#[repr(C)]
116pub struct VMDynamicFunctionContext<T> {
117 pub address: *const VMFunctionBody,
122
123 pub ctx: T,
125}
126
127unsafe impl<T: Sized + Send + Sync> Send for VMDynamicFunctionContext<T> {}
130unsafe impl<T: Sized + Send + Sync> Sync for VMDynamicFunctionContext<T> {}
133
134impl<T: Sized + Clone + Send + Sync> Clone for VMDynamicFunctionContext<T> {
135 fn clone(&self) -> Self {
136 Self {
137 address: self.address,
138 ctx: self.ctx.clone(),
139 }
140 }
141}
142
143#[cfg(test)]
144mod test_vmdynamicfunction_import_context {
145 use super::VMDynamicFunctionContext;
146 use crate::VMOffsets;
147 use core::mem::offset_of;
148 use std::mem::size_of;
149 use wasmer_types::ModuleInfo;
150
151 #[test]
152 fn check_vmdynamicfunction_import_context_offsets() {
153 let module = ModuleInfo::new();
154 let offsets = VMOffsets::new(size_of::<*mut u8>() as u8, &module);
155 assert_eq!(
156 size_of::<VMDynamicFunctionContext<usize>>(),
157 usize::from(offsets.size_of_vmdynamicfunction_import_context())
158 );
159 assert_eq!(
160 offset_of!(VMDynamicFunctionContext<usize>, address),
161 usize::from(offsets.vmdynamicfunction_import_context_address())
162 );
163 assert_eq!(
164 offset_of!(VMDynamicFunctionContext<usize>, ctx),
165 usize::from(offsets.vmdynamicfunction_import_context_ctx())
166 );
167 }
168}
169
170#[derive(Debug, Copy, Clone, Eq, PartialEq)]
172#[repr(C)]
173pub enum VMFunctionKind {
174 Static,
181
182 Dynamic,
188}
189
190#[derive(Clone)]
193#[repr(C)]
194pub struct VMTableImport {
195 pub definition: NonNull<VMTableDefinition>,
197
198 pub handle: InternalStoreHandle<VMTable>,
200}
201
202#[cfg(test)]
203mod test_vmtable_import {
204 use super::VMTableImport;
205 use crate::VMOffsets;
206 use core::mem::offset_of;
207 use std::mem::size_of;
208 use wasmer_types::ModuleInfo;
209
210 #[test]
211 fn check_vmtable_import_offsets() {
212 let module = ModuleInfo::new();
213 let offsets = VMOffsets::new(size_of::<*mut u8>() as u8, &module);
214 assert_eq!(
215 size_of::<VMTableImport>(),
216 usize::from(offsets.size_of_vmtable_import())
217 );
218 assert_eq!(
219 offset_of!(VMTableImport, definition),
220 usize::from(offsets.vmtable_import_definition())
221 );
222 }
223}
224
225#[derive(Clone)]
228#[repr(C)]
229pub struct VMMemoryImport {
230 pub definition: NonNull<VMMemoryDefinition>,
232
233 pub handle: InternalStoreHandle<VMMemory>,
235}
236
237#[cfg(test)]
238mod test_vmmemory_import {
239 use super::VMMemoryImport;
240 use crate::VMOffsets;
241 use core::mem::offset_of;
242 use std::mem::size_of;
243 use wasmer_types::ModuleInfo;
244
245 #[test]
246 fn check_vmmemory_import_offsets() {
247 let module = ModuleInfo::new();
248 let offsets = VMOffsets::new(size_of::<*mut u8>() as u8, &module);
249 assert_eq!(
250 size_of::<VMMemoryImport>(),
251 usize::from(offsets.size_of_vmmemory_import())
252 );
253 assert_eq!(
254 offset_of!(VMMemoryImport, definition),
255 usize::from(offsets.vmmemory_import_definition())
256 );
257 assert_eq!(
258 offset_of!(VMMemoryImport, handle),
259 usize::from(offsets.vmmemory_import_handle())
260 );
261 }
262}
263
264#[derive(Clone)]
267#[repr(C)]
268pub struct VMGlobalImport {
269 pub definition: NonNull<VMGlobalDefinition>,
271
272 pub handle: InternalStoreHandle<VMGlobal>,
274}
275
276unsafe impl Send for VMGlobalImport {}
281unsafe impl Sync for VMGlobalImport {}
287
288#[cfg(test)]
289mod test_vmglobal_import {
290 use super::VMGlobalImport;
291 use crate::VMOffsets;
292 use core::mem::offset_of;
293 use std::mem::size_of;
294 use wasmer_types::ModuleInfo;
295
296 #[test]
297 fn check_vmglobal_import_offsets() {
298 let module = ModuleInfo::new();
299 let offsets = VMOffsets::new(size_of::<*mut u8>() as u8, &module);
300 assert_eq!(
301 size_of::<VMGlobalImport>(),
302 usize::from(offsets.size_of_vmglobal_import())
303 );
304 assert_eq!(
305 offset_of!(VMGlobalImport, definition),
306 usize::from(offsets.vmglobal_import_definition())
307 );
308 }
309}
310
311pub(crate) unsafe fn memory_copy(
322 dst_mem: &VMMemoryDefinition,
323 src_mem: &VMMemoryDefinition,
324 dst: u32,
325 src: u32,
326 len: u32,
327) -> Result<(), Trap> {
328 unsafe {
329 if src
331 .checked_add(len)
332 .is_none_or(|n| usize::try_from(n).unwrap() > src_mem.current_length)
333 || dst
334 .checked_add(len)
335 .is_none_or(|m| usize::try_from(m).unwrap() > dst_mem.current_length)
336 {
337 return Err(Trap::lib(TrapCode::HeapAccessOutOfBounds));
338 }
339
340 let dst = usize::try_from(dst).unwrap();
341 let src = usize::try_from(src).unwrap();
342
343 let dst = dst_mem.base.add(dst);
346 let src = src_mem.base.add(src);
347 ptr::copy(src, dst, len as usize);
348
349 Ok(())
350 }
351}
352
353pub(crate) unsafe fn memory_fill(
364 mem: &VMMemoryDefinition,
365 dst: u32,
366 val: u32,
367 len: u32,
368) -> Result<(), Trap> {
369 unsafe {
370 if dst
371 .checked_add(len)
372 .is_none_or(|m| usize::try_from(m).unwrap() > mem.current_length)
373 {
374 return Err(Trap::lib(TrapCode::HeapAccessOutOfBounds));
375 }
376
377 let dst = isize::try_from(dst).unwrap();
378 let val = val as u8;
379
380 let dst = mem.base.offset(dst);
383 ptr::write_bytes(dst, val, len as usize);
384
385 Ok(())
386 }
387}
388
389pub(crate) fn memory32_atomic_check_notify(mem: &VMMemoryDefinition, dst: u32) -> Result<(), Trap> {
395 const TYPE_SIZE: usize = size_of::<u32>();
396 let dst = usize::try_from(dst).unwrap();
397 if dst
398 .checked_add(TYPE_SIZE)
399 .is_none_or(|end| end > mem.current_length)
400 {
401 return Err(Trap::lib(TrapCode::HeapAccessOutOfBounds));
402 }
403
404 if !dst.is_multiple_of(TYPE_SIZE) {
405 return Err(Trap::lib(TrapCode::UnalignedAtomic));
406 }
407 Ok(())
408}
409
410pub(crate) unsafe fn memory32_atomic_check32(
419 mem: &VMMemoryDefinition,
420 dst: u32,
421 val: u32,
422) -> Result<u32, Trap> {
423 unsafe {
424 const TYPE_SIZE: usize = size_of::<u32>();
425 let dst = usize::try_from(dst).unwrap();
426 if dst
427 .checked_add(TYPE_SIZE)
428 .is_none_or(|end| end > mem.current_length)
429 {
430 return Err(Trap::lib(TrapCode::HeapAccessOutOfBounds));
431 }
432
433 if !dst.is_multiple_of(TYPE_SIZE) {
434 return Err(Trap::lib(TrapCode::UnalignedAtomic));
435 }
436 let Ok(dst) = isize::try_from(dst) else {
437 return Err(Trap::lib(TrapCode::HeapAccessOutOfBounds));
438 };
439
440 let dst = mem.base.offset(dst) as *mut u32;
443 let read_val = AtomicU32::from_ptr(dst).load(Ordering::Acquire);
444 let ret = if read_val == val { 0 } else { 1 };
445 Ok(ret)
446 }
447}
448
449pub(crate) unsafe fn memory32_atomic_check64(
458 mem: &VMMemoryDefinition,
459 dst: u32,
460 val: u64,
461) -> Result<u32, Trap> {
462 unsafe {
463 const TYPE_SIZE: usize = size_of::<u64>();
464 let dst = usize::try_from(dst).unwrap();
465 if dst
466 .checked_add(TYPE_SIZE)
467 .is_none_or(|end| end > mem.current_length)
468 {
469 return Err(Trap::lib(TrapCode::HeapAccessOutOfBounds));
470 }
471
472 if !dst.is_multiple_of(TYPE_SIZE) {
473 return Err(Trap::lib(TrapCode::UnalignedAtomic));
474 }
475 let Ok(dst) = isize::try_from(dst) else {
476 return Err(Trap::lib(TrapCode::HeapAccessOutOfBounds));
477 };
478
479 let dst = mem.base.offset(dst) as *mut u64;
482 let read_val = AtomicU64::from_ptr(dst).load(Ordering::Acquire);
483 let ret = if read_val == val { 0 } else { 1 };
484 Ok(ret)
485 }
486}
487
488#[derive(Debug, Clone, Copy)]
491#[repr(C)]
492pub struct VMTableDefinition {
493 pub base: *mut u8,
495
496 pub current_elements: u32,
498}
499
500#[cfg(test)]
501mod test_vmtable_definition {
502 use super::VMTableDefinition;
503 use crate::VMOffsets;
504 use core::mem::offset_of;
505 use std::mem::size_of;
506 use wasmer_types::ModuleInfo;
507
508 #[test]
509 fn check_vmtable_definition_offsets() {
510 let module = ModuleInfo::new();
511 let offsets = VMOffsets::new(size_of::<*mut u8>() as u8, &module);
512 assert_eq!(
513 size_of::<VMTableDefinition>(),
514 usize::from(offsets.size_of_vmtable_definition())
515 );
516 assert_eq!(
517 offset_of!(VMTableDefinition, base),
518 usize::from(offsets.vmtable_definition_base())
519 );
520 assert_eq!(
521 offset_of!(VMTableDefinition, current_elements),
522 usize::from(offsets.vmtable_definition_current_elements())
523 );
524 }
525}
526
527#[derive(Debug, Clone)]
532#[repr(C, align(16))]
533pub struct VMGlobalDefinition {
534 pub val: RawValue,
536}
537
538#[cfg(test)]
539mod test_vmglobal_definition {
540 use super::VMGlobalDefinition;
541 use crate::{VMFuncRef, VMOffsets};
542 use more_asserts::assert_ge;
543 use std::mem::{align_of, size_of};
544 use wasmer_types::ModuleInfo;
545
546 #[test]
547 fn check_vmglobal_definition_alignment() {
548 assert_ge!(align_of::<VMGlobalDefinition>(), align_of::<i32>());
549 assert_ge!(align_of::<VMGlobalDefinition>(), align_of::<i64>());
550 assert_ge!(align_of::<VMGlobalDefinition>(), align_of::<f32>());
551 assert_ge!(align_of::<VMGlobalDefinition>(), align_of::<f64>());
552 assert_ge!(align_of::<VMGlobalDefinition>(), align_of::<VMFuncRef>());
553 assert_ge!(align_of::<VMGlobalDefinition>(), align_of::<[u8; 16]>());
554 }
555
556 #[test]
557 fn check_vmglobal_definition_offsets() {
558 let module = ModuleInfo::new();
559 let offsets = VMOffsets::new(size_of::<*mut u8>() as u8, &module);
560 assert_eq!(
561 size_of::<VMGlobalDefinition>(),
562 usize::from(offsets.size_of_vmglobal_local())
563 );
564 }
565
566 #[test]
567 fn check_vmglobal_begins_aligned() {
568 let module = ModuleInfo::new();
569 let offsets = VMOffsets::new(size_of::<*mut u8>() as u8, &module);
570 assert_eq!(offsets.vmctx_globals_begin() % 16, 0);
571 }
572}
573
574impl VMGlobalDefinition {
575 pub fn new() -> Self {
577 Self {
578 val: Default::default(),
579 }
580 }
581}
582
583#[repr(C)]
586#[cfg_attr(feature = "artifact-size", derive(loupe::MemoryUsage))]
587pub struct VMSharedTagIndex(u32);
588
589impl VMSharedTagIndex {
590 pub fn new(value: u32) -> Self {
592 Self(value)
593 }
594
595 pub fn index(&self) -> u32 {
597 self.0
598 }
599}
600
601#[repr(C)]
604#[cfg_attr(feature = "artifact-size", derive(loupe::MemoryUsage))]
605#[derive(Debug, Eq, PartialEq, Clone, Copy, Hash)]
606pub struct VMSignatureHash(u32);
607
608impl VMSignatureHash {
609 pub fn new(value: u32) -> Self {
611 Self(value)
612 }
613}
614
615#[derive(Debug, Clone, Copy)]
619#[repr(C)]
620pub struct VMCallerCheckedAnyfunc {
621 pub func_ptr: *const VMFunctionBody,
623 pub type_signature_hash: VMSignatureHash,
625 pub vmctx: VMFunctionContext,
627 pub call_trampoline: VMTrampoline,
630 }
632
633unsafe extern "C" fn null_call_trampoline(
634 _vmctx: *mut VMContext,
635 _callee: *const VMFunctionBody,
636 _values: *mut RawValue,
637) {
638 unreachable!("null funcref trampoline should never be invoked");
639}
640
641impl VMCallerCheckedAnyfunc {
642 pub fn null() -> Self {
644 Self {
645 func_ptr: ptr::null(),
646 type_signature_hash: VMSignatureHash(0),
647 vmctx: VMFunctionContext {
648 host_env: ptr::null_mut(),
649 },
650 call_trampoline: null_call_trampoline,
651 }
652 }
653}
654
655impl PartialEq for VMCallerCheckedAnyfunc {
656 fn eq(&self, other: &Self) -> bool {
657 self.func_ptr == other.func_ptr
658 && self.type_signature_hash == other.type_signature_hash
659 && self.vmctx == other.vmctx
660 && ptr::fn_addr_eq(self.call_trampoline, other.call_trampoline)
661 }
662}
663
664impl Eq for VMCallerCheckedAnyfunc {}
665
666impl Hash for VMCallerCheckedAnyfunc {
667 fn hash<H: Hasher>(&self, state: &mut H) {
668 self.func_ptr.hash(state);
669 self.type_signature_hash.hash(state);
670 self.vmctx.hash(state);
671 ptr::hash(self.call_trampoline as *const (), state);
672 }
673}
674
675#[cfg(test)]
676mod test_vmcaller_checked_anyfunc {
677 use super::VMCallerCheckedAnyfunc;
678 use crate::VMOffsets;
679 use core::mem::offset_of;
680 use std::mem::size_of;
681 use wasmer_types::ModuleInfo;
682
683 #[test]
684 fn check_vmcaller_checked_anyfunc_offsets() {
685 let module = ModuleInfo::new();
686 let offsets = VMOffsets::new(size_of::<*mut u8>() as u8, &module);
687 assert_eq!(
688 size_of::<VMCallerCheckedAnyfunc>(),
689 usize::from(offsets.size_of_vmcaller_checked_anyfunc())
690 );
691 assert_eq!(
692 offset_of!(VMCallerCheckedAnyfunc, func_ptr),
693 usize::from(offsets.vmcaller_checked_anyfunc_func_ptr())
694 );
695 assert_eq!(
696 offset_of!(VMCallerCheckedAnyfunc, type_signature_hash),
697 usize::from(offsets.vmcaller_checked_anyfunc_signature_hash())
698 );
699 assert_eq!(
700 offset_of!(VMCallerCheckedAnyfunc, vmctx),
701 usize::from(offsets.vmcaller_checked_anyfunc_vmctx())
702 );
703 }
704}
705
706#[repr(C)]
709pub struct VMBuiltinFunctionsArray {
710 ptrs: [usize; Self::len()],
711}
712
713impl VMBuiltinFunctionsArray {
714 pub const fn len() -> usize {
715 VMBuiltinFunctionIndex::builtin_functions_total_number() as usize
716 }
717
718 pub fn initialized() -> Self {
719 use crate::libcalls::*;
720
721 let mut ptrs = [0; Self::len()];
722
723 ptrs[VMBuiltinFunctionIndex::get_memory32_grow_index().index() as usize] =
724 wasmer_vm_memory32_grow as *const () as usize;
725 ptrs[VMBuiltinFunctionIndex::get_imported_memory32_grow_index().index() as usize] =
726 wasmer_vm_imported_memory32_grow as *const () as usize;
727 ptrs[VMBuiltinFunctionIndex::get_memory32_size_index().index() as usize] =
728 wasmer_vm_memory32_size as *const () as usize;
729 ptrs[VMBuiltinFunctionIndex::get_imported_memory32_size_index().index() as usize] =
730 wasmer_vm_imported_memory32_size as *const () as usize;
731 ptrs[VMBuiltinFunctionIndex::get_table_copy_index().index() as usize] =
732 wasmer_vm_table_copy as *const () as usize;
733 ptrs[VMBuiltinFunctionIndex::get_table_init_index().index() as usize] =
734 wasmer_vm_table_init as *const () as usize;
735 ptrs[VMBuiltinFunctionIndex::get_elem_drop_index().index() as usize] =
736 wasmer_vm_elem_drop as *const () as usize;
737 ptrs[VMBuiltinFunctionIndex::get_memory_copy_index().index() as usize] =
738 wasmer_vm_memory32_copy as *const () as usize;
739 ptrs[VMBuiltinFunctionIndex::get_memory_fill_index().index() as usize] =
740 wasmer_vm_memory32_fill as *const () as usize;
741 ptrs[VMBuiltinFunctionIndex::get_imported_memory_fill_index().index() as usize] =
742 wasmer_vm_imported_memory32_fill as *const () as usize;
743 ptrs[VMBuiltinFunctionIndex::get_memory_init_index().index() as usize] =
744 wasmer_vm_memory32_init as *const () as usize;
745 ptrs[VMBuiltinFunctionIndex::get_data_drop_index().index() as usize] =
746 wasmer_vm_data_drop as *const () as usize;
747 ptrs[VMBuiltinFunctionIndex::get_raise_trap_index().index() as usize] =
748 wasmer_vm_raise_trap as *const () as usize;
749 ptrs[VMBuiltinFunctionIndex::get_table_size_index().index() as usize] =
750 wasmer_vm_table_size as *const () as usize;
751 ptrs[VMBuiltinFunctionIndex::get_imported_table_size_index().index() as usize] =
752 wasmer_vm_imported_table_size as *const () as usize;
753 ptrs[VMBuiltinFunctionIndex::get_table_grow_index().index() as usize] =
754 wasmer_vm_table_grow as *const () as usize;
755 ptrs[VMBuiltinFunctionIndex::get_imported_table_grow_index().index() as usize] =
756 wasmer_vm_imported_table_grow as *const () as usize;
757 ptrs[VMBuiltinFunctionIndex::get_table_get_index().index() as usize] =
758 wasmer_vm_table_get as *const () as usize;
759 ptrs[VMBuiltinFunctionIndex::get_imported_table_get_index().index() as usize] =
760 wasmer_vm_imported_table_get as *const () as usize;
761 ptrs[VMBuiltinFunctionIndex::get_table_set_index().index() as usize] =
762 wasmer_vm_table_set as *const () as usize;
763 ptrs[VMBuiltinFunctionIndex::get_imported_table_set_index().index() as usize] =
764 wasmer_vm_imported_table_set as *const () as usize;
765 ptrs[VMBuiltinFunctionIndex::get_func_ref_index().index() as usize] =
766 wasmer_vm_func_ref as *const () as usize;
767 ptrs[VMBuiltinFunctionIndex::get_table_fill_index().index() as usize] =
768 wasmer_vm_table_fill as *const () as usize;
769 ptrs[VMBuiltinFunctionIndex::get_memory_atomic_wait32_index().index() as usize] =
770 wasmer_vm_memory32_atomic_wait32 as *const () as usize;
771 ptrs[VMBuiltinFunctionIndex::get_imported_memory_atomic_wait32_index().index() as usize] =
772 wasmer_vm_imported_memory32_atomic_wait32 as *const () as usize;
773 ptrs[VMBuiltinFunctionIndex::get_memory_atomic_wait64_index().index() as usize] =
774 wasmer_vm_memory32_atomic_wait64 as *const () as usize;
775 ptrs[VMBuiltinFunctionIndex::get_imported_memory_atomic_wait64_index().index() as usize] =
776 wasmer_vm_imported_memory32_atomic_wait64 as *const () as usize;
777 ptrs[VMBuiltinFunctionIndex::get_memory_atomic_notify_index().index() as usize] =
778 wasmer_vm_memory32_atomic_notify as *const () as usize;
779 ptrs[VMBuiltinFunctionIndex::get_imported_memory_atomic_notify_index().index() as usize] =
780 wasmer_vm_imported_memory32_atomic_notify as *const () as usize;
781 ptrs[VMBuiltinFunctionIndex::get_imported_debug_usize_index().index() as usize] =
782 wasmer_vm_dbg_usize as *const () as usize;
783 ptrs[VMBuiltinFunctionIndex::get_imported_debug_str_index().index() as usize] =
784 wasmer_vm_dbg_str as *const () as usize;
785 ptrs[VMBuiltinFunctionIndex::get_imported_personality2_index().index() as usize] =
786 wasmer_eh_personality2 as *const () as usize;
787 ptrs[VMBuiltinFunctionIndex::get_imported_alloc_exception_index().index() as usize] =
788 wasmer_vm_alloc_exception as *const () as usize;
789 ptrs[VMBuiltinFunctionIndex::get_imported_throw_index().index() as usize] =
790 wasmer_vm_throw as *const () as usize;
791 ptrs[VMBuiltinFunctionIndex::get_imported_read_exnref_index().index() as usize] =
792 wasmer_vm_read_exnref as *const () as usize;
793 ptrs[VMBuiltinFunctionIndex::get_imported_exception_into_exnref_index().index() as usize] =
794 wasmer_vm_exception_into_exnref as *const () as usize;
795
796 debug_assert!(ptrs.iter().cloned().all(|p| p != 0));
797
798 Self { ptrs }
799 }
800}
801
802#[derive(Debug)]
812#[repr(C, align(16))] pub struct VMContext {}
814
815impl VMContext {
816 #[allow(clippy::cast_ptr_alignment)]
822 #[inline]
823 pub(crate) unsafe fn instance(&self) -> &Instance {
824 unsafe {
825 &*((self as *const Self as *mut u8).offset(-Instance::vmctx_offset())
826 as *const Instance)
827 }
828 }
829
830 #[inline]
831 pub(crate) unsafe fn instance_mut(&mut self) -> &mut Instance {
832 unsafe {
833 &mut *((self as *const Self as *mut u8).offset(-Instance::vmctx_offset())
834 as *mut Instance)
835 }
836 }
837}
838
839pub type VMTrampoline = unsafe extern "C" fn(
841 *mut VMContext, *const VMFunctionBody, *mut RawValue, );
845
846#[derive(Debug, Copy, Clone)]
850#[repr(C)]
851pub struct VMMemoryDefinition {
852 pub base: *mut u8,
854
855 pub current_length: usize,
857}
858
859unsafe impl Send for VMMemoryDefinition {}
863unsafe impl Sync for VMMemoryDefinition {}
869
870#[cfg(test)]
871mod test_vmmemory_definition {
872 use super::VMMemoryDefinition;
873 use crate::VMOffsets;
874 use core::mem::offset_of;
875 use std::mem::size_of;
876 use wasmer_types::ModuleInfo;
877
878 #[test]
879 fn check_vmmemory_definition_offsets() {
880 let module = ModuleInfo::new();
881 let offsets = VMOffsets::new(size_of::<*mut u8>() as u8, &module);
882 assert_eq!(
883 size_of::<VMMemoryDefinition>(),
884 usize::from(offsets.size_of_vmmemory_definition())
885 );
886 assert_eq!(
887 offset_of!(VMMemoryDefinition, base),
888 usize::from(offsets.vmmemory_definition_base())
889 );
890 assert_eq!(
891 offset_of!(VMMemoryDefinition, current_length),
892 usize::from(offsets.vmmemory_definition_current_length())
893 );
894 }
895}