1#[cfg(feature = "component-model")]
5use crate::component;
6use crate::{
7 BuiltinFunctionIndex, DefinedFuncIndex, HostCall, ModuleInternedTypeIndex, StaticModuleIndex,
8};
9use core::{cmp, fmt};
10use serde_derive::{Deserialize, Serialize};
11
12#[repr(u32)]
17#[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
18#[cfg_attr(test, derive(arbitrary::Arbitrary))]
19pub enum FuncKeyKind {
20 DefinedWasmFunction = FuncKey::new_kind(0b000),
22
23 ArrayToWasmTrampoline = FuncKey::new_kind(0b001),
25
26 WasmToArrayTrampoline = FuncKey::new_kind(0b010),
28
29 WasmToBuiltinTrampoline = FuncKey::new_kind(0b011),
31
32 PulleyHostCall = FuncKey::new_kind(0b100),
34
35 #[cfg(feature = "component-model")]
37 ComponentTrampoline = FuncKey::new_kind(0b101),
38
39 #[cfg(feature = "component-model")]
41 ResourceDropTrampoline = FuncKey::new_kind(0b110),
42
43 #[cfg(feature = "component-model")]
45 UnsafeIntrinsic = FuncKey::new_kind(0b111),
46}
47
48impl From<FuncKeyKind> for u32 {
49 fn from(kind: FuncKeyKind) -> Self {
50 kind as u32
51 }
52}
53
54impl FuncKeyKind {
55 pub fn into_raw(self) -> u32 {
57 self.into()
58 }
59
60 pub fn from_raw(raw: u32) -> Self {
64 match raw {
65 x if x == Self::DefinedWasmFunction.into() => Self::DefinedWasmFunction,
66 x if x == Self::ArrayToWasmTrampoline.into() => Self::ArrayToWasmTrampoline,
67 x if x == Self::WasmToArrayTrampoline.into() => Self::WasmToArrayTrampoline,
68 x if x == Self::WasmToBuiltinTrampoline.into() => Self::WasmToBuiltinTrampoline,
69 x if x == Self::PulleyHostCall.into() => Self::PulleyHostCall,
70
71 #[cfg(feature = "component-model")]
72 x if x == Self::ComponentTrampoline.into() => Self::ComponentTrampoline,
73 #[cfg(feature = "component-model")]
74 x if x == Self::ResourceDropTrampoline.into() => Self::ResourceDropTrampoline,
75 #[cfg(feature = "component-model")]
76 x if x == Self::UnsafeIntrinsic.into() => Self::UnsafeIntrinsic,
77
78 _ => panic!("invalid raw value passed to `FuncKind::from_raw`: {raw}"),
79 }
80 }
81}
82
83#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Serialize, Deserialize)]
87pub struct FuncKeyNamespace(u32);
88
89impl fmt::Debug for FuncKeyNamespace {
90 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
91 struct Hex<T: fmt::LowerHex>(T);
92 impl<T: fmt::LowerHex> fmt::Debug for Hex<T> {
93 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
94 write!(f, "{:#x}", self.0)
95 }
96 }
97 f.debug_struct("FuncKeyNamespace")
98 .field("raw", &Hex(self.0))
99 .field("kind", &self.kind())
100 .field("module", &self.module())
101 .finish()
102 }
103}
104
105impl From<FuncKeyNamespace> for u32 {
106 fn from(ns: FuncKeyNamespace) -> Self {
107 ns.0
108 }
109}
110
111impl FuncKeyNamespace {
112 pub fn into_raw(self) -> u32 {
114 self.0
115 }
116
117 pub fn from_raw(raw: u32) -> Self {
121 match FuncKeyKind::from_raw(raw & FuncKey::KIND_MASK) {
122 FuncKeyKind::DefinedWasmFunction | FuncKeyKind::ArrayToWasmTrampoline => Self(raw),
123 FuncKeyKind::WasmToArrayTrampoline
124 | FuncKeyKind::WasmToBuiltinTrampoline
125 | FuncKeyKind::PulleyHostCall => {
126 assert_eq!(raw & FuncKey::MODULE_MASK, 0);
127 Self(raw)
128 }
129
130 #[cfg(feature = "component-model")]
131 FuncKeyKind::ComponentTrampoline => {
132 let _ = Abi::from_raw(raw & FuncKey::MODULE_MASK);
133 Self(raw)
134 }
135
136 #[cfg(feature = "component-model")]
137 FuncKeyKind::ResourceDropTrampoline => {
138 assert_eq!(raw & FuncKey::MODULE_MASK, 0);
139 Self(raw)
140 }
141
142 #[cfg(feature = "component-model")]
143 FuncKeyKind::UnsafeIntrinsic => {
144 let _ = Abi::from_raw(raw & FuncKey::MODULE_MASK);
145 Self(raw)
146 }
147 }
148 }
149
150 pub fn kind(&self) -> FuncKeyKind {
152 let raw = self.0 & FuncKey::KIND_MASK;
153 FuncKeyKind::from_raw(raw)
154 }
155
156 fn module(&self) -> u32 {
157 self.0 & FuncKey::MODULE_MASK
158 }
159}
160
161#[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord, Hash, Serialize, Deserialize)]
163pub struct FuncKeyIndex(u32);
164
165impl From<FuncKeyIndex> for u32 {
166 fn from(index: FuncKeyIndex) -> Self {
167 index.0
168 }
169}
170
171impl FuncKeyIndex {
172 pub fn into_raw(self) -> u32 {
174 self.0
175 }
176
177 pub fn from_raw(raw: u32) -> Self {
183 FuncKeyIndex(raw)
184 }
185}
186
187#[derive(Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
189#[cfg_attr(test, derive(arbitrary::Arbitrary))]
190pub enum Abi {
191 Wasm = 0,
193 Array = 1,
195}
196
197#[cfg(feature = "component-model")]
198impl Abi {
199 fn from_raw(raw: u32) -> Self {
200 match raw {
201 x if x == Self::Wasm.into_raw() => Self::Wasm,
202 x if x == Self::Array.into_raw() => Self::Array,
203 _ => panic!("invalid raw representation passed to `Abi::from_raw`: {raw}"),
204 }
205 }
206
207 fn into_raw(self) -> u32 {
208 (self as u8).into()
209 }
210}
211
212#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
215pub enum FuncKey {
216 DefinedWasmFunction(StaticModuleIndex, DefinedFuncIndex),
218
219 ArrayToWasmTrampoline(StaticModuleIndex, DefinedFuncIndex),
221
222 WasmToArrayTrampoline(ModuleInternedTypeIndex),
224
225 WasmToBuiltinTrampoline(BuiltinFunctionIndex),
227
228 PulleyHostCall(HostCall),
230
231 #[cfg(feature = "component-model")]
233 ComponentTrampoline(Abi, component::TrampolineIndex),
234
235 #[cfg(feature = "component-model")]
237 ResourceDropTrampoline,
238
239 #[cfg(feature = "component-model")]
241 UnsafeIntrinsic(Abi, component::UnsafeIntrinsic),
242}
243
244impl Ord for FuncKey {
245 fn cmp(&self, other: &Self) -> cmp::Ordering {
246 let raw_self = self.into_raw_parts();
249 let raw_other = other.into_raw_parts();
250 raw_self.cmp(&raw_other)
251 }
252}
253
254impl PartialOrd for FuncKey {
255 fn partial_cmp(&self, other: &Self) -> Option<cmp::Ordering> {
256 Some(self.cmp(other))
257 }
258}
259
260impl FuncKey {
261 const KIND_BITS: u32 = 3;
262 const KIND_OFFSET: u32 = 32 - Self::KIND_BITS;
263 const KIND_MASK: u32 = ((1 << Self::KIND_BITS) - 1) << Self::KIND_OFFSET;
264 const MODULE_MASK: u32 = !Self::KIND_MASK;
265
266 const fn new_kind(kind: u32) -> u32 {
267 assert!(kind < (1 << Self::KIND_BITS));
268 kind << Self::KIND_OFFSET
269 }
270
271 #[inline]
273 pub fn into_parts(self) -> (FuncKeyNamespace, FuncKeyIndex) {
274 let (namespace, index) = match self {
275 FuncKey::DefinedWasmFunction(module, def_func) => {
276 assert_eq!(module.as_u32() & Self::KIND_MASK, 0);
277 let namespace = FuncKeyKind::DefinedWasmFunction.into_raw() | module.as_u32();
278 let index = def_func.as_u32();
279 (namespace, index)
280 }
281 FuncKey::ArrayToWasmTrampoline(module, def_func) => {
282 assert_eq!(module.as_u32() & Self::KIND_MASK, 0);
283 let namespace = FuncKeyKind::ArrayToWasmTrampoline.into_raw() | module.as_u32();
284 let index = def_func.as_u32();
285 (namespace, index)
286 }
287 FuncKey::WasmToArrayTrampoline(ty) => {
288 let namespace = FuncKeyKind::WasmToArrayTrampoline.into_raw();
289 let index = ty.as_u32();
290 (namespace, index)
291 }
292 FuncKey::WasmToBuiltinTrampoline(builtin) => {
293 let namespace = FuncKeyKind::WasmToBuiltinTrampoline.into_raw();
294 let index = builtin.index();
295 (namespace, index)
296 }
297 FuncKey::PulleyHostCall(host_call) => {
298 let namespace = FuncKeyKind::PulleyHostCall.into_raw();
299 let index = host_call.index();
300 (namespace, index)
301 }
302
303 #[cfg(feature = "component-model")]
304 FuncKey::ComponentTrampoline(abi, trampoline) => {
305 let abi = abi.into_raw();
306 assert_eq!(abi & Self::KIND_MASK, 0);
307 let namespace = FuncKeyKind::ComponentTrampoline.into_raw() | abi;
308 let index = trampoline.as_u32();
309 (namespace, index)
310 }
311 #[cfg(feature = "component-model")]
312 FuncKey::ResourceDropTrampoline => {
313 let namespace = FuncKeyKind::ResourceDropTrampoline.into_raw();
314 let index = 0;
315 (namespace, index)
316 }
317 #[cfg(feature = "component-model")]
318 FuncKey::UnsafeIntrinsic(abi, intrinsic) => {
319 let abi = abi.into_raw();
320 assert_eq!(abi & Self::KIND_MASK, 0);
321 let namespace = FuncKeyKind::UnsafeIntrinsic.into_raw() | abi;
322 let index = intrinsic.index();
323 (namespace, index)
324 }
325 };
326 (FuncKeyNamespace(namespace), FuncKeyIndex(index))
327 }
328
329 pub fn kind(self) -> FuncKeyKind {
331 self.namespace().kind()
332 }
333
334 pub fn namespace(self) -> FuncKeyNamespace {
336 self.into_parts().0
337 }
338
339 pub fn index(self) -> FuncKeyIndex {
341 self.into_parts().1
342 }
343
344 pub fn abi(self) -> Abi {
346 match self {
347 FuncKey::DefinedWasmFunction(_, _) => Abi::Wasm,
348 FuncKey::ArrayToWasmTrampoline(_, _) => Abi::Array,
349 FuncKey::WasmToArrayTrampoline(_) => Abi::Wasm,
350 FuncKey::WasmToBuiltinTrampoline(_) => Abi::Wasm,
351 FuncKey::PulleyHostCall(_) => Abi::Wasm,
352 #[cfg(feature = "component-model")]
353 FuncKey::ComponentTrampoline(abi, _) => abi,
354 #[cfg(feature = "component-model")]
355 FuncKey::ResourceDropTrampoline => Abi::Wasm,
356 #[cfg(feature = "component-model")]
357 FuncKey::UnsafeIntrinsic(abi, _) => abi,
358 }
359 }
360
361 pub fn into_raw_parts(self) -> (u32, u32) {
371 let (ns, index) = self.into_parts();
372 (ns.into_raw(), index.into_raw())
373 }
374
375 pub fn from_parts(namespace: FuncKeyNamespace, index: FuncKeyIndex) -> Self {
384 Self::from_raw_parts(namespace.into_raw(), index.into_raw())
385 }
386
387 pub fn from_raw_parts(a: u32, b: u32) -> Self {
394 match FuncKeyKind::from_raw(a & Self::KIND_MASK) {
395 FuncKeyKind::DefinedWasmFunction => {
396 let module = StaticModuleIndex::from_u32(a & Self::MODULE_MASK);
397 let def_func = DefinedFuncIndex::from_u32(b);
398 Self::DefinedWasmFunction(module, def_func)
399 }
400 FuncKeyKind::ArrayToWasmTrampoline => {
401 let module = StaticModuleIndex::from_u32(a & Self::MODULE_MASK);
402 let def_func = DefinedFuncIndex::from_u32(b);
403 Self::ArrayToWasmTrampoline(module, def_func)
404 }
405 FuncKeyKind::WasmToArrayTrampoline => {
406 assert_eq!(a & Self::MODULE_MASK, 0);
407 let ty = ModuleInternedTypeIndex::from_u32(b);
408 Self::WasmToArrayTrampoline(ty)
409 }
410 FuncKeyKind::WasmToBuiltinTrampoline => {
411 assert_eq!(a & Self::MODULE_MASK, 0);
412 let builtin = BuiltinFunctionIndex::from_u32(b);
413 Self::WasmToBuiltinTrampoline(builtin)
414 }
415 FuncKeyKind::PulleyHostCall => {
416 assert_eq!(a & Self::MODULE_MASK, 0);
417 let host_call = HostCall::from_index(b);
418 Self::PulleyHostCall(host_call)
419 }
420
421 #[cfg(feature = "component-model")]
422 FuncKeyKind::ComponentTrampoline => {
423 let abi = Abi::from_raw(a & Self::MODULE_MASK);
424 let trampoline = component::TrampolineIndex::from_u32(b);
425 Self::ComponentTrampoline(abi, trampoline)
426 }
427 #[cfg(feature = "component-model")]
428 FuncKeyKind::ResourceDropTrampoline => {
429 assert_eq!(a & Self::MODULE_MASK, 0);
430 assert_eq!(b, 0);
431 Self::ResourceDropTrampoline
432 }
433 #[cfg(feature = "component-model")]
434 FuncKeyKind::UnsafeIntrinsic => {
435 let abi = Abi::from_raw(a & Self::MODULE_MASK);
436 let intrinsic = component::UnsafeIntrinsic::from_u32(b);
437 Self::UnsafeIntrinsic(abi, intrinsic)
438 }
439 }
440 }
441
442 pub fn from_raw_u64(value: u64) -> Self {
448 let hi = u32::try_from(value >> 32).unwrap();
449 let lo = u32::try_from(value & 0xffff_ffff).unwrap();
450 FuncKey::from_raw_parts(hi, lo)
451 }
452
453 pub fn into_raw_u64(&self) -> u64 {
457 let (hi, lo) = self.into_raw_parts();
458 (u64::from(hi) << 32) | u64::from(lo)
459 }
460
461 pub fn unwrap_defined_wasm_function(self) -> (StaticModuleIndex, DefinedFuncIndex) {
463 match self {
464 Self::DefinedWasmFunction(module, def_func) => (module, def_func),
465 _ => panic!("`FuncKey::unwrap_defined_wasm_function` called on {self:?}"),
466 }
467 }
468
469 pub fn unwrap_array_to_wasm_trampoline(self) -> (StaticModuleIndex, DefinedFuncIndex) {
471 match self {
472 Self::ArrayToWasmTrampoline(module, def_func) => (module, def_func),
473 _ => panic!("`FuncKey::unwrap_array_to_wasm_trampoline` called on {self:?}"),
474 }
475 }
476
477 pub fn unwrap_wasm_to_array_trampoline(self) -> ModuleInternedTypeIndex {
479 match self {
480 Self::WasmToArrayTrampoline(ty) => ty,
481 _ => panic!("`FuncKey::unwrap_wasm_to_array_trampoline` called on {self:?}"),
482 }
483 }
484
485 pub fn unwrap_wasm_to_builtin_trampoline(self) -> BuiltinFunctionIndex {
487 match self {
488 Self::WasmToBuiltinTrampoline(builtin) => builtin,
489 _ => panic!("`FuncKey::unwrap_wasm_to_builtin_trampoline` called on {self:?}"),
490 }
491 }
492
493 pub fn unwrap_pulley_host_call(self) -> HostCall {
495 match self {
496 Self::PulleyHostCall(host_call) => host_call,
497 _ => panic!("`FuncKey::unwrap_pulley_host_call` called on {self:?}"),
498 }
499 }
500
501 #[cfg(feature = "component-model")]
503 pub fn unwrap_component_trampoline(self) -> (crate::Abi, component::TrampolineIndex) {
504 match self {
505 Self::ComponentTrampoline(abi, trampoline) => (abi, trampoline),
506 _ => panic!("`FuncKey::unwrap_component_trampoline` called on {self:?}"),
507 }
508 }
509
510 #[cfg(feature = "component-model")]
512 pub fn unwrap_resource_drop_trampoline(self) {
513 match self {
514 Self::ResourceDropTrampoline => {}
515 _ => panic!("`FuncKey::unwrap_resource_drop_trampoline` called on {self:?}"),
516 }
517 }
518}