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 crate::probestack::PROBESTACK;
41use crate::table::{RawTableElement, TableElement};
42use crate::trap::{raise_lib_trap, Trap, TrapCode};
43use crate::vmcontext::VMContext;
44use crate::{on_host_stack, VMFuncRef};
45pub use wasmer_types::LibCall;
46use wasmer_types::{
47    DataIndex, ElemIndex, FunctionIndex, LocalMemoryIndex, LocalTableIndex, MemoryIndex,
48    TableIndex, Type,
49};
50
51/// Implementation of f32.ceil
52#[no_mangle]
53pub extern "C" fn wasmer_vm_f32_ceil(x: f32) -> f32 {
54    x.ceil()
55}
56
57/// Implementation of f32.floor
58#[no_mangle]
59pub extern "C" fn wasmer_vm_f32_floor(x: f32) -> f32 {
60    x.floor()
61}
62
63/// Implementation of f32.trunc
64#[no_mangle]
65pub extern "C" fn wasmer_vm_f32_trunc(x: f32) -> f32 {
66    x.trunc()
67}
68
69/// Implementation of f32.nearest
70#[allow(clippy::float_arithmetic, clippy::float_cmp)]
71#[no_mangle]
72pub extern "C" fn wasmer_vm_f32_nearest(x: f32) -> f32 {
73    // Rust doesn't have a nearest function, so do it manually.
74    if x == 0.0 {
75        // Preserve the sign of zero.
76        x
77    } else {
78        // Nearest is either ceil or floor depending on which is nearest or even.
79        let u = x.ceil();
80        let d = x.floor();
81        let um = (x - u).abs();
82        let dm = (x - d).abs();
83        if um < dm
84            || (um == dm && {
85                let h = u / 2.;
86                h.floor() == h
87            })
88        {
89            u
90        } else {
91            d
92        }
93    }
94}
95
96/// Implementation of f64.ceil
97#[no_mangle]
98pub extern "C" fn wasmer_vm_f64_ceil(x: f64) -> f64 {
99    x.ceil()
100}
101
102/// Implementation of f64.floor
103#[no_mangle]
104pub extern "C" fn wasmer_vm_f64_floor(x: f64) -> f64 {
105    x.floor()
106}
107
108/// Implementation of f64.trunc
109#[no_mangle]
110pub extern "C" fn wasmer_vm_f64_trunc(x: f64) -> f64 {
111    x.trunc()
112}
113
114/// Implementation of f64.nearest
115#[allow(clippy::float_arithmetic, clippy::float_cmp)]
116#[no_mangle]
117pub extern "C" fn wasmer_vm_f64_nearest(x: f64) -> f64 {
118    // Rust doesn't have a nearest function, so do it manually.
119    if x == 0.0 {
120        // Preserve the sign of zero.
121        x
122    } else {
123        // Nearest is either ceil or floor depending on which is nearest or even.
124        let u = x.ceil();
125        let d = x.floor();
126        let um = (x - u).abs();
127        let dm = (x - d).abs();
128        if um < dm
129            || (um == dm && {
130                let h = u / 2.;
131                h.floor() == h
132            })
133        {
134            u
135        } else {
136            d
137        }
138    }
139}
140
141/// Implementation of memory.grow for locally-defined 32-bit memories.
142///
143/// # Safety
144///
145/// `vmctx` must be dereferenceable.
146#[no_mangle]
147pub unsafe extern "C" fn wasmer_vm_memory32_grow(
148    vmctx: *mut VMContext,
149    delta: u32,
150    memory_index: u32,
151) -> u32 {
152    on_host_stack(|| {
153        let instance = (*vmctx).instance_mut();
154        let memory_index = LocalMemoryIndex::from_u32(memory_index);
155
156        instance
157            .memory_grow(memory_index, delta)
158            .map(|pages| pages.0)
159            .unwrap_or(u32::MAX)
160    })
161}
162
163/// Implementation of memory.grow for imported 32-bit memories.
164///
165/// # Safety
166///
167/// `vmctx` must be dereferenceable.
168#[no_mangle]
169pub unsafe extern "C" fn wasmer_vm_imported_memory32_grow(
170    vmctx: *mut VMContext,
171    delta: u32,
172    memory_index: u32,
173) -> u32 {
174    on_host_stack(|| {
175        let instance = (*vmctx).instance_mut();
176        let memory_index = MemoryIndex::from_u32(memory_index);
177
178        instance
179            .imported_memory_grow(memory_index, delta)
180            .map(|pages| pages.0)
181            .unwrap_or(u32::MAX)
182    })
183}
184
185/// Implementation of memory.size for locally-defined 32-bit memories.
186///
187/// # Safety
188///
189/// `vmctx` must be dereferenceable.
190#[no_mangle]
191pub unsafe extern "C" fn wasmer_vm_memory32_size(vmctx: *mut VMContext, memory_index: u32) -> u32 {
192    let instance = (*vmctx).instance();
193    let memory_index = LocalMemoryIndex::from_u32(memory_index);
194
195    instance.memory_size(memory_index).0
196}
197
198/// Implementation of memory.size for imported 32-bit memories.
199///
200/// # Safety
201///
202/// `vmctx` must be dereferenceable.
203#[no_mangle]
204pub unsafe extern "C" fn wasmer_vm_imported_memory32_size(
205    vmctx: *mut VMContext,
206    memory_index: u32,
207) -> u32 {
208    let instance = (*vmctx).instance();
209    let memory_index = MemoryIndex::from_u32(memory_index);
210
211    instance.imported_memory_size(memory_index).0
212}
213
214/// Implementation of `table.copy`.
215///
216/// # Safety
217///
218/// `vmctx` must be dereferenceable.
219#[no_mangle]
220pub unsafe extern "C" fn wasmer_vm_table_copy(
221    vmctx: *mut VMContext,
222    dst_table_index: u32,
223    src_table_index: u32,
224    dst: u32,
225    src: u32,
226    len: u32,
227) {
228    let result = {
229        let dst_table_index = TableIndex::from_u32(dst_table_index);
230        let src_table_index = TableIndex::from_u32(src_table_index);
231        if dst_table_index == src_table_index {
232            let table = (*vmctx).instance_mut().get_table(dst_table_index);
233            table.copy_within(dst, src, len)
234        } else {
235            let dst_table = (*vmctx).instance_mut().get_table(dst_table_index);
236            let src_table = (*vmctx).instance_mut().get_table(src_table_index);
237            dst_table.copy(src_table, dst, src, len)
238        }
239    };
240    if let Err(trap) = result {
241        raise_lib_trap(trap);
242    }
243}
244
245/// Implementation of `table.init`.
246///
247/// # Safety
248///
249/// `vmctx` must be dereferenceable.
250#[no_mangle]
251pub unsafe extern "C" fn wasmer_vm_table_init(
252    vmctx: *mut VMContext,
253    table_index: u32,
254    elem_index: u32,
255    dst: u32,
256    src: u32,
257    len: u32,
258) {
259    let result = {
260        let table_index = TableIndex::from_u32(table_index);
261        let elem_index = ElemIndex::from_u32(elem_index);
262        let instance = (*vmctx).instance_mut();
263        instance.table_init(table_index, elem_index, dst, src, len)
264    };
265    if let Err(trap) = result {
266        raise_lib_trap(trap);
267    }
268}
269
270/// Implementation of `table.fill`.
271///
272/// # Safety
273///
274/// `vmctx` must be dereferenceable.
275#[no_mangle]
276pub unsafe extern "C" fn wasmer_vm_table_fill(
277    vmctx: *mut VMContext,
278    table_index: u32,
279    start_idx: u32,
280    item: RawTableElement,
281    len: u32,
282) {
283    let result = {
284        let table_index = TableIndex::from_u32(table_index);
285        let instance = (*vmctx).instance_mut();
286        let elem = match instance.get_table(table_index).ty().ty {
287            Type::ExternRef => TableElement::ExternRef(item.extern_ref),
288            Type::FuncRef => TableElement::FuncRef(item.func_ref),
289            _ => panic!("Unrecognized table type: does not contain references"),
290        };
291
292        instance.table_fill(table_index, start_idx, elem, len)
293    };
294    if let Err(trap) = result {
295        raise_lib_trap(trap);
296    }
297}
298
299/// Implementation of `table.size`.
300///
301/// # Safety
302///
303/// `vmctx` must be dereferenceable.
304#[no_mangle]
305pub unsafe extern "C" fn wasmer_vm_table_size(vmctx: *mut VMContext, table_index: u32) -> u32 {
306    let instance = (*vmctx).instance();
307    let table_index = LocalTableIndex::from_u32(table_index);
308
309    instance.table_size(table_index)
310}
311
312/// Implementation of `table.size` for imported tables.
313///
314/// # Safety
315///
316/// `vmctx` must be dereferenceable.
317#[no_mangle]
318pub unsafe extern "C" fn wasmer_vm_imported_table_size(
319    vmctx: *mut VMContext,
320    table_index: u32,
321) -> u32 {
322    let instance = (*vmctx).instance();
323    let table_index = TableIndex::from_u32(table_index);
324
325    instance.imported_table_size(table_index)
326}
327
328/// Implementation of `table.get`.
329///
330/// # Safety
331///
332/// `vmctx` must be dereferenceable.
333#[no_mangle]
334pub unsafe extern "C" fn wasmer_vm_table_get(
335    vmctx: *mut VMContext,
336    table_index: u32,
337    elem_index: u32,
338) -> RawTableElement {
339    let instance = (*vmctx).instance();
340    let table_index = LocalTableIndex::from_u32(table_index);
341
342    // TODO: type checking, maybe have specialized accessors
343    match instance.table_get(table_index, elem_index) {
344        Some(table_ref) => table_ref.into(),
345        None => raise_lib_trap(Trap::lib(TrapCode::TableAccessOutOfBounds)),
346    }
347}
348
349/// Implementation of `table.get` for imported tables.
350///
351/// # Safety
352///
353/// `vmctx` must be dereferenceable.
354#[no_mangle]
355pub unsafe extern "C" fn wasmer_vm_imported_table_get(
356    vmctx: *mut VMContext,
357    table_index: u32,
358    elem_index: u32,
359) -> RawTableElement {
360    let instance = (*vmctx).instance_mut();
361    let table_index = TableIndex::from_u32(table_index);
362
363    // TODO: type checking, maybe have specialized accessors
364    match instance.imported_table_get(table_index, elem_index) {
365        Some(table_ref) => table_ref.into(),
366        None => raise_lib_trap(Trap::lib(TrapCode::TableAccessOutOfBounds)),
367    }
368}
369
370/// Implementation of `table.set`.
371///
372/// # Safety
373///
374/// `vmctx` must be dereferenceable.
375///
376/// It is the caller's responsibility to increment the ref count of any ref counted
377/// type before passing it to this function.
378#[no_mangle]
379pub unsafe extern "C" fn wasmer_vm_table_set(
380    vmctx: *mut VMContext,
381    table_index: u32,
382    elem_index: u32,
383    value: RawTableElement,
384) {
385    let instance = (*vmctx).instance_mut();
386    let table_index = TableIndex::from_u32(table_index);
387    let table_index = instance
388        .module_ref()
389        .local_table_index(table_index)
390        .unwrap();
391
392    let elem = match instance.get_local_table(table_index).ty().ty {
393        Type::ExternRef => TableElement::ExternRef(value.extern_ref),
394        Type::FuncRef => TableElement::FuncRef(value.func_ref),
395        _ => panic!("Unrecognized table type: does not contain references"),
396    };
397
398    // TODO: type checking, maybe have specialized accessors
399    let result = instance.table_set(table_index, elem_index, elem);
400
401    if let Err(trap) = result {
402        raise_lib_trap(trap);
403    }
404}
405
406/// Implementation of `table.set` for imported tables.
407///
408/// # Safety
409///
410/// `vmctx` must be dereferenceable.
411#[no_mangle]
412pub unsafe extern "C" fn wasmer_vm_imported_table_set(
413    vmctx: *mut VMContext,
414    table_index: u32,
415    elem_index: u32,
416    value: RawTableElement,
417) {
418    let instance = (*vmctx).instance_mut();
419    let table_index = TableIndex::from_u32(table_index);
420    let elem = match instance.get_table(table_index).ty().ty {
421        Type::ExternRef => TableElement::ExternRef(value.extern_ref),
422        Type::FuncRef => TableElement::FuncRef(value.func_ref),
423        _ => panic!("Unrecognized table type: does not contain references"),
424    };
425
426    let result = instance.imported_table_set(table_index, elem_index, elem);
427
428    if let Err(trap) = result {
429        raise_lib_trap(trap);
430    }
431}
432
433/// Implementation of `table.grow` for locally-defined tables.
434///
435/// # Safety
436///
437/// `vmctx` must be dereferenceable.
438#[no_mangle]
439pub unsafe extern "C" fn wasmer_vm_table_grow(
440    vmctx: *mut VMContext,
441    init_value: RawTableElement,
442    delta: u32,
443    table_index: u32,
444) -> u32 {
445    on_host_stack(|| {
446        let instance = (*vmctx).instance_mut();
447        let table_index = LocalTableIndex::from_u32(table_index);
448
449        let init_value = match instance.get_local_table(table_index).ty().ty {
450            Type::ExternRef => TableElement::ExternRef(init_value.extern_ref),
451            Type::FuncRef => TableElement::FuncRef(init_value.func_ref),
452            _ => panic!("Unrecognized table type: does not contain references"),
453        };
454
455        instance
456            .table_grow(table_index, delta, init_value)
457            .unwrap_or(u32::MAX)
458    })
459}
460
461/// Implementation of `table.grow` for imported tables.
462///
463/// # Safety
464///
465/// `vmctx` must be dereferenceable.
466#[no_mangle]
467pub unsafe extern "C" fn wasmer_vm_imported_table_grow(
468    vmctx: *mut VMContext,
469    init_value: RawTableElement,
470    delta: u32,
471    table_index: u32,
472) -> u32 {
473    on_host_stack(|| {
474        let instance = (*vmctx).instance_mut();
475        let table_index = TableIndex::from_u32(table_index);
476        let init_value = match instance.get_table(table_index).ty().ty {
477            Type::ExternRef => TableElement::ExternRef(init_value.extern_ref),
478            Type::FuncRef => TableElement::FuncRef(init_value.func_ref),
479            _ => panic!("Unrecognized table type: does not contain references"),
480        };
481
482        instance
483            .imported_table_grow(table_index, delta, init_value)
484            .unwrap_or(u32::MAX)
485    })
486}
487
488/// Implementation of `func.ref`.
489///
490/// # Safety
491///
492/// `vmctx` must be dereferenceable.
493#[no_mangle]
494pub unsafe extern "C" fn wasmer_vm_func_ref(
495    vmctx: *mut VMContext,
496    function_index: u32,
497) -> VMFuncRef {
498    let instance = (*vmctx).instance();
499    let function_index = FunctionIndex::from_u32(function_index);
500
501    instance.func_ref(function_index).unwrap()
502}
503
504/// Implementation of `elem.drop`.
505///
506/// # Safety
507///
508/// `vmctx` must be dereferenceable.
509#[no_mangle]
510pub unsafe extern "C" fn wasmer_vm_elem_drop(vmctx: *mut VMContext, elem_index: u32) {
511    on_host_stack(|| {
512        let elem_index = ElemIndex::from_u32(elem_index);
513        let instance = (*vmctx).instance();
514        instance.elem_drop(elem_index);
515    })
516}
517
518/// Implementation of `memory.copy` for locally defined memories.
519///
520/// # Safety
521///
522/// `vmctx` must be dereferenceable.
523#[no_mangle]
524pub unsafe extern "C" fn wasmer_vm_memory32_copy(
525    vmctx: *mut VMContext,
526    memory_index: u32,
527    dst: u32,
528    src: u32,
529    len: u32,
530) {
531    let result = {
532        let memory_index = LocalMemoryIndex::from_u32(memory_index);
533        let instance = (*vmctx).instance();
534        instance.local_memory_copy(memory_index, dst, src, len)
535    };
536    if let Err(trap) = result {
537        raise_lib_trap(trap);
538    }
539}
540
541/// Implementation of `memory.copy` for imported memories.
542///
543/// # Safety
544///
545/// `vmctx` must be dereferenceable.
546#[no_mangle]
547pub unsafe extern "C" fn wasmer_vm_imported_memory32_copy(
548    vmctx: *mut VMContext,
549    memory_index: u32,
550    dst: u32,
551    src: u32,
552    len: u32,
553) {
554    let result = {
555        let memory_index = MemoryIndex::from_u32(memory_index);
556        let instance = (*vmctx).instance();
557        instance.imported_memory_copy(memory_index, dst, src, len)
558    };
559    if let Err(trap) = result {
560        raise_lib_trap(trap);
561    }
562}
563
564/// Implementation of `memory.fill` for locally defined memories.
565///
566/// # Safety
567///
568/// `vmctx` must be dereferenceable.
569#[no_mangle]
570pub unsafe extern "C" fn wasmer_vm_memory32_fill(
571    vmctx: *mut VMContext,
572    memory_index: u32,
573    dst: u32,
574    val: u32,
575    len: u32,
576) {
577    let result = {
578        let memory_index = LocalMemoryIndex::from_u32(memory_index);
579        let instance = (*vmctx).instance();
580        instance.local_memory_fill(memory_index, dst, val, len)
581    };
582    if let Err(trap) = result {
583        raise_lib_trap(trap);
584    }
585}
586
587/// Implementation of `memory.fill` for imported memories.
588///
589/// # Safety
590///
591/// `vmctx` must be dereferenceable.
592#[no_mangle]
593pub unsafe extern "C" fn wasmer_vm_imported_memory32_fill(
594    vmctx: *mut VMContext,
595    memory_index: u32,
596    dst: u32,
597    val: u32,
598    len: u32,
599) {
600    let result = {
601        let memory_index = MemoryIndex::from_u32(memory_index);
602        let instance = (*vmctx).instance();
603        instance.imported_memory_fill(memory_index, dst, val, len)
604    };
605    if let Err(trap) = result {
606        raise_lib_trap(trap);
607    }
608}
609
610/// Implementation of `memory.init`.
611///
612/// # Safety
613///
614/// `vmctx` must be dereferenceable.
615#[no_mangle]
616pub unsafe extern "C" fn wasmer_vm_memory32_init(
617    vmctx: *mut VMContext,
618    memory_index: u32,
619    data_index: u32,
620    dst: u32,
621    src: u32,
622    len: u32,
623) {
624    let result = {
625        let memory_index = MemoryIndex::from_u32(memory_index);
626        let data_index = DataIndex::from_u32(data_index);
627        let instance = (*vmctx).instance();
628        instance.memory_init(memory_index, data_index, dst, src, len)
629    };
630    if let Err(trap) = result {
631        raise_lib_trap(trap);
632    }
633}
634
635/// Implementation of `data.drop`.
636///
637/// # Safety
638///
639/// `vmctx` must be dereferenceable.
640#[no_mangle]
641pub unsafe extern "C" fn wasmer_vm_data_drop(vmctx: *mut VMContext, data_index: u32) {
642    on_host_stack(|| {
643        let data_index = DataIndex::from_u32(data_index);
644        let instance = (*vmctx).instance();
645        instance.data_drop(data_index)
646    })
647}
648
649/// Implementation for raising a trap
650///
651/// # Safety
652///
653/// Only safe to call when wasm code is on the stack, aka `wasmer_call` or
654/// `wasmer_call_trampoline` must have been previously called.
655#[no_mangle]
656pub unsafe extern "C" fn wasmer_vm_raise_trap(trap_code: TrapCode) -> ! {
657    let trap = Trap::lib(trap_code);
658    raise_lib_trap(trap)
659}
660
661/// Probestack check
662///
663/// # Safety
664///
665/// This function does not follow the standard function ABI, and is called as
666/// part of the function prologue.
667#[no_mangle]
668pub static wasmer_vm_probestack: unsafe extern "C" fn() = PROBESTACK;
669
670/// Implementation of memory.wait32 for locally-defined 32-bit memories.
671///
672/// # Safety
673///
674/// `vmctx` must be dereferenceable.
675#[no_mangle]
676pub unsafe extern "C" fn wasmer_vm_memory32_atomic_wait32(
677    vmctx: *mut VMContext,
678    memory_index: u32,
679    dst: u32,
680    val: u32,
681    timeout: i64,
682) -> u32 {
683    let result = {
684        let instance = (*vmctx).instance_mut();
685        let memory_index = LocalMemoryIndex::from_u32(memory_index);
686
687        instance.local_memory_wait32(memory_index, dst, val, timeout)
688    };
689    if let Err(trap) = result {
690        raise_lib_trap(trap);
691    }
692    result.unwrap()
693}
694
695/// Implementation of memory.wait32 for imported 32-bit memories.
696///
697/// # Safety
698///
699/// `vmctx` must be dereferenceable.
700#[no_mangle]
701pub unsafe extern "C" fn wasmer_vm_imported_memory32_atomic_wait32(
702    vmctx: *mut VMContext,
703    memory_index: u32,
704    dst: u32,
705    val: u32,
706    timeout: i64,
707) -> u32 {
708    let result = {
709        let instance = (*vmctx).instance_mut();
710        let memory_index = MemoryIndex::from_u32(memory_index);
711
712        instance.imported_memory_wait32(memory_index, dst, val, timeout)
713    };
714    if let Err(trap) = result {
715        raise_lib_trap(trap);
716    }
717    result.unwrap()
718}
719
720/// Implementation of memory.wait64 for locally-defined 32-bit memories.
721///
722/// # Safety
723///
724/// `vmctx` must be dereferenceable.
725#[no_mangle]
726pub unsafe extern "C" fn wasmer_vm_memory32_atomic_wait64(
727    vmctx: *mut VMContext,
728    memory_index: u32,
729    dst: u32,
730    val: u64,
731    timeout: i64,
732) -> u32 {
733    let result = {
734        let instance = (*vmctx).instance_mut();
735        let memory_index = LocalMemoryIndex::from_u32(memory_index);
736
737        instance.local_memory_wait64(memory_index, dst, val, timeout)
738    };
739    if let Err(trap) = result {
740        raise_lib_trap(trap);
741    }
742    result.unwrap()
743}
744
745/// Implementation of memory.wait64 for imported 32-bit memories.
746///
747/// # Safety
748///
749/// `vmctx` must be dereferenceable.
750#[no_mangle]
751pub unsafe extern "C" fn wasmer_vm_imported_memory32_atomic_wait64(
752    vmctx: *mut VMContext,
753    memory_index: u32,
754    dst: u32,
755    val: u64,
756    timeout: i64,
757) -> u32 {
758    let result = {
759        let instance = (*vmctx).instance_mut();
760        let memory_index = MemoryIndex::from_u32(memory_index);
761
762        instance.imported_memory_wait64(memory_index, dst, val, timeout)
763    };
764    if let Err(trap) = result {
765        raise_lib_trap(trap);
766    }
767    result.unwrap()
768}
769
770/// Implementation of memory.notfy for locally-defined 32-bit memories.
771///
772/// # Safety
773///
774/// `vmctx` must be dereferenceable.
775#[no_mangle]
776pub unsafe extern "C" fn wasmer_vm_memory32_atomic_notify(
777    vmctx: *mut VMContext,
778    memory_index: u32,
779    dst: u32,
780    cnt: u32,
781) -> u32 {
782    let result = {
783        let instance = (*vmctx).instance_mut();
784        let memory_index = LocalMemoryIndex::from_u32(memory_index);
785
786        instance.local_memory_notify(memory_index, dst, cnt)
787    };
788    if let Err(trap) = result {
789        raise_lib_trap(trap);
790    }
791    result.unwrap()
792}
793
794/// Implementation of memory.notfy for imported 32-bit memories.
795///
796/// # Safety
797///
798/// `vmctx` must be dereferenceable.
799#[no_mangle]
800pub unsafe extern "C" fn wasmer_vm_imported_memory32_atomic_notify(
801    vmctx: *mut VMContext,
802    memory_index: u32,
803    dst: u32,
804    cnt: u32,
805) -> u32 {
806    let result = {
807        let instance = (*vmctx).instance_mut();
808        let memory_index = MemoryIndex::from_u32(memory_index);
809
810        instance.imported_memory_notify(memory_index, dst, cnt)
811    };
812    if let Err(trap) = result {
813        raise_lib_trap(trap);
814    }
815    result.unwrap()
816}
817
818/// The function pointer to a libcall
819pub fn function_pointer(libcall: LibCall) -> usize {
820    match libcall {
821        LibCall::CeilF32 => wasmer_vm_f32_ceil as usize,
822        LibCall::CeilF64 => wasmer_vm_f64_ceil as usize,
823        LibCall::FloorF32 => wasmer_vm_f32_floor as usize,
824        LibCall::FloorF64 => wasmer_vm_f64_floor as usize,
825        LibCall::NearestF32 => wasmer_vm_f32_nearest as usize,
826        LibCall::NearestF64 => wasmer_vm_f64_nearest as usize,
827        LibCall::TruncF32 => wasmer_vm_f32_trunc as usize,
828        LibCall::TruncF64 => wasmer_vm_f64_trunc as usize,
829        LibCall::Memory32Size => wasmer_vm_memory32_size as usize,
830        LibCall::ImportedMemory32Size => wasmer_vm_imported_memory32_size as usize,
831        LibCall::TableCopy => wasmer_vm_table_copy as usize,
832        LibCall::TableInit => wasmer_vm_table_init as usize,
833        LibCall::TableFill => wasmer_vm_table_fill as usize,
834        LibCall::TableSize => wasmer_vm_table_size as usize,
835        LibCall::ImportedTableSize => wasmer_vm_imported_table_size as usize,
836        LibCall::TableGet => wasmer_vm_table_get as usize,
837        LibCall::ImportedTableGet => wasmer_vm_imported_table_get as usize,
838        LibCall::TableSet => wasmer_vm_table_set as usize,
839        LibCall::ImportedTableSet => wasmer_vm_imported_table_set as usize,
840        LibCall::TableGrow => wasmer_vm_table_grow as usize,
841        LibCall::ImportedTableGrow => wasmer_vm_imported_table_grow as usize,
842        LibCall::FuncRef => wasmer_vm_func_ref as usize,
843        LibCall::ElemDrop => wasmer_vm_elem_drop as usize,
844        LibCall::Memory32Copy => wasmer_vm_memory32_copy as usize,
845        LibCall::ImportedMemory32Copy => wasmer_vm_imported_memory32_copy as usize,
846        LibCall::Memory32Fill => wasmer_vm_memory32_fill as usize,
847        LibCall::ImportedMemory32Fill => wasmer_vm_imported_memory32_fill as usize,
848        LibCall::Memory32Init => wasmer_vm_memory32_init as usize,
849        LibCall::DataDrop => wasmer_vm_data_drop as usize,
850        LibCall::Probestack => wasmer_vm_probestack as usize,
851        LibCall::RaiseTrap => wasmer_vm_raise_trap as usize,
852        LibCall::Memory32AtomicWait32 => wasmer_vm_memory32_atomic_wait32 as usize,
853        LibCall::ImportedMemory32AtomicWait32 => wasmer_vm_imported_memory32_atomic_wait32 as usize,
854        LibCall::Memory32AtomicWait64 => wasmer_vm_memory32_atomic_wait64 as usize,
855        LibCall::ImportedMemory32AtomicWait64 => wasmer_vm_imported_memory32_atomic_wait64 as usize,
856        LibCall::Memory32AtomicNotify => wasmer_vm_memory32_atomic_notify as usize,
857        LibCall::ImportedMemory32AtomicNotify => wasmer_vm_imported_memory32_atomic_notify as usize,
858    }
859}