wasmtime_environ/component/
intrinsic.rs

1//! Wasmtime compile-time intrinsic definitions.
2
3use crate::prelude::*;
4use core::str::FromStr;
5use serde_derive::{Deserialize, Serialize};
6
7/// Invoke a macro for each of our unsafe intrinsics.
8#[macro_export]
9macro_rules! for_each_unsafe_intrinsic {
10    ($mac:ident) => {
11        $mac! {
12            "store-data-address" => StoreDataAddress : store_data_address() -> u64;
13
14            "u8-native-load" => U8NativeLoad : u8_native_load(address: u64) -> u8;
15            "u8-native-store" => U8NativeStore : u8_native_store(address: u64, value: u8);
16
17            "u16-native-load" => U16NativeLoad : u16_native_load(address: u64) -> u16;
18            "u16-native-store" => U16NativeStore : u16_native_store(address: u64, value: u16);
19
20            "u32-native-load" => U32NativeLoad : u32_native_load(address: u64) -> u32;
21            "u32-native-store" => U32NativeStore : u32_native_store(address: u64, value: u32);
22
23            "u64-native-load" => U64NativeLoad : u64_native_load(address: u64) -> u64;
24            "u64-native-store" => U64NativeStore : u64_native_store(address: u64, value: u64);
25        }
26    };
27}
28
29macro_rules! define_unsafe_intrinsics {
30    (
31        $(
32            $symbol:expr => $variant:ident : $ctor:ident ( $( $param:ident : $param_ty:ident ),* ) $( -> $result_ty:ident )? ;
33        )*
34    ) => {
35        /// An index type for Wasmtime's intrinsics available to compile-time
36        /// builtins.
37        #[repr(u32)]
38        #[derive(Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash, Serialize, Deserialize)]
39        pub enum UnsafeIntrinsic {
40            $(
41                #[doc = concat!("The `", $symbol, "` intrinsic.")]
42                $variant,
43            )*
44        }
45
46        impl UnsafeIntrinsic {
47            /// Returns the total number of unsafe intrinsics.
48            pub const fn len() -> u32 {
49                let mut len = 0;
50                $(
51                    let _ = Self::$variant;
52                    len += 1;
53                )*
54                len
55            }
56
57            /// Construct an `UnsafeIntrinsic` from its `u32` index.
58            ///
59            /// Panics on invalid indices.
60            pub const fn from_u32(i: u32) -> Self {
61                assert!(i < Self::len());
62                $(
63                    if i == Self::$variant.index() {
64                        return Self::$variant;
65                    }
66                )*
67                unreachable!()
68            }
69
70            /// Get this intrinsic's index.
71            pub const fn index(&self) -> u32 {
72                *self as u32
73            }
74
75            /// Get this intrinsic's name.
76            pub const fn name(&self) -> &'static str {
77                match self {
78                    $(
79                        Self::$variant => $symbol,
80                    )*
81                }
82            }
83
84            /// Get this intrinsic's parameters, as core Wasm value types.
85            pub const fn core_params(&self) -> &'static [$crate::WasmValType] {
86                match self {
87                    $(
88                        Self::$variant => &[ $( define_unsafe_intrinsics!(@core_type $param_ty) ),* ],
89                    )*
90                }
91            }
92
93            /// Get this intrinsic's results, as core Wasm value types.
94            pub const fn core_results(&self) -> &'static [$crate::WasmValType] {
95                match self {
96                    $(
97                        Self::$variant => &[ $( define_unsafe_intrinsics!(@core_type $result_ty) )? ],
98                    )*
99                }
100            }
101
102            /// Get this intrinsic's parameters, as component model interface types.
103            pub const fn component_params(&self) -> &'static [$crate::component::InterfaceType] {
104                match self {
105                    $(
106                        Self::$variant => &[ $( define_unsafe_intrinsics!(@component_type $param_ty) ),* ],
107                    )*
108                }
109            }
110
111            /// Get this intrinsic's results, as component model interface types.
112            pub const fn component_results(&self) -> &'static [$crate::component::InterfaceType] {
113                match self {
114                    $(
115                        Self::$variant => &[ $( define_unsafe_intrinsics!(@component_type $result_ty) ),* ],
116                    )*
117                }
118            }
119        }
120
121        impl FromStr for UnsafeIntrinsic {
122            type Err = Error;
123
124            fn from_str(s: &str) -> Result<Self> {
125                match s {
126                    $(
127                        $symbol => Ok(Self::$variant),
128                    )*
129                    _ => bail!("invalid unsafe intrinsic: {s:?}"),
130                }
131            }
132        }
133    };
134
135    (@core_type u8) => { $crate::WasmValType::I32 };
136    (@core_type u16) => { $crate::WasmValType::I32 };
137    (@core_type u32) => { $crate::WasmValType::I32 };
138    (@core_type u64) => { $crate::WasmValType::I64 };
139
140    (@component_type u8) => { $crate::component::InterfaceType::U8 };
141    (@component_type u16) => { $crate::component::InterfaceType::U16 };
142    (@component_type u32) => { $crate::component::InterfaceType::U32 };
143    (@component_type u64) => { $crate::component::InterfaceType::U64 };
144}
145
146for_each_unsafe_intrinsic!(define_unsafe_intrinsics);