wasmer_types/
libcalls.rs

1use enum_iterator::Sequence;
2use rkyv::{Archive, Deserialize as RkyvDeserialize, Serialize as RkyvSerialize};
3#[cfg(feature = "enable-serde")]
4use serde::{Deserialize, Serialize};
5use std::fmt;
6
7/// The name of a runtime library routine.
8///
9/// This list is likely to grow over time.
10#[derive(
11    Copy, Clone, Debug, PartialEq, Eq, Hash, Sequence, RkyvSerialize, RkyvDeserialize, Archive,
12)]
13#[cfg_attr(feature = "enable-serde", derive(Serialize, Deserialize))]
14#[cfg_attr(feature = "artifact-size", derive(loupe::MemoryUsage))]
15#[rkyv(derive(Debug, Hash, PartialEq, Eq), compare(PartialEq))]
16#[repr(u16)]
17pub enum LibCall {
18    /// ceil.f32
19    CeilF32,
20
21    /// ceil.f64
22    CeilF64,
23
24    /// floor.f32
25    FloorF32,
26
27    /// floor.f64
28    FloorF64,
29
30    /// nearest.f32
31    NearestF32,
32
33    /// nearest.f64
34    NearestF64,
35
36    /// sqrt.f32
37    SqrtF32,
38
39    /// sqrt.f64
40    SqrtF64,
41
42    /// trunc.f32
43    TruncF32,
44
45    /// trunc.f64
46    TruncF64,
47
48    /// memory.size for local functions
49    Memory32Size,
50
51    /// memory.size for imported functions
52    ImportedMemory32Size,
53
54    /// table.copy
55    TableCopy,
56
57    /// table.init
58    TableInit,
59
60    /// table.fill
61    TableFill,
62
63    /// table.size for local tables
64    TableSize,
65
66    /// table.size for imported tables
67    ImportedTableSize,
68
69    /// table.get for local tables
70    TableGet,
71
72    /// table.get for imported tables
73    ImportedTableGet,
74
75    /// table.set for local tables
76    TableSet,
77
78    /// table.set for imported tables
79    ImportedTableSet,
80
81    /// table.grow for local tables
82    TableGrow,
83
84    /// table.grow for imported tables
85    ImportedTableGrow,
86
87    /// ref.func
88    FuncRef,
89
90    /// elem.drop
91    ElemDrop,
92
93    /// memory.copy for local memories
94    Memory32Copy,
95
96    /// memory.copy for imported memories
97    ImportedMemory32Copy,
98
99    /// memory.fill for local memories
100    Memory32Fill,
101
102    /// memory.fill for imported memories
103    ImportedMemory32Fill,
104
105    /// memory.init
106    Memory32Init,
107
108    /// data.drop
109    DataDrop,
110
111    /// A custom trap
112    RaiseTrap,
113
114    /// probe for stack overflow. These are emitted for functions which need
115    /// when the `enable_probestack` setting is true.
116    Probestack,
117
118    /// memory.atomic.wait32 for local memories
119    Memory32AtomicWait32,
120
121    /// memory.atomic.wait32 for imported memories
122    ImportedMemory32AtomicWait32,
123
124    /// memory.atomic.wait64 for local memories
125    Memory32AtomicWait64,
126
127    /// memory.atomic.wait64 for imported memories
128    ImportedMemory32AtomicWait64,
129
130    /// memory.atomic.notify for local memories
131    Memory32AtomicNotify,
132
133    /// memory.atomic.notify for imported memories
134    ImportedMemory32AtomicNotify,
135
136    /// throw
137    Throw,
138
139    /// allocate exception object and get an exnref for it
140    AllocException,
141    /// Get the values buffer pointer out of an exnref
142    ReadExnRef,
143    /// Given a caught native exception pointer, get the exnref and delete the exception itself
144    LibunwindExceptionIntoExnRef,
145
146    /// The personality function
147    EHPersonality,
148    /// The second stage of the EH personality function
149    EHPersonality2,
150
151    /// debug_usize
152    DebugUsize,
153    /// debug_str
154    DebugStr,
155
156    // Soft-float routines emitted by LLVM when targeting platforms without hardware floating-point.
157    // Standard toolchains (compiler-rt / libgcc) provide these, but wasmer needs to know their
158    // addresses to link JIT-compiled objects.
159    // Ordered to match the GCC runtime library documentation (§3.2).
160    // https://gcc.gnu.org/onlinedocs/gccint/Soft-float-library-routines.html
161
162    // §3.2.1 Arithmetic
163    /// __addsf3
164    Addsf3,
165    /// __adddf3
166    Adddf3,
167    /// __subsf3
168    Subsf3,
169    /// __subdf3
170    Subdf3,
171    /// __mulsf3
172    Mulsf3,
173    /// __muldf3
174    Muldf3,
175    /// __divsf3
176    Divsf3,
177    /// __divdf3
178    Divdf3,
179    /// __negsf2
180    Negsf2,
181    /// __negdf2
182    Negdf2,
183
184    // §3.2.2 Conversion
185    /// __extendsfdf2
186    Extendsfdf2,
187    /// __truncdfsf2
188    Truncdfsf2,
189    /// __fixsfsi
190    Fixsfsi,
191    /// __fixdfsi
192    Fixdfsi,
193    /// __fixsfdi
194    Fixsfdi,
195    /// __fixdfdi
196    Fixdfdi,
197    /// __fixunssfsi
198    Fixunssfsi,
199    /// __fixunsdfsi
200    Fixunsdfsi,
201    /// __fixunssfdi
202    Fixunssfdi,
203    /// __fixunsdfdi
204    Fixunsdfdi,
205    /// __floatsisf
206    Floatsisf,
207    /// __floatsidf
208    Floatsidf,
209    /// __floatdisf
210    Floatdisf,
211    /// __floatdidf
212    Floatdidf,
213    /// __floatunsisf
214    Floatunsisf,
215    /// __floatunsidf
216    Floatunsidf,
217    /// __floatundisf
218    Floatundisf,
219    /// __floatundidf
220    Floatundidf,
221
222    // §3.2.3 Comparison
223    /// __unordsf2
224    Unordsf2,
225    /// __unorddf2
226    Unorddf2,
227    /// __eqsf2
228    Eqsf2,
229    /// __eqdf2
230    Eqdf2,
231    /// __nesf2
232    Nesf2,
233    /// __nedf2
234    Nedf2,
235    /// __gesf2
236    Gesf2,
237    /// __gedf2
238    Gedf2,
239    /// __ltsf2
240    Ltsf2,
241    /// __ltdf2
242    Ltdf2,
243    /// __lesf2
244    Lesf2,
245    /// __ledf2
246    Ledf2,
247    /// __gtsf2
248    Gtsf2,
249    /// __gtdf2
250    Gtdf2,
251}
252
253impl LibCall {
254    /// Return the function name associated to the libcall.
255    pub fn to_function_name(&self) -> &str {
256        match self {
257            Self::CeilF32 => "wasmer_vm_f32_ceil",
258            Self::CeilF64 => "wasmer_vm_f64_ceil",
259            Self::FloorF32 => "wasmer_vm_f32_floor",
260            Self::FloorF64 => "wasmer_vm_f64_floor",
261            Self::NearestF32 => "wasmer_vm_f32_nearest",
262            Self::NearestF64 => "wasmer_vm_f64_nearest",
263            Self::SqrtF32 => "wasmer_vm_f32_sqrt",
264            Self::SqrtF64 => "wasmer_vm_f64_sqrt",
265            Self::TruncF32 => "wasmer_vm_f32_trunc",
266            Self::TruncF64 => "wasmer_vm_f64_trunc",
267            Self::Memory32Size => "wasmer_vm_memory32_size",
268            Self::ImportedMemory32Size => "wasmer_vm_imported_memory32_size",
269            Self::TableCopy => "wasmer_vm_table_copy",
270            Self::TableInit => "wasmer_vm_table_init",
271            Self::TableFill => "wasmer_vm_table_fill",
272            Self::TableSize => "wasmer_vm_table_size",
273            Self::ImportedTableSize => "wasmer_vm_imported_table_size",
274            Self::TableGet => "wasmer_vm_table_get",
275            Self::ImportedTableGet => "wasmer_vm_imported_table_get",
276            Self::TableSet => "wasmer_vm_table_set",
277            Self::ImportedTableSet => "wasmer_vm_imported_table_set",
278            Self::TableGrow => "wasmer_vm_table_grow",
279            Self::ImportedTableGrow => "wasmer_vm_imported_table_grow",
280            Self::FuncRef => "wasmer_vm_func_ref",
281            Self::ElemDrop => "wasmer_vm_elem_drop",
282            Self::Memory32Copy => "wasmer_vm_memory32_copy",
283            Self::ImportedMemory32Copy => "wasmer_vm_imported_memory32_copy",
284            Self::Memory32Fill => "wasmer_vm_memory32_fill",
285            Self::ImportedMemory32Fill => "wasmer_vm_imported_memory32_fill",
286            Self::Memory32Init => "wasmer_vm_memory32_init",
287            Self::DataDrop => "wasmer_vm_data_drop",
288            Self::RaiseTrap => "wasmer_vm_raise_trap",
289            // We have to do this because macOS requires a leading `_` and it's not
290            // a normal function, it's a static variable, so we have to do it manually.
291            #[cfg(target_vendor = "apple")]
292            Self::Probestack => "_wasmer_vm_probestack",
293            #[cfg(not(target_vendor = "apple"))]
294            Self::Probestack => "wasmer_vm_probestack",
295            Self::Memory32AtomicWait32 => "wasmer_vm_memory32_atomic_wait32",
296            Self::ImportedMemory32AtomicWait32 => "wasmer_vm_imported_memory32_atomic_wait32",
297            Self::Memory32AtomicWait64 => "wasmer_vm_memory32_atomic_wait64",
298            Self::ImportedMemory32AtomicWait64 => "wasmer_vm_imported_memory32_atomic_wait64",
299            Self::Memory32AtomicNotify => "wasmer_vm_memory32_atomic_notify",
300            Self::ImportedMemory32AtomicNotify => "wasmer_vm_imported_memory32_atomic_notify",
301            Self::Throw => "wasmer_vm_throw",
302            Self::EHPersonality => "wasmer_eh_personality",
303            Self::EHPersonality2 => "wasmer_eh_personality2",
304            Self::AllocException => "wasmer_vm_alloc_exception",
305            Self::ReadExnRef => "wasmer_vm_read_exnref",
306            Self::LibunwindExceptionIntoExnRef => "wasmer_vm_exception_into_exnref",
307            Self::DebugUsize => "wasmer_vm_dbg_usize",
308            Self::DebugStr => "wasmer_vm_dbg_str",
309            // --- Soft-float libcalls ---
310            Self::Addsf3 => "__addsf3",
311            Self::Adddf3 => "__adddf3",
312            Self::Subsf3 => "__subsf3",
313            Self::Subdf3 => "__subdf3",
314            Self::Mulsf3 => "__mulsf3",
315            Self::Muldf3 => "__muldf3",
316            Self::Divsf3 => "__divsf3",
317            Self::Divdf3 => "__divdf3",
318            Self::Negsf2 => "__negsf2",
319            Self::Negdf2 => "__negdf2",
320            Self::Extendsfdf2 => "__extendsfdf2",
321            Self::Truncdfsf2 => "__truncdfsf2",
322            Self::Fixsfsi => "__fixsfsi",
323            Self::Fixdfsi => "__fixdfsi",
324            Self::Fixsfdi => "__fixsfdi",
325            Self::Fixdfdi => "__fixdfdi",
326            Self::Fixunssfsi => "__fixunssfsi",
327            Self::Fixunsdfsi => "__fixunsdfsi",
328            Self::Fixunssfdi => "__fixunssfdi",
329            Self::Fixunsdfdi => "__fixunsdfdi",
330            Self::Floatsisf => "__floatsisf",
331            Self::Floatsidf => "__floatsidf",
332            Self::Floatdisf => "__floatdisf",
333            Self::Floatdidf => "__floatdidf",
334            Self::Floatunsisf => "__floatunsisf",
335            Self::Floatunsidf => "__floatunsidf",
336            Self::Floatundisf => "__floatundisf",
337            Self::Floatundidf => "__floatundidf",
338            Self::Unordsf2 => "__unordsf2",
339            Self::Unorddf2 => "__unorddf2",
340            Self::Eqsf2 => "__eqsf2",
341            Self::Eqdf2 => "__eqdf2",
342            Self::Nesf2 => "__nesf2",
343            Self::Nedf2 => "__nedf2",
344            Self::Gesf2 => "__gesf2",
345            Self::Gedf2 => "__gedf2",
346            Self::Ltsf2 => "__ltsf2",
347            Self::Ltdf2 => "__ltdf2",
348            Self::Lesf2 => "__lesf2",
349            Self::Ledf2 => "__ledf2",
350            Self::Gtsf2 => "__gtsf2",
351            Self::Gtdf2 => "__gtdf2",
352        }
353    }
354}
355
356impl fmt::Display for LibCall {
357    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
358        fmt::Debug::fmt(self, f)
359    }
360}