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 TaskCancel {
290 instance: RuntimeComponentInstanceIndex,
291 },
292 WaitableSetNew {
293 instance: RuntimeComponentInstanceIndex,
294 },
295 WaitableSetWait {
296 instance: RuntimeComponentInstanceIndex,
297 async_: bool,
298 memory: MemoryId,
299 },
300 WaitableSetPoll {
301 instance: RuntimeComponentInstanceIndex,
302 async_: bool,
303 memory: MemoryId,
304 },
305 WaitableSetDrop {
306 instance: RuntimeComponentInstanceIndex,
307 },
308 WaitableJoin {
309 instance: RuntimeComponentInstanceIndex,
310 },
311 Yield {
312 async_: bool,
313 },
314 SubtaskDrop {
315 instance: RuntimeComponentInstanceIndex,
316 },
317 SubtaskCancel {
318 instance: RuntimeComponentInstanceIndex,
319 async_: bool,
320 },
321 StreamNew {
322 ty: TypeStreamTableIndex,
323 },
324 StreamRead {
325 ty: TypeStreamTableIndex,
326 options: CanonicalOptions,
327 },
328 StreamWrite {
329 ty: TypeStreamTableIndex,
330 options: CanonicalOptions,
331 },
332 StreamCancelRead {
333 ty: TypeStreamTableIndex,
334 async_: bool,
335 },
336 StreamCancelWrite {
337 ty: TypeStreamTableIndex,
338 async_: bool,
339 },
340 StreamCloseReadable {
341 ty: TypeStreamTableIndex,
342 },
343 StreamCloseWritable {
344 ty: TypeStreamTableIndex,
345 },
346 FutureNew {
347 ty: TypeFutureTableIndex,
348 },
349 FutureRead {
350 ty: TypeFutureTableIndex,
351 options: CanonicalOptions,
352 },
353 FutureWrite {
354 ty: TypeFutureTableIndex,
355 options: CanonicalOptions,
356 },
357 FutureCancelRead {
358 ty: TypeFutureTableIndex,
359 async_: bool,
360 },
361 FutureCancelWrite {
362 ty: TypeFutureTableIndex,
363 async_: bool,
364 },
365 FutureCloseReadable {
366 ty: TypeFutureTableIndex,
367 },
368 FutureCloseWritable {
369 ty: TypeFutureTableIndex,
370 },
371 ErrorContextNew {
372 ty: TypeComponentLocalErrorContextTableIndex,
373 options: CanonicalOptions,
374 },
375 ErrorContextDebugMessage {
376 ty: TypeComponentLocalErrorContextTableIndex,
377 options: CanonicalOptions,
378 },
379 ErrorContextDrop {
380 ty: TypeComponentLocalErrorContextTableIndex,
381 },
382 ResourceTransferOwn,
383 ResourceTransferBorrow,
384 ResourceEnterCall,
385 ResourceExitCall,
386 PrepareCall {
387 memory: Option<MemoryId>,
388 },
389 SyncStartCall {
390 callback: Option<CallbackId>,
391 },
392 AsyncStartCall {
393 callback: Option<CallbackId>,
394 post_return: Option<PostReturnId>,
395 },
396 FutureTransfer,
397 StreamTransfer,
398 ErrorContextTransfer,
399 ContextGet(u32),
400 ContextSet(u32),
401}
402
403#[derive(Copy, Clone, Hash, Eq, PartialEq)]
404#[expect(missing_docs, reason = "self-describing fields")]
405pub struct FutureInfo {
406 pub instance: RuntimeComponentInstanceIndex,
407 pub payload_type: Option<InterfaceType>,
408}
409
410#[derive(Copy, Clone, Hash, Eq, PartialEq)]
411#[expect(missing_docs, reason = "self-describing fields")]
412pub struct StreamInfo {
413 pub instance: RuntimeComponentInstanceIndex,
414 pub payload_type: InterfaceType,
415}
416
417#[derive(Clone, Hash, Eq, PartialEq)]
419#[expect(missing_docs, reason = "self-describing fields")]
420pub struct CanonicalOptions {
421 pub instance: RuntimeComponentInstanceIndex,
422 pub string_encoding: StringEncoding,
423 pub memory: Option<MemoryId>,
424 pub realloc: Option<ReallocId>,
425 pub callback: Option<CallbackId>,
426 pub post_return: Option<PostReturnId>,
427 pub async_: bool,
428}
429
430#[expect(missing_docs, reason = "self-describing fields")]
432pub struct Resource {
433 pub rep: WasmValType,
434 pub dtor: Option<CoreDef>,
435 pub instance: RuntimeComponentInstanceIndex,
436}
437
438pub struct Intern<K: EntityRef, V> {
444 intern_map: HashMap<V, K>,
445 key_map: PrimaryMap<K, V>,
446}
447
448impl<K, V> Intern<K, V>
449where
450 K: EntityRef,
451{
452 pub fn push(&mut self, value: V) -> K
459 where
460 V: Hash + Eq + Clone,
461 {
462 *self
463 .intern_map
464 .entry(value.clone())
465 .or_insert_with(|| self.key_map.push(value))
466 }
467
468 pub fn iter(&self) -> impl Iterator<Item = (K, &V)> {
470 self.key_map.iter()
471 }
472}
473
474impl<K: EntityRef, V> Index<K> for Intern<K, V> {
475 type Output = V;
476 fn index(&self, key: K) -> &V {
477 &self.key_map[key]
478 }
479}
480
481impl<K: EntityRef, V> Default for Intern<K, V> {
482 fn default() -> Intern<K, V> {
483 Intern {
484 intern_map: HashMap::new(),
485 key_map: PrimaryMap::new(),
486 }
487 }
488}
489
490impl ComponentDfg {
491 pub fn finish(
494 self,
495 wasmtime_types: &mut ComponentTypesBuilder,
496 wasmparser_types: wasmparser::types::TypesRef<'_>,
497 ) -> Result<ComponentTranslation> {
498 let mut linearize = LinearizeDfg {
499 dfg: &self,
500 initializers: Vec::new(),
501 runtime_memories: Default::default(),
502 runtime_tables: Default::default(),
503 runtime_post_return: Default::default(),
504 runtime_reallocs: Default::default(),
505 runtime_callbacks: Default::default(),
506 runtime_instances: Default::default(),
507 num_lowerings: 0,
508 trampolines: Default::default(),
509 trampoline_defs: Default::default(),
510 trampoline_map: Default::default(),
511 };
512
513 for item in linearize.dfg.side_effects.iter() {
517 linearize.side_effect(item);
518 }
519
520 let mut export_items = PrimaryMap::new();
523 let mut exports = NameMap::default();
524 for (name, export) in self.exports.iter() {
525 let export =
526 linearize.export(export, &mut export_items, wasmtime_types, wasmparser_types)?;
527 exports.insert(name, &mut NameMapNoIntern, false, export)?;
528 }
529
530 Ok(ComponentTranslation {
535 trampolines: linearize.trampoline_defs,
536 component: Component {
537 exports,
538 export_items,
539 initializers: linearize.initializers,
540 trampolines: linearize.trampolines,
541 num_lowerings: linearize.num_lowerings,
542
543 num_runtime_memories: linearize.runtime_memories.len() as u32,
544 num_runtime_tables: linearize.runtime_tables.len() as u32,
545 num_runtime_post_returns: linearize.runtime_post_return.len() as u32,
546 num_runtime_reallocs: linearize.runtime_reallocs.len() as u32,
547 num_runtime_callbacks: linearize.runtime_callbacks.len() as u32,
548 num_runtime_instances: linearize.runtime_instances.len() as u32,
549 imports: self.imports,
550 import_types: self.import_types,
551 num_runtime_component_instances: self.num_runtime_component_instances,
552 num_future_tables: self.num_future_tables,
553 num_stream_tables: self.num_stream_tables,
554 num_error_context_tables: self.num_error_context_tables,
555 num_resources: (self.resources.len() + self.imported_resources.len()) as u32,
556 imported_resources: self.imported_resources,
557 defined_resource_instances: self
558 .resources
559 .iter()
560 .map(|(_, r)| r.instance)
561 .collect(),
562 },
563 })
564 }
565
566 pub fn resource_index(&self, defined: DefinedResourceIndex) -> ResourceIndex {
569 ResourceIndex::from_u32(defined.as_u32() + (self.imported_resources.len() as u32))
570 }
571}
572
573struct LinearizeDfg<'a> {
574 dfg: &'a ComponentDfg,
575 initializers: Vec<GlobalInitializer>,
576 trampolines: PrimaryMap<TrampolineIndex, ModuleInternedTypeIndex>,
577 trampoline_defs: PrimaryMap<TrampolineIndex, info::Trampoline>,
578 trampoline_map: HashMap<TrampolineIndex, TrampolineIndex>,
579 runtime_memories: HashMap<MemoryId, RuntimeMemoryIndex>,
580 runtime_tables: HashMap<TableId, RuntimeTableIndex>,
581 runtime_reallocs: HashMap<ReallocId, RuntimeReallocIndex>,
582 runtime_callbacks: HashMap<CallbackId, RuntimeCallbackIndex>,
583 runtime_post_return: HashMap<PostReturnId, RuntimePostReturnIndex>,
584 runtime_instances: HashMap<RuntimeInstance, RuntimeInstanceIndex>,
585 num_lowerings: u32,
586}
587
588#[derive(Copy, Clone, Hash, Eq, PartialEq)]
589enum RuntimeInstance {
590 Normal(InstanceId),
591 Adapter(AdapterModuleId),
592}
593
594impl LinearizeDfg<'_> {
595 fn side_effect(&mut self, effect: &SideEffect) {
596 match effect {
597 SideEffect::Instance(i) => {
598 self.instantiate(*i, &self.dfg.instances[*i]);
599 }
600 SideEffect::Resource(i) => {
601 self.resource(*i, &self.dfg.resources[*i]);
602 }
603 }
604 }
605
606 fn instantiate(&mut self, instance: InstanceId, args: &Instance) {
607 log::trace!("creating instance {instance:?}");
608 let instantiation = match args {
609 Instance::Static(index, args) => InstantiateModule::Static(
610 *index,
611 args.iter().map(|def| self.core_def(def)).collect(),
612 ),
613 Instance::Import(index, args) => InstantiateModule::Import(
614 *index,
615 args.iter()
616 .map(|(module, values)| {
617 let values = values
618 .iter()
619 .map(|(name, def)| (name.clone(), self.core_def(def)))
620 .collect();
621 (module.clone(), values)
622 })
623 .collect(),
624 ),
625 };
626 let index = RuntimeInstanceIndex::new(self.runtime_instances.len());
627 self.initializers
628 .push(GlobalInitializer::InstantiateModule(instantiation));
629 let prev = self
630 .runtime_instances
631 .insert(RuntimeInstance::Normal(instance), index);
632 assert!(prev.is_none());
633 }
634
635 fn resource(&mut self, index: DefinedResourceIndex, resource: &Resource) {
636 let dtor = resource.dtor.as_ref().map(|dtor| self.core_def(dtor));
637 self.initializers
638 .push(GlobalInitializer::Resource(info::Resource {
639 dtor,
640 index,
641 rep: resource.rep,
642 instance: resource.instance,
643 }));
644 }
645
646 fn export(
647 &mut self,
648 export: &Export,
649 items: &mut PrimaryMap<ExportIndex, info::Export>,
650 wasmtime_types: &mut ComponentTypesBuilder,
651 wasmparser_types: wasmparser::types::TypesRef<'_>,
652 ) -> Result<ExportIndex> {
653 let item = match export {
654 Export::LiftedFunction { ty, func, options } => {
655 let func = self.core_def(func);
656 let options = self.options(options);
657 info::Export::LiftedFunction {
658 ty: *ty,
659 func,
660 options,
661 }
662 }
663 Export::ModuleStatic { ty, index } => info::Export::ModuleStatic {
664 ty: wasmtime_types.convert_module(wasmparser_types, *ty)?,
665 index: *index,
666 },
667 Export::ModuleImport { ty, import } => info::Export::ModuleImport {
668 ty: *ty,
669 import: *import,
670 },
671 Export::Instance { ty, exports } => info::Export::Instance {
672 ty: *ty,
673 exports: {
674 let mut map = NameMap::default();
675 for (name, export) in exports {
676 let export =
677 self.export(export, items, wasmtime_types, wasmparser_types)?;
678 map.insert(name, &mut NameMapNoIntern, false, export)?;
679 }
680 map
681 },
682 },
683 Export::Type(def) => info::Export::Type(*def),
684 };
685 Ok(items.push(item))
686 }
687
688 fn options(&mut self, options: &CanonicalOptions) -> info::CanonicalOptions {
689 let memory = options.memory.map(|mem| self.runtime_memory(mem));
690 let realloc = options.realloc.map(|mem| self.runtime_realloc(mem));
691 let callback = options.callback.map(|mem| self.runtime_callback(mem));
692 let post_return = options.post_return.map(|mem| self.runtime_post_return(mem));
693 info::CanonicalOptions {
694 instance: options.instance,
695 string_encoding: options.string_encoding,
696 memory,
697 realloc,
698 callback,
699 post_return,
700 async_: options.async_,
701 }
702 }
703
704 fn runtime_memory(&mut self, mem: MemoryId) -> RuntimeMemoryIndex {
705 self.intern(
706 mem,
707 |me| &mut me.runtime_memories,
708 |me, mem| me.core_export(&me.dfg.memories[mem]),
709 |index, export| GlobalInitializer::ExtractMemory(ExtractMemory { index, export }),
710 )
711 }
712
713 fn runtime_realloc(&mut self, realloc: ReallocId) -> RuntimeReallocIndex {
714 self.intern(
715 realloc,
716 |me| &mut me.runtime_reallocs,
717 |me, realloc| me.core_def(&me.dfg.reallocs[realloc]),
718 |index, def| GlobalInitializer::ExtractRealloc(ExtractRealloc { index, def }),
719 )
720 }
721
722 fn runtime_callback(&mut self, callback: CallbackId) -> RuntimeCallbackIndex {
723 self.intern(
724 callback,
725 |me| &mut me.runtime_callbacks,
726 |me, callback| me.core_def(&me.dfg.callbacks[callback]),
727 |index, def| GlobalInitializer::ExtractCallback(ExtractCallback { index, def }),
728 )
729 }
730
731 fn runtime_post_return(&mut self, post_return: PostReturnId) -> RuntimePostReturnIndex {
732 self.intern(
733 post_return,
734 |me| &mut me.runtime_post_return,
735 |me, post_return| me.core_def(&me.dfg.post_returns[post_return]),
736 |index, def| GlobalInitializer::ExtractPostReturn(ExtractPostReturn { index, def }),
737 )
738 }
739
740 fn core_def(&mut self, def: &CoreDef) -> info::CoreDef {
741 match def {
742 CoreDef::Export(e) => info::CoreDef::Export(self.core_export(e)),
743 CoreDef::InstanceFlags(i) => info::CoreDef::InstanceFlags(*i),
744 CoreDef::Adapter(id) => info::CoreDef::Export(self.adapter(*id)),
745 CoreDef::Trampoline(index) => info::CoreDef::Trampoline(self.trampoline(*index)),
746 }
747 }
748
749 fn trampoline(&mut self, index: TrampolineIndex) -> TrampolineIndex {
750 if let Some(idx) = self.trampoline_map.get(&index) {
751 return *idx;
752 }
753 let (signature, trampoline) = &self.dfg.trampolines[index];
754 let trampoline = match trampoline {
755 Trampoline::LowerImport {
756 import,
757 options,
758 lower_ty,
759 } => {
760 let index = LoweredIndex::from_u32(self.num_lowerings);
761 self.num_lowerings += 1;
762 self.initializers.push(GlobalInitializer::LowerImport {
763 index,
764 import: *import,
765 });
766 info::Trampoline::LowerImport {
767 index,
768 options: self.options(options),
769 lower_ty: *lower_ty,
770 }
771 }
772 Trampoline::Transcoder {
773 op,
774 from,
775 from64,
776 to,
777 to64,
778 } => info::Trampoline::Transcoder {
779 op: *op,
780 from: self.runtime_memory(*from),
781 from64: *from64,
782 to: self.runtime_memory(*to),
783 to64: *to64,
784 },
785 Trampoline::AlwaysTrap => info::Trampoline::AlwaysTrap,
786 Trampoline::ResourceNew(ty) => info::Trampoline::ResourceNew(*ty),
787 Trampoline::ResourceDrop(ty) => info::Trampoline::ResourceDrop(*ty),
788 Trampoline::ResourceRep(ty) => info::Trampoline::ResourceRep(*ty),
789 Trampoline::BackpressureSet { instance } => info::Trampoline::BackpressureSet {
790 instance: *instance,
791 },
792 Trampoline::TaskReturn { results, options } => info::Trampoline::TaskReturn {
793 results: *results,
794 options: self.options(options),
795 },
796 Trampoline::TaskCancel { instance } => info::Trampoline::TaskCancel {
797 instance: *instance,
798 },
799 Trampoline::WaitableSetNew { instance } => info::Trampoline::WaitableSetNew {
800 instance: *instance,
801 },
802 Trampoline::WaitableSetWait {
803 instance,
804 async_,
805 memory,
806 } => info::Trampoline::WaitableSetWait {
807 instance: *instance,
808 async_: *async_,
809 memory: self.runtime_memory(*memory),
810 },
811 Trampoline::WaitableSetPoll {
812 instance,
813 async_,
814 memory,
815 } => info::Trampoline::WaitableSetPoll {
816 instance: *instance,
817 async_: *async_,
818 memory: self.runtime_memory(*memory),
819 },
820 Trampoline::WaitableSetDrop { instance } => info::Trampoline::WaitableSetDrop {
821 instance: *instance,
822 },
823 Trampoline::WaitableJoin { instance } => info::Trampoline::WaitableJoin {
824 instance: *instance,
825 },
826 Trampoline::Yield { async_ } => info::Trampoline::Yield { async_: *async_ },
827 Trampoline::SubtaskDrop { instance } => info::Trampoline::SubtaskDrop {
828 instance: *instance,
829 },
830 Trampoline::SubtaskCancel { instance, async_ } => info::Trampoline::SubtaskCancel {
831 instance: *instance,
832 async_: *async_,
833 },
834 Trampoline::StreamNew { ty } => info::Trampoline::StreamNew { ty: *ty },
835 Trampoline::StreamRead { ty, options } => info::Trampoline::StreamRead {
836 ty: *ty,
837 options: self.options(options),
838 },
839 Trampoline::StreamWrite { ty, options } => info::Trampoline::StreamWrite {
840 ty: *ty,
841 options: self.options(options),
842 },
843 Trampoline::StreamCancelRead { ty, async_ } => info::Trampoline::StreamCancelRead {
844 ty: *ty,
845 async_: *async_,
846 },
847 Trampoline::StreamCancelWrite { ty, async_ } => info::Trampoline::StreamCancelWrite {
848 ty: *ty,
849 async_: *async_,
850 },
851 Trampoline::StreamCloseReadable { ty } => {
852 info::Trampoline::StreamCloseReadable { ty: *ty }
853 }
854 Trampoline::StreamCloseWritable { ty } => {
855 info::Trampoline::StreamCloseWritable { ty: *ty }
856 }
857 Trampoline::FutureNew { ty } => info::Trampoline::FutureNew { ty: *ty },
858 Trampoline::FutureRead { ty, options } => info::Trampoline::FutureRead {
859 ty: *ty,
860 options: self.options(options),
861 },
862 Trampoline::FutureWrite { ty, options } => info::Trampoline::FutureWrite {
863 ty: *ty,
864 options: self.options(options),
865 },
866 Trampoline::FutureCancelRead { ty, async_ } => info::Trampoline::FutureCancelRead {
867 ty: *ty,
868 async_: *async_,
869 },
870 Trampoline::FutureCancelWrite { ty, async_ } => info::Trampoline::FutureCancelWrite {
871 ty: *ty,
872 async_: *async_,
873 },
874 Trampoline::FutureCloseReadable { ty } => {
875 info::Trampoline::FutureCloseReadable { ty: *ty }
876 }
877 Trampoline::FutureCloseWritable { ty } => {
878 info::Trampoline::FutureCloseWritable { ty: *ty }
879 }
880 Trampoline::ErrorContextNew { ty, options } => info::Trampoline::ErrorContextNew {
881 ty: *ty,
882 options: self.options(options),
883 },
884 Trampoline::ErrorContextDebugMessage { ty, options } => {
885 info::Trampoline::ErrorContextDebugMessage {
886 ty: *ty,
887 options: self.options(options),
888 }
889 }
890 Trampoline::ErrorContextDrop { ty } => info::Trampoline::ErrorContextDrop { ty: *ty },
891 Trampoline::ResourceTransferOwn => info::Trampoline::ResourceTransferOwn,
892 Trampoline::ResourceTransferBorrow => info::Trampoline::ResourceTransferBorrow,
893 Trampoline::ResourceEnterCall => info::Trampoline::ResourceEnterCall,
894 Trampoline::ResourceExitCall => info::Trampoline::ResourceExitCall,
895 Trampoline::PrepareCall { memory } => info::Trampoline::PrepareCall {
896 memory: memory.map(|v| self.runtime_memory(v)),
897 },
898 Trampoline::SyncStartCall { callback } => info::Trampoline::SyncStartCall {
899 callback: callback.map(|v| self.runtime_callback(v)),
900 },
901 Trampoline::AsyncStartCall {
902 callback,
903 post_return,
904 } => info::Trampoline::AsyncStartCall {
905 callback: callback.map(|v| self.runtime_callback(v)),
906 post_return: post_return.map(|v| self.runtime_post_return(v)),
907 },
908 Trampoline::FutureTransfer => info::Trampoline::FutureTransfer,
909 Trampoline::StreamTransfer => info::Trampoline::StreamTransfer,
910 Trampoline::ErrorContextTransfer => info::Trampoline::ErrorContextTransfer,
911 Trampoline::ContextGet(i) => info::Trampoline::ContextGet(*i),
912 Trampoline::ContextSet(i) => info::Trampoline::ContextSet(*i),
913 };
914 let i1 = self.trampolines.push(*signature);
915 let i2 = self.trampoline_defs.push(trampoline);
916 assert_eq!(i1, i2);
917 self.trampoline_map.insert(index, i1);
918 i1
919 }
920
921 fn core_export<T>(&mut self, export: &CoreExport<T>) -> info::CoreExport<T>
922 where
923 T: Clone,
924 {
925 let instance = export.instance;
926 log::trace!("referencing export of {instance:?}");
927 info::CoreExport {
928 instance: self.runtime_instances[&RuntimeInstance::Normal(instance)],
929 item: export.item.clone(),
930 }
931 }
932
933 fn adapter(&mut self, adapter: AdapterId) -> info::CoreExport<EntityIndex> {
934 let (adapter_module, entity_index) = self.dfg.adapter_partitionings[adapter];
935
936 let instance = self.adapter_module(adapter_module);
940
941 info::CoreExport {
943 instance,
944 item: ExportItem::Index(entity_index),
945 }
946 }
947
948 fn adapter_module(&mut self, adapter_module: AdapterModuleId) -> RuntimeInstanceIndex {
949 self.intern(
950 RuntimeInstance::Adapter(adapter_module),
951 |me| &mut me.runtime_instances,
952 |me, _| {
953 log::debug!("instantiating {adapter_module:?}");
954 let (module_index, args) = &me.dfg.adapter_modules[adapter_module];
955 let args = args.iter().map(|arg| me.core_def(arg)).collect();
956 let instantiate = InstantiateModule::Static(*module_index, args);
957 GlobalInitializer::InstantiateModule(instantiate)
958 },
959 |_, init| init,
960 )
961 }
962
963 fn intern<K, V, T>(
978 &mut self,
979 key: K,
980 map: impl Fn(&mut Self) -> &mut HashMap<K, V>,
981 generate: impl FnOnce(&mut Self, K) -> T,
982 init: impl FnOnce(V, T) -> GlobalInitializer,
983 ) -> V
984 where
985 K: Hash + Eq + Copy,
986 V: EntityRef,
987 {
988 if let Some(val) = map(self).get(&key) {
989 return *val;
990 }
991 let tmp = generate(self, key);
992 let index = V::new(map(self).len());
993 self.initializers.push(init(index, tmp));
994 let prev = map(self).insert(key, index);
995 assert!(prev.is_none());
996 index
997 }
998}