wasmtime_environ/
hostcall.rs

1use crate::BuiltinFunctionIndex;
2#[cfg(feature = "component-model")]
3use crate::component::ComponentBuiltinFunctionIndex;
4
5/// Enumeration of all possible ways that wasm may execute code in the
6/// host.
7///
8/// This type is intended to be serialized into a 32-bit index (or smaller) and
9/// is used by Pulley for example to identify how transitions from the guest to
10/// the host are performed.
11#[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
12#[cfg_attr(test, derive(arbitrary::Arbitrary))]
13pub enum HostCall {
14    /// An "array call" is being done which means that the wasm is calling the
15    /// host using the array calling convention (e.g. `VMArrayCallNative`).
16    ArrayCall,
17
18    /// A builtin function, e.g. for `memory.grow`, is being called. Each
19    /// builtin has its own ABI.
20    Builtin(BuiltinFunctionIndex),
21
22    /// A lowered component function is being called. This is done by a
23    /// trampoline generated by Cranelift and is distinct from the array calling
24    /// convention.
25    ///
26    /// This correspond to `VMLoweringCallee`.
27    #[cfg(feature = "component-model")]
28    ComponentLowerImport,
29
30    /// A builtin function, but specifically for components. For example string
31    /// transcoders.
32    #[cfg(feature = "component-model")]
33    ComponentBuiltin(ComponentBuiltinFunctionIndex),
34}
35
36impl HostCall {
37    /// Returns a 32-bit index for this hostcall.
38    pub const fn index(&self) -> u32 {
39        match self {
40            HostCall::ArrayCall => 0,
41            HostCall::Builtin(i) => 1 + i.index(),
42            #[cfg(feature = "component-model")]
43            HostCall::ComponentLowerImport => 1 + BuiltinFunctionIndex::len(),
44            #[cfg(feature = "component-model")]
45            HostCall::ComponentBuiltin(i) => 2 + BuiltinFunctionIndex::len() + i.index(),
46        }
47    }
48
49    /// Create a `HostCall` from the result of an earlier call to
50    /// `HostCall::index`.
51    pub fn from_index(index: u32) -> Self {
52        let host_call = match index {
53            0 => Self::ArrayCall,
54            _ if index < 1 + BuiltinFunctionIndex::len() => {
55                Self::Builtin(BuiltinFunctionIndex::from_u32(index - 1))
56            }
57            #[cfg(feature = "component-model")]
58            _ if index == 1 + BuiltinFunctionIndex::len() => Self::ComponentLowerImport,
59            #[cfg(feature = "component-model")]
60            _ if index < 2 + BuiltinFunctionIndex::len() + ComponentBuiltinFunctionIndex::len() => {
61                Self::ComponentBuiltin(ComponentBuiltinFunctionIndex::from_u32(
62                    index - 2 - BuiltinFunctionIndex::len(),
63                ))
64            }
65            _ => panic!("bad host call index: {index}"),
66        };
67        debug_assert_eq!(index, host_call.index());
68        host_call
69    }
70}
71
72impl From<BuiltinFunctionIndex> for HostCall {
73    fn from(idx: BuiltinFunctionIndex) -> HostCall {
74        HostCall::Builtin(idx)
75    }
76}
77
78#[cfg(feature = "component-model")]
79impl From<ComponentBuiltinFunctionIndex> for HostCall {
80    fn from(idx: ComponentBuiltinFunctionIndex) -> HostCall {
81        HostCall::ComponentBuiltin(idx)
82    }
83}