Skip to main content

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            "context-get-i32-0" => ContextGetI32_0 : context_get_i32_0() -> u32;
27            "context-set-i32-0" => ContextSetI32_0 : context_set_i32_0(val: u32);
28            "context-get-i32-1" => ContextGetI32_1 : context_get_i32_1() -> u32;
29            "context-set-i32-1" => ContextSetI32_1 : context_set_i32_1(val: u32);
30        }
31    };
32}
33
34macro_rules! define_unsafe_intrinsics {
35    (
36        $(
37            $symbol:expr => $variant:ident : $ctor:ident ( $( $param:ident : $param_ty:ident ),* ) $( -> $result_ty:ident )? ;
38        )*
39    ) => {
40        /// An index type for Wasmtime's intrinsics available to compile-time
41        /// builtins.
42        #[repr(u32)]
43        #[derive(Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash, Serialize, Deserialize)]
44        pub enum UnsafeIntrinsic {
45            $(
46                #[doc = concat!("The `", $symbol, "` intrinsic.")]
47                $variant,
48            )*
49        }
50
51        impl UnsafeIntrinsic {
52            /// Returns the total number of unsafe intrinsics.
53            pub const fn len() -> u32 {
54                let mut len = 0;
55                $(
56                    let _ = Self::$variant;
57                    len += 1;
58                )*
59                len
60            }
61
62            /// Construct an `UnsafeIntrinsic` from its `u32` index.
63            ///
64            /// Panics on invalid indices.
65            pub const fn from_u32(i: u32) -> Self {
66                assert!(i < Self::len());
67                $(
68                    if i == Self::$variant.index() {
69                        return Self::$variant;
70                    }
71                )*
72                unreachable!()
73            }
74
75            /// Get this intrinsic's index.
76            pub const fn index(&self) -> u32 {
77                *self as u32
78            }
79
80            /// Get this intrinsic's name.
81            pub const fn name(&self) -> &'static str {
82                match self {
83                    $(
84                        Self::$variant => $symbol,
85                    )*
86                }
87            }
88
89            /// Get this intrinsic's parameters, as core Wasm value types.
90            pub const fn core_params(&self) -> &'static [$crate::WasmValType] {
91                match self {
92                    $(
93                        Self::$variant => &[ $( define_unsafe_intrinsics!(@core_type $param_ty) ),* ],
94                    )*
95                }
96            }
97
98            /// Get this intrinsic's results, as core Wasm value types.
99            pub const fn core_results(&self) -> &'static [$crate::WasmValType] {
100                match self {
101                    $(
102                        Self::$variant => &[ $( define_unsafe_intrinsics!(@core_type $result_ty) )? ],
103                    )*
104                }
105            }
106
107            /// Get this intrinsic's parameters, as component model interface types.
108            pub const fn component_params(&self) -> &'static [$crate::component::InterfaceType] {
109                match self {
110                    $(
111                        Self::$variant => &[ $( define_unsafe_intrinsics!(@component_type $param_ty) ),* ],
112                    )*
113                }
114            }
115
116            /// Get this intrinsic's results, as component model interface types.
117            pub const fn component_results(&self) -> &'static [$crate::component::InterfaceType] {
118                match self {
119                    $(
120                        Self::$variant => &[ $( define_unsafe_intrinsics!(@component_type $result_ty) ),* ],
121                    )*
122                }
123            }
124        }
125
126        impl FromStr for UnsafeIntrinsic {
127            type Err = Error;
128
129            fn from_str(s: &str) -> Result<Self> {
130                match s {
131                    $(
132                        $symbol => Ok(Self::$variant),
133                    )*
134                    _ => bail!("invalid unsafe intrinsic: {s:?}"),
135                }
136            }
137        }
138    };
139
140    (@core_type u8) => { $crate::WasmValType::I32 };
141    (@core_type u16) => { $crate::WasmValType::I32 };
142    (@core_type u32) => { $crate::WasmValType::I32 };
143    (@core_type u64) => { $crate::WasmValType::I64 };
144
145    (@component_type u8) => { $crate::component::InterfaceType::U8 };
146    (@component_type u16) => { $crate::component::InterfaceType::U16 };
147    (@component_type u32) => { $crate::component::InterfaceType::U32 };
148    (@component_type u64) => { $crate::component::InterfaceType::U64 };
149}
150
151for_each_unsafe_intrinsic!(define_unsafe_intrinsics);