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