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