substrate_wasmtime_runtime/
vmcontext.rs1use crate::instance::Instance;
5use std::any::Any;
6use std::sync::atomic::{AtomicUsize, Ordering::SeqCst};
7use std::{ptr, u32};
8use wasmtime_environ::BuiltinFunctionIndex;
9
10#[derive(Debug, Copy, Clone)]
12#[repr(C)]
13pub struct VMFunctionImport {
14 pub body: *const VMFunctionBody,
16
17 pub vmctx: *mut VMContext,
19}
20
21#[cfg(test)]
22mod test_vmfunction_import {
23 use super::VMFunctionImport;
24 use memoffset::offset_of;
25 use std::mem::size_of;
26 use wasmtime_environ::{Module, VMOffsets};
27
28 #[test]
29 fn check_vmfunction_import_offsets() {
30 let module = Module::new();
31 let offsets = VMOffsets::new(size_of::<*mut u8>() as u8, &module.local);
32 assert_eq!(
33 size_of::<VMFunctionImport>(),
34 usize::from(offsets.size_of_vmfunction_import())
35 );
36 assert_eq!(
37 offset_of!(VMFunctionImport, body),
38 usize::from(offsets.vmfunction_import_body())
39 );
40 assert_eq!(
41 offset_of!(VMFunctionImport, vmctx),
42 usize::from(offsets.vmfunction_import_vmctx())
43 );
44 }
45}
46
47#[repr(C)]
52pub struct VMFunctionBody(u8);
53
54#[cfg(test)]
55mod test_vmfunction_body {
56 use super::VMFunctionBody;
57 use std::mem::size_of;
58
59 #[test]
60 fn check_vmfunction_body_offsets() {
61 assert_eq!(size_of::<VMFunctionBody>(), 1);
62 }
63}
64
65#[derive(Debug, Copy, Clone)]
68#[repr(C)]
69pub struct VMTableImport {
70 pub from: *mut VMTableDefinition,
72
73 pub vmctx: *mut VMContext,
75}
76
77#[cfg(test)]
78mod test_vmtable_import {
79 use super::VMTableImport;
80 use memoffset::offset_of;
81 use std::mem::size_of;
82 use wasmtime_environ::{Module, VMOffsets};
83
84 #[test]
85 fn check_vmtable_import_offsets() {
86 let module = Module::new();
87 let offsets = VMOffsets::new(size_of::<*mut u8>() as u8, &module.local);
88 assert_eq!(
89 size_of::<VMTableImport>(),
90 usize::from(offsets.size_of_vmtable_import())
91 );
92 assert_eq!(
93 offset_of!(VMTableImport, from),
94 usize::from(offsets.vmtable_import_from())
95 );
96 assert_eq!(
97 offset_of!(VMTableImport, vmctx),
98 usize::from(offsets.vmtable_import_vmctx())
99 );
100 }
101}
102
103#[derive(Debug, Copy, Clone)]
106#[repr(C)]
107pub struct VMMemoryImport {
108 pub from: *mut VMMemoryDefinition,
110
111 pub vmctx: *mut VMContext,
113}
114
115#[cfg(test)]
116mod test_vmmemory_import {
117 use super::VMMemoryImport;
118 use memoffset::offset_of;
119 use std::mem::size_of;
120 use wasmtime_environ::{Module, VMOffsets};
121
122 #[test]
123 fn check_vmmemory_import_offsets() {
124 let module = Module::new();
125 let offsets = VMOffsets::new(size_of::<*mut u8>() as u8, &module.local);
126 assert_eq!(
127 size_of::<VMMemoryImport>(),
128 usize::from(offsets.size_of_vmmemory_import())
129 );
130 assert_eq!(
131 offset_of!(VMMemoryImport, from),
132 usize::from(offsets.vmmemory_import_from())
133 );
134 assert_eq!(
135 offset_of!(VMMemoryImport, vmctx),
136 usize::from(offsets.vmmemory_import_vmctx())
137 );
138 }
139}
140
141#[derive(Debug, Copy, Clone)]
144#[repr(C)]
145pub struct VMGlobalImport {
146 pub from: *mut VMGlobalDefinition,
148}
149
150#[cfg(test)]
151mod test_vmglobal_import {
152 use super::VMGlobalImport;
153 use memoffset::offset_of;
154 use std::mem::size_of;
155 use wasmtime_environ::{Module, VMOffsets};
156
157 #[test]
158 fn check_vmglobal_import_offsets() {
159 let module = Module::new();
160 let offsets = VMOffsets::new(size_of::<*mut u8>() as u8, &module.local);
161 assert_eq!(
162 size_of::<VMGlobalImport>(),
163 usize::from(offsets.size_of_vmglobal_import())
164 );
165 assert_eq!(
166 offset_of!(VMGlobalImport, from),
167 usize::from(offsets.vmglobal_import_from())
168 );
169 }
170}
171
172#[derive(Debug, Copy, Clone)]
176#[repr(C)]
177pub struct VMMemoryDefinition {
178 pub base: *mut u8,
180
181 pub current_length: usize,
183}
184
185#[cfg(test)]
186mod test_vmmemory_definition {
187 use super::VMMemoryDefinition;
188 use memoffset::offset_of;
189 use std::mem::size_of;
190 use wasmtime_environ::{Module, VMOffsets};
191
192 #[test]
193 fn check_vmmemory_definition_offsets() {
194 let module = Module::new();
195 let offsets = VMOffsets::new(size_of::<*mut u8>() as u8, &module.local);
196 assert_eq!(
197 size_of::<VMMemoryDefinition>(),
198 usize::from(offsets.size_of_vmmemory_definition())
199 );
200 assert_eq!(
201 offset_of!(VMMemoryDefinition, base),
202 usize::from(offsets.vmmemory_definition_base())
203 );
204 assert_eq!(
205 offset_of!(VMMemoryDefinition, current_length),
206 usize::from(offsets.vmmemory_definition_current_length())
207 );
208 }
215}
216
217#[derive(Debug, Copy, Clone)]
220#[repr(C)]
221pub struct VMTableDefinition {
222 pub base: *mut u8,
224
225 pub current_elements: u32,
227}
228
229#[cfg(test)]
230mod test_vmtable_definition {
231 use super::VMTableDefinition;
232 use memoffset::offset_of;
233 use std::mem::size_of;
234 use wasmtime_environ::{Module, VMOffsets};
235
236 #[test]
237 fn check_vmtable_definition_offsets() {
238 let module = Module::new();
239 let offsets = VMOffsets::new(size_of::<*mut u8>() as u8, &module.local);
240 assert_eq!(
241 size_of::<VMTableDefinition>(),
242 usize::from(offsets.size_of_vmtable_definition())
243 );
244 assert_eq!(
245 offset_of!(VMTableDefinition, base),
246 usize::from(offsets.vmtable_definition_base())
247 );
248 assert_eq!(
249 offset_of!(VMTableDefinition, current_elements),
250 usize::from(offsets.vmtable_definition_current_elements())
251 );
252 }
253}
254
255#[derive(Debug, Copy, Clone)]
260#[repr(C, align(16))]
261pub struct VMGlobalDefinition {
262 storage: [u8; 16],
263 }
265
266#[cfg(test)]
267mod test_vmglobal_definition {
268 use super::VMGlobalDefinition;
269 use more_asserts::assert_ge;
270 use std::mem::{align_of, size_of};
271 use wasmtime_environ::{Module, VMOffsets};
272
273 #[test]
274 fn check_vmglobal_definition_alignment() {
275 assert_ge!(align_of::<VMGlobalDefinition>(), align_of::<i32>());
276 assert_ge!(align_of::<VMGlobalDefinition>(), align_of::<i64>());
277 assert_ge!(align_of::<VMGlobalDefinition>(), align_of::<f32>());
278 assert_ge!(align_of::<VMGlobalDefinition>(), align_of::<f64>());
279 assert_ge!(align_of::<VMGlobalDefinition>(), align_of::<[u8; 16]>());
280 }
281
282 #[test]
283 fn check_vmglobal_definition_offsets() {
284 let module = Module::new();
285 let offsets = VMOffsets::new(size_of::<*mut u8>() as u8, &module.local);
286 assert_eq!(
287 size_of::<VMGlobalDefinition>(),
288 usize::from(offsets.size_of_vmglobal_definition())
289 );
290 }
291
292 #[test]
293 fn check_vmglobal_begins_aligned() {
294 let module = Module::new();
295 let offsets = VMOffsets::new(size_of::<*mut u8>() as u8, &module.local);
296 assert_eq!(offsets.vmctx_globals_begin() % 16, 0);
297 }
298}
299
300impl VMGlobalDefinition {
301 pub fn new() -> Self {
303 Self { storage: [0; 16] }
304 }
305
306 #[allow(clippy::cast_ptr_alignment)]
308 pub unsafe fn as_i32(&self) -> &i32 {
309 &*(self.storage.as_ref().as_ptr() as *const i32)
310 }
311
312 #[allow(clippy::cast_ptr_alignment)]
314 pub unsafe fn as_i32_mut(&mut self) -> &mut i32 {
315 &mut *(self.storage.as_mut().as_mut_ptr() as *mut i32)
316 }
317
318 #[allow(clippy::cast_ptr_alignment)]
320 pub unsafe fn as_u32(&self) -> &u32 {
321 &*(self.storage.as_ref().as_ptr() as *const u32)
322 }
323
324 #[allow(clippy::cast_ptr_alignment)]
326 pub unsafe fn as_u32_mut(&mut self) -> &mut u32 {
327 &mut *(self.storage.as_mut().as_mut_ptr() as *mut u32)
328 }
329
330 #[allow(clippy::cast_ptr_alignment)]
332 pub unsafe fn as_i64(&self) -> &i64 {
333 &*(self.storage.as_ref().as_ptr() as *const i64)
334 }
335
336 #[allow(clippy::cast_ptr_alignment)]
338 pub unsafe fn as_i64_mut(&mut self) -> &mut i64 {
339 &mut *(self.storage.as_mut().as_mut_ptr() as *mut i64)
340 }
341
342 #[allow(clippy::cast_ptr_alignment)]
344 pub unsafe fn as_u64(&self) -> &u64 {
345 &*(self.storage.as_ref().as_ptr() as *const u64)
346 }
347
348 #[allow(clippy::cast_ptr_alignment)]
350 pub unsafe fn as_u64_mut(&mut self) -> &mut u64 {
351 &mut *(self.storage.as_mut().as_mut_ptr() as *mut u64)
352 }
353
354 #[allow(clippy::cast_ptr_alignment)]
356 pub unsafe fn as_f32(&self) -> &f32 {
357 &*(self.storage.as_ref().as_ptr() as *const f32)
358 }
359
360 #[allow(clippy::cast_ptr_alignment)]
362 pub unsafe fn as_f32_mut(&mut self) -> &mut f32 {
363 &mut *(self.storage.as_mut().as_mut_ptr() as *mut f32)
364 }
365
366 #[allow(clippy::cast_ptr_alignment)]
368 pub unsafe fn as_f32_bits(&self) -> &u32 {
369 &*(self.storage.as_ref().as_ptr() as *const u32)
370 }
371
372 #[allow(clippy::cast_ptr_alignment)]
374 pub unsafe fn as_f32_bits_mut(&mut self) -> &mut u32 {
375 &mut *(self.storage.as_mut().as_mut_ptr() as *mut u32)
376 }
377
378 #[allow(clippy::cast_ptr_alignment)]
380 pub unsafe fn as_f64(&self) -> &f64 {
381 &*(self.storage.as_ref().as_ptr() as *const f64)
382 }
383
384 #[allow(clippy::cast_ptr_alignment)]
386 pub unsafe fn as_f64_mut(&mut self) -> &mut f64 {
387 &mut *(self.storage.as_mut().as_mut_ptr() as *mut f64)
388 }
389
390 #[allow(clippy::cast_ptr_alignment)]
392 pub unsafe fn as_f64_bits(&self) -> &u64 {
393 &*(self.storage.as_ref().as_ptr() as *const u64)
394 }
395
396 #[allow(clippy::cast_ptr_alignment)]
398 pub unsafe fn as_f64_bits_mut(&mut self) -> &mut u64 {
399 &mut *(self.storage.as_mut().as_mut_ptr() as *mut u64)
400 }
401
402 #[allow(clippy::cast_ptr_alignment)]
404 pub unsafe fn as_u128(&self) -> &u128 {
405 &*(self.storage.as_ref().as_ptr() as *const u128)
406 }
407
408 #[allow(clippy::cast_ptr_alignment)]
410 pub unsafe fn as_u128_mut(&mut self) -> &mut u128 {
411 &mut *(self.storage.as_mut().as_mut_ptr() as *mut u128)
412 }
413
414 #[allow(clippy::cast_ptr_alignment)]
416 pub unsafe fn as_u128_bits(&self) -> &[u8; 16] {
417 &*(self.storage.as_ref().as_ptr() as *const [u8; 16])
418 }
419
420 #[allow(clippy::cast_ptr_alignment)]
422 pub unsafe fn as_u128_bits_mut(&mut self) -> &mut [u8; 16] {
423 &mut *(self.storage.as_mut().as_mut_ptr() as *mut [u8; 16])
424 }
425}
426
427#[repr(C)]
430#[derive(Debug, Eq, PartialEq, Clone, Copy, Hash)]
431pub struct VMSharedSignatureIndex(u32);
432
433#[cfg(test)]
434mod test_vmshared_signature_index {
435 use super::VMSharedSignatureIndex;
436 use std::mem::size_of;
437 use wasmtime_environ::{Module, TargetSharedSignatureIndex, VMOffsets};
438
439 #[test]
440 fn check_vmshared_signature_index() {
441 let module = Module::new();
442 let offsets = VMOffsets::new(size_of::<*mut u8>() as u8, &module.local);
443 assert_eq!(
444 size_of::<VMSharedSignatureIndex>(),
445 usize::from(offsets.size_of_vmshared_signature_index())
446 );
447 }
448
449 #[test]
450 fn check_target_shared_signature_index() {
451 assert_eq!(
452 size_of::<VMSharedSignatureIndex>(),
453 size_of::<TargetSharedSignatureIndex>()
454 );
455 }
456}
457
458impl VMSharedSignatureIndex {
459 pub fn new(value: u32) -> Self {
461 Self(value)
462 }
463}
464
465impl Default for VMSharedSignatureIndex {
466 fn default() -> Self {
467 Self::new(u32::MAX)
468 }
469}
470
471#[derive(Debug, Clone)]
475#[repr(C)]
476pub struct VMCallerCheckedAnyfunc {
477 pub func_ptr: *const VMFunctionBody,
479 pub type_index: VMSharedSignatureIndex,
481 pub vmctx: *mut VMContext,
483 }
485
486#[cfg(test)]
487mod test_vmcaller_checked_anyfunc {
488 use super::VMCallerCheckedAnyfunc;
489 use memoffset::offset_of;
490 use std::mem::size_of;
491 use wasmtime_environ::{Module, VMOffsets};
492
493 #[test]
494 fn check_vmcaller_checked_anyfunc_offsets() {
495 let module = Module::new();
496 let offsets = VMOffsets::new(size_of::<*mut u8>() as u8, &module.local);
497 assert_eq!(
498 size_of::<VMCallerCheckedAnyfunc>(),
499 usize::from(offsets.size_of_vmcaller_checked_anyfunc())
500 );
501 assert_eq!(
502 offset_of!(VMCallerCheckedAnyfunc, func_ptr),
503 usize::from(offsets.vmcaller_checked_anyfunc_func_ptr())
504 );
505 assert_eq!(
506 offset_of!(VMCallerCheckedAnyfunc, type_index),
507 usize::from(offsets.vmcaller_checked_anyfunc_type_index())
508 );
509 assert_eq!(
510 offset_of!(VMCallerCheckedAnyfunc, vmctx),
511 usize::from(offsets.vmcaller_checked_anyfunc_vmctx())
512 );
513 }
514}
515
516impl Default for VMCallerCheckedAnyfunc {
517 fn default() -> Self {
518 Self {
519 func_ptr: ptr::null_mut(),
520 type_index: Default::default(),
521 vmctx: ptr::null_mut(),
522 }
523 }
524}
525
526#[repr(C)]
529pub struct VMBuiltinFunctionsArray {
530 ptrs: [usize; Self::len()],
531}
532
533impl VMBuiltinFunctionsArray {
534 pub const fn len() -> usize {
535 BuiltinFunctionIndex::builtin_functions_total_number() as usize
536 }
537
538 pub fn initialized() -> Self {
539 use crate::libcalls::*;
540
541 let mut ptrs = [0; Self::len()];
542
543 ptrs[BuiltinFunctionIndex::get_memory32_grow_index().index() as usize] =
544 wasmtime_memory32_grow as usize;
545 ptrs[BuiltinFunctionIndex::get_imported_memory32_grow_index().index() as usize] =
546 wasmtime_imported_memory32_grow as usize;
547
548 ptrs[BuiltinFunctionIndex::get_memory32_size_index().index() as usize] =
549 wasmtime_memory32_size as usize;
550 ptrs[BuiltinFunctionIndex::get_imported_memory32_size_index().index() as usize] =
551 wasmtime_imported_memory32_size as usize;
552
553 ptrs[BuiltinFunctionIndex::get_table_copy_index().index() as usize] =
554 wasmtime_table_copy as usize;
555
556 ptrs[BuiltinFunctionIndex::get_table_init_index().index() as usize] =
557 wasmtime_table_init as usize;
558 ptrs[BuiltinFunctionIndex::get_elem_drop_index().index() as usize] =
559 wasmtime_elem_drop as usize;
560
561 ptrs[BuiltinFunctionIndex::get_defined_memory_copy_index().index() as usize] =
562 wasmtime_defined_memory_copy as usize;
563 ptrs[BuiltinFunctionIndex::get_imported_memory_copy_index().index() as usize] =
564 wasmtime_imported_memory_copy as usize;
565 ptrs[BuiltinFunctionIndex::get_memory_fill_index().index() as usize] =
566 wasmtime_memory_fill as usize;
567 ptrs[BuiltinFunctionIndex::get_imported_memory_fill_index().index() as usize] =
568 wasmtime_imported_memory_fill as usize;
569 ptrs[BuiltinFunctionIndex::get_memory_init_index().index() as usize] =
570 wasmtime_memory_init as usize;
571 ptrs[BuiltinFunctionIndex::get_data_drop_index().index() as usize] =
572 wasmtime_data_drop as usize;
573
574 debug_assert!(ptrs.iter().cloned().all(|p| p != 0));
575
576 Self { ptrs }
577 }
578}
579
580#[derive(Debug, Copy, Clone)]
584#[repr(C, align(16))]
585pub struct VMInvokeArgument([u8; 16]);
586
587#[cfg(test)]
588mod test_vm_invoke_argument {
589 use super::VMInvokeArgument;
590 use std::mem::{align_of, size_of};
591 use wasmtime_environ::{Module, VMOffsets};
592
593 #[test]
594 fn check_vm_invoke_argument_alignment() {
595 assert_eq!(align_of::<VMInvokeArgument>(), 16);
596 }
597
598 #[test]
599 fn check_vmglobal_definition_offsets() {
600 let module = Module::new();
601 let offsets = VMOffsets::new(size_of::<*mut u8>() as u8, &module.local);
602 assert_eq!(
603 size_of::<VMInvokeArgument>(),
604 usize::from(offsets.size_of_vmglobal_definition())
605 );
606 }
607}
608
609impl VMInvokeArgument {
610 pub fn new() -> Self {
612 Self([0; 16])
613 }
614}
615
616#[derive(Debug)]
619#[repr(C)]
620pub struct VMInterrupts {
621 pub stack_limit: AtomicUsize,
626}
627
628impl VMInterrupts {
629 pub fn interrupt(&self) {
631 self.stack_limit
632 .store(wasmtime_environ::INTERRUPTED, SeqCst);
633 }
634}
635
636impl Default for VMInterrupts {
637 fn default() -> VMInterrupts {
638 VMInterrupts {
639 stack_limit: AtomicUsize::new(usize::max_value()),
640 }
641 }
642}
643
644#[cfg(test)]
645mod test_vminterrupts {
646 use super::VMInterrupts;
647 use memoffset::offset_of;
648 use std::mem::size_of;
649 use wasmtime_environ::{Module, VMOffsets};
650
651 #[test]
652 fn check_vminterrupts_interrupted_offset() {
653 let module = Module::new();
654 let offsets = VMOffsets::new(size_of::<*mut u8>() as u8, &module.local);
655 assert_eq!(
656 offset_of!(VMInterrupts, stack_limit),
657 usize::from(offsets.vminterrupts_stack_limit())
658 );
659 }
660}
661
662#[derive(Debug)]
672#[repr(C, align(16))] pub struct VMContext {}
674
675impl VMContext {
676 #[allow(clippy::cast_ptr_alignment)]
682 #[inline]
683 pub(crate) unsafe fn instance(&self) -> &Instance {
684 &*((self as *const Self as *mut u8).offset(-Instance::vmctx_offset()) as *const Instance)
685 }
686
687 #[inline]
693 pub unsafe fn host_state(&self) -> &dyn Any {
694 self.instance().host_state()
695 }
696}
697
698pub type VMTrampoline = unsafe extern "C" fn(
700 *mut VMContext, *mut VMContext, *const VMFunctionBody, *mut u128, );