Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
bytecodealliance
GitHub Repository: bytecodealliance/wasmtime
Path: blob/main/crates/environ/src/key.rs
3054 views
1
//! Keys for identifying functions during compilation, in call graphs, and when
2
//! resolving relocations.
3
4
#[cfg(feature = "component-model")]
5
use crate::component;
6
use crate::{
7
BuiltinFunctionIndex, DefinedFuncIndex, HostCall, ModuleInternedTypeIndex, StaticModuleIndex,
8
};
9
use core::{cmp, fmt};
10
use serde_derive::{Deserialize, Serialize};
11
12
/// The kind of a function that is being compiled, linked, or otherwise
13
/// referenced.
14
///
15
/// This is like a `FuncKey` but without any payload values.
16
#[repr(u32)]
17
#[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
18
#[cfg_attr(test, derive(arbitrary::Arbitrary))]
19
pub enum FuncKeyKind {
20
/// A Wasm-defined function.
21
DefinedWasmFunction = FuncKey::new_kind(0b0000),
22
23
/// A trampoline from an array-caller to the given Wasm-callee.
24
ArrayToWasmTrampoline = FuncKey::new_kind(0b0001),
25
26
/// A trampoline from a Wasm-caller to an array-callee of the given type.
27
WasmToArrayTrampoline = FuncKey::new_kind(0b0010),
28
29
/// A trampoline from a Wasm-caller to the given builtin.
30
WasmToBuiltinTrampoline = FuncKey::new_kind(0b0011),
31
32
/// A trampoline from the patchable ABI to the given builtin.
33
PatchableToBuiltinTrampoline = FuncKey::new_kind(0b0100),
34
35
/// A Pulley-specific host call.
36
PulleyHostCall = FuncKey::new_kind(0b0101),
37
38
/// A Wasm-caller to component builtin trampoline.
39
#[cfg(feature = "component-model")]
40
ComponentTrampoline = FuncKey::new_kind(0b0110),
41
42
/// A Wasm-caller to array-callee `resource.drop` trampoline.
43
#[cfg(feature = "component-model")]
44
ResourceDropTrampoline = FuncKey::new_kind(0b0111),
45
46
/// A Wasmtime unsafe intrinsic function.
47
#[cfg(feature = "component-model")]
48
UnsafeIntrinsic = FuncKey::new_kind(0b1000),
49
}
50
51
impl From<FuncKeyKind> for u32 {
52
fn from(kind: FuncKeyKind) -> Self {
53
kind as u32
54
}
55
}
56
57
impl FuncKeyKind {
58
/// Get this kind's raw representation.
59
pub fn into_raw(self) -> u32 {
60
self.into()
61
}
62
63
/// Construct a `FuncKind` from its raw representation.
64
///
65
/// Panics when given invalid raw representations.
66
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
/// The namespace half of a `FuncKey`.
90
///
91
/// This is an opaque combination of the key's kind and module index, if any.
92
#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Serialize, Deserialize)]
93
pub struct FuncKeyNamespace(u32);
94
95
impl 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
111
impl From<FuncKeyNamespace> for u32 {
112
fn from(ns: FuncKeyNamespace) -> Self {
113
ns.0
114
}
115
}
116
117
impl FuncKeyNamespace {
118
/// Get this `FuncNamespace`'s raw representation.
119
pub fn into_raw(self) -> u32 {
120
self.0
121
}
122
123
/// Construct a `FuncNamespace` from its raw representation.
124
///
125
/// Panics when given invalid raw representations.
126
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
/// Get this `FuncNamespace`'s kind.
158
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
/// The index half of a `FuncKey`.
169
#[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord, Hash, Serialize, Deserialize)]
170
pub struct FuncKeyIndex(u32);
171
172
impl From<FuncKeyIndex> for u32 {
173
fn from(index: FuncKeyIndex) -> Self {
174
index.0
175
}
176
}
177
178
impl FuncKeyIndex {
179
/// Get this index's raw representation.
180
pub fn into_raw(self) -> u32 {
181
self.0
182
}
183
184
/// Construct a `FuncKeyIndex` from its raw representation.
185
///
186
/// Invalid raw representations will not be caught eagerly, but will cause
187
/// panics when paired with a `FuncKeyNamespace` to create a whole
188
/// `FuncKey`.
189
pub fn from_raw(raw: u32) -> Self {
190
FuncKeyIndex(raw)
191
}
192
}
193
194
/// ABI signature of functions that are generated here.
195
#[derive(Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
196
#[cfg_attr(test, derive(arbitrary::Arbitrary))]
197
pub enum Abi {
198
/// The "wasm" ABI, or suitable to be a `wasm_call` field of a `VMFuncRef`.
199
Wasm = 0,
200
/// The "array" ABI, or suitable to be an `array_call` field.
201
Array = 1,
202
/// The "patchable" ABI. Signature same as Wasm ABI, but
203
/// Cranelift-level (machine-level) ABI is different (no
204
/// clobbers).
205
Patchable = 2,
206
}
207
208
#[cfg(feature = "component-model")]
209
impl 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
/// A sortable, comparable function key for compilation output, call graph
225
/// edges, and relocations.
226
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
227
pub enum FuncKey {
228
/// A Wasm-defined function.
229
DefinedWasmFunction(StaticModuleIndex, DefinedFuncIndex),
230
231
/// A trampoline from an array-caller to the given Wasm-callee.
232
ArrayToWasmTrampoline(StaticModuleIndex, DefinedFuncIndex),
233
234
/// A trampoline from a Wasm-caller to an array-callee of the given type.
235
WasmToArrayTrampoline(ModuleInternedTypeIndex),
236
237
/// A trampoline from a Wasm-caller to the given builtin.
238
WasmToBuiltinTrampoline(BuiltinFunctionIndex),
239
240
/// A Pulley-specific host call.
241
PulleyHostCall(HostCall),
242
243
/// A trampoline from the patchable ABI to the given builtin.
244
PatchableToBuiltinTrampoline(BuiltinFunctionIndex),
245
246
/// A Wasm-caller to component builtin trampoline.
247
#[cfg(feature = "component-model")]
248
ComponentTrampoline(Abi, component::TrampolineIndex),
249
250
/// A Wasm-caller to array-callee `resource.drop` trampoline.
251
#[cfg(feature = "component-model")]
252
ResourceDropTrampoline,
253
254
/// A Wasmtime intrinsic function.
255
#[cfg(feature = "component-model")]
256
UnsafeIntrinsic(Abi, component::UnsafeIntrinsic),
257
}
258
259
impl Ord for FuncKey {
260
fn cmp(&self, other: &Self) -> cmp::Ordering {
261
// Make sure to sort by our raw parts, because `CompiledFunctionsTable`
262
// relies on this for its binary search tables.
263
let raw_self = self.into_raw_parts();
264
let raw_other = other.into_raw_parts();
265
raw_self.cmp(&raw_other)
266
}
267
}
268
269
impl PartialOrd for FuncKey {
270
fn partial_cmp(&self, other: &Self) -> Option<cmp::Ordering> {
271
Some(self.cmp(other))
272
}
273
}
274
275
impl 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
/// Split this key into its namespace and index halves.
287
#[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
/// Get this key's kind.
350
pub fn kind(self) -> FuncKeyKind {
351
self.namespace().kind()
352
}
353
354
/// Get this key's namespace.
355
pub fn namespace(self) -> FuncKeyNamespace {
356
self.into_parts().0
357
}
358
359
/// Get this key's index.
360
pub fn index(self) -> FuncKeyIndex {
361
self.into_parts().1
362
}
363
364
/// Get ABI of the function that this key is defining.
365
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
/// Get the raw, underlying `(namespace, index)` representation of this
383
/// compilation key.
384
///
385
/// The resulting values should only be used for (eventually) calling
386
/// `FuncKey::from_raw_parts` or `FuncKey{Namespace,Index}::from_raw`.
387
//
388
// NB: We use two `u32`s to exactly match
389
// `cranelift_codegen::ir::UserExternalName` and ensure that we can map
390
// one-to-one between that and `FuncKey`.
391
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
/// Create a key from its namespace and index parts.
397
///
398
/// Should only be called with namespaces and indices that are ultimately
399
/// derived from the same key. For example, if you attempt to pair an index
400
/// and namespace that come from different keys, that may panic. If it
401
/// happens not to panic, you'll end up with a valid key that names an
402
/// arbitrary function in the given namespace, but that function probably
403
/// does not actually exist in the compilation artifact.
404
pub fn from_parts(namespace: FuncKeyNamespace, index: FuncKeyIndex) -> Self {
405
Self::from_raw_parts(namespace.into_raw(), index.into_raw())
406
}
407
408
/// Create a key from its raw, underlying representation.
409
///
410
/// Should only be given the results of a previous call to
411
/// `FuncKey::into_raw_parts`.
412
///
413
/// Panics when given invalid raw parts.
414
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
/// Create a key from a raw packed `u64` representation.
469
///
470
/// Should only be given a value produced by `into_raw_u64()`.
471
///
472
/// Panics when given an invalid value.
473
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
/// Produce a packed `u64` representation of this key.
480
///
481
/// May be used with `from_raw_64()` to reconstruct this key.
482
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
/// Unwrap a `FuncKey::DefinedWasmFunction` or else panic.
488
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
/// Unwrap a `FuncKey::ArrayToWasmTrampoline` or else panic.
496
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
/// Unwrap a `FuncKey::WasmToArrayTrampoline` or else panic.
504
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
/// Unwrap a `FuncKey::WasmToBuiltinTrampoline` or else panic.
512
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
/// Unwrap a `FuncKey::PulleyHostCall` or else panic.
520
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
/// Unwrap a `FuncKey::ComponentTrampoline` or else panic.
528
#[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
/// Unwrap a `FuncKey::ResourceDropTrampoline` or else panic.
537
#[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
/// Is this "Store-invariant"? This allows us to execute
546
/// EngineCode directly rather than StoreCode.
547
///
548
/// Any function that is either directly from Wasm code, or calls
549
/// it directly (not indirected through a runtime-provided
550
/// function pointer), is "store-variant": we need to use a
551
/// StoreCode-specific version of the code to hit any patching
552
/// that our specific instantiations may have (due to debugging
553
/// breakpoints, etc). Trampolines into the runtime cannot be
554
/// patched and so can use EngineCode instead. This allows for
555
/// less complex plumbing in some places where we can avoid
556
/// looking up the StoreCode (or having access to the Store).
557
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
}
571
572