wasmtime_environ/
builtin.rs

1/// Helper macro to iterate over all builtin functions and their signatures.
2#[macro_export]
3macro_rules! foreach_builtin_function {
4    ($mac:ident) => {
5        $mac! {
6            // Returns an index for wasm's `memory.grow` builtin function.
7            memory32_grow(vmctx: vmctx, delta: i64, index: i32) -> pointer;
8            // Returns an index for wasm's `table.copy` when both tables are locally
9            // defined.
10            table_copy(vmctx: vmctx, dst_index: i32, src_index: i32, dst: i32, src: i32, len: i32);
11            // Returns an index for wasm's `table.init`.
12            table_init(vmctx: vmctx, table: i32, elem: i32, dst: i32, src: i32, len: i32);
13            // Returns an index for wasm's `elem.drop`.
14            elem_drop(vmctx: vmctx, elem: i32);
15            // Returns an index for wasm's `memory.copy`
16            memory_copy(vmctx: vmctx, dst_index: i32, dst: i64, src_index: i32, src: i64, len: i64);
17            // Returns an index for wasm's `memory.fill` instruction.
18            memory_fill(vmctx: vmctx, memory: i32, dst: i64, val: i32, len: i64);
19            // Returns an index for wasm's `memory.init` instruction.
20            memory_init(vmctx: vmctx, memory: i32, data: i32, dst: i64, src: i32, len: i32);
21            // Returns a value for wasm's `ref.func` instruction.
22            ref_func(vmctx: vmctx, func: i32) -> pointer;
23            // Returns an index for wasm's `data.drop` instruction.
24            data_drop(vmctx: vmctx, data: i32);
25            // Returns a table entry after lazily initializing it.
26            table_get_lazy_init_func_ref(vmctx: vmctx, table: i32, index: i32) -> pointer;
27            // Returns an index for Wasm's `table.grow` instruction for `funcref`s.
28            table_grow_func_ref(vmctx: vmctx, table: i32, delta: i32, init: pointer) -> i32;
29            // Returns an index for Wasm's `table.fill` instruction for `funcref`s.
30            table_fill_func_ref(vmctx: vmctx, table: i32, dst: i32, val: pointer, len: i32);
31            // Returns an index for wasm's `memory.atomic.notify` instruction.
32            #[cfg(feature = "threads")]
33            memory_atomic_notify(vmctx: vmctx, memory: i32, addr: i64, count: i32) -> i32;
34            // Returns an index for wasm's `memory.atomic.wait32` instruction.
35            #[cfg(feature = "threads")]
36            memory_atomic_wait32(vmctx: vmctx, memory: i32, addr: i64, expected: i32, timeout: i64) -> i32;
37            // Returns an index for wasm's `memory.atomic.wait64` instruction.
38            #[cfg(feature = "threads")]
39            memory_atomic_wait64(vmctx: vmctx, memory: i32, addr: i64, expected: i64, timeout: i64) -> i32;
40            // Invoked when fuel has run out while executing a function.
41            out_of_gas(vmctx: vmctx);
42            // Invoked when we reach a new epoch.
43            new_epoch(vmctx: vmctx) -> i64;
44            // Invoked before malloc returns.
45            #[cfg(feature = "wmemcheck")]
46            check_malloc(vmctx: vmctx, addr: i32, len: i32) -> i32;
47            // Invoked before the free returns.
48            #[cfg(feature = "wmemcheck")]
49            check_free(vmctx: vmctx, addr: i32) -> i32;
50            // Invoked before a load is executed.
51            #[cfg(feature = "wmemcheck")]
52            check_load(vmctx: vmctx, num_bytes: i32, addr: i32, offset: i32) -> i32;
53            // Invoked before a store is executed.
54            #[cfg(feature = "wmemcheck")]
55            check_store(vmctx: vmctx, num_bytes: i32, addr: i32, offset: i32) -> i32;
56            // Invoked after malloc is called.
57            #[cfg(feature = "wmemcheck")]
58            malloc_start(vmctx: vmctx);
59            // Invoked after free is called.
60            #[cfg(feature = "wmemcheck")]
61            free_start(vmctx: vmctx);
62            // Invoked when wasm stack pointer is updated.
63            #[cfg(feature = "wmemcheck")]
64            update_stack_pointer(vmctx: vmctx, value: i32);
65            // Invoked before memory.grow is called.
66            #[cfg(feature = "wmemcheck")]
67            update_mem_size(vmctx: vmctx, num_bytes: i32);
68
69            // Drop a non-stack GC reference (eg an overwritten table entry)
70            // once it will no longer be used again. (Note: `val` is not of type
71            // `reference` because it needn't appear in any stack maps, as it
72            // must not be live after this call.)
73            #[cfg(feature = "gc")]
74            drop_gc_ref(vmctx: vmctx, val: i32);
75
76            // Do a GC, treating the optional `root` as a GC root and returning
77            // the updated `root` (so that, in the case of moving collectors,
78            // callers have a valid version of `root` again).
79            #[cfg(feature = "gc")]
80            gc(vmctx: vmctx, root: reference) -> reference;
81
82            // Implementation of Wasm's `global.get` instruction for globals
83            // containing GC references.
84            #[cfg(feature = "gc")]
85            gc_ref_global_get(vmctx: vmctx, global: i32) -> reference;
86
87            // Implementation of Wasm's `global.set` instruction for globals
88            // containing GC references.
89            #[cfg(feature = "gc")]
90            gc_ref_global_set(vmctx: vmctx, global: i32, val: reference);
91
92            // Returns an index for Wasm's `table.grow` instruction for GC references.
93            #[cfg(feature = "gc")]
94            table_grow_gc_ref(vmctx: vmctx, table: i32, delta: i32, init: reference) -> i32;
95
96            // Returns an index for Wasm's `table.fill` instruction for GC references.
97            #[cfg(feature = "gc")]
98            table_fill_gc_ref(vmctx: vmctx, table: i32, dst: i32, val: reference, len: i32);
99        }
100    };
101}
102
103/// An index type for builtin functions.
104#[derive(Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
105pub struct BuiltinFunctionIndex(u32);
106
107impl BuiltinFunctionIndex {
108    /// Create a new `BuiltinFunctionIndex` from its index
109    pub const fn from_u32(i: u32) -> Self {
110        Self(i)
111    }
112
113    /// Return the index as an u32 number.
114    pub const fn index(&self) -> u32 {
115        self.0
116    }
117}
118
119macro_rules! declare_indexes {
120    (
121        $(
122            $( #[$attr:meta] )*
123            $name:ident( $( $pname:ident: $param:ident ),* ) $( -> $result:ident )?;
124        )*
125    ) => {
126        impl BuiltinFunctionIndex {
127            declare_indexes!(
128                @indices;
129                0;
130                $( $( #[$attr] )* $name; )*
131            );
132
133            /// Returns a symbol name for this builtin.
134            pub fn name(&self) -> &'static str {
135                $(
136                    $( #[$attr] )*
137                    if *self == BuiltinFunctionIndex::$name() {
138                        return stringify!($name);
139                    }
140                )*
141                unreachable!()
142            }
143        }
144    };
145
146    // Base case: no more indices to declare, so define the total number of
147    // function indices.
148    (
149        @indices;
150        $len:expr;
151    ) => {
152        /// Returns the total number of builtin functions.
153        pub const fn builtin_functions_total_number() -> u32 {
154            $len
155        }
156    };
157
158    // Recursive case: declare the next index, and then keep declaring the rest of
159    // the indices.
160    (
161         @indices;
162         $index:expr;
163         $( #[$this_attr:meta] )*
164         $this_name:ident;
165         $(
166             $( #[$rest_attr:meta] )*
167             $rest_name:ident;
168         )*
169    ) => {
170        $( #[$this_attr] )*
171        #[allow(missing_docs)]
172        pub const fn $this_name() -> Self {
173            Self($index)
174        }
175
176        declare_indexes!(
177            @indices;
178            ($index + 1);
179            $( $( #[$rest_attr] )* $rest_name; )*
180        );
181    }
182}
183
184foreach_builtin_function!(declare_indexes);