1use crate::component::*;
31use crate::prelude::*;
32use crate::{EntityIndex, EntityRef, ModuleInternedTypeIndex, PrimaryMap, WasmValType};
33use anyhow::Result;
34use indexmap::IndexMap;
35use std::collections::HashMap;
36use std::hash::Hash;
37use std::ops::Index;
38use wasmparser::component_types::ComponentCoreModuleTypeId;
39
40#[derive(Default)]
42pub struct ComponentDfg {
43 pub import_types: PrimaryMap<ImportIndex, (String, TypeDef)>,
45
46 pub imports: PrimaryMap<RuntimeImportIndex, (ImportIndex, Vec<String>)>,
48
49 pub exports: IndexMap<String, Export>,
51
52 pub trampolines: Intern<TrampolineIndex, (ModuleInternedTypeIndex, Trampoline)>,
55
56 pub reallocs: Intern<ReallocId, CoreDef>,
59
60 pub callbacks: Intern<CallbackId, CoreDef>,
62
63 pub post_returns: Intern<PostReturnId, CoreDef>,
65
66 pub memories: Intern<MemoryId, CoreExport<MemoryIndex>>,
68
69 pub adapters: Intern<AdapterId, Adapter>,
75
76 pub instances: PrimaryMap<InstanceId, Instance>,
83
84 pub num_runtime_component_instances: u32,
87
88 pub adapter_modules: PrimaryMap<AdapterModuleId, (StaticModuleIndex, Vec<CoreDef>)>,
98
99 pub adapter_partitionings: PrimaryMap<AdapterId, (AdapterModuleId, EntityIndex)>,
110
111 pub resources: PrimaryMap<DefinedResourceIndex, Resource>,
117
118 pub imported_resources: PrimaryMap<ResourceIndex, RuntimeImportIndex>,
122
123 pub num_future_tables: usize,
125
126 pub num_stream_tables: usize,
128
129 pub num_error_context_tables: usize,
132
133 pub side_effects: Vec<SideEffect>,
140}
141
142pub enum SideEffect {
144 Instance(InstanceId),
151
152 Resource(DefinedResourceIndex),
159}
160
161macro_rules! id {
162 ($(pub struct $name:ident(u32);)*) => ($(
163 #[derive(Debug, Copy, Clone, Hash, Eq, PartialEq)]
164 #[expect(missing_docs, reason = "tedious to document")]
165 pub struct $name(u32);
166 cranelift_entity::entity_impl!($name);
167 )*)
168}
169
170id! {
171 pub struct InstanceId(u32);
172 pub struct MemoryId(u32);
173 pub struct TableId(u32);
174 pub struct ReallocId(u32);
175 pub struct CallbackId(u32);
176 pub struct AdapterId(u32);
177 pub struct PostReturnId(u32);
178 pub struct AdapterModuleId(u32);
179}
180
181#[expect(missing_docs, reason = "tedious to document variants")]
183pub enum Instance {
184 Static(StaticModuleIndex, Box<[CoreDef]>),
185 Import(
186 RuntimeImportIndex,
187 IndexMap<String, IndexMap<String, CoreDef>>,
188 ),
189}
190
191#[expect(missing_docs, reason = "tedious to document variants")]
193pub enum Export {
194 LiftedFunction {
195 ty: TypeFuncIndex,
196 func: CoreDef,
197 options: CanonicalOptions,
198 },
199 ModuleStatic {
200 ty: ComponentCoreModuleTypeId,
201 index: StaticModuleIndex,
202 },
203 ModuleImport {
204 ty: TypeModuleIndex,
205 import: RuntimeImportIndex,
206 },
207 Instance {
208 ty: TypeComponentInstanceIndex,
209 exports: IndexMap<String, Export>,
210 },
211 Type(TypeDef),
212}
213
214#[derive(Debug, Clone, Hash, Eq, PartialEq)]
216#[expect(missing_docs, reason = "tedious to document variants")]
217pub enum CoreDef {
218 Export(CoreExport<EntityIndex>),
219 InstanceFlags(RuntimeComponentInstanceIndex),
220 Trampoline(TrampolineIndex),
221 Adapter(AdapterId),
230}
231
232impl<T> From<CoreExport<T>> for CoreDef
233where
234 EntityIndex: From<T>,
235{
236 fn from(export: CoreExport<T>) -> CoreDef {
237 CoreDef::Export(export.map_index(|i| i.into()))
238 }
239}
240
241#[derive(Debug, Clone, Hash, Eq, PartialEq)]
243#[expect(missing_docs, reason = "self-describing fields")]
244pub struct CoreExport<T> {
245 pub instance: InstanceId,
246 pub item: ExportItem<T>,
247}
248
249impl<T> CoreExport<T> {
250 #[expect(missing_docs, reason = "self-describing function")]
251 pub fn map_index<U>(self, f: impl FnOnce(T) -> U) -> CoreExport<U> {
252 CoreExport {
253 instance: self.instance,
254 item: match self.item {
255 ExportItem::Index(i) => ExportItem::Index(f(i)),
256 ExportItem::Name(s) => ExportItem::Name(s),
257 },
258 }
259 }
260}
261
262#[derive(Clone, PartialEq, Eq, Hash)]
264#[expect(missing_docs, reason = "self-describing fields")]
265pub enum Trampoline {
266 LowerImport {
267 import: RuntimeImportIndex,
268 options: CanonicalOptions,
269 lower_ty: TypeFuncIndex,
270 },
271 Transcoder {
272 op: Transcode,
273 from: MemoryId,
274 from64: bool,
275 to: MemoryId,
276 to64: bool,
277 },
278 AlwaysTrap,
279 ResourceNew(TypeResourceTableIndex),
280 ResourceRep(TypeResourceTableIndex),
281 ResourceDrop(TypeResourceTableIndex),
282 BackpressureSet {
283 instance: RuntimeComponentInstanceIndex,
284 },
285 TaskReturn {
286 results: TypeTupleIndex,
287 options: CanonicalOptions,
288 },
289 WaitableSetNew {
290 instance: RuntimeComponentInstanceIndex,
291 },
292 WaitableSetWait {
293 instance: RuntimeComponentInstanceIndex,
294 async_: bool,
295 memory: MemoryId,
296 },
297 WaitableSetPoll {
298 instance: RuntimeComponentInstanceIndex,
299 async_: bool,
300 memory: MemoryId,
301 },
302 WaitableSetDrop {
303 instance: RuntimeComponentInstanceIndex,
304 },
305 WaitableJoin {
306 instance: RuntimeComponentInstanceIndex,
307 },
308 Yield {
309 async_: bool,
310 },
311 SubtaskDrop {
312 instance: RuntimeComponentInstanceIndex,
313 },
314 StreamNew {
315 ty: TypeStreamTableIndex,
316 },
317 StreamRead {
318 ty: TypeStreamTableIndex,
319 options: CanonicalOptions,
320 },
321 StreamWrite {
322 ty: TypeStreamTableIndex,
323 options: CanonicalOptions,
324 },
325 StreamCancelRead {
326 ty: TypeStreamTableIndex,
327 async_: bool,
328 },
329 StreamCancelWrite {
330 ty: TypeStreamTableIndex,
331 async_: bool,
332 },
333 StreamCloseReadable {
334 ty: TypeStreamTableIndex,
335 },
336 StreamCloseWritable {
337 ty: TypeStreamTableIndex,
338 },
339 FutureNew {
340 ty: TypeFutureTableIndex,
341 },
342 FutureRead {
343 ty: TypeFutureTableIndex,
344 options: CanonicalOptions,
345 },
346 FutureWrite {
347 ty: TypeFutureTableIndex,
348 options: CanonicalOptions,
349 },
350 FutureCancelRead {
351 ty: TypeFutureTableIndex,
352 async_: bool,
353 },
354 FutureCancelWrite {
355 ty: TypeFutureTableIndex,
356 async_: bool,
357 },
358 FutureCloseReadable {
359 ty: TypeFutureTableIndex,
360 },
361 FutureCloseWritable {
362 ty: TypeFutureTableIndex,
363 },
364 ErrorContextNew {
365 ty: TypeComponentLocalErrorContextTableIndex,
366 options: CanonicalOptions,
367 },
368 ErrorContextDebugMessage {
369 ty: TypeComponentLocalErrorContextTableIndex,
370 options: CanonicalOptions,
371 },
372 ErrorContextDrop {
373 ty: TypeComponentLocalErrorContextTableIndex,
374 },
375 ResourceTransferOwn,
376 ResourceTransferBorrow,
377 ResourceEnterCall,
378 ResourceExitCall,
379 SyncEnterCall,
380 SyncExitCall {
381 callback: Option<CallbackId>,
382 },
383 AsyncEnterCall,
384 AsyncExitCall {
385 callback: Option<CallbackId>,
386 post_return: Option<PostReturnId>,
387 },
388 FutureTransfer,
389 StreamTransfer,
390 ErrorContextTransfer,
391}
392
393#[derive(Copy, Clone, Hash, Eq, PartialEq)]
394#[expect(missing_docs, reason = "self-describing fields")]
395pub struct FutureInfo {
396 pub instance: RuntimeComponentInstanceIndex,
397 pub payload_type: Option<InterfaceType>,
398}
399
400#[derive(Copy, Clone, Hash, Eq, PartialEq)]
401#[expect(missing_docs, reason = "self-describing fields")]
402pub struct StreamInfo {
403 pub instance: RuntimeComponentInstanceIndex,
404 pub payload_type: InterfaceType,
405}
406
407#[derive(Clone, Hash, Eq, PartialEq)]
409#[expect(missing_docs, reason = "self-describing fields")]
410pub struct CanonicalOptions {
411 pub instance: RuntimeComponentInstanceIndex,
412 pub string_encoding: StringEncoding,
413 pub memory: Option<MemoryId>,
414 pub realloc: Option<ReallocId>,
415 pub callback: Option<CallbackId>,
416 pub post_return: Option<PostReturnId>,
417 pub async_: bool,
418}
419
420#[expect(missing_docs, reason = "self-describing fields")]
422pub struct Resource {
423 pub rep: WasmValType,
424 pub dtor: Option<CoreDef>,
425 pub instance: RuntimeComponentInstanceIndex,
426}
427
428pub struct Intern<K: EntityRef, V> {
434 intern_map: HashMap<V, K>,
435 key_map: PrimaryMap<K, V>,
436}
437
438impl<K, V> Intern<K, V>
439where
440 K: EntityRef,
441{
442 pub fn push(&mut self, value: V) -> K
449 where
450 V: Hash + Eq + Clone,
451 {
452 *self
453 .intern_map
454 .entry(value.clone())
455 .or_insert_with(|| self.key_map.push(value))
456 }
457
458 pub fn iter(&self) -> impl Iterator<Item = (K, &V)> {
460 self.key_map.iter()
461 }
462}
463
464impl<K: EntityRef, V> Index<K> for Intern<K, V> {
465 type Output = V;
466 fn index(&self, key: K) -> &V {
467 &self.key_map[key]
468 }
469}
470
471impl<K: EntityRef, V> Default for Intern<K, V> {
472 fn default() -> Intern<K, V> {
473 Intern {
474 intern_map: HashMap::new(),
475 key_map: PrimaryMap::new(),
476 }
477 }
478}
479
480impl ComponentDfg {
481 pub fn finish(
484 self,
485 wasmtime_types: &mut ComponentTypesBuilder,
486 wasmparser_types: wasmparser::types::TypesRef<'_>,
487 ) -> Result<ComponentTranslation> {
488 let mut linearize = LinearizeDfg {
489 dfg: &self,
490 initializers: Vec::new(),
491 runtime_memories: Default::default(),
492 runtime_tables: Default::default(),
493 runtime_post_return: Default::default(),
494 runtime_reallocs: Default::default(),
495 runtime_callbacks: Default::default(),
496 runtime_instances: Default::default(),
497 num_lowerings: 0,
498 trampolines: Default::default(),
499 trampoline_defs: Default::default(),
500 trampoline_map: Default::default(),
501 };
502
503 for item in linearize.dfg.side_effects.iter() {
507 linearize.side_effect(item);
508 }
509
510 let mut export_items = PrimaryMap::new();
513 let mut exports = NameMap::default();
514 for (name, export) in self.exports.iter() {
515 let export =
516 linearize.export(export, &mut export_items, wasmtime_types, wasmparser_types)?;
517 exports.insert(name, &mut NameMapNoIntern, false, export)?;
518 }
519
520 Ok(ComponentTranslation {
525 trampolines: linearize.trampoline_defs,
526 component: Component {
527 exports,
528 export_items,
529 initializers: linearize.initializers,
530 trampolines: linearize.trampolines,
531 num_lowerings: linearize.num_lowerings,
532
533 num_runtime_memories: linearize.runtime_memories.len() as u32,
534 num_runtime_tables: linearize.runtime_tables.len() as u32,
535 num_runtime_post_returns: linearize.runtime_post_return.len() as u32,
536 num_runtime_reallocs: linearize.runtime_reallocs.len() as u32,
537 num_runtime_callbacks: linearize.runtime_callbacks.len() as u32,
538 num_runtime_instances: linearize.runtime_instances.len() as u32,
539 imports: self.imports,
540 import_types: self.import_types,
541 num_runtime_component_instances: self.num_runtime_component_instances,
542 num_future_tables: self.num_future_tables,
543 num_stream_tables: self.num_stream_tables,
544 num_error_context_tables: self.num_error_context_tables,
545 num_resources: (self.resources.len() + self.imported_resources.len()) as u32,
546 imported_resources: self.imported_resources,
547 defined_resource_instances: self
548 .resources
549 .iter()
550 .map(|(_, r)| r.instance)
551 .collect(),
552 },
553 })
554 }
555
556 pub fn resource_index(&self, defined: DefinedResourceIndex) -> ResourceIndex {
559 ResourceIndex::from_u32(defined.as_u32() + (self.imported_resources.len() as u32))
560 }
561}
562
563struct LinearizeDfg<'a> {
564 dfg: &'a ComponentDfg,
565 initializers: Vec<GlobalInitializer>,
566 trampolines: PrimaryMap<TrampolineIndex, ModuleInternedTypeIndex>,
567 trampoline_defs: PrimaryMap<TrampolineIndex, info::Trampoline>,
568 trampoline_map: HashMap<TrampolineIndex, TrampolineIndex>,
569 runtime_memories: HashMap<MemoryId, RuntimeMemoryIndex>,
570 runtime_tables: HashMap<TableId, RuntimeTableIndex>,
571 runtime_reallocs: HashMap<ReallocId, RuntimeReallocIndex>,
572 runtime_callbacks: HashMap<CallbackId, RuntimeCallbackIndex>,
573 runtime_post_return: HashMap<PostReturnId, RuntimePostReturnIndex>,
574 runtime_instances: HashMap<RuntimeInstance, RuntimeInstanceIndex>,
575 num_lowerings: u32,
576}
577
578#[derive(Copy, Clone, Hash, Eq, PartialEq)]
579enum RuntimeInstance {
580 Normal(InstanceId),
581 Adapter(AdapterModuleId),
582}
583
584impl LinearizeDfg<'_> {
585 fn side_effect(&mut self, effect: &SideEffect) {
586 match effect {
587 SideEffect::Instance(i) => {
588 self.instantiate(*i, &self.dfg.instances[*i]);
589 }
590 SideEffect::Resource(i) => {
591 self.resource(*i, &self.dfg.resources[*i]);
592 }
593 }
594 }
595
596 fn instantiate(&mut self, instance: InstanceId, args: &Instance) {
597 log::trace!("creating instance {instance:?}");
598 let instantiation = match args {
599 Instance::Static(index, args) => InstantiateModule::Static(
600 *index,
601 args.iter().map(|def| self.core_def(def)).collect(),
602 ),
603 Instance::Import(index, args) => InstantiateModule::Import(
604 *index,
605 args.iter()
606 .map(|(module, values)| {
607 let values = values
608 .iter()
609 .map(|(name, def)| (name.clone(), self.core_def(def)))
610 .collect();
611 (module.clone(), values)
612 })
613 .collect(),
614 ),
615 };
616 let index = RuntimeInstanceIndex::new(self.runtime_instances.len());
617 self.initializers
618 .push(GlobalInitializer::InstantiateModule(instantiation));
619 let prev = self
620 .runtime_instances
621 .insert(RuntimeInstance::Normal(instance), index);
622 assert!(prev.is_none());
623 }
624
625 fn resource(&mut self, index: DefinedResourceIndex, resource: &Resource) {
626 let dtor = resource.dtor.as_ref().map(|dtor| self.core_def(dtor));
627 self.initializers
628 .push(GlobalInitializer::Resource(info::Resource {
629 dtor,
630 index,
631 rep: resource.rep,
632 instance: resource.instance,
633 }));
634 }
635
636 fn export(
637 &mut self,
638 export: &Export,
639 items: &mut PrimaryMap<ExportIndex, info::Export>,
640 wasmtime_types: &mut ComponentTypesBuilder,
641 wasmparser_types: wasmparser::types::TypesRef<'_>,
642 ) -> Result<ExportIndex> {
643 let item = match export {
644 Export::LiftedFunction { ty, func, options } => {
645 let func = self.core_def(func);
646 let options = self.options(options);
647 info::Export::LiftedFunction {
648 ty: *ty,
649 func,
650 options,
651 }
652 }
653 Export::ModuleStatic { ty, index } => info::Export::ModuleStatic {
654 ty: wasmtime_types.convert_module(wasmparser_types, *ty)?,
655 index: *index,
656 },
657 Export::ModuleImport { ty, import } => info::Export::ModuleImport {
658 ty: *ty,
659 import: *import,
660 },
661 Export::Instance { ty, exports } => info::Export::Instance {
662 ty: *ty,
663 exports: {
664 let mut map = NameMap::default();
665 for (name, export) in exports {
666 let export =
667 self.export(export, items, wasmtime_types, wasmparser_types)?;
668 map.insert(name, &mut NameMapNoIntern, false, export)?;
669 }
670 map
671 },
672 },
673 Export::Type(def) => info::Export::Type(*def),
674 };
675 Ok(items.push(item))
676 }
677
678 fn options(&mut self, options: &CanonicalOptions) -> info::CanonicalOptions {
679 let memory = options.memory.map(|mem| self.runtime_memory(mem));
680 let realloc = options.realloc.map(|mem| self.runtime_realloc(mem));
681 let callback = options.callback.map(|mem| self.runtime_callback(mem));
682 let post_return = options.post_return.map(|mem| self.runtime_post_return(mem));
683 info::CanonicalOptions {
684 instance: options.instance,
685 string_encoding: options.string_encoding,
686 memory,
687 realloc,
688 callback,
689 post_return,
690 async_: options.async_,
691 }
692 }
693
694 fn runtime_memory(&mut self, mem: MemoryId) -> RuntimeMemoryIndex {
695 self.intern(
696 mem,
697 |me| &mut me.runtime_memories,
698 |me, mem| me.core_export(&me.dfg.memories[mem]),
699 |index, export| GlobalInitializer::ExtractMemory(ExtractMemory { index, export }),
700 )
701 }
702
703 fn runtime_realloc(&mut self, realloc: ReallocId) -> RuntimeReallocIndex {
704 self.intern(
705 realloc,
706 |me| &mut me.runtime_reallocs,
707 |me, realloc| me.core_def(&me.dfg.reallocs[realloc]),
708 |index, def| GlobalInitializer::ExtractRealloc(ExtractRealloc { index, def }),
709 )
710 }
711
712 fn runtime_callback(&mut self, callback: CallbackId) -> RuntimeCallbackIndex {
713 self.intern(
714 callback,
715 |me| &mut me.runtime_callbacks,
716 |me, callback| me.core_def(&me.dfg.callbacks[callback]),
717 |index, def| GlobalInitializer::ExtractCallback(ExtractCallback { index, def }),
718 )
719 }
720
721 fn runtime_post_return(&mut self, post_return: PostReturnId) -> RuntimePostReturnIndex {
722 self.intern(
723 post_return,
724 |me| &mut me.runtime_post_return,
725 |me, post_return| me.core_def(&me.dfg.post_returns[post_return]),
726 |index, def| GlobalInitializer::ExtractPostReturn(ExtractPostReturn { index, def }),
727 )
728 }
729
730 fn core_def(&mut self, def: &CoreDef) -> info::CoreDef {
731 match def {
732 CoreDef::Export(e) => info::CoreDef::Export(self.core_export(e)),
733 CoreDef::InstanceFlags(i) => info::CoreDef::InstanceFlags(*i),
734 CoreDef::Adapter(id) => info::CoreDef::Export(self.adapter(*id)),
735 CoreDef::Trampoline(index) => info::CoreDef::Trampoline(self.trampoline(*index)),
736 }
737 }
738
739 fn trampoline(&mut self, index: TrampolineIndex) -> TrampolineIndex {
740 if let Some(idx) = self.trampoline_map.get(&index) {
741 return *idx;
742 }
743 let (signature, trampoline) = &self.dfg.trampolines[index];
744 let trampoline = match trampoline {
745 Trampoline::LowerImport {
746 import,
747 options,
748 lower_ty,
749 } => {
750 let index = LoweredIndex::from_u32(self.num_lowerings);
751 self.num_lowerings += 1;
752 self.initializers.push(GlobalInitializer::LowerImport {
753 index,
754 import: *import,
755 });
756 info::Trampoline::LowerImport {
757 index,
758 options: self.options(options),
759 lower_ty: *lower_ty,
760 }
761 }
762 Trampoline::Transcoder {
763 op,
764 from,
765 from64,
766 to,
767 to64,
768 } => info::Trampoline::Transcoder {
769 op: *op,
770 from: self.runtime_memory(*from),
771 from64: *from64,
772 to: self.runtime_memory(*to),
773 to64: *to64,
774 },
775 Trampoline::AlwaysTrap => info::Trampoline::AlwaysTrap,
776 Trampoline::ResourceNew(ty) => info::Trampoline::ResourceNew(*ty),
777 Trampoline::ResourceDrop(ty) => info::Trampoline::ResourceDrop(*ty),
778 Trampoline::ResourceRep(ty) => info::Trampoline::ResourceRep(*ty),
779 Trampoline::BackpressureSet { instance } => info::Trampoline::BackpressureSet {
780 instance: *instance,
781 },
782 Trampoline::TaskReturn { results, options } => info::Trampoline::TaskReturn {
783 results: *results,
784 options: self.options(options),
785 },
786 Trampoline::WaitableSetNew { instance } => info::Trampoline::WaitableSetNew {
787 instance: *instance,
788 },
789 Trampoline::WaitableSetWait {
790 instance,
791 async_,
792 memory,
793 } => info::Trampoline::WaitableSetWait {
794 instance: *instance,
795 async_: *async_,
796 memory: self.runtime_memory(*memory),
797 },
798 Trampoline::WaitableSetPoll {
799 instance,
800 async_,
801 memory,
802 } => info::Trampoline::WaitableSetPoll {
803 instance: *instance,
804 async_: *async_,
805 memory: self.runtime_memory(*memory),
806 },
807 Trampoline::WaitableSetDrop { instance } => info::Trampoline::WaitableSetDrop {
808 instance: *instance,
809 },
810 Trampoline::WaitableJoin { instance } => info::Trampoline::WaitableJoin {
811 instance: *instance,
812 },
813 Trampoline::Yield { async_ } => info::Trampoline::Yield { async_: *async_ },
814 Trampoline::SubtaskDrop { instance } => info::Trampoline::SubtaskDrop {
815 instance: *instance,
816 },
817 Trampoline::StreamNew { ty } => info::Trampoline::StreamNew { ty: *ty },
818 Trampoline::StreamRead { ty, options } => info::Trampoline::StreamRead {
819 ty: *ty,
820 options: self.options(options),
821 },
822 Trampoline::StreamWrite { ty, options } => info::Trampoline::StreamWrite {
823 ty: *ty,
824 options: self.options(options),
825 },
826 Trampoline::StreamCancelRead { ty, async_ } => info::Trampoline::StreamCancelRead {
827 ty: *ty,
828 async_: *async_,
829 },
830 Trampoline::StreamCancelWrite { ty, async_ } => info::Trampoline::StreamCancelWrite {
831 ty: *ty,
832 async_: *async_,
833 },
834 Trampoline::StreamCloseReadable { ty } => {
835 info::Trampoline::StreamCloseReadable { ty: *ty }
836 }
837 Trampoline::StreamCloseWritable { ty } => {
838 info::Trampoline::StreamCloseWritable { ty: *ty }
839 }
840 Trampoline::FutureNew { ty } => info::Trampoline::FutureNew { ty: *ty },
841 Trampoline::FutureRead { ty, options } => info::Trampoline::FutureRead {
842 ty: *ty,
843 options: self.options(options),
844 },
845 Trampoline::FutureWrite { ty, options } => info::Trampoline::FutureWrite {
846 ty: *ty,
847 options: self.options(options),
848 },
849 Trampoline::FutureCancelRead { ty, async_ } => info::Trampoline::FutureCancelRead {
850 ty: *ty,
851 async_: *async_,
852 },
853 Trampoline::FutureCancelWrite { ty, async_ } => info::Trampoline::FutureCancelWrite {
854 ty: *ty,
855 async_: *async_,
856 },
857 Trampoline::FutureCloseReadable { ty } => {
858 info::Trampoline::FutureCloseReadable { ty: *ty }
859 }
860 Trampoline::FutureCloseWritable { ty } => {
861 info::Trampoline::FutureCloseWritable { ty: *ty }
862 }
863 Trampoline::ErrorContextNew { ty, options } => info::Trampoline::ErrorContextNew {
864 ty: *ty,
865 options: self.options(options),
866 },
867 Trampoline::ErrorContextDebugMessage { ty, options } => {
868 info::Trampoline::ErrorContextDebugMessage {
869 ty: *ty,
870 options: self.options(options),
871 }
872 }
873 Trampoline::ErrorContextDrop { ty } => info::Trampoline::ErrorContextDrop { ty: *ty },
874 Trampoline::ResourceTransferOwn => info::Trampoline::ResourceTransferOwn,
875 Trampoline::ResourceTransferBorrow => info::Trampoline::ResourceTransferBorrow,
876 Trampoline::ResourceEnterCall => info::Trampoline::ResourceEnterCall,
877 Trampoline::ResourceExitCall => info::Trampoline::ResourceExitCall,
878 Trampoline::SyncEnterCall => info::Trampoline::SyncEnterCall,
879 Trampoline::SyncExitCall { callback } => info::Trampoline::SyncExitCall {
880 callback: callback.map(|v| self.runtime_callback(v)),
881 },
882 Trampoline::AsyncEnterCall => info::Trampoline::AsyncEnterCall,
883 Trampoline::AsyncExitCall {
884 callback,
885 post_return,
886 } => info::Trampoline::AsyncExitCall {
887 callback: callback.map(|v| self.runtime_callback(v)),
888 post_return: post_return.map(|v| self.runtime_post_return(v)),
889 },
890 Trampoline::FutureTransfer => info::Trampoline::FutureTransfer,
891 Trampoline::StreamTransfer => info::Trampoline::StreamTransfer,
892 Trampoline::ErrorContextTransfer => info::Trampoline::ErrorContextTransfer,
893 };
894 let i1 = self.trampolines.push(*signature);
895 let i2 = self.trampoline_defs.push(trampoline);
896 assert_eq!(i1, i2);
897 self.trampoline_map.insert(index, i1);
898 i1
899 }
900
901 fn core_export<T>(&mut self, export: &CoreExport<T>) -> info::CoreExport<T>
902 where
903 T: Clone,
904 {
905 let instance = export.instance;
906 log::trace!("referencing export of {instance:?}");
907 info::CoreExport {
908 instance: self.runtime_instances[&RuntimeInstance::Normal(instance)],
909 item: export.item.clone(),
910 }
911 }
912
913 fn adapter(&mut self, adapter: AdapterId) -> info::CoreExport<EntityIndex> {
914 let (adapter_module, entity_index) = self.dfg.adapter_partitionings[adapter];
915
916 let instance = self.adapter_module(adapter_module);
920
921 info::CoreExport {
923 instance,
924 item: ExportItem::Index(entity_index),
925 }
926 }
927
928 fn adapter_module(&mut self, adapter_module: AdapterModuleId) -> RuntimeInstanceIndex {
929 self.intern(
930 RuntimeInstance::Adapter(adapter_module),
931 |me| &mut me.runtime_instances,
932 |me, _| {
933 log::debug!("instantiating {adapter_module:?}");
934 let (module_index, args) = &me.dfg.adapter_modules[adapter_module];
935 let args = args.iter().map(|arg| me.core_def(arg)).collect();
936 let instantiate = InstantiateModule::Static(*module_index, args);
937 GlobalInitializer::InstantiateModule(instantiate)
938 },
939 |_, init| init,
940 )
941 }
942
943 fn intern<K, V, T>(
958 &mut self,
959 key: K,
960 map: impl Fn(&mut Self) -> &mut HashMap<K, V>,
961 generate: impl FnOnce(&mut Self, K) -> T,
962 init: impl FnOnce(V, T) -> GlobalInitializer,
963 ) -> V
964 where
965 K: Hash + Eq + Copy,
966 V: EntityRef,
967 {
968 if let Some(val) = map(self).get(&key) {
969 return *val;
970 }
971 let tmp = generate(self, key);
972 let index = V::new(map(self).len());
973 self.initializers.push(init(index, tmp));
974 let prev = map(self).insert(key, index);
975 assert!(prev.is_none());
976 index
977 }
978}