wasmer_vm/
libcalls.rs

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