1use crate::component::*;
31use crate::prelude::*;
32use crate::{EntityIndex, EntityRef, ModuleInternedTypeIndex, PrimaryMap, WasmValType};
33use anyhow::Result;
34use indexmap::IndexMap;
35use info::LinearMemoryOptions;
36use std::collections::HashMap;
37use std::hash::Hash;
38use std::ops::Index;
39use wasmparser::component_types::ComponentCoreModuleTypeId;
40
41#[derive(Default)]
43pub struct ComponentDfg {
44 pub import_types: PrimaryMap<ImportIndex, (String, TypeDef)>,
46
47 pub imports: PrimaryMap<RuntimeImportIndex, (ImportIndex, Vec<String>)>,
49
50 pub exports: IndexMap<String, Export>,
52
53 pub trampolines: Intern<TrampolineIndex, (ModuleInternedTypeIndex, Trampoline)>,
56
57 pub reallocs: Intern<ReallocId, CoreDef>,
60
61 pub callbacks: Intern<CallbackId, CoreDef>,
63
64 pub post_returns: Intern<PostReturnId, CoreDef>,
66
67 pub memories: Intern<MemoryId, CoreExport<MemoryIndex>>,
69
70 pub adapters: Intern<AdapterId, Adapter>,
76
77 pub instances: PrimaryMap<InstanceId, Instance>,
84
85 pub num_runtime_component_instances: u32,
88
89 pub adapter_modules: PrimaryMap<AdapterModuleId, (StaticModuleIndex, Vec<CoreDef>)>,
99
100 pub adapter_partitionings: PrimaryMap<AdapterId, (AdapterModuleId, EntityIndex)>,
111
112 pub resources: PrimaryMap<DefinedResourceIndex, Resource>,
118
119 pub imported_resources: PrimaryMap<ResourceIndex, RuntimeImportIndex>,
123
124 pub num_future_tables: usize,
126
127 pub num_stream_tables: usize,
129
130 pub num_error_context_tables: usize,
133
134 pub side_effects: Vec<SideEffect>,
141
142 pub options: Intern<OptionsId, CanonicalOptions>,
145}
146
147pub enum SideEffect {
149 Instance(InstanceId),
156
157 Resource(DefinedResourceIndex),
164}
165
166#[derive(Clone, Copy, Default)]
172pub enum AbstractInstantiations<'a> {
173 Many,
175
176 One(&'a [info::CoreDef]),
179
180 #[default]
182 None,
183}
184
185impl AbstractInstantiations<'_> {
186 pub fn join(&mut self, other: Self) {
190 *self = match (*self, other) {
191 (Self::Many, _) | (_, Self::Many) => Self::Many,
192 (Self::One(a), Self::One(b)) if a == b => Self::One(a),
193 (Self::One(_), Self::One(_)) => Self::Many,
194 (Self::One(a), Self::None) | (Self::None, Self::One(a)) => Self::One(a),
195 (Self::None, Self::None) => Self::None,
196 }
197 }
198}
199
200macro_rules! id {
201 ($(pub struct $name:ident(u32);)*) => ($(
202 #[derive(Debug, Copy, Clone, Hash, Eq, PartialEq)]
203 #[expect(missing_docs, reason = "tedious to document")]
204 pub struct $name(u32);
205 cranelift_entity::entity_impl!($name);
206 )*)
207}
208
209id! {
210 pub struct InstanceId(u32);
211 pub struct MemoryId(u32);
212 pub struct TableId(u32);
213 pub struct ReallocId(u32);
214 pub struct CallbackId(u32);
215 pub struct AdapterId(u32);
216 pub struct PostReturnId(u32);
217 pub struct AdapterModuleId(u32);
218 pub struct OptionsId(u32);
219}
220
221#[expect(missing_docs, reason = "tedious to document variants")]
223pub enum Instance {
224 Static(StaticModuleIndex, Box<[CoreDef]>),
225 Import(
226 RuntimeImportIndex,
227 IndexMap<String, IndexMap<String, CoreDef>>,
228 ),
229}
230
231#[expect(missing_docs, reason = "tedious to document variants")]
233pub enum Export {
234 LiftedFunction {
235 ty: TypeFuncIndex,
236 func: CoreDef,
237 options: OptionsId,
238 },
239 ModuleStatic {
240 ty: ComponentCoreModuleTypeId,
241 index: StaticModuleIndex,
242 },
243 ModuleImport {
244 ty: TypeModuleIndex,
245 import: RuntimeImportIndex,
246 },
247 Instance {
248 ty: TypeComponentInstanceIndex,
249 exports: IndexMap<String, Export>,
250 },
251 Type(TypeDef),
252}
253
254#[derive(Debug, Clone, Hash, Eq, PartialEq)]
256#[expect(missing_docs, reason = "tedious to document variants")]
257pub enum CoreDef {
258 Export(CoreExport<EntityIndex>),
259 InstanceFlags(RuntimeComponentInstanceIndex),
260 Trampoline(TrampolineIndex),
261 Adapter(AdapterId),
270}
271
272impl<T> From<CoreExport<T>> for CoreDef
273where
274 EntityIndex: From<T>,
275{
276 fn from(export: CoreExport<T>) -> CoreDef {
277 CoreDef::Export(export.map_index(|i| i.into()))
278 }
279}
280
281#[derive(Debug, Clone, Hash, Eq, PartialEq)]
283#[expect(missing_docs, reason = "self-describing fields")]
284pub struct CoreExport<T> {
285 pub instance: InstanceId,
286 pub item: ExportItem<T>,
287}
288
289impl<T> CoreExport<T> {
290 #[expect(missing_docs, reason = "self-describing function")]
291 pub fn map_index<U>(self, f: impl FnOnce(T) -> U) -> CoreExport<U> {
292 CoreExport {
293 instance: self.instance,
294 item: match self.item {
295 ExportItem::Index(i) => ExportItem::Index(f(i)),
296 ExportItem::Name(s) => ExportItem::Name(s),
297 },
298 }
299 }
300}
301
302#[derive(Clone, PartialEq, Eq, Hash)]
304#[expect(missing_docs, reason = "self-describing fields")]
305pub enum Trampoline {
306 LowerImport {
307 import: RuntimeImportIndex,
308 options: OptionsId,
309 lower_ty: TypeFuncIndex,
310 },
311 Transcoder {
312 op: Transcode,
313 from: MemoryId,
314 from64: bool,
315 to: MemoryId,
316 to64: bool,
317 },
318 AlwaysTrap,
319 ResourceNew(TypeResourceTableIndex),
320 ResourceRep(TypeResourceTableIndex),
321 ResourceDrop(TypeResourceTableIndex),
322 BackpressureSet {
323 instance: RuntimeComponentInstanceIndex,
324 },
325 TaskReturn {
326 results: TypeTupleIndex,
327 options: OptionsId,
328 },
329 TaskCancel {
330 instance: RuntimeComponentInstanceIndex,
331 },
332 WaitableSetNew {
333 instance: RuntimeComponentInstanceIndex,
334 },
335 WaitableSetWait {
336 options: OptionsId,
337 },
338 WaitableSetPoll {
339 options: OptionsId,
340 },
341 WaitableSetDrop {
342 instance: RuntimeComponentInstanceIndex,
343 },
344 WaitableJoin {
345 instance: RuntimeComponentInstanceIndex,
346 },
347 Yield {
348 async_: bool,
349 },
350 SubtaskDrop {
351 instance: RuntimeComponentInstanceIndex,
352 },
353 SubtaskCancel {
354 instance: RuntimeComponentInstanceIndex,
355 async_: bool,
356 },
357 StreamNew {
358 ty: TypeStreamTableIndex,
359 },
360 StreamRead {
361 ty: TypeStreamTableIndex,
362 options: OptionsId,
363 },
364 StreamWrite {
365 ty: TypeStreamTableIndex,
366 options: OptionsId,
367 },
368 StreamCancelRead {
369 ty: TypeStreamTableIndex,
370 async_: bool,
371 },
372 StreamCancelWrite {
373 ty: TypeStreamTableIndex,
374 async_: bool,
375 },
376 StreamDropReadable {
377 ty: TypeStreamTableIndex,
378 },
379 StreamDropWritable {
380 ty: TypeStreamTableIndex,
381 },
382 FutureNew {
383 ty: TypeFutureTableIndex,
384 },
385 FutureRead {
386 ty: TypeFutureTableIndex,
387 options: OptionsId,
388 },
389 FutureWrite {
390 ty: TypeFutureTableIndex,
391 options: OptionsId,
392 },
393 FutureCancelRead {
394 ty: TypeFutureTableIndex,
395 async_: bool,
396 },
397 FutureCancelWrite {
398 ty: TypeFutureTableIndex,
399 async_: bool,
400 },
401 FutureDropReadable {
402 ty: TypeFutureTableIndex,
403 },
404 FutureDropWritable {
405 ty: TypeFutureTableIndex,
406 },
407 ErrorContextNew {
408 ty: TypeComponentLocalErrorContextTableIndex,
409 options: OptionsId,
410 },
411 ErrorContextDebugMessage {
412 ty: TypeComponentLocalErrorContextTableIndex,
413 options: OptionsId,
414 },
415 ErrorContextDrop {
416 ty: TypeComponentLocalErrorContextTableIndex,
417 },
418 ResourceTransferOwn,
419 ResourceTransferBorrow,
420 ResourceEnterCall,
421 ResourceExitCall,
422 PrepareCall {
423 memory: Option<MemoryId>,
424 },
425 SyncStartCall {
426 callback: Option<CallbackId>,
427 },
428 AsyncStartCall {
429 callback: Option<CallbackId>,
430 post_return: Option<PostReturnId>,
431 },
432 FutureTransfer,
433 StreamTransfer,
434 ErrorContextTransfer,
435 ContextGet(u32),
436 ContextSet(u32),
437}
438
439#[derive(Copy, Clone, Hash, Eq, PartialEq)]
440#[expect(missing_docs, reason = "self-describing fields")]
441pub struct FutureInfo {
442 pub instance: RuntimeComponentInstanceIndex,
443 pub payload_type: Option<InterfaceType>,
444}
445
446#[derive(Copy, Clone, Hash, Eq, PartialEq)]
447#[expect(missing_docs, reason = "self-describing fields")]
448pub struct StreamInfo {
449 pub instance: RuntimeComponentInstanceIndex,
450 pub payload_type: InterfaceType,
451}
452
453#[derive(Clone, Hash, Eq, PartialEq)]
455#[expect(missing_docs, reason = "self-describing fields")]
456pub enum CanonicalOptionsDataModel {
457 Gc {},
458 LinearMemory {
459 memory: Option<MemoryId>,
460 realloc: Option<ReallocId>,
461 },
462}
463
464#[derive(Clone, Hash, Eq, PartialEq)]
466#[expect(missing_docs, reason = "self-describing fields")]
467pub struct CanonicalOptions {
468 pub instance: RuntimeComponentInstanceIndex,
469 pub string_encoding: StringEncoding,
470 pub callback: Option<CallbackId>,
471 pub post_return: Option<PostReturnId>,
472 pub async_: bool,
473 pub core_type: ModuleInternedTypeIndex,
474 pub data_model: CanonicalOptionsDataModel,
475}
476
477#[expect(missing_docs, reason = "self-describing fields")]
479pub struct Resource {
480 pub rep: WasmValType,
481 pub dtor: Option<CoreDef>,
482 pub instance: RuntimeComponentInstanceIndex,
483}
484
485pub struct Intern<K: EntityRef, V> {
491 intern_map: HashMap<V, K>,
492 key_map: PrimaryMap<K, V>,
493}
494
495impl<K, V> Intern<K, V>
496where
497 K: EntityRef,
498{
499 pub fn push(&mut self, value: V) -> K
506 where
507 V: Hash + Eq + Clone,
508 {
509 *self
510 .intern_map
511 .entry(value.clone())
512 .or_insert_with(|| self.key_map.push(value))
513 }
514
515 pub fn iter(&self) -> impl Iterator<Item = (K, &V)> {
517 self.key_map.iter()
518 }
519}
520
521impl<K: EntityRef, V> Index<K> for Intern<K, V> {
522 type Output = V;
523 fn index(&self, key: K) -> &V {
524 &self.key_map[key]
525 }
526}
527
528impl<K: EntityRef, V> Default for Intern<K, V> {
529 fn default() -> Intern<K, V> {
530 Intern {
531 intern_map: HashMap::new(),
532 key_map: PrimaryMap::new(),
533 }
534 }
535}
536
537impl ComponentDfg {
538 pub fn finish(
541 self,
542 wasmtime_types: &mut ComponentTypesBuilder,
543 wasmparser_types: wasmparser::types::TypesRef<'_>,
544 ) -> Result<ComponentTranslation> {
545 let mut linearize = LinearizeDfg {
546 dfg: &self,
547 initializers: Vec::new(),
548 runtime_memories: Default::default(),
549 runtime_tables: Default::default(),
550 runtime_post_return: Default::default(),
551 runtime_reallocs: Default::default(),
552 runtime_callbacks: Default::default(),
553 runtime_instances: Default::default(),
554 num_lowerings: 0,
555 trampolines: Default::default(),
556 trampoline_defs: Default::default(),
557 trampoline_map: Default::default(),
558 options: Default::default(),
559 options_map: Default::default(),
560 };
561
562 for item in linearize.dfg.side_effects.iter() {
566 linearize.side_effect(item);
567 }
568
569 let mut export_items = PrimaryMap::new();
572 let mut exports = NameMap::default();
573 for (name, export) in self.exports.iter() {
574 let export =
575 linearize.export(export, &mut export_items, wasmtime_types, wasmparser_types)?;
576 exports.insert(name, &mut NameMapNoIntern, false, export)?;
577 }
578
579 Ok(ComponentTranslation {
584 trampolines: linearize.trampoline_defs,
585 component: Component {
586 exports,
587 export_items,
588 initializers: linearize.initializers,
589 trampolines: linearize.trampolines,
590 num_lowerings: linearize.num_lowerings,
591 options: linearize.options,
592
593 num_runtime_memories: linearize.runtime_memories.len() as u32,
594 num_runtime_tables: linearize.runtime_tables.len() as u32,
595 num_runtime_post_returns: linearize.runtime_post_return.len() as u32,
596 num_runtime_reallocs: linearize.runtime_reallocs.len() as u32,
597 num_runtime_callbacks: linearize.runtime_callbacks.len() as u32,
598 num_runtime_instances: linearize.runtime_instances.len() as u32,
599 imports: self.imports,
600 import_types: self.import_types,
601 num_runtime_component_instances: self.num_runtime_component_instances,
602 num_future_tables: self.num_future_tables,
603 num_stream_tables: self.num_stream_tables,
604 num_error_context_tables: self.num_error_context_tables,
605 num_resources: (self.resources.len() + self.imported_resources.len()) as u32,
606 imported_resources: self.imported_resources,
607 defined_resource_instances: self
608 .resources
609 .iter()
610 .map(|(_, r)| r.instance)
611 .collect(),
612 },
613 })
614 }
615
616 pub fn resource_index(&self, defined: DefinedResourceIndex) -> ResourceIndex {
619 ResourceIndex::from_u32(defined.as_u32() + (self.imported_resources.len() as u32))
620 }
621}
622
623struct LinearizeDfg<'a> {
624 dfg: &'a ComponentDfg,
625 initializers: Vec<GlobalInitializer>,
626 trampolines: PrimaryMap<TrampolineIndex, ModuleInternedTypeIndex>,
627 trampoline_defs: PrimaryMap<TrampolineIndex, info::Trampoline>,
628 options: PrimaryMap<OptionsIndex, info::CanonicalOptions>,
629 trampoline_map: HashMap<TrampolineIndex, TrampolineIndex>,
630 runtime_memories: HashMap<MemoryId, RuntimeMemoryIndex>,
631 runtime_tables: HashMap<TableId, RuntimeTableIndex>,
632 runtime_reallocs: HashMap<ReallocId, RuntimeReallocIndex>,
633 runtime_callbacks: HashMap<CallbackId, RuntimeCallbackIndex>,
634 runtime_post_return: HashMap<PostReturnId, RuntimePostReturnIndex>,
635 runtime_instances: HashMap<RuntimeInstance, RuntimeInstanceIndex>,
636 options_map: HashMap<OptionsId, OptionsIndex>,
637 num_lowerings: u32,
638}
639
640#[derive(Copy, Clone, Hash, Eq, PartialEq)]
641enum RuntimeInstance {
642 Normal(InstanceId),
643 Adapter(AdapterModuleId),
644}
645
646impl LinearizeDfg<'_> {
647 fn side_effect(&mut self, effect: &SideEffect) {
648 match effect {
649 SideEffect::Instance(i) => {
650 self.instantiate(*i, &self.dfg.instances[*i]);
651 }
652 SideEffect::Resource(i) => {
653 self.resource(*i, &self.dfg.resources[*i]);
654 }
655 }
656 }
657
658 fn instantiate(&mut self, instance: InstanceId, args: &Instance) {
659 log::trace!("creating instance {instance:?}");
660 let instantiation = match args {
661 Instance::Static(index, args) => InstantiateModule::Static(
662 *index,
663 args.iter().map(|def| self.core_def(def)).collect(),
664 ),
665 Instance::Import(index, args) => InstantiateModule::Import(
666 *index,
667 args.iter()
668 .map(|(module, values)| {
669 let values = values
670 .iter()
671 .map(|(name, def)| (name.clone(), self.core_def(def)))
672 .collect();
673 (module.clone(), values)
674 })
675 .collect(),
676 ),
677 };
678 let index = RuntimeInstanceIndex::new(self.runtime_instances.len());
679 self.initializers
680 .push(GlobalInitializer::InstantiateModule(instantiation));
681 let prev = self
682 .runtime_instances
683 .insert(RuntimeInstance::Normal(instance), index);
684 assert!(prev.is_none());
685 }
686
687 fn resource(&mut self, index: DefinedResourceIndex, resource: &Resource) {
688 let dtor = resource.dtor.as_ref().map(|dtor| self.core_def(dtor));
689 self.initializers
690 .push(GlobalInitializer::Resource(info::Resource {
691 dtor,
692 index,
693 rep: resource.rep,
694 instance: resource.instance,
695 }));
696 }
697
698 fn export(
699 &mut self,
700 export: &Export,
701 items: &mut PrimaryMap<ExportIndex, info::Export>,
702 wasmtime_types: &mut ComponentTypesBuilder,
703 wasmparser_types: wasmparser::types::TypesRef<'_>,
704 ) -> Result<ExportIndex> {
705 let item = match export {
706 Export::LiftedFunction { ty, func, options } => {
707 let func = self.core_def(func);
708 let options = self.options(*options);
709 info::Export::LiftedFunction {
710 ty: *ty,
711 func,
712 options,
713 }
714 }
715 Export::ModuleStatic { ty, index } => info::Export::ModuleStatic {
716 ty: wasmtime_types.convert_module(wasmparser_types, *ty)?,
717 index: *index,
718 },
719 Export::ModuleImport { ty, import } => info::Export::ModuleImport {
720 ty: *ty,
721 import: *import,
722 },
723 Export::Instance { ty, exports } => info::Export::Instance {
724 ty: *ty,
725 exports: {
726 let mut map = NameMap::default();
727 for (name, export) in exports {
728 let export =
729 self.export(export, items, wasmtime_types, wasmparser_types)?;
730 map.insert(name, &mut NameMapNoIntern, false, export)?;
731 }
732 map
733 },
734 },
735 Export::Type(def) => info::Export::Type(*def),
736 };
737 Ok(items.push(item))
738 }
739
740 fn options(&mut self, options: OptionsId) -> OptionsIndex {
741 self.intern_no_init(
742 options,
743 |me| &mut me.options_map,
744 |me, options| me.convert_options(options),
745 )
746 }
747
748 fn convert_options(&mut self, options: OptionsId) -> OptionsIndex {
749 let options = &self.dfg.options[options];
750 let data_model = match options.data_model {
751 CanonicalOptionsDataModel::Gc {} => info::CanonicalOptionsDataModel::Gc {},
752 CanonicalOptionsDataModel::LinearMemory { memory, realloc } => {
753 info::CanonicalOptionsDataModel::LinearMemory(LinearMemoryOptions {
754 memory: memory.map(|mem| self.runtime_memory(mem)),
755 realloc: realloc.map(|mem| self.runtime_realloc(mem)),
756 })
757 }
758 };
759 let callback = options.callback.map(|mem| self.runtime_callback(mem));
760 let post_return = options.post_return.map(|mem| self.runtime_post_return(mem));
761 let options = info::CanonicalOptions {
762 instance: options.instance,
763 string_encoding: options.string_encoding,
764 callback,
765 post_return,
766 async_: options.async_,
767 core_type: options.core_type,
768 data_model,
769 };
770 self.options.push(options)
771 }
772
773 fn runtime_memory(&mut self, mem: MemoryId) -> RuntimeMemoryIndex {
774 self.intern(
775 mem,
776 |me| &mut me.runtime_memories,
777 |me, mem| me.core_export(&me.dfg.memories[mem]),
778 |index, export| GlobalInitializer::ExtractMemory(ExtractMemory { index, export }),
779 )
780 }
781
782 fn runtime_realloc(&mut self, realloc: ReallocId) -> RuntimeReallocIndex {
783 self.intern(
784 realloc,
785 |me| &mut me.runtime_reallocs,
786 |me, realloc| me.core_def(&me.dfg.reallocs[realloc]),
787 |index, def| GlobalInitializer::ExtractRealloc(ExtractRealloc { index, def }),
788 )
789 }
790
791 fn runtime_callback(&mut self, callback: CallbackId) -> RuntimeCallbackIndex {
792 self.intern(
793 callback,
794 |me| &mut me.runtime_callbacks,
795 |me, callback| me.core_def(&me.dfg.callbacks[callback]),
796 |index, def| GlobalInitializer::ExtractCallback(ExtractCallback { index, def }),
797 )
798 }
799
800 fn runtime_post_return(&mut self, post_return: PostReturnId) -> RuntimePostReturnIndex {
801 self.intern(
802 post_return,
803 |me| &mut me.runtime_post_return,
804 |me, post_return| me.core_def(&me.dfg.post_returns[post_return]),
805 |index, def| GlobalInitializer::ExtractPostReturn(ExtractPostReturn { index, def }),
806 )
807 }
808
809 fn core_def(&mut self, def: &CoreDef) -> info::CoreDef {
810 match def {
811 CoreDef::Export(e) => info::CoreDef::Export(self.core_export(e)),
812 CoreDef::InstanceFlags(i) => info::CoreDef::InstanceFlags(*i),
813 CoreDef::Adapter(id) => info::CoreDef::Export(self.adapter(*id)),
814 CoreDef::Trampoline(index) => info::CoreDef::Trampoline(self.trampoline(*index)),
815 }
816 }
817
818 fn trampoline(&mut self, index: TrampolineIndex) -> TrampolineIndex {
819 if let Some(idx) = self.trampoline_map.get(&index) {
820 return *idx;
821 }
822 let (signature, trampoline) = &self.dfg.trampolines[index];
823 let trampoline = match trampoline {
824 Trampoline::LowerImport {
825 import,
826 options,
827 lower_ty,
828 } => {
829 let index = LoweredIndex::from_u32(self.num_lowerings);
830 self.num_lowerings += 1;
831 self.initializers.push(GlobalInitializer::LowerImport {
832 index,
833 import: *import,
834 });
835 info::Trampoline::LowerImport {
836 index,
837 options: self.options(*options),
838 lower_ty: *lower_ty,
839 }
840 }
841 Trampoline::Transcoder {
842 op,
843 from,
844 from64,
845 to,
846 to64,
847 } => info::Trampoline::Transcoder {
848 op: *op,
849 from: self.runtime_memory(*from),
850 from64: *from64,
851 to: self.runtime_memory(*to),
852 to64: *to64,
853 },
854 Trampoline::AlwaysTrap => info::Trampoline::AlwaysTrap,
855 Trampoline::ResourceNew(ty) => info::Trampoline::ResourceNew(*ty),
856 Trampoline::ResourceDrop(ty) => info::Trampoline::ResourceDrop(*ty),
857 Trampoline::ResourceRep(ty) => info::Trampoline::ResourceRep(*ty),
858 Trampoline::BackpressureSet { instance } => info::Trampoline::BackpressureSet {
859 instance: *instance,
860 },
861 Trampoline::TaskReturn { results, options } => info::Trampoline::TaskReturn {
862 results: *results,
863 options: self.options(*options),
864 },
865 Trampoline::TaskCancel { instance } => info::Trampoline::TaskCancel {
866 instance: *instance,
867 },
868 Trampoline::WaitableSetNew { instance } => info::Trampoline::WaitableSetNew {
869 instance: *instance,
870 },
871 Trampoline::WaitableSetWait { options } => info::Trampoline::WaitableSetWait {
872 options: self.options(*options),
873 },
874 Trampoline::WaitableSetPoll { options } => info::Trampoline::WaitableSetPoll {
875 options: self.options(*options),
876 },
877 Trampoline::WaitableSetDrop { instance } => info::Trampoline::WaitableSetDrop {
878 instance: *instance,
879 },
880 Trampoline::WaitableJoin { instance } => info::Trampoline::WaitableJoin {
881 instance: *instance,
882 },
883 Trampoline::Yield { async_ } => info::Trampoline::Yield { async_: *async_ },
884 Trampoline::SubtaskDrop { instance } => info::Trampoline::SubtaskDrop {
885 instance: *instance,
886 },
887 Trampoline::SubtaskCancel { instance, async_ } => info::Trampoline::SubtaskCancel {
888 instance: *instance,
889 async_: *async_,
890 },
891 Trampoline::StreamNew { ty } => info::Trampoline::StreamNew { ty: *ty },
892 Trampoline::StreamRead { ty, options } => info::Trampoline::StreamRead {
893 ty: *ty,
894 options: self.options(*options),
895 },
896 Trampoline::StreamWrite { ty, options } => info::Trampoline::StreamWrite {
897 ty: *ty,
898 options: self.options(*options),
899 },
900 Trampoline::StreamCancelRead { ty, async_ } => info::Trampoline::StreamCancelRead {
901 ty: *ty,
902 async_: *async_,
903 },
904 Trampoline::StreamCancelWrite { ty, async_ } => info::Trampoline::StreamCancelWrite {
905 ty: *ty,
906 async_: *async_,
907 },
908 Trampoline::StreamDropReadable { ty } => {
909 info::Trampoline::StreamDropReadable { ty: *ty }
910 }
911 Trampoline::StreamDropWritable { ty } => {
912 info::Trampoline::StreamDropWritable { ty: *ty }
913 }
914 Trampoline::FutureNew { ty } => info::Trampoline::FutureNew { ty: *ty },
915 Trampoline::FutureRead { ty, options } => info::Trampoline::FutureRead {
916 ty: *ty,
917 options: self.options(*options),
918 },
919 Trampoline::FutureWrite { ty, options } => info::Trampoline::FutureWrite {
920 ty: *ty,
921 options: self.options(*options),
922 },
923 Trampoline::FutureCancelRead { ty, async_ } => info::Trampoline::FutureCancelRead {
924 ty: *ty,
925 async_: *async_,
926 },
927 Trampoline::FutureCancelWrite { ty, async_ } => info::Trampoline::FutureCancelWrite {
928 ty: *ty,
929 async_: *async_,
930 },
931 Trampoline::FutureDropReadable { ty } => {
932 info::Trampoline::FutureDropReadable { ty: *ty }
933 }
934 Trampoline::FutureDropWritable { ty } => {
935 info::Trampoline::FutureDropWritable { ty: *ty }
936 }
937 Trampoline::ErrorContextNew { ty, options } => info::Trampoline::ErrorContextNew {
938 ty: *ty,
939 options: self.options(*options),
940 },
941 Trampoline::ErrorContextDebugMessage { ty, options } => {
942 info::Trampoline::ErrorContextDebugMessage {
943 ty: *ty,
944 options: self.options(*options),
945 }
946 }
947 Trampoline::ErrorContextDrop { ty } => info::Trampoline::ErrorContextDrop { ty: *ty },
948 Trampoline::ResourceTransferOwn => info::Trampoline::ResourceTransferOwn,
949 Trampoline::ResourceTransferBorrow => info::Trampoline::ResourceTransferBorrow,
950 Trampoline::ResourceEnterCall => info::Trampoline::ResourceEnterCall,
951 Trampoline::ResourceExitCall => info::Trampoline::ResourceExitCall,
952 Trampoline::PrepareCall { memory } => info::Trampoline::PrepareCall {
953 memory: memory.map(|v| self.runtime_memory(v)),
954 },
955 Trampoline::SyncStartCall { callback } => info::Trampoline::SyncStartCall {
956 callback: callback.map(|v| self.runtime_callback(v)),
957 },
958 Trampoline::AsyncStartCall {
959 callback,
960 post_return,
961 } => info::Trampoline::AsyncStartCall {
962 callback: callback.map(|v| self.runtime_callback(v)),
963 post_return: post_return.map(|v| self.runtime_post_return(v)),
964 },
965 Trampoline::FutureTransfer => info::Trampoline::FutureTransfer,
966 Trampoline::StreamTransfer => info::Trampoline::StreamTransfer,
967 Trampoline::ErrorContextTransfer => info::Trampoline::ErrorContextTransfer,
968 Trampoline::ContextGet(i) => info::Trampoline::ContextGet(*i),
969 Trampoline::ContextSet(i) => info::Trampoline::ContextSet(*i),
970 };
971 let i1 = self.trampolines.push(*signature);
972 let i2 = self.trampoline_defs.push(trampoline);
973 assert_eq!(i1, i2);
974 self.trampoline_map.insert(index, i1);
975 i1
976 }
977
978 fn core_export<T>(&mut self, export: &CoreExport<T>) -> info::CoreExport<T>
979 where
980 T: Clone,
981 {
982 let instance = export.instance;
983 log::trace!("referencing export of {instance:?}");
984 info::CoreExport {
985 instance: self.runtime_instances[&RuntimeInstance::Normal(instance)],
986 item: export.item.clone(),
987 }
988 }
989
990 fn adapter(&mut self, adapter: AdapterId) -> info::CoreExport<EntityIndex> {
991 let (adapter_module, entity_index) = self.dfg.adapter_partitionings[adapter];
992
993 let instance = self.adapter_module(adapter_module);
997
998 info::CoreExport {
1000 instance,
1001 item: ExportItem::Index(entity_index),
1002 }
1003 }
1004
1005 fn adapter_module(&mut self, adapter_module: AdapterModuleId) -> RuntimeInstanceIndex {
1006 self.intern(
1007 RuntimeInstance::Adapter(adapter_module),
1008 |me| &mut me.runtime_instances,
1009 |me, _| {
1010 log::debug!("instantiating {adapter_module:?}");
1011 let (module_index, args) = &me.dfg.adapter_modules[adapter_module];
1012 let args = args.iter().map(|arg| me.core_def(arg)).collect();
1013 let instantiate = InstantiateModule::Static(*module_index, args);
1014 GlobalInitializer::InstantiateModule(instantiate)
1015 },
1016 |_, init| init,
1017 )
1018 }
1019
1020 fn intern<K, V, T>(
1035 &mut self,
1036 key: K,
1037 map: impl Fn(&mut Self) -> &mut HashMap<K, V>,
1038 generate: impl FnOnce(&mut Self, K) -> T,
1039 init: impl FnOnce(V, T) -> GlobalInitializer,
1040 ) -> V
1041 where
1042 K: Hash + Eq + Copy,
1043 V: EntityRef,
1044 {
1045 self.intern_(key, map, generate, |me, key, val| {
1046 me.initializers.push(init(key, val));
1047 })
1048 }
1049
1050 fn intern_no_init<K, V, T>(
1051 &mut self,
1052 key: K,
1053 map: impl Fn(&mut Self) -> &mut HashMap<K, V>,
1054 generate: impl FnOnce(&mut Self, K) -> T,
1055 ) -> V
1056 where
1057 K: Hash + Eq + Copy,
1058 V: EntityRef,
1059 {
1060 self.intern_(key, map, generate, |_me, _key, _val| {})
1061 }
1062
1063 fn intern_<K, V, T>(
1064 &mut self,
1065 key: K,
1066 map: impl Fn(&mut Self) -> &mut HashMap<K, V>,
1067 generate: impl FnOnce(&mut Self, K) -> T,
1068 init: impl FnOnce(&mut Self, V, T),
1069 ) -> V
1070 where
1071 K: Hash + Eq + Copy,
1072 V: EntityRef,
1073 {
1074 if let Some(val) = map(self).get(&key) {
1075 return *val;
1076 }
1077 let tmp = generate(self, key);
1078 let index = V::new(map(self).len());
1079 init(self, index, tmp);
1080 let prev = map(self).insert(key, index);
1081 assert!(prev.is_none());
1082 index
1083 }
1084}