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(0b0000),
22
23 ArrayToWasmTrampoline = FuncKey::new_kind(0b0001),
25
26 WasmToArrayTrampoline = FuncKey::new_kind(0b0010),
28
29 WasmToBuiltinTrampoline = FuncKey::new_kind(0b0011),
31
32 PatchableToBuiltinTrampoline = FuncKey::new_kind(0b0100),
34
35 PulleyHostCall = FuncKey::new_kind(0b0101),
37
38 #[cfg(feature = "component-model")]
40 ComponentTrampoline = FuncKey::new_kind(0b0110),
41
42 #[cfg(feature = "component-model")]
44 ResourceDropTrampoline = FuncKey::new_kind(0b0111),
45
46 #[cfg(feature = "component-model")]
48 UnsafeIntrinsic = FuncKey::new_kind(0b1000),
49}
50
51impl From<FuncKeyKind> for u32 {
52 fn from(kind: FuncKeyKind) -> Self {
53 kind as u32
54 }
55}
56
57impl FuncKeyKind {
58 pub fn into_raw(self) -> u32 {
60 self.into()
61 }
62
63 pub fn from_raw(raw: u32) -> Self {
67 match raw {
68 x if x == Self::DefinedWasmFunction.into() => Self::DefinedWasmFunction,
69 x if x == Self::ArrayToWasmTrampoline.into() => Self::ArrayToWasmTrampoline,
70 x if x == Self::WasmToArrayTrampoline.into() => Self::WasmToArrayTrampoline,
71 x if x == Self::WasmToBuiltinTrampoline.into() => Self::WasmToBuiltinTrampoline,
72 x if x == Self::PatchableToBuiltinTrampoline.into() => {
73 Self::PatchableToBuiltinTrampoline
74 }
75 x if x == Self::PulleyHostCall.into() => Self::PulleyHostCall,
76
77 #[cfg(feature = "component-model")]
78 x if x == Self::ComponentTrampoline.into() => Self::ComponentTrampoline,
79 #[cfg(feature = "component-model")]
80 x if x == Self::ResourceDropTrampoline.into() => Self::ResourceDropTrampoline,
81 #[cfg(feature = "component-model")]
82 x if x == Self::UnsafeIntrinsic.into() => Self::UnsafeIntrinsic,
83
84 _ => panic!("invalid raw value passed to `FuncKind::from_raw`: {raw}"),
85 }
86 }
87}
88
89#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Serialize, Deserialize)]
93pub struct FuncKeyNamespace(u32);
94
95impl fmt::Debug for FuncKeyNamespace {
96 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
97 struct Hex<T: fmt::LowerHex>(T);
98 impl<T: fmt::LowerHex> fmt::Debug for Hex<T> {
99 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
100 write!(f, "{:#x}", self.0)
101 }
102 }
103 f.debug_struct("FuncKeyNamespace")
104 .field("raw", &Hex(self.0))
105 .field("kind", &self.kind())
106 .field("module", &self.module())
107 .finish()
108 }
109}
110
111impl From<FuncKeyNamespace> for u32 {
112 fn from(ns: FuncKeyNamespace) -> Self {
113 ns.0
114 }
115}
116
117impl FuncKeyNamespace {
118 pub fn into_raw(self) -> u32 {
120 self.0
121 }
122
123 pub fn from_raw(raw: u32) -> Self {
127 match FuncKeyKind::from_raw(raw & FuncKey::KIND_MASK) {
128 FuncKeyKind::DefinedWasmFunction | FuncKeyKind::ArrayToWasmTrampoline => Self(raw),
129 FuncKeyKind::WasmToArrayTrampoline
130 | FuncKeyKind::WasmToBuiltinTrampoline
131 | FuncKeyKind::PatchableToBuiltinTrampoline
132 | FuncKeyKind::PulleyHostCall => {
133 assert_eq!(raw & FuncKey::MODULE_MASK, 0);
134 Self(raw)
135 }
136
137 #[cfg(feature = "component-model")]
138 FuncKeyKind::ComponentTrampoline => {
139 let _ = Abi::from_raw(raw & FuncKey::MODULE_MASK);
140 Self(raw)
141 }
142
143 #[cfg(feature = "component-model")]
144 FuncKeyKind::ResourceDropTrampoline => {
145 assert_eq!(raw & FuncKey::MODULE_MASK, 0);
146 Self(raw)
147 }
148
149 #[cfg(feature = "component-model")]
150 FuncKeyKind::UnsafeIntrinsic => {
151 let _ = Abi::from_raw(raw & FuncKey::MODULE_MASK);
152 Self(raw)
153 }
154 }
155 }
156
157 pub fn kind(&self) -> FuncKeyKind {
159 let raw = self.0 & FuncKey::KIND_MASK;
160 FuncKeyKind::from_raw(raw)
161 }
162
163 fn module(&self) -> u32 {
164 self.0 & FuncKey::MODULE_MASK
165 }
166}
167
168#[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord, Hash, Serialize, Deserialize)]
170pub struct FuncKeyIndex(u32);
171
172impl From<FuncKeyIndex> for u32 {
173 fn from(index: FuncKeyIndex) -> Self {
174 index.0
175 }
176}
177
178impl FuncKeyIndex {
179 pub fn into_raw(self) -> u32 {
181 self.0
182 }
183
184 pub fn from_raw(raw: u32) -> Self {
190 FuncKeyIndex(raw)
191 }
192}
193
194#[derive(Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
196#[cfg_attr(test, derive(arbitrary::Arbitrary))]
197pub enum Abi {
198 Wasm = 0,
200 Array = 1,
202 Patchable = 2,
206}
207
208#[cfg(feature = "component-model")]
209impl Abi {
210 fn from_raw(raw: u32) -> Self {
211 match raw {
212 x if x == Self::Wasm.into_raw() => Self::Wasm,
213 x if x == Self::Array.into_raw() => Self::Array,
214 x if x == Self::Patchable.into_raw() => Self::Patchable,
215 _ => panic!("invalid raw representation passed to `Abi::from_raw`: {raw}"),
216 }
217 }
218
219 fn into_raw(self) -> u32 {
220 (self as u8).into()
221 }
222}
223
224#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
227pub enum FuncKey {
228 DefinedWasmFunction(StaticModuleIndex, DefinedFuncIndex),
230
231 ArrayToWasmTrampoline(StaticModuleIndex, DefinedFuncIndex),
233
234 WasmToArrayTrampoline(ModuleInternedTypeIndex),
236
237 WasmToBuiltinTrampoline(BuiltinFunctionIndex),
239
240 PulleyHostCall(HostCall),
242
243 PatchableToBuiltinTrampoline(BuiltinFunctionIndex),
245
246 #[cfg(feature = "component-model")]
248 ComponentTrampoline(Abi, component::TrampolineIndex),
249
250 #[cfg(feature = "component-model")]
252 ResourceDropTrampoline,
253
254 #[cfg(feature = "component-model")]
256 UnsafeIntrinsic(Abi, component::UnsafeIntrinsic),
257}
258
259impl Ord for FuncKey {
260 fn cmp(&self, other: &Self) -> cmp::Ordering {
261 let raw_self = self.into_raw_parts();
264 let raw_other = other.into_raw_parts();
265 raw_self.cmp(&raw_other)
266 }
267}
268
269impl PartialOrd for FuncKey {
270 fn partial_cmp(&self, other: &Self) -> Option<cmp::Ordering> {
271 Some(self.cmp(other))
272 }
273}
274
275impl FuncKey {
276 const KIND_BITS: u32 = 4;
277 const KIND_OFFSET: u32 = 32 - Self::KIND_BITS;
278 const KIND_MASK: u32 = ((1 << Self::KIND_BITS) - 1) << Self::KIND_OFFSET;
279 const MODULE_MASK: u32 = !Self::KIND_MASK;
280
281 const fn new_kind(kind: u32) -> u32 {
282 assert!(kind < (1 << Self::KIND_BITS));
283 kind << Self::KIND_OFFSET
284 }
285
286 #[inline]
288 pub fn into_parts(self) -> (FuncKeyNamespace, FuncKeyIndex) {
289 let (namespace, index) = match self {
290 FuncKey::DefinedWasmFunction(module, def_func) => {
291 assert_eq!(module.as_u32() & Self::KIND_MASK, 0);
292 let namespace = FuncKeyKind::DefinedWasmFunction.into_raw() | module.as_u32();
293 let index = def_func.as_u32();
294 (namespace, index)
295 }
296 FuncKey::ArrayToWasmTrampoline(module, def_func) => {
297 assert_eq!(module.as_u32() & Self::KIND_MASK, 0);
298 let namespace = FuncKeyKind::ArrayToWasmTrampoline.into_raw() | module.as_u32();
299 let index = def_func.as_u32();
300 (namespace, index)
301 }
302 FuncKey::WasmToArrayTrampoline(ty) => {
303 let namespace = FuncKeyKind::WasmToArrayTrampoline.into_raw();
304 let index = ty.as_u32();
305 (namespace, index)
306 }
307 FuncKey::WasmToBuiltinTrampoline(builtin) => {
308 let namespace = FuncKeyKind::WasmToBuiltinTrampoline.into_raw();
309 let index = builtin.index();
310 (namespace, index)
311 }
312 FuncKey::PatchableToBuiltinTrampoline(builtin) => {
313 let namespace = FuncKeyKind::PatchableToBuiltinTrampoline.into_raw();
314 let index = builtin.index();
315 (namespace, index)
316 }
317 FuncKey::PulleyHostCall(host_call) => {
318 let namespace = FuncKeyKind::PulleyHostCall.into_raw();
319 let index = host_call.index();
320 (namespace, index)
321 }
322
323 #[cfg(feature = "component-model")]
324 FuncKey::ComponentTrampoline(abi, trampoline) => {
325 let abi = abi.into_raw();
326 assert_eq!(abi & Self::KIND_MASK, 0);
327 let namespace = FuncKeyKind::ComponentTrampoline.into_raw() | abi;
328 let index = trampoline.as_u32();
329 (namespace, index)
330 }
331 #[cfg(feature = "component-model")]
332 FuncKey::ResourceDropTrampoline => {
333 let namespace = FuncKeyKind::ResourceDropTrampoline.into_raw();
334 let index = 0;
335 (namespace, index)
336 }
337 #[cfg(feature = "component-model")]
338 FuncKey::UnsafeIntrinsic(abi, intrinsic) => {
339 let abi = abi.into_raw();
340 assert_eq!(abi & Self::KIND_MASK, 0);
341 let namespace = FuncKeyKind::UnsafeIntrinsic.into_raw() | abi;
342 let index = intrinsic.index();
343 (namespace, index)
344 }
345 };
346 (FuncKeyNamespace(namespace), FuncKeyIndex(index))
347 }
348
349 pub fn kind(self) -> FuncKeyKind {
351 self.namespace().kind()
352 }
353
354 pub fn namespace(self) -> FuncKeyNamespace {
356 self.into_parts().0
357 }
358
359 pub fn index(self) -> FuncKeyIndex {
361 self.into_parts().1
362 }
363
364 pub fn abi(self) -> Abi {
366 match self {
367 FuncKey::DefinedWasmFunction(_, _) => Abi::Wasm,
368 FuncKey::ArrayToWasmTrampoline(_, _) => Abi::Array,
369 FuncKey::WasmToArrayTrampoline(_) => Abi::Wasm,
370 FuncKey::WasmToBuiltinTrampoline(_) => Abi::Wasm,
371 FuncKey::PatchableToBuiltinTrampoline(_) => Abi::Patchable,
372 FuncKey::PulleyHostCall(_) => Abi::Wasm,
373 #[cfg(feature = "component-model")]
374 FuncKey::ComponentTrampoline(abi, _) => abi,
375 #[cfg(feature = "component-model")]
376 FuncKey::ResourceDropTrampoline => Abi::Wasm,
377 #[cfg(feature = "component-model")]
378 FuncKey::UnsafeIntrinsic(abi, _) => abi,
379 }
380 }
381
382 pub fn into_raw_parts(self) -> (u32, u32) {
392 let (ns, index) = self.into_parts();
393 (ns.into_raw(), index.into_raw())
394 }
395
396 pub fn from_parts(namespace: FuncKeyNamespace, index: FuncKeyIndex) -> Self {
405 Self::from_raw_parts(namespace.into_raw(), index.into_raw())
406 }
407
408 pub fn from_raw_parts(a: u32, b: u32) -> Self {
415 match FuncKeyKind::from_raw(a & Self::KIND_MASK) {
416 FuncKeyKind::DefinedWasmFunction => {
417 let module = StaticModuleIndex::from_u32(a & Self::MODULE_MASK);
418 let def_func = DefinedFuncIndex::from_u32(b);
419 Self::DefinedWasmFunction(module, def_func)
420 }
421 FuncKeyKind::ArrayToWasmTrampoline => {
422 let module = StaticModuleIndex::from_u32(a & Self::MODULE_MASK);
423 let def_func = DefinedFuncIndex::from_u32(b);
424 Self::ArrayToWasmTrampoline(module, def_func)
425 }
426 FuncKeyKind::WasmToArrayTrampoline => {
427 assert_eq!(a & Self::MODULE_MASK, 0);
428 let ty = ModuleInternedTypeIndex::from_u32(b);
429 Self::WasmToArrayTrampoline(ty)
430 }
431 FuncKeyKind::WasmToBuiltinTrampoline => {
432 assert_eq!(a & Self::MODULE_MASK, 0);
433 let builtin = BuiltinFunctionIndex::from_u32(b);
434 Self::WasmToBuiltinTrampoline(builtin)
435 }
436 FuncKeyKind::PatchableToBuiltinTrampoline => {
437 assert_eq!(a & Self::MODULE_MASK, 0);
438 let builtin = BuiltinFunctionIndex::from_u32(b);
439 Self::PatchableToBuiltinTrampoline(builtin)
440 }
441 FuncKeyKind::PulleyHostCall => {
442 assert_eq!(a & Self::MODULE_MASK, 0);
443 let host_call = HostCall::from_index(b);
444 Self::PulleyHostCall(host_call)
445 }
446
447 #[cfg(feature = "component-model")]
448 FuncKeyKind::ComponentTrampoline => {
449 let abi = Abi::from_raw(a & Self::MODULE_MASK);
450 let trampoline = component::TrampolineIndex::from_u32(b);
451 Self::ComponentTrampoline(abi, trampoline)
452 }
453 #[cfg(feature = "component-model")]
454 FuncKeyKind::ResourceDropTrampoline => {
455 assert_eq!(a & Self::MODULE_MASK, 0);
456 assert_eq!(b, 0);
457 Self::ResourceDropTrampoline
458 }
459 #[cfg(feature = "component-model")]
460 FuncKeyKind::UnsafeIntrinsic => {
461 let abi = Abi::from_raw(a & Self::MODULE_MASK);
462 let intrinsic = component::UnsafeIntrinsic::from_u32(b);
463 Self::UnsafeIntrinsic(abi, intrinsic)
464 }
465 }
466 }
467
468 pub fn from_raw_u64(value: u64) -> Self {
474 let hi = u32::try_from(value >> 32).unwrap();
475 let lo = u32::try_from(value & 0xffff_ffff).unwrap();
476 FuncKey::from_raw_parts(hi, lo)
477 }
478
479 pub fn into_raw_u64(&self) -> u64 {
483 let (hi, lo) = self.into_raw_parts();
484 (u64::from(hi) << 32) | u64::from(lo)
485 }
486
487 pub fn unwrap_defined_wasm_function(self) -> (StaticModuleIndex, DefinedFuncIndex) {
489 match self {
490 Self::DefinedWasmFunction(module, def_func) => (module, def_func),
491 _ => panic!("`FuncKey::unwrap_defined_wasm_function` called on {self:?}"),
492 }
493 }
494
495 pub fn unwrap_array_to_wasm_trampoline(self) -> (StaticModuleIndex, DefinedFuncIndex) {
497 match self {
498 Self::ArrayToWasmTrampoline(module, def_func) => (module, def_func),
499 _ => panic!("`FuncKey::unwrap_array_to_wasm_trampoline` called on {self:?}"),
500 }
501 }
502
503 pub fn unwrap_wasm_to_array_trampoline(self) -> ModuleInternedTypeIndex {
505 match self {
506 Self::WasmToArrayTrampoline(ty) => ty,
507 _ => panic!("`FuncKey::unwrap_wasm_to_array_trampoline` called on {self:?}"),
508 }
509 }
510
511 pub fn unwrap_wasm_to_builtin_trampoline(self) -> BuiltinFunctionIndex {
513 match self {
514 Self::WasmToBuiltinTrampoline(builtin) => builtin,
515 _ => panic!("`FuncKey::unwrap_wasm_to_builtin_trampoline` called on {self:?}"),
516 }
517 }
518
519 pub fn unwrap_pulley_host_call(self) -> HostCall {
521 match self {
522 Self::PulleyHostCall(host_call) => host_call,
523 _ => panic!("`FuncKey::unwrap_pulley_host_call` called on {self:?}"),
524 }
525 }
526
527 #[cfg(feature = "component-model")]
529 pub fn unwrap_component_trampoline(self) -> (crate::Abi, component::TrampolineIndex) {
530 match self {
531 Self::ComponentTrampoline(abi, trampoline) => (abi, trampoline),
532 _ => panic!("`FuncKey::unwrap_component_trampoline` called on {self:?}"),
533 }
534 }
535
536 #[cfg(feature = "component-model")]
538 pub fn unwrap_resource_drop_trampoline(self) {
539 match self {
540 Self::ResourceDropTrampoline => {}
541 _ => panic!("`FuncKey::unwrap_resource_drop_trampoline` called on {self:?}"),
542 }
543 }
544
545 pub fn is_store_invariant(&self) -> bool {
558 match self {
559 Self::DefinedWasmFunction(..) | Self::ArrayToWasmTrampoline(..) => false,
560 Self::WasmToArrayTrampoline(..)
561 | Self::WasmToBuiltinTrampoline(..)
562 | Self::PatchableToBuiltinTrampoline(..)
563 | Self::PulleyHostCall(..) => true,
564 #[cfg(feature = "component-model")]
565 Self::ComponentTrampoline(..)
566 | Self::ResourceDropTrampoline
567 | Self::UnsafeIntrinsic(..) => true,
568 }
569 }
570}