1 //! Support for the component model in Wasmtime.
2 //!
3 //! This module contains all of the internal type definitions used by Wasmtime
4 //! to process the component model. Despite everything being `pub` here this is
5 //! not the public interface of Wasmtime to the component model. Instead this is
6 //! the internal support to mirror the core wasm support that Wasmtime already
7 //! implements.
8 //!
9 //! Some main items contained within here are:
10 //!
11 //! * Type hierarchy information for the component model
12 //! * Translation of a component into Wasmtime's representation
13 //! * Type information about a component used at runtime
14 //!
15 //! This module also contains a lot of Serialize/Deserialize types which are
16 //! encoded in the final compiled image for a component.
17 //!
18 //! Note that this entire module is gated behind the `component-model` Cargo
19 //! feature.
20 
21 /// Canonical ABI-defined constant for the maximum number of "flat" parameters
22 /// to a wasm function, or the maximum number of parameters a core wasm function
23 /// will take for just the parameters used. Over this number the heap is used
24 /// for transferring parameters.
25 pub const MAX_FLAT_PARAMS: usize = 16;
26 
27 /// Similar to `MAX_FLAT_PARAMS`, but used for async-lowered imports instead of
28 /// sync ones.
29 pub const MAX_FLAT_ASYNC_PARAMS: usize = 4;
30 
31 /// Canonical ABI-defined constant for the maximum number of "flat" results.
32 /// This number of results are returned directly from wasm and otherwise results
33 /// are transferred through memory.
34 pub const MAX_FLAT_RESULTS: usize = 1;
35 
36 /// Sentinel value in `result_count_or_max_if_async` as part of the
37 /// `prepare_call` libcall which indicates that preparation is being done for an
38 /// async function that produces no result, aka there is no return pointer.
39 pub const PREPARE_ASYNC_NO_RESULT: u32 = u32::MAX;
40 
41 /// Sentinel value in `result_count_or_max_if_async` as part of the
42 /// `prepare_call` libcall which indicates that preparation is being done for an
43 /// async function that produces at least one result, aka there is a return
44 /// pointer.
45 pub const PREPARE_ASYNC_WITH_RESULT: u32 = u32::MAX - 1;
46 
47 /// Bit flag for indicating async-lifted exports
48 ///
49 /// This flag may be passed to the `async-start` built-in function (which is
50 /// called from both async->async and async->sync adapters) to indicate that the
51 /// callee is an async-lifted export.
52 pub const START_FLAG_ASYNC_CALLEE: i32 = 1 << 0;
53 
54 mod artifacts;
55 mod info;
56 mod intrinsic;
57 mod names;
58 mod types;
59 mod vmcomponent_offsets;
60 pub use self::artifacts::*;
61 pub use self::info::*;
62 pub use self::intrinsic::*;
63 pub use self::names::*;
64 pub use self::types::*;
65 pub use self::vmcomponent_offsets::*;
66 
67 #[cfg(feature = "compile")]
68 mod compiler;
69 #[cfg(feature = "compile")]
70 pub mod dfg;
71 #[cfg(feature = "compile")]
72 mod translate;
73 #[cfg(feature = "compile")]
74 mod types_builder;
75 #[cfg(feature = "compile")]
76 pub use self::compiler::*;
77 #[cfg(feature = "compile")]
78 pub use self::translate::*;
79 #[cfg(feature = "compile")]
80 pub use self::types_builder::*;
81 
82 /// Helper macro, like `foreach_transcoder`, to iterate over builtins for
83 /// components unrelated to transcoding.
84 #[macro_export]
85 macro_rules! foreach_builtin_component_function {
86     ($mac:ident) => {
87         $mac! {
88             resource_new32(vmctx: vmctx, caller_instance: u32, resource: u32, rep: u32) -> u64;
89             resource_rep32(vmctx: vmctx, caller_instance: u32, resource: u32, idx: u32) -> u64;
90 
91             // Returns an `Option<u32>` where `None` is "no destructor needed"
92             // and `Some(val)` is "run the destructor on this rep". The option
93             // is encoded as a 64-bit integer where the low bit is Some/None
94             // and bits 1-33 are the payload.
95             resource_drop(vmctx: vmctx, caller_instance: u32, resource: u32, idx: u32) -> u64;
96 
97             resource_transfer_own(vmctx: vmctx, src_idx: u32, src_table: u32, dst_table: u32) -> u64;
98             resource_transfer_borrow(vmctx: vmctx, src_idx: u32, src_table: u32, dst_table: u32) -> u64;
99 
100             enter_sync_call(vmctx: vmctx, caller_instance: u32, callee_async: u32, callee_instance: u32) -> bool;
101             exit_sync_call(vmctx: vmctx) -> bool;
102 
103             #[cfg(feature = "component-model-async")]
104             backpressure_modify(vmctx: vmctx, caller_instance: u32, increment: u8) -> bool;
105             #[cfg(feature = "component-model-async")]
106             task_return(vmctx: vmctx, caller_instance: u32, ty: u32, options: u32, storage: ptr_u8, storage_len: size) -> bool;
107             #[cfg(feature = "component-model-async")]
108             task_cancel(vmctx: vmctx, caller_instance: u32) -> bool;
109             #[cfg(feature = "component-model-async")]
110             waitable_set_new(vmctx: vmctx, caller_instance: u32) -> u64;
111             #[cfg(feature = "component-model-async")]
112             waitable_set_wait(vmctx: vmctx, caller_instance: u32, options: u32, set: u32, payload: u32) -> u64;
113             #[cfg(feature = "component-model-async")]
114             waitable_set_poll(vmctx: vmctx, caller_instance: u32, options: u32, set: u32, payload: u32) -> u64;
115             #[cfg(feature = "component-model-async")]
116             waitable_set_drop(vmctx: vmctx, caller_instance: u32, set: u32) -> bool;
117             #[cfg(feature = "component-model-async")]
118             waitable_join(vmctx: vmctx, caller_instance: u32, set: u32, waitable: u32) -> bool;
119             #[cfg(feature = "component-model-async")]
120             thread_yield(vmctx: vmctx, caller_instance: u32, cancellable: u8) -> u32;
121             #[cfg(feature = "component-model-async")]
122             subtask_drop(vmctx: vmctx, caller_instance: u32, task_id: u32) -> bool;
123             #[cfg(feature = "component-model-async")]
124             subtask_cancel(vmctx: vmctx, caller_instance: u32, async_: u8, task_id: u32) -> u64;
125             #[cfg(feature = "component-model-async")]
126             prepare_call(
127                 vmctx: vmctx,
128                 memory: ptr_u8,
129                 start: ptr_u8,
130                 return_: ptr_u8,
131                 caller_instance: u32,
132                 callee_instance: u32,
133                 task_return_type: u32,
134                 callee_async: u32,
135                 string_encoding: u32,
136                 result_count_or_max_if_async: u32,
137                 storage: ptr_u8,
138                 storage_len: size
139             ) -> bool;
140             #[cfg(feature = "component-model-async")]
141             sync_start(vmctx: vmctx, callback: ptr_u8, storage: ptr_u8, storage_len: size, callee: ptr_u8, param_count: u32) -> bool;
142             #[cfg(feature = "component-model-async")]
143             async_start(vmctx: vmctx, callback: ptr_u8, post_return: ptr_u8, callee: ptr_u8, param_count: u32, result_count: u32, flags: u32) -> u64;
144             #[cfg(feature = "component-model-async")]
145             future_new(vmctx: vmctx, caller_instance: u32, ty: u32) -> u64;
146             #[cfg(feature = "component-model-async")]
147             future_write(vmctx: vmctx, caller_instance: u32, ty: u32, options: u32, future: u32, address: u32) -> u64;
148             #[cfg(feature = "component-model-async")]
149             future_read(vmctx: vmctx, caller_instance: u32, ty: u32, options: u32, future: u32, address: u32) -> u64;
150             #[cfg(feature = "component-model-async")]
151             future_cancel_write(vmctx: vmctx, caller_instance: u32, ty: u32, async_: u8, writer: u32) -> u64;
152             #[cfg(feature = "component-model-async")]
153             future_cancel_read(vmctx: vmctx, caller_instance: u32, ty: u32, async_: u8, reader: u32) -> u64;
154             #[cfg(feature = "component-model-async")]
155             future_drop_writable(vmctx: vmctx, caller_instance: u32, ty: u32, writer: u32) -> bool;
156             #[cfg(feature = "component-model-async")]
157             future_drop_readable(vmctx: vmctx, caller_instance: u32, ty: u32, reader: u32) -> bool;
158             #[cfg(feature = "component-model-async")]
159             stream_new(vmctx: vmctx, caller_instance: u32, ty: u32) -> u64;
160             #[cfg(feature = "component-model-async")]
161             stream_write(vmctx: vmctx, caller_instance: u32, ty: u32, options: u32, stream: u32, address: u32, count: u32) -> u64;
162             #[cfg(feature = "component-model-async")]
163             stream_read(vmctx: vmctx, caller_instance: u32, ty: u32, options: u32, stream: u32, address: u32, count: u32) -> u64;
164             #[cfg(feature = "component-model-async")]
165             stream_cancel_write(vmctx: vmctx, caller_instance: u32, ty: u32, async_: u8, writer: u32) -> u64;
166             #[cfg(feature = "component-model-async")]
167             stream_cancel_read(vmctx: vmctx, caller_instance: u32, ty: u32, async_: u8, reader: u32) -> u64;
168             #[cfg(feature = "component-model-async")]
169             stream_drop_writable(vmctx: vmctx, caller_instance: u32, ty: u32, writer: u32) -> bool;
170             #[cfg(feature = "component-model-async")]
171             stream_drop_readable(vmctx: vmctx, caller_instance: u32, ty: u32, reader: u32) -> bool;
172             #[cfg(feature = "component-model-async")]
173             flat_stream_write(vmctx: vmctx, caller_instance: u32, ty: u32, options:u32, payload_size: u32, payload_align: u32, stream: u32, address: u32, count: u32) -> u64;
174             #[cfg(feature = "component-model-async")]
175             flat_stream_read(vmctx: vmctx, caller_instance: u32, ty: u32, options: u32, payload_size: u32, payload_align: u32, stream: u32, address: u32, count: u32) -> u64;
176             #[cfg(feature = "component-model-async")]
177             error_context_new(vmctx: vmctx, caller_instance: u32, ty: u32, options: u32, debug_msg_address: u32, debug_msg_len: u32) -> u64;
178             #[cfg(feature = "component-model-async")]
179             error_context_debug_message(vmctx: vmctx, caller_instance: u32, ty: u32, options: u32, err_ctx_handle: u32, debug_msg_address: u32) -> bool;
180             #[cfg(feature = "component-model-async")]
181             error_context_drop(vmctx: vmctx, caller_instance: u32, ty: u32, err_ctx_handle: u32) -> bool;
182             #[cfg(feature = "component-model-async")]
183             future_transfer(vmctx: vmctx, src_idx: u32, src_table: u32, dst_table: u32) -> u64;
184             #[cfg(feature = "component-model-async")]
185             stream_transfer(vmctx: vmctx, src_idx: u32, src_table: u32, dst_table: u32) -> u64;
186             #[cfg(feature = "component-model-async")]
187             error_context_transfer(vmctx: vmctx, src_idx: u32, src_table: u32, dst_table: u32) -> u64;
188             #[cfg(feature = "component-model-async")]
189             context_get(vmctx: vmctx, caller_instance: u32, slot: u32) -> u64;
190             #[cfg(feature = "component-model-async")]
191             context_set(vmctx: vmctx, caller_instance: u32, slot: u32, val: u32) -> bool;
192             #[cfg(feature = "component-model-async")]
193             thread_index(vmctx: vmctx) -> u64;
194             #[cfg(feature = "component-model-async")]
195             thread_new_indirect(vmctx: vmctx, caller_instance: u32, func_ty_id: u32, func_table_idx: u32, func_idx: u32, context: u32) -> u64;
196             #[cfg(feature = "component-model-async")]
197             thread_suspend_to_suspended(vmctx: vmctx, caller_instance: u32, cancellable: u8, thread_idx: u32) -> u32;
198             #[cfg(feature = "component-model-async")]
199             thread_suspend_to(vmctx: vmctx, caller_instance: u32, cancellable: u8, thread_idx: u32) -> u32;
200             #[cfg(feature = "component-model-async")]
201             thread_suspend(vmctx: vmctx, caller_instance: u32, cancellable: u8) -> u32;
202             #[cfg(feature = "component-model-async")]
203             thread_unsuspend(vmctx: vmctx, caller_instance: u32, thread_idx: u32) -> bool;
204             #[cfg(feature = "component-model-async")]
205             thread_yield_to_suspended(vmctx: vmctx, caller_instance: u32, cancellable: u8, thread_idx: u32) -> u32;
206 
207             trap(vmctx: vmctx, code: u32) -> bool;
208 
209             utf8_to_utf8(vmctx: vmctx, src: ptr_u8, len: size, dst: ptr_u8) -> bool;
210             utf16_to_utf16(vmctx: vmctx, src: ptr_u16, len: size, dst: ptr_u16) -> bool;
211             latin1_to_latin1(vmctx: vmctx, src: ptr_u8, len: size, dst: ptr_u8) -> bool;
212             latin1_to_utf16(vmctx: vmctx, src: ptr_u8, len: size, dst: ptr_u16) -> bool;
213             utf8_to_utf16(vmctx: vmctx, src: ptr_u8, len: size, dst: ptr_u16) -> size;
214             utf16_to_utf8(vmctx: vmctx, src: ptr_u16, src_len: size, dst: ptr_u8, dst_len: size, ret2: ptr_size) -> size;
215             latin1_to_utf8(vmctx: vmctx, src: ptr_u8, src_len: size, dst: ptr_u8, dst_len: size, ret2: ptr_size) -> size;
216             utf16_to_compact_probably_utf16(vmctx: vmctx, src: ptr_u16, len: size, dst: ptr_u16) -> size;
217             utf8_to_latin1(vmctx: vmctx, src: ptr_u8, len: size, dst: ptr_u8, ret2: ptr_size) -> size;
218             utf16_to_latin1(vmctx: vmctx, src: ptr_u16, len: size, dst: ptr_u8, ret2: ptr_size) -> size;
219             utf8_to_compact_utf16(vmctx: vmctx, src: ptr_u8, src_len: size, dst: ptr_u16, dst_len: size, bytes_so_far: size) -> size;
220             utf16_to_compact_utf16(vmctx: vmctx, src: ptr_u16, src_len: size, dst: ptr_u16, dst_len: size, bytes_so_far: size) -> size;
221         }
222     };
223 }
224 
225 // Define `struct ComponentBuiltinFunctionIndex`
226 declare_builtin_index! {
227     /// An index type for component builtin functions.
228     pub struct ComponentBuiltinFunctionIndex: foreach_builtin_component_function;
229 }
230