wasmer_vm/
libcalls.rs

1// This file contains code from external sources.
2// Attributions: https://github.com/wasmerio/wasmer/blob/main/docs/ATTRIBUTIONS.md
3
4//! Runtime library calls.
5//!
6//! Note that Wasm compilers may sometimes perform these inline rather than
7//! calling them, particularly when CPUs have special instructions which compute
8//! them directly.
9//!
10//! These functions are called by compiled Wasm code, and therefore must take
11//! certain care about some things:
12//!
13//! * They must always be `pub extern "C"` and should only contain basic, raw
14//!   i32/i64/f32/f64/pointer parameters that are safe to pass across the system
15//!   ABI!
16//!
17//! * If any nested function propagates an `Err(trap)` out to the library
18//!   function frame, we need to raise it. This involves some nasty and quite
19//!   unsafe code under the covers! Notable, after raising the trap, drops
20//!   **will not** be run for local variables! This can lead to things like
21//!   leaking `VMInstance`s which leads to never deallocating JIT code,
22//!   instances, and modules! Therefore, always use nested blocks to ensure
23//!   drops run before raising a trap:
24//!
25//!   ```ignore
26//!   pub extern "C" fn my_lib_function(...) {
27//!       let result = {
28//!           // Do everything in here so drops run at the end of the block.
29//!           ...
30//!       };
31//!       if let Err(trap) = result {
32//!           // Now we can safely raise the trap without leaking!
33//!           raise_lib_trap(trap);
34//!       }
35//!   }
36//!   ```
37
38#![allow(missing_docs)] // For some reason lint fails saying that `LibCall` is not documented, when it actually is
39
40use 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/// Implementation of f32.ceil
58#[no_mangle]
59pub extern "C" fn wasmer_vm_f32_ceil(x: f32) -> f32 {
60    x.ceil()
61}
62
63/// Implementation of f32.floor
64#[no_mangle]
65pub extern "C" fn wasmer_vm_f32_floor(x: f32) -> f32 {
66    x.floor()
67}
68
69/// Implementation of f32.trunc
70#[no_mangle]
71pub extern "C" fn wasmer_vm_f32_trunc(x: f32) -> f32 {
72    x.trunc()
73}
74
75/// Implementation of f32.nearest
76#[allow(clippy::float_arithmetic, clippy::float_cmp)]
77#[no_mangle]
78pub extern "C" fn wasmer_vm_f32_nearest(x: f32) -> f32 {
79    // Rust doesn't have a nearest function, so do it manually.
80    if x == 0.0 {
81        // Preserve the sign of zero.
82        x
83    } else {
84        // Nearest is either ceil or floor depending on which is nearest or even.
85        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/// Implementation of f64.ceil
103#[no_mangle]
104pub extern "C" fn wasmer_vm_f64_ceil(x: f64) -> f64 {
105    x.ceil()
106}
107
108/// Implementation of f64.floor
109#[no_mangle]
110pub extern "C" fn wasmer_vm_f64_floor(x: f64) -> f64 {
111    x.floor()
112}
113
114/// Implementation of f64.trunc
115#[no_mangle]
116pub extern "C" fn wasmer_vm_f64_trunc(x: f64) -> f64 {
117    x.trunc()
118}
119
120/// Implementation of f64.nearest
121#[allow(clippy::float_arithmetic, clippy::float_cmp)]
122#[no_mangle]
123pub extern "C" fn wasmer_vm_f64_nearest(x: f64) -> f64 {
124    // Rust doesn't have a nearest function, so do it manually.
125    if x == 0.0 {
126        // Preserve the sign of zero.
127        x
128    } else {
129        // Nearest is either ceil or floor depending on which is nearest or even.
130        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/// Implementation of memory.grow for locally-defined 32-bit memories.
148///
149/// # Safety
150///
151/// `vmctx` must be dereferenceable.
152#[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/// Implementation of memory.grow for imported 32-bit memories.
170///
171/// # Safety
172///
173/// `vmctx` must be dereferenceable.
174#[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/// Implementation of memory.size for locally-defined 32-bit memories.
192///
193/// # Safety
194///
195/// `vmctx` must be dereferenceable.
196#[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/// Implementation of memory.size for imported 32-bit memories.
205///
206/// # Safety
207///
208/// `vmctx` must be dereferenceable.
209#[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/// Implementation of `table.copy`.
221///
222/// # Safety
223///
224/// `vmctx` must be dereferenceable.
225#[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/// Implementation of `table.init`.
252///
253/// # Safety
254///
255/// `vmctx` must be dereferenceable.
256#[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/// Implementation of `table.fill`.
277///
278/// # Safety
279///
280/// `vmctx` must be dereferenceable.
281#[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/// Implementation of `table.size`.
306///
307/// # Safety
308///
309/// `vmctx` must be dereferenceable.
310#[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/// Implementation of `table.size` for imported tables.
319///
320/// # Safety
321///
322/// `vmctx` must be dereferenceable.
323#[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/// Implementation of `table.get`.
335///
336/// # Safety
337///
338/// `vmctx` must be dereferenceable.
339#[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    // TODO: type checking, maybe have specialized accessors
349    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/// Implementation of `table.get` for imported tables.
356///
357/// # Safety
358///
359/// `vmctx` must be dereferenceable.
360#[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    // TODO: type checking, maybe have specialized accessors
370    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/// Implementation of `table.set`.
377///
378/// # Safety
379///
380/// `vmctx` must be dereferenceable.
381///
382/// It is the caller's responsibility to increment the ref count of any ref counted
383/// type before passing it to this function.
384#[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    // TODO: type checking, maybe have specialized accessors
405    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/// Implementation of `table.set` for imported tables.
413///
414/// # Safety
415///
416/// `vmctx` must be dereferenceable.
417#[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/// Implementation of `table.grow` for locally-defined tables.
440///
441/// # Safety
442///
443/// `vmctx` must be dereferenceable.
444#[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/// Implementation of `table.grow` for imported tables.
468///
469/// # Safety
470///
471/// `vmctx` must be dereferenceable.
472#[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/// Implementation of `func.ref`.
495///
496/// # Safety
497///
498/// `vmctx` must be dereferenceable.
499#[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/// Implementation of `elem.drop`.
511///
512/// # Safety
513///
514/// `vmctx` must be dereferenceable.
515#[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/// Implementation of `memory.copy` for locally defined memories.
525///
526/// # Safety
527///
528/// `vmctx` must be dereferenceable.
529#[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/// Implementation of `memory.copy` for imported memories.
548///
549/// # Safety
550///
551/// `vmctx` must be dereferenceable.
552#[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/// Implementation of `memory.fill` for locally defined memories.
571///
572/// # Safety
573///
574/// `vmctx` must be dereferenceable.
575#[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/// Implementation of `memory.fill` for imported memories.
594///
595/// # Safety
596///
597/// `vmctx` must be dereferenceable.
598#[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/// Implementation of `memory.init`.
617///
618/// # Safety
619///
620/// `vmctx` must be dereferenceable.
621#[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/// Implementation of `data.drop`.
642///
643/// # Safety
644///
645/// `vmctx` must be dereferenceable.
646#[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/// Implementation for raising a trap
656///
657/// # Safety
658///
659/// Only safe to call when wasm code is on the stack, aka `wasmer_call` or
660/// `wasmer_call_trampoline` must have been previously called.
661#[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/// Implementation for throwing an exception.
668///
669/// # Safety
670///
671/// Calls libunwind to perform unwinding magic.
672#[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/// Implementation for throwing an exception.
678///
679/// # Safety
680///
681/// Calls libunwind to perform unwinding magic.
682#[no_mangle]
683pub unsafe extern "C-unwind" fn wasmer_vm_rethrow(exc: *mut UwExceptionWrapper) -> ! {
684    eh::rethrow(exc)
685}
686
687/// (debug) Print an usize.
688#[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/// Implementation for allocating an exception.
697#[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/// Implementation for deleting the data of an exception.
703///
704/// # Safety
705///
706/// `exception` must be dereferenceable.
707#[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/// Implementation for reading a [`WasmerException`] from a [`UwExceptionWrapper`].
717/// # Safety
718///
719/// `exception` must be dereferenceable.
720#[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/// Probestack check
736///
737/// # Safety
738///
739/// This function does not follow the standard function ABI, and is called as
740/// part of the function prologue.
741#[no_mangle]
742pub static wasmer_vm_probestack: unsafe extern "C" fn() = PROBESTACK;
743
744/// Implementation of memory.wait32 for locally-defined 32-bit memories.
745///
746/// # Safety
747///
748/// `vmctx` must be dereferenceable.
749#[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/// Implementation of memory.wait32 for imported 32-bit memories.
770///
771/// # Safety
772///
773/// `vmctx` must be dereferenceable.
774#[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/// Implementation of memory.wait64 for locally-defined 32-bit memories.
795///
796/// # Safety
797///
798/// `vmctx` must be dereferenceable.
799#[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/// Implementation of memory.wait64 for imported 32-bit memories.
820///
821/// # Safety
822///
823/// `vmctx` must be dereferenceable.
824#[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/// Implementation of memory.notfy for locally-defined 32-bit memories.
845///
846/// # Safety
847///
848/// `vmctx` must be dereferenceable.
849#[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/// Implementation of memory.notfy for imported 32-bit memories.
869///
870/// # Safety
871///
872/// `vmctx` must be dereferenceable.
873#[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
892/// The function pointer to a libcall
893pub 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}