1#![allow(missing_docs)] use std::panic;
41mod eh;
42pub use eh::wasmer_eh_personality;
43use eh::UwExceptionWrapper;
44pub(crate) use eh::WasmerException;
45
46use crate::probestack::PROBESTACK;
47use crate::table::{RawTableElement, TableElement};
48use crate::trap::{raise_lib_trap, Trap, TrapCode};
49use crate::vmcontext::VMContext;
50use crate::{on_host_stack, VMFuncRef};
51pub use wasmer_types::LibCall;
52use wasmer_types::{
53 DataIndex, ElemIndex, FunctionIndex, LocalMemoryIndex, LocalTableIndex, MemoryIndex,
54 TableIndex, Type,
55};
56
57#[no_mangle]
59pub extern "C" fn wasmer_vm_f32_ceil(x: f32) -> f32 {
60 x.ceil()
61}
62
63#[no_mangle]
65pub extern "C" fn wasmer_vm_f32_floor(x: f32) -> f32 {
66 x.floor()
67}
68
69#[no_mangle]
71pub extern "C" fn wasmer_vm_f32_trunc(x: f32) -> f32 {
72 x.trunc()
73}
74
75#[allow(clippy::float_arithmetic, clippy::float_cmp)]
77#[no_mangle]
78pub extern "C" fn wasmer_vm_f32_nearest(x: f32) -> f32 {
79 if x == 0.0 {
81 x
83 } else {
84 let u = x.ceil();
86 let d = x.floor();
87 let um = (x - u).abs();
88 let dm = (x - d).abs();
89 if um < dm
90 || (um == dm && {
91 let h = u / 2.;
92 h.floor() == h
93 })
94 {
95 u
96 } else {
97 d
98 }
99 }
100}
101
102#[no_mangle]
104pub extern "C" fn wasmer_vm_f64_ceil(x: f64) -> f64 {
105 x.ceil()
106}
107
108#[no_mangle]
110pub extern "C" fn wasmer_vm_f64_floor(x: f64) -> f64 {
111 x.floor()
112}
113
114#[no_mangle]
116pub extern "C" fn wasmer_vm_f64_trunc(x: f64) -> f64 {
117 x.trunc()
118}
119
120#[allow(clippy::float_arithmetic, clippy::float_cmp)]
122#[no_mangle]
123pub extern "C" fn wasmer_vm_f64_nearest(x: f64) -> f64 {
124 if x == 0.0 {
126 x
128 } else {
129 let u = x.ceil();
131 let d = x.floor();
132 let um = (x - u).abs();
133 let dm = (x - d).abs();
134 if um < dm
135 || (um == dm && {
136 let h = u / 2.;
137 h.floor() == h
138 })
139 {
140 u
141 } else {
142 d
143 }
144 }
145}
146
147#[no_mangle]
153pub unsafe extern "C" fn wasmer_vm_memory32_grow(
154 vmctx: *mut VMContext,
155 delta: u32,
156 memory_index: u32,
157) -> u32 {
158 on_host_stack(|| {
159 let instance = (*vmctx).instance_mut();
160 let memory_index = LocalMemoryIndex::from_u32(memory_index);
161
162 instance
163 .memory_grow(memory_index, delta)
164 .map(|pages| pages.0)
165 .unwrap_or(u32::MAX)
166 })
167}
168
169#[no_mangle]
175pub unsafe extern "C" fn wasmer_vm_imported_memory32_grow(
176 vmctx: *mut VMContext,
177 delta: u32,
178 memory_index: u32,
179) -> u32 {
180 on_host_stack(|| {
181 let instance = (*vmctx).instance_mut();
182 let memory_index = MemoryIndex::from_u32(memory_index);
183
184 instance
185 .imported_memory_grow(memory_index, delta)
186 .map(|pages| pages.0)
187 .unwrap_or(u32::MAX)
188 })
189}
190
191#[no_mangle]
197pub unsafe extern "C" fn wasmer_vm_memory32_size(vmctx: *mut VMContext, memory_index: u32) -> u32 {
198 let instance = (*vmctx).instance();
199 let memory_index = LocalMemoryIndex::from_u32(memory_index);
200
201 instance.memory_size(memory_index).0
202}
203
204#[no_mangle]
210pub unsafe extern "C" fn wasmer_vm_imported_memory32_size(
211 vmctx: *mut VMContext,
212 memory_index: u32,
213) -> u32 {
214 let instance = (*vmctx).instance();
215 let memory_index = MemoryIndex::from_u32(memory_index);
216
217 instance.imported_memory_size(memory_index).0
218}
219
220#[no_mangle]
226pub unsafe extern "C" fn wasmer_vm_table_copy(
227 vmctx: *mut VMContext,
228 dst_table_index: u32,
229 src_table_index: u32,
230 dst: u32,
231 src: u32,
232 len: u32,
233) {
234 let result = {
235 let dst_table_index = TableIndex::from_u32(dst_table_index);
236 let src_table_index = TableIndex::from_u32(src_table_index);
237 if dst_table_index == src_table_index {
238 let table = (*vmctx).instance_mut().get_table(dst_table_index);
239 table.copy_within(dst, src, len)
240 } else {
241 let dst_table = (*vmctx).instance_mut().get_table(dst_table_index);
242 let src_table = (*vmctx).instance_mut().get_table(src_table_index);
243 dst_table.copy(src_table, dst, src, len)
244 }
245 };
246 if let Err(trap) = result {
247 raise_lib_trap(trap);
248 }
249}
250
251#[no_mangle]
257pub unsafe extern "C" fn wasmer_vm_table_init(
258 vmctx: *mut VMContext,
259 table_index: u32,
260 elem_index: u32,
261 dst: u32,
262 src: u32,
263 len: u32,
264) {
265 let result = {
266 let table_index = TableIndex::from_u32(table_index);
267 let elem_index = ElemIndex::from_u32(elem_index);
268 let instance = (*vmctx).instance_mut();
269 instance.table_init(table_index, elem_index, dst, src, len)
270 };
271 if let Err(trap) = result {
272 raise_lib_trap(trap);
273 }
274}
275
276#[no_mangle]
282pub unsafe extern "C" fn wasmer_vm_table_fill(
283 vmctx: *mut VMContext,
284 table_index: u32,
285 start_idx: u32,
286 item: RawTableElement,
287 len: u32,
288) {
289 let result = {
290 let table_index = TableIndex::from_u32(table_index);
291 let instance = (*vmctx).instance_mut();
292 let elem = match instance.get_table(table_index).ty().ty {
293 Type::ExternRef => TableElement::ExternRef(item.extern_ref),
294 Type::FuncRef => TableElement::FuncRef(item.func_ref),
295 _ => panic!("Unrecognized table type: does not contain references"),
296 };
297
298 instance.table_fill(table_index, start_idx, elem, len)
299 };
300 if let Err(trap) = result {
301 raise_lib_trap(trap);
302 }
303}
304
305#[no_mangle]
311pub unsafe extern "C" fn wasmer_vm_table_size(vmctx: *mut VMContext, table_index: u32) -> u32 {
312 let instance = (*vmctx).instance();
313 let table_index = LocalTableIndex::from_u32(table_index);
314
315 instance.table_size(table_index)
316}
317
318#[no_mangle]
324pub unsafe extern "C" fn wasmer_vm_imported_table_size(
325 vmctx: *mut VMContext,
326 table_index: u32,
327) -> u32 {
328 let instance = (*vmctx).instance();
329 let table_index = TableIndex::from_u32(table_index);
330
331 instance.imported_table_size(table_index)
332}
333
334#[no_mangle]
340pub unsafe extern "C" fn wasmer_vm_table_get(
341 vmctx: *mut VMContext,
342 table_index: u32,
343 elem_index: u32,
344) -> RawTableElement {
345 let instance = (*vmctx).instance();
346 let table_index = LocalTableIndex::from_u32(table_index);
347
348 match instance.table_get(table_index, elem_index) {
350 Some(table_ref) => table_ref.into(),
351 None => raise_lib_trap(Trap::lib(TrapCode::TableAccessOutOfBounds)),
352 }
353}
354
355#[no_mangle]
361pub unsafe extern "C" fn wasmer_vm_imported_table_get(
362 vmctx: *mut VMContext,
363 table_index: u32,
364 elem_index: u32,
365) -> RawTableElement {
366 let instance = (*vmctx).instance_mut();
367 let table_index = TableIndex::from_u32(table_index);
368
369 match instance.imported_table_get(table_index, elem_index) {
371 Some(table_ref) => table_ref.into(),
372 None => raise_lib_trap(Trap::lib(TrapCode::TableAccessOutOfBounds)),
373 }
374}
375
376#[no_mangle]
385pub unsafe extern "C" fn wasmer_vm_table_set(
386 vmctx: *mut VMContext,
387 table_index: u32,
388 elem_index: u32,
389 value: RawTableElement,
390) {
391 let instance = (*vmctx).instance_mut();
392 let table_index = TableIndex::from_u32(table_index);
393 let table_index = instance
394 .module_ref()
395 .local_table_index(table_index)
396 .unwrap();
397
398 let elem = match instance.get_local_table(table_index).ty().ty {
399 Type::ExternRef => TableElement::ExternRef(value.extern_ref),
400 Type::FuncRef => TableElement::FuncRef(value.func_ref),
401 _ => panic!("Unrecognized table type: does not contain references"),
402 };
403
404 let result = instance.table_set(table_index, elem_index, elem);
406
407 if let Err(trap) = result {
408 raise_lib_trap(trap);
409 }
410}
411
412#[no_mangle]
418pub unsafe extern "C" fn wasmer_vm_imported_table_set(
419 vmctx: *mut VMContext,
420 table_index: u32,
421 elem_index: u32,
422 value: RawTableElement,
423) {
424 let instance = (*vmctx).instance_mut();
425 let table_index = TableIndex::from_u32(table_index);
426 let elem = match instance.get_table(table_index).ty().ty {
427 Type::ExternRef => TableElement::ExternRef(value.extern_ref),
428 Type::FuncRef => TableElement::FuncRef(value.func_ref),
429 _ => panic!("Unrecognized table type: does not contain references"),
430 };
431
432 let result = instance.imported_table_set(table_index, elem_index, elem);
433
434 if let Err(trap) = result {
435 raise_lib_trap(trap);
436 }
437}
438
439#[no_mangle]
445pub unsafe extern "C" fn wasmer_vm_table_grow(
446 vmctx: *mut VMContext,
447 init_value: RawTableElement,
448 delta: u32,
449 table_index: u32,
450) -> u32 {
451 on_host_stack(|| {
452 let instance = (*vmctx).instance_mut();
453 let table_index = LocalTableIndex::from_u32(table_index);
454
455 let init_value = match instance.get_local_table(table_index).ty().ty {
456 Type::ExternRef => TableElement::ExternRef(init_value.extern_ref),
457 Type::FuncRef => TableElement::FuncRef(init_value.func_ref),
458 _ => panic!("Unrecognized table type: does not contain references"),
459 };
460
461 instance
462 .table_grow(table_index, delta, init_value)
463 .unwrap_or(u32::MAX)
464 })
465}
466
467#[no_mangle]
473pub unsafe extern "C" fn wasmer_vm_imported_table_grow(
474 vmctx: *mut VMContext,
475 init_value: RawTableElement,
476 delta: u32,
477 table_index: u32,
478) -> u32 {
479 on_host_stack(|| {
480 let instance = (*vmctx).instance_mut();
481 let table_index = TableIndex::from_u32(table_index);
482 let init_value = match instance.get_table(table_index).ty().ty {
483 Type::ExternRef => TableElement::ExternRef(init_value.extern_ref),
484 Type::FuncRef => TableElement::FuncRef(init_value.func_ref),
485 _ => panic!("Unrecognized table type: does not contain references"),
486 };
487
488 instance
489 .imported_table_grow(table_index, delta, init_value)
490 .unwrap_or(u32::MAX)
491 })
492}
493
494#[no_mangle]
500pub unsafe extern "C" fn wasmer_vm_func_ref(
501 vmctx: *mut VMContext,
502 function_index: u32,
503) -> VMFuncRef {
504 let instance = (*vmctx).instance();
505 let function_index = FunctionIndex::from_u32(function_index);
506
507 instance.func_ref(function_index).unwrap()
508}
509
510#[no_mangle]
516pub unsafe extern "C" fn wasmer_vm_elem_drop(vmctx: *mut VMContext, elem_index: u32) {
517 on_host_stack(|| {
518 let elem_index = ElemIndex::from_u32(elem_index);
519 let instance = (*vmctx).instance();
520 instance.elem_drop(elem_index);
521 })
522}
523
524#[no_mangle]
530pub unsafe extern "C" fn wasmer_vm_memory32_copy(
531 vmctx: *mut VMContext,
532 memory_index: u32,
533 dst: u32,
534 src: u32,
535 len: u32,
536) {
537 let result = {
538 let memory_index = LocalMemoryIndex::from_u32(memory_index);
539 let instance = (*vmctx).instance();
540 instance.local_memory_copy(memory_index, dst, src, len)
541 };
542 if let Err(trap) = result {
543 raise_lib_trap(trap);
544 }
545}
546
547#[no_mangle]
553pub unsafe extern "C" fn wasmer_vm_imported_memory32_copy(
554 vmctx: *mut VMContext,
555 memory_index: u32,
556 dst: u32,
557 src: u32,
558 len: u32,
559) {
560 let result = {
561 let memory_index = MemoryIndex::from_u32(memory_index);
562 let instance = (*vmctx).instance();
563 instance.imported_memory_copy(memory_index, dst, src, len)
564 };
565 if let Err(trap) = result {
566 raise_lib_trap(trap);
567 }
568}
569
570#[no_mangle]
576pub unsafe extern "C" fn wasmer_vm_memory32_fill(
577 vmctx: *mut VMContext,
578 memory_index: u32,
579 dst: u32,
580 val: u32,
581 len: u32,
582) {
583 let result = {
584 let memory_index = LocalMemoryIndex::from_u32(memory_index);
585 let instance = (*vmctx).instance();
586 instance.local_memory_fill(memory_index, dst, val, len)
587 };
588 if let Err(trap) = result {
589 raise_lib_trap(trap);
590 }
591}
592
593#[no_mangle]
599pub unsafe extern "C" fn wasmer_vm_imported_memory32_fill(
600 vmctx: *mut VMContext,
601 memory_index: u32,
602 dst: u32,
603 val: u32,
604 len: u32,
605) {
606 let result = {
607 let memory_index = MemoryIndex::from_u32(memory_index);
608 let instance = (*vmctx).instance();
609 instance.imported_memory_fill(memory_index, dst, val, len)
610 };
611 if let Err(trap) = result {
612 raise_lib_trap(trap);
613 }
614}
615
616#[no_mangle]
622pub unsafe extern "C" fn wasmer_vm_memory32_init(
623 vmctx: *mut VMContext,
624 memory_index: u32,
625 data_index: u32,
626 dst: u32,
627 src: u32,
628 len: u32,
629) {
630 let result = {
631 let memory_index = MemoryIndex::from_u32(memory_index);
632 let data_index = DataIndex::from_u32(data_index);
633 let instance = (*vmctx).instance();
634 instance.memory_init(memory_index, data_index, dst, src, len)
635 };
636 if let Err(trap) = result {
637 raise_lib_trap(trap);
638 }
639}
640
641#[no_mangle]
647pub unsafe extern "C" fn wasmer_vm_data_drop(vmctx: *mut VMContext, data_index: u32) {
648 on_host_stack(|| {
649 let data_index = DataIndex::from_u32(data_index);
650 let instance = (*vmctx).instance();
651 instance.data_drop(data_index)
652 })
653}
654
655#[no_mangle]
662pub unsafe extern "C" fn wasmer_vm_raise_trap(trap_code: TrapCode) -> ! {
663 let trap = Trap::lib(trap_code);
664 raise_lib_trap(trap)
665}
666
667#[no_mangle]
673pub unsafe extern "C-unwind" fn wasmer_vm_throw(tag: u64, data_ptr: usize, data_size: u64) -> ! {
674 eh::throw(tag, data_ptr, data_size)
675}
676
677#[no_mangle]
683pub unsafe extern "C-unwind" fn wasmer_vm_rethrow(exc: *mut UwExceptionWrapper) -> ! {
684 eh::rethrow(exc)
685}
686
687#[no_mangle]
689pub extern "C-unwind" fn wasmer_vm_dbg_usize(value: usize) {
690 #[allow(clippy::print_stdout)]
691 {
692 println!("wasmer_vm_dbg_usize: {value}");
693 }
694}
695
696#[no_mangle]
698pub extern "C-unwind" fn wasmer_vm_alloc_exception(size: usize) -> u64 {
699 Vec::<u8>::with_capacity(size).leak().as_ptr() as usize as u64
700}
701
702#[no_mangle]
708pub unsafe extern "C-unwind" fn wasmer_vm_delete_exception(exception: *mut WasmerException) {
709 if !exception.is_null() {
710 let size = (*exception).data_size as usize;
711 let data = Vec::<u8>::from_raw_parts((*exception).data_ptr as *mut u8, size, size);
712 std::mem::drop(data);
713 }
714}
715
716#[no_mangle]
721pub unsafe extern "C-unwind" fn wasmer_vm_read_exception(
722 exception: *const UwExceptionWrapper,
723) -> *const WasmerException {
724 if !exception.is_null() {
725 if let Some(w) = (*exception).cause.downcast_ref() {
726 w as *const WasmerException
727 } else {
728 panic!()
729 }
730 } else {
731 std::ptr::null()
732 }
733}
734
735#[no_mangle]
742pub static wasmer_vm_probestack: unsafe extern "C" fn() = PROBESTACK;
743
744#[no_mangle]
750pub unsafe extern "C" fn wasmer_vm_memory32_atomic_wait32(
751 vmctx: *mut VMContext,
752 memory_index: u32,
753 dst: u32,
754 val: u32,
755 timeout: i64,
756) -> u32 {
757 let result = {
758 let instance = (*vmctx).instance_mut();
759 let memory_index = LocalMemoryIndex::from_u32(memory_index);
760
761 instance.local_memory_wait32(memory_index, dst, val, timeout)
762 };
763 if let Err(trap) = result {
764 raise_lib_trap(trap);
765 }
766 result.unwrap()
767}
768
769#[no_mangle]
775pub unsafe extern "C" fn wasmer_vm_imported_memory32_atomic_wait32(
776 vmctx: *mut VMContext,
777 memory_index: u32,
778 dst: u32,
779 val: u32,
780 timeout: i64,
781) -> u32 {
782 let result = {
783 let instance = (*vmctx).instance_mut();
784 let memory_index = MemoryIndex::from_u32(memory_index);
785
786 instance.imported_memory_wait32(memory_index, dst, val, timeout)
787 };
788 if let Err(trap) = result {
789 raise_lib_trap(trap);
790 }
791 result.unwrap()
792}
793
794#[no_mangle]
800pub unsafe extern "C" fn wasmer_vm_memory32_atomic_wait64(
801 vmctx: *mut VMContext,
802 memory_index: u32,
803 dst: u32,
804 val: u64,
805 timeout: i64,
806) -> u32 {
807 let result = {
808 let instance = (*vmctx).instance_mut();
809 let memory_index = LocalMemoryIndex::from_u32(memory_index);
810
811 instance.local_memory_wait64(memory_index, dst, val, timeout)
812 };
813 if let Err(trap) = result {
814 raise_lib_trap(trap);
815 }
816 result.unwrap()
817}
818
819#[no_mangle]
825pub unsafe extern "C" fn wasmer_vm_imported_memory32_atomic_wait64(
826 vmctx: *mut VMContext,
827 memory_index: u32,
828 dst: u32,
829 val: u64,
830 timeout: i64,
831) -> u32 {
832 let result = {
833 let instance = (*vmctx).instance_mut();
834 let memory_index = MemoryIndex::from_u32(memory_index);
835
836 instance.imported_memory_wait64(memory_index, dst, val, timeout)
837 };
838 if let Err(trap) = result {
839 raise_lib_trap(trap);
840 }
841 result.unwrap()
842}
843
844#[no_mangle]
850pub unsafe extern "C" fn wasmer_vm_memory32_atomic_notify(
851 vmctx: *mut VMContext,
852 memory_index: u32,
853 dst: u32,
854 cnt: u32,
855) -> u32 {
856 let result = {
857 let instance = (*vmctx).instance_mut();
858 let memory_index = LocalMemoryIndex::from_u32(memory_index);
859
860 instance.local_memory_notify(memory_index, dst, cnt)
861 };
862 if let Err(trap) = result {
863 raise_lib_trap(trap);
864 }
865 result.unwrap()
866}
867
868#[no_mangle]
874pub unsafe extern "C" fn wasmer_vm_imported_memory32_atomic_notify(
875 vmctx: *mut VMContext,
876 memory_index: u32,
877 dst: u32,
878 cnt: u32,
879) -> u32 {
880 let result = {
881 let instance = (*vmctx).instance_mut();
882 let memory_index = MemoryIndex::from_u32(memory_index);
883
884 instance.imported_memory_notify(memory_index, dst, cnt)
885 };
886 if let Err(trap) = result {
887 raise_lib_trap(trap);
888 }
889 result.unwrap()
890}
891
892pub fn function_pointer(libcall: LibCall) -> usize {
894 match libcall {
895 LibCall::CeilF32 => wasmer_vm_f32_ceil as usize,
896 LibCall::CeilF64 => wasmer_vm_f64_ceil as usize,
897 LibCall::FloorF32 => wasmer_vm_f32_floor as usize,
898 LibCall::FloorF64 => wasmer_vm_f64_floor as usize,
899 LibCall::NearestF32 => wasmer_vm_f32_nearest as usize,
900 LibCall::NearestF64 => wasmer_vm_f64_nearest as usize,
901 LibCall::TruncF32 => wasmer_vm_f32_trunc as usize,
902 LibCall::TruncF64 => wasmer_vm_f64_trunc as usize,
903 LibCall::Memory32Size => wasmer_vm_memory32_size as usize,
904 LibCall::ImportedMemory32Size => wasmer_vm_imported_memory32_size as usize,
905 LibCall::TableCopy => wasmer_vm_table_copy as usize,
906 LibCall::TableInit => wasmer_vm_table_init as usize,
907 LibCall::TableFill => wasmer_vm_table_fill as usize,
908 LibCall::TableSize => wasmer_vm_table_size as usize,
909 LibCall::ImportedTableSize => wasmer_vm_imported_table_size as usize,
910 LibCall::TableGet => wasmer_vm_table_get as usize,
911 LibCall::ImportedTableGet => wasmer_vm_imported_table_get as usize,
912 LibCall::TableSet => wasmer_vm_table_set as usize,
913 LibCall::ImportedTableSet => wasmer_vm_imported_table_set as usize,
914 LibCall::TableGrow => wasmer_vm_table_grow as usize,
915 LibCall::ImportedTableGrow => wasmer_vm_imported_table_grow as usize,
916 LibCall::FuncRef => wasmer_vm_func_ref as usize,
917 LibCall::ElemDrop => wasmer_vm_elem_drop as usize,
918 LibCall::Memory32Copy => wasmer_vm_memory32_copy as usize,
919 LibCall::ImportedMemory32Copy => wasmer_vm_imported_memory32_copy as usize,
920 LibCall::Memory32Fill => wasmer_vm_memory32_fill as usize,
921 LibCall::ImportedMemory32Fill => wasmer_vm_imported_memory32_fill as usize,
922 LibCall::Memory32Init => wasmer_vm_memory32_init as usize,
923 LibCall::DataDrop => wasmer_vm_data_drop as usize,
924 LibCall::Probestack => wasmer_vm_probestack as usize,
925 LibCall::RaiseTrap => wasmer_vm_raise_trap as usize,
926 LibCall::Memory32AtomicWait32 => wasmer_vm_memory32_atomic_wait32 as usize,
927 LibCall::ImportedMemory32AtomicWait32 => wasmer_vm_imported_memory32_atomic_wait32 as usize,
928 LibCall::Memory32AtomicWait64 => wasmer_vm_memory32_atomic_wait64 as usize,
929 LibCall::ImportedMemory32AtomicWait64 => wasmer_vm_imported_memory32_atomic_wait64 as usize,
930 LibCall::Memory32AtomicNotify => wasmer_vm_memory32_atomic_notify as usize,
931 LibCall::ImportedMemory32AtomicNotify => wasmer_vm_imported_memory32_atomic_notify as usize,
932 LibCall::Throw => wasmer_vm_throw as usize,
933 LibCall::Rethrow => wasmer_vm_rethrow as usize,
934 LibCall::EHPersonality => wasmer_eh_personality as usize,
935 LibCall::AllocException => wasmer_vm_alloc_exception as usize,
936 LibCall::DeleteException => wasmer_vm_delete_exception as usize,
937 LibCall::ReadException => wasmer_vm_read_exception as usize,
938 LibCall::DebugUsize => wasmer_vm_dbg_usize as usize,
939 }
940}