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 `start-call` built-in function to indicate
50/// that the callee is an async-lifted export.
51pub const START_FLAG_ASYNC_CALLEE: i32 = 1 << 0;
52
53/// Bit flag for indicating async-lowered imports
54///
55/// This flag may be passed to the `start-call` built-in function to indicate
56/// that the caller is an async-lowered import, in which case the call's status
57/// is returned rather than blocking until the callee produces its results.
58pub const START_FLAG_ASYNC_CALLER: i32 = 1 << 1;
59
60mod artifacts;
61mod info;
62mod intrinsic;
63mod names;
64mod types;
65mod vmcomponent_offsets;
66pub use self::artifacts::*;
67pub use self::info::*;
68pub use self::intrinsic::*;
69pub use self::names::*;
70pub use self::types::*;
71pub use self::vmcomponent_offsets::*;
72
73#[cfg(feature = "compile")]
74mod compiler;
75#[cfg(feature = "compile")]
76pub mod dfg;
77#[cfg(feature = "compile")]
78mod same_vmctx;
79#[cfg(feature = "compile")]
80mod thread_transparency;
81#[cfg(feature = "compile")]
82mod translate;
83#[cfg(feature = "compile")]
84mod types_builder;
85#[cfg(feature = "compile")]
86pub use self::compiler::*;
87#[cfg(feature = "compile")]
88pub use self::same_vmctx::analyze_same_vmctx_imports;
89#[cfg(feature = "compile")]
90pub use self::thread_transparency::transparent_adapters;
91#[cfg(feature = "compile")]
92pub use self::translate::*;
93#[cfg(feature = "compile")]
94pub use self::types_builder::*;
95
96/// Helper macro, like `foreach_transcoder`, to iterate over builtins for
97/// components unrelated to transcoding.
98#[macro_export]
99macro_rules! foreach_builtin_component_function {
100    ($mac:ident) => {
101        $mac! {
102            resource_new32(vmctx: vmctx, caller_instance: u32, resource: u32, rep: u32) -> u64;
103            resource_rep32(vmctx: vmctx, caller_instance: u32, resource: u32, idx: u32) -> u64;
104
105            // Returns an `Option<u32>` where `None` is "no destructor needed"
106            // and `Some(val)` is "run the destructor on this rep". The option
107            // is encoded as a 64-bit integer where the low bit is Some/None
108            // and bits 1-33 are the payload.
109            resource_drop(vmctx: vmctx, caller_instance: u32, resource: u32, idx: u32) -> u64;
110
111            resource_transfer_own(vmctx: vmctx, src_idx: u32, src_table: u32, dst_table: u32) -> u64;
112            resource_transfer_borrow(vmctx: vmctx, src_idx: u32, src_table: u32, dst_table: u32) -> u64;
113            // Same as `resource_transfer_borrow` but for when the destination
114            // instance owns the resource, in which case it receives the
115            // representation directly and no destination table is involved.
116            resource_transfer_borrow_to_owner(vmctx: vmctx, src_idx: u32, src_table: u32) -> u64;
117
118            enter_sync_call(vmctx: vmctx, callee_async: u32, callee_instance: u32) -> bool;
119            exit_sync_call(vmctx: vmctx) -> bool;
120
121            // Returns the store's hostcall fuel.
122            hostcall_fuel(vmctx: vmctx) -> u64;
123
124            #[cfg(feature = "component-model-async")]
125            backpressure_modify(vmctx: vmctx, caller_instance: u32, increment: u8) -> bool;
126            #[cfg(feature = "component-model-async")]
127            task_return(vmctx: vmctx, caller_instance: u32, ty: u32, options: u32, storage: ptr_u8, storage_len: size) -> bool;
128            #[cfg(feature = "component-model-async")]
129            task_cancel(vmctx: vmctx, caller_instance: u32) -> bool;
130            #[cfg(feature = "component-model-async")]
131            waitable_set_new(vmctx: vmctx, caller_instance: u32) -> u64;
132            // FIXME(#4311): `payload` needs to be a `u64` for memory64
133            #[cfg(feature = "component-model-async")]
134            waitable_set_wait(vmctx: vmctx, caller_instance: u32, options: u32, set: u32, payload: u32) -> u64;
135            // FIXME(#4311): `payload` needs to be a `u64` for memory64
136            #[cfg(feature = "component-model-async")]
137            waitable_set_poll(vmctx: vmctx, caller_instance: u32, options: u32, set: u32, payload: u32) -> u64;
138            #[cfg(feature = "component-model-async")]
139            waitable_set_drop(vmctx: vmctx, caller_instance: u32, set: u32) -> bool;
140            #[cfg(feature = "component-model-async")]
141            waitable_join(vmctx: vmctx, caller_instance: u32, set: u32, waitable: u32) -> bool;
142            #[cfg(feature = "component-model-async")]
143            subtask_drop(vmctx: vmctx, caller_instance: u32, task_id: u32) -> bool;
144            #[cfg(feature = "component-model-async")]
145            subtask_cancel(vmctx: vmctx, caller_instance: u32, async_: u8, task_id: u32) -> u64;
146            #[cfg(feature = "component-model-async")]
147            prepare_call(
148                vmctx: vmctx,
149                memory: ptr_u8,
150                start: ptr_u8,
151                return_: ptr_u8,
152                caller_instance: u32,
153                callee_instance: u32,
154                task_return_type: u32,
155                callee_async: u32,
156                string_encoding: u32,
157                result_count_or_max_if_async: u32,
158                storage: ptr_u8,
159                storage_len: size
160            ) -> bool;
161            #[cfg(feature = "component-model-async")]
162            start_call(vmctx: vmctx, callback: ptr_u8, post_return: ptr_u8, storage: ptr_u8, storage_len: size, callee: ptr_u8, param_count: u32, result_count: u32, flags: u32) -> bool;
163            #[cfg(feature = "component-model-async")]
164            future_new(vmctx: vmctx, caller_instance: u32, ty: u32) -> u64;
165            // FIXME(#4311): `address` needs to be a `u64` for memory64
166            #[cfg(feature = "component-model-async")]
167            future_write(vmctx: vmctx, caller_instance: u32, ty: u32, options: u32, future: u32, address: u32) -> u64;
168            // FIXME(#4311): `address` needs to be a `u64` for memory64
169            #[cfg(feature = "component-model-async")]
170            future_read(vmctx: vmctx, caller_instance: u32, ty: u32, options: u32, future: u32, address: u32) -> u64;
171            #[cfg(feature = "component-model-async")]
172            future_cancel_write(vmctx: vmctx, caller_instance: u32, ty: u32, async_: u8, writer: u32) -> u64;
173            #[cfg(feature = "component-model-async")]
174            future_cancel_read(vmctx: vmctx, caller_instance: u32, ty: u32, async_: u8, reader: u32) -> u64;
175            #[cfg(feature = "component-model-async")]
176            future_drop_writable(vmctx: vmctx, caller_instance: u32, ty: u32, writer: u32) -> bool;
177            #[cfg(feature = "component-model-async")]
178            future_drop_readable(vmctx: vmctx, caller_instance: u32, ty: u32, reader: u32) -> bool;
179            #[cfg(feature = "component-model-async")]
180            stream_new(vmctx: vmctx, caller_instance: u32, ty: u32) -> u64;
181            // FIXME(#4311): `address` and `count` need to be `u64`s for memory64
182            #[cfg(feature = "component-model-async")]
183            stream_write(vmctx: vmctx, caller_instance: u32, ty: u32, options: u32, stream: u32, address: u32, count: u32) -> u64;
184            // FIXME(#4311): `address` and `count` need to be `u64`s for memory64
185            #[cfg(feature = "component-model-async")]
186            stream_read(vmctx: vmctx, caller_instance: u32, ty: u32, options: u32, stream: u32, address: u32, count: u32) -> u64;
187            #[cfg(feature = "component-model-async")]
188            stream_cancel_write(vmctx: vmctx, caller_instance: u32, ty: u32, async_: u8, writer: u32) -> u64;
189            #[cfg(feature = "component-model-async")]
190            stream_cancel_read(vmctx: vmctx, caller_instance: u32, ty: u32, async_: u8, reader: u32) -> u64;
191            #[cfg(feature = "component-model-async")]
192            stream_drop_writable(vmctx: vmctx, caller_instance: u32, ty: u32, writer: u32) -> bool;
193            #[cfg(feature = "component-model-async")]
194            stream_drop_readable(vmctx: vmctx, caller_instance: u32, ty: u32, reader: u32) -> bool;
195            // FIXME(#4311): `address` and `count` need to be `u64`s for memory64
196            #[cfg(feature = "component-model-async")]
197            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;
198            // FIXME(#4311): `address` and `count` need to be `u64`s for memory64
199            #[cfg(feature = "component-model-async")]
200            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;
201            // FIXME(#4311): `debug_msg_address` and `debug_msg_len` need to be `u64`s for memory64
202            #[cfg(feature = "component-model-async")]
203            error_context_new(vmctx: vmctx, caller_instance: u32, ty: u32, options: u32, debug_msg_address: u32, debug_msg_len: u32) -> u64;
204            // FIXME(#4311): `debug_msg_address` needs to be a `u64` for memory64
205            #[cfg(feature = "component-model-async")]
206            error_context_debug_message(vmctx: vmctx, caller_instance: u32, ty: u32, options: u32, err_ctx_handle: u32, debug_msg_address: u32) -> bool;
207            #[cfg(feature = "component-model-async")]
208            error_context_drop(vmctx: vmctx, caller_instance: u32, ty: u32, err_ctx_handle: u32) -> bool;
209            #[cfg(feature = "component-model-async")]
210            future_transfer(vmctx: vmctx, src_idx: u32, src_table: u32, dst_table: u32) -> u64;
211            #[cfg(feature = "component-model-async")]
212            stream_transfer(vmctx: vmctx, src_idx: u32, src_table: u32, dst_table: u32) -> u64;
213            #[cfg(feature = "component-model-async")]
214            error_context_transfer(vmctx: vmctx, src_idx: u32, src_table: u32, dst_table: u32) -> u64;
215            #[cfg(feature = "component-model-async")]
216            thread_index(vmctx: vmctx) -> u64;
217            #[cfg(feature = "component-model-async")]
218            thread_new_indirect(vmctx: vmctx, caller_instance: u32, func_ty_id: u32, func_table_idx: u32, func_idx: u32, context: u32) -> u64;
219            #[cfg(feature = "component-model-async")]
220            thread_resume_later(vmctx: vmctx, caller_instance: u32, thread_idx: u32) -> bool;
221            #[cfg(feature = "component-model-async")]
222            thread_suspend(vmctx: vmctx, caller_instance: u32) -> u32;
223            #[cfg(feature = "component-model-async")]
224            thread_yield(vmctx: vmctx, caller_instance: u32) -> u32;
225            #[cfg(feature = "component-model-async")]
226            thread_suspend_then_resume(vmctx: vmctx, caller_instance: u32, thread_idx: u32) -> u32;
227            #[cfg(feature = "component-model-async")]
228            thread_yield_then_resume(vmctx: vmctx, caller_instance: u32, thread_idx: u32) -> u32;
229            #[cfg(feature = "component-model-async")]
230            thread_suspend_then_promote(vmctx: vmctx, caller_instance: u32, thread_idx: u32) -> u32;
231            #[cfg(feature = "component-model-async")]
232            thread_yield_then_promote(vmctx: vmctx, caller_instance: u32, thread_idx: u32) -> u32;
233
234            utf8_to_utf8(vmctx: vmctx, src: ptr_u8, len: size, dst: ptr_u8) -> bool;
235            utf16_to_utf16(vmctx: vmctx, src: ptr_u16, len: size, dst: ptr_u16) -> bool;
236            latin1_to_latin1(vmctx: vmctx, src: ptr_u8, len: size, dst: ptr_u8) -> bool;
237            latin1_to_utf16(vmctx: vmctx, src: ptr_u8, len: size, dst: ptr_u16) -> bool;
238            utf8_to_utf16(vmctx: vmctx, src: ptr_u8, len: size, dst: ptr_u16) -> size;
239            utf16_to_utf8(vmctx: vmctx, src: ptr_u16, src_len: size, dst: ptr_u8, dst_len: size, first_pass: u32, ret2: ptr_size) -> size;
240            latin1_to_utf8(vmctx: vmctx, src: ptr_u8, src_len: size, dst: ptr_u8, dst_len: size, first_pass: u32, ret2: ptr_size) -> size;
241            utf16_to_compact_probably_utf16(vmctx: vmctx, src: ptr_u16, len: size, dst: ptr_u16) -> size;
242            utf8_to_latin1(vmctx: vmctx, src: ptr_u8, len: size, dst: ptr_u8, ret2: ptr_size) -> size;
243            utf16_to_latin1(vmctx: vmctx, src: ptr_u16, len: size, dst: ptr_u8, ret2: ptr_size) -> size;
244            utf8_to_compact_utf16(vmctx: vmctx, src: ptr_u8, src_len: size, dst: ptr_u16, dst_len: size, bytes_so_far: size) -> size;
245            utf16_to_compact_utf16(vmctx: vmctx, src: ptr_u16, src_len: size, dst: ptr_u16, dst_len: size, bytes_so_far: size) -> size;
246        }
247    };
248}
249
250// Define `struct ComponentBuiltinFunctionIndex`
251declare_builtin_index! {
252    /// An index type for component builtin functions.
253    pub struct ComponentBuiltinFunctionIndex: foreach_builtin_component_function;
254}