Skip to main content

wasmtime_environ/
component.rs

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.
25pub const MAX_FLAT_PARAMS: usize = 16;
26
27/// Similar to `MAX_FLAT_PARAMS`, but used for async-lowered imports instead of
28/// sync ones.
29pub 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.
34pub 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.
39pub 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.
45pub 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.
52pub const START_FLAG_ASYNC_CALLEE: i32 = 1 << 0;
53
54mod artifacts;
55mod info;
56mod intrinsic;
57mod names;
58mod types;
59mod vmcomponent_offsets;
60pub use self::artifacts::*;
61pub use self::info::*;
62pub use self::intrinsic::*;
63pub use self::names::*;
64pub use self::types::*;
65pub use self::vmcomponent_offsets::*;
66
67#[cfg(feature = "compile")]
68mod compiler;
69#[cfg(feature = "compile")]
70pub mod dfg;
71#[cfg(feature = "compile")]
72mod translate;
73#[cfg(feature = "compile")]
74mod types_builder;
75#[cfg(feature = "compile")]
76pub use self::compiler::*;
77#[cfg(feature = "compile")]
78pub use self::translate::*;
79#[cfg(feature = "compile")]
80pub use self::types_builder::*;
81
82/// Helper macro, like `foreach_transcoder`, to iterate over builtins for
83/// components unrelated to transcoding.
84#[macro_export]
85macro_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            resource_enter_call(vmctx: vmctx);
100            resource_exit_call(vmctx: vmctx) -> bool;
101
102            #[cfg(feature = "component-model-async")]
103            enter_sync_call(vmctx: vmctx, caller_instance: u32, callee_async: u32, callee_instance: u32) -> bool;
104            #[cfg(feature = "component-model-async")]
105            exit_sync_call(vmctx: vmctx) -> bool;
106
107            #[cfg(feature = "component-model-async")]
108            backpressure_modify(vmctx: vmctx, caller_instance: u32, increment: u8) -> bool;
109            #[cfg(feature = "component-model-async")]
110            task_return(vmctx: vmctx, caller_instance: u32, ty: u32, options: u32, storage: ptr_u8, storage_len: size) -> bool;
111            #[cfg(feature = "component-model-async")]
112            task_cancel(vmctx: vmctx, caller_instance: u32) -> bool;
113            #[cfg(feature = "component-model-async")]
114            waitable_set_new(vmctx: vmctx, caller_instance: u32) -> u64;
115            #[cfg(feature = "component-model-async")]
116            waitable_set_wait(vmctx: vmctx, caller_instance: u32, options: u32, set: u32, payload: u32) -> u64;
117            #[cfg(feature = "component-model-async")]
118            waitable_set_poll(vmctx: vmctx, caller_instance: u32, options: u32, set: u32, payload: u32) -> u64;
119            #[cfg(feature = "component-model-async")]
120            waitable_set_drop(vmctx: vmctx, caller_instance: u32, set: u32) -> bool;
121            #[cfg(feature = "component-model-async")]
122            waitable_join(vmctx: vmctx, caller_instance: u32, set: u32, waitable: u32) -> bool;
123            #[cfg(feature = "component-model-async")]
124            thread_yield(vmctx: vmctx, caller_instance: u32, cancellable: u8) -> u32;
125            #[cfg(feature = "component-model-async")]
126            subtask_drop(vmctx: vmctx, caller_instance: u32, task_id: u32) -> bool;
127            #[cfg(feature = "component-model-async")]
128            subtask_cancel(vmctx: vmctx, caller_instance: u32, async_: u8, task_id: u32) -> u64;
129            #[cfg(feature = "component-model-async")]
130            prepare_call(
131                vmctx: vmctx,
132                memory: ptr_u8,
133                start: ptr_u8,
134                return_: ptr_u8,
135                caller_instance: u32,
136                callee_instance: u32,
137                task_return_type: u32,
138                callee_async: u32,
139                string_encoding: u32,
140                result_count_or_max_if_async: u32,
141                storage: ptr_u8,
142                storage_len: size
143            ) -> bool;
144            #[cfg(feature = "component-model-async")]
145            sync_start(vmctx: vmctx, callback: ptr_u8, storage: ptr_u8, storage_len: size, callee: ptr_u8, param_count: u32) -> bool;
146            #[cfg(feature = "component-model-async")]
147            async_start(vmctx: vmctx, callback: ptr_u8, post_return: ptr_u8, callee: ptr_u8, param_count: u32, result_count: u32, flags: u32) -> u64;
148            #[cfg(feature = "component-model-async")]
149            future_new(vmctx: vmctx, caller_instance: u32, ty: u32) -> u64;
150            #[cfg(feature = "component-model-async")]
151            future_write(vmctx: vmctx, caller_instance: u32, ty: u32, options: u32, future: u32, address: u32) -> u64;
152            #[cfg(feature = "component-model-async")]
153            future_read(vmctx: vmctx, caller_instance: u32, ty: u32, options: u32, future: u32, address: u32) -> u64;
154            #[cfg(feature = "component-model-async")]
155            future_cancel_write(vmctx: vmctx, caller_instance: u32, ty: u32, async_: u8, writer: u32) -> u64;
156            #[cfg(feature = "component-model-async")]
157            future_cancel_read(vmctx: vmctx, caller_instance: u32, ty: u32, async_: u8, reader: u32) -> u64;
158            #[cfg(feature = "component-model-async")]
159            future_drop_writable(vmctx: vmctx, caller_instance: u32, ty: u32, writer: u32) -> bool;
160            #[cfg(feature = "component-model-async")]
161            future_drop_readable(vmctx: vmctx, caller_instance: u32, ty: u32, reader: u32) -> bool;
162            #[cfg(feature = "component-model-async")]
163            stream_new(vmctx: vmctx, caller_instance: u32, ty: u32) -> u64;
164            #[cfg(feature = "component-model-async")]
165            stream_write(vmctx: vmctx, caller_instance: u32, ty: u32, options: u32, stream: u32, address: u32, count: u32) -> u64;
166            #[cfg(feature = "component-model-async")]
167            stream_read(vmctx: vmctx, caller_instance: u32, ty: u32, options: u32, stream: u32, address: u32, count: u32) -> u64;
168            #[cfg(feature = "component-model-async")]
169            stream_cancel_write(vmctx: vmctx, caller_instance: u32, ty: u32, async_: u8, writer: u32) -> u64;
170            #[cfg(feature = "component-model-async")]
171            stream_cancel_read(vmctx: vmctx, caller_instance: u32, ty: u32, async_: u8, reader: u32) -> u64;
172            #[cfg(feature = "component-model-async")]
173            stream_drop_writable(vmctx: vmctx, caller_instance: u32, ty: u32, writer: u32) -> bool;
174            #[cfg(feature = "component-model-async")]
175            stream_drop_readable(vmctx: vmctx, caller_instance: u32, ty: u32, reader: u32) -> bool;
176            #[cfg(feature = "component-model-async")]
177            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;
178            #[cfg(feature = "component-model-async")]
179            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;
180            #[cfg(feature = "component-model-async")]
181            error_context_new(vmctx: vmctx, caller_instance: u32, ty: u32, options: u32, debug_msg_address: u32, debug_msg_len: u32) -> u64;
182            #[cfg(feature = "component-model-async")]
183            error_context_debug_message(vmctx: vmctx, caller_instance: u32, ty: u32, options: u32, err_ctx_handle: u32, debug_msg_address: u32) -> bool;
184            #[cfg(feature = "component-model-async")]
185            error_context_drop(vmctx: vmctx, caller_instance: u32, ty: u32, err_ctx_handle: u32) -> bool;
186            #[cfg(feature = "component-model-async")]
187            future_transfer(vmctx: vmctx, src_idx: u32, src_table: u32, dst_table: u32) -> u64;
188            #[cfg(feature = "component-model-async")]
189            stream_transfer(vmctx: vmctx, src_idx: u32, src_table: u32, dst_table: u32) -> u64;
190            #[cfg(feature = "component-model-async")]
191            error_context_transfer(vmctx: vmctx, src_idx: u32, src_table: u32, dst_table: u32) -> u64;
192            #[cfg(feature = "component-model-async")]
193            context_get(vmctx: vmctx, caller_instance: u32, slot: u32) -> u64;
194            #[cfg(feature = "component-model-async")]
195            context_set(vmctx: vmctx, caller_instance: u32, slot: u32, val: u32) -> bool;
196            #[cfg(feature = "component-model-async")]
197            thread_index(vmctx: vmctx) -> u64;
198            #[cfg(feature = "component-model-async")]
199            thread_new_indirect(vmctx: vmctx, caller_instance: u32, func_ty_id: u32, func_table_idx: u32, func_idx: u32, context: u32) -> u64;
200            #[cfg(feature = "component-model-async")]
201            thread_switch_to(vmctx: vmctx, caller_instance: u32, cancellable: u8, thread_idx: u32) -> u32;
202            #[cfg(feature = "component-model-async")]
203            thread_suspend(vmctx: vmctx, caller_instance: u32, cancellable: u8) -> u32;
204            #[cfg(feature = "component-model-async")]
205            thread_resume_later(vmctx: vmctx, caller_instance: u32, thread_idx: u32) -> bool;
206            #[cfg(feature = "component-model-async")]
207            thread_yield_to(vmctx: vmctx, caller_instance: u32, cancellable: u8, thread_idx: u32) -> u32;
208
209            trap(vmctx: vmctx, code: u32) -> bool;
210
211            utf8_to_utf8(vmctx: vmctx, src: ptr_u8, len: size, dst: ptr_u8) -> bool;
212            utf16_to_utf16(vmctx: vmctx, src: ptr_u16, len: size, dst: ptr_u16) -> bool;
213            latin1_to_latin1(vmctx: vmctx, src: ptr_u8, len: size, dst: ptr_u8) -> bool;
214            latin1_to_utf16(vmctx: vmctx, src: ptr_u8, len: size, dst: ptr_u16) -> bool;
215            utf8_to_utf16(vmctx: vmctx, src: ptr_u8, len: size, dst: ptr_u16) -> size;
216            utf16_to_utf8(vmctx: vmctx, src: ptr_u16, src_len: size, dst: ptr_u8, dst_len: size, ret2: ptr_size) -> size;
217            latin1_to_utf8(vmctx: vmctx, src: ptr_u8, src_len: size, dst: ptr_u8, dst_len: size, ret2: ptr_size) -> size;
218            utf16_to_compact_probably_utf16(vmctx: vmctx, src: ptr_u16, len: size, dst: ptr_u16) -> size;
219            utf8_to_latin1(vmctx: vmctx, src: ptr_u8, len: size, dst: ptr_u8, ret2: ptr_size) -> size;
220            utf16_to_latin1(vmctx: vmctx, src: ptr_u16, len: size, dst: ptr_u8, ret2: ptr_size) -> size;
221            utf8_to_compact_utf16(vmctx: vmctx, src: ptr_u8, src_len: size, dst: ptr_u16, dst_len: size, bytes_so_far: size) -> size;
222            utf16_to_compact_utf16(vmctx: vmctx, src: ptr_u16, src_len: size, dst: ptr_u16, dst_len: size, bytes_so_far: size) -> size;
223        }
224    };
225}
226
227// Define `struct ComponentBuiltinFunctionIndex`
228declare_builtin_index! {
229    /// An index type for component builtin functions.
230    pub struct ComponentBuiltinFunctionIndex: foreach_builtin_component_function;
231}