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