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);