1 use crate::BuiltinFunctionIndex; 2 #[cfg(feature = "component-model")] 3 use 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))] 13 pub 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 36 impl HostCall { 37 /// Returns a 32-bit index for this hostcall. index(&self) -> u3238 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`. from_index(index: u32) -> Self51 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 72 impl From<BuiltinFunctionIndex> for HostCall { from(idx: BuiltinFunctionIndex) -> HostCall73 fn from(idx: BuiltinFunctionIndex) -> HostCall { 74 HostCall::Builtin(idx) 75 } 76 } 77 78 #[cfg(feature = "component-model")] 79 impl From<ComponentBuiltinFunctionIndex> for HostCall { from(idx: ComponentBuiltinFunctionIndex) -> HostCall80 fn from(idx: ComponentBuiltinFunctionIndex) -> HostCall { 81 HostCall::ComponentBuiltin(idx) 82 } 83 } 84