1use crate::component::*;
31use crate::prelude::*;
32use crate::{EntityIndex, EntityRef, ModuleInternedTypeIndex, PrimaryMap, WasmValType};
33use anyhow::Result;
34use cranelift_entity::packed_option::PackedOption;
35use indexmap::IndexMap;
36use info::LinearMemoryOptions;
37use std::collections::HashMap;
38use std::hash::Hash;
39use std::ops::Index;
40use wasmparser::component_types::ComponentCoreModuleTypeId;
41
42#[derive(Default)]
44pub struct ComponentDfg {
45 pub import_types: PrimaryMap<ImportIndex, (String, TypeDef)>,
47
48 pub imports: PrimaryMap<RuntimeImportIndex, (ImportIndex, Vec<String>)>,
50
51 pub exports: IndexMap<String, Export>,
53
54 pub trampolines: Intern<TrampolineIndex, (ModuleInternedTypeIndex, Trampoline)>,
57
58 pub unsafe_intrinsics: [PackedOption<ModuleInternedTypeIndex>; UnsafeIntrinsic::len() as usize],
61
62 pub reallocs: Intern<ReallocId, CoreDef>,
65
66 pub callbacks: Intern<CallbackId, CoreDef>,
68
69 pub post_returns: Intern<PostReturnId, CoreDef>,
71
72 pub memories: Intern<MemoryId, CoreExport<MemoryIndex>>,
74
75 pub tables: Intern<TableId, CoreExport<TableIndex>>,
77
78 pub adapters: Intern<AdapterId, Adapter>,
84
85 pub instances: PrimaryMap<InstanceId, Instance>,
92
93 pub num_runtime_component_instances: u32,
96
97 pub adapter_modules: PrimaryMap<AdapterModuleId, (StaticModuleIndex, Vec<CoreDef>)>,
107
108 pub adapter_partitionings: PrimaryMap<AdapterId, (AdapterModuleId, EntityIndex)>,
119
120 pub resources: PrimaryMap<DefinedResourceIndex, Resource>,
126
127 pub imported_resources: PrimaryMap<ResourceIndex, RuntimeImportIndex>,
131
132 pub num_future_tables: usize,
134
135 pub num_stream_tables: usize,
137
138 pub num_error_context_tables: usize,
141
142 pub side_effects: Vec<SideEffect>,
149
150 pub options: Intern<OptionsId, CanonicalOptions>,
153}
154
155pub enum SideEffect {
157 Instance(InstanceId),
164
165 Resource(DefinedResourceIndex),
172}
173
174#[derive(Clone, Copy, Default)]
180pub enum AbstractInstantiations<'a> {
181 Many,
183
184 One(&'a [info::CoreDef]),
187
188 #[default]
190 None,
191}
192
193impl AbstractInstantiations<'_> {
194 pub fn join(&mut self, other: Self) {
198 *self = match (*self, other) {
199 (Self::Many, _) | (_, Self::Many) => Self::Many,
200 (Self::One(a), Self::One(b)) if a == b => Self::One(a),
201 (Self::One(_), Self::One(_)) => Self::Many,
202 (Self::One(a), Self::None) | (Self::None, Self::One(a)) => Self::One(a),
203 (Self::None, Self::None) => Self::None,
204 }
205 }
206}
207
208macro_rules! id {
209 ($(pub struct $name:ident(u32);)*) => ($(
210 #[derive(Debug, Copy, Clone, Hash, Eq, PartialEq)]
211 #[expect(missing_docs, reason = "tedious to document")]
212 pub struct $name(u32);
213 cranelift_entity::entity_impl!($name);
214 )*)
215}
216
217id! {
218 pub struct InstanceId(u32);
219 pub struct MemoryId(u32);
220 pub struct TableId(u32);
221 pub struct ReallocId(u32);
222 pub struct CallbackId(u32);
223 pub struct AdapterId(u32);
224 pub struct PostReturnId(u32);
225 pub struct AdapterModuleId(u32);
226 pub struct OptionsId(u32);
227}
228
229#[expect(missing_docs, reason = "tedious to document variants")]
231pub enum Instance {
232 Static(StaticModuleIndex, Box<[CoreDef]>),
233 Import(
234 RuntimeImportIndex,
235 IndexMap<String, IndexMap<String, CoreDef>>,
236 ),
237}
238
239#[expect(missing_docs, reason = "tedious to document variants")]
241pub enum Export {
242 LiftedFunction {
243 ty: TypeFuncIndex,
244 func: CoreDef,
245 options: OptionsId,
246 },
247 ModuleStatic {
248 ty: ComponentCoreModuleTypeId,
249 index: StaticModuleIndex,
250 },
251 ModuleImport {
252 ty: TypeModuleIndex,
253 import: RuntimeImportIndex,
254 },
255 Instance {
256 ty: TypeComponentInstanceIndex,
257 exports: IndexMap<String, Export>,
258 },
259 Type(TypeDef),
260}
261
262#[derive(Debug, Clone, Hash, Eq, PartialEq)]
264#[expect(missing_docs, reason = "tedious to document variants")]
265pub enum CoreDef {
266 Export(CoreExport<EntityIndex>),
267 InstanceFlags(RuntimeComponentInstanceIndex),
268 Trampoline(TrampolineIndex),
269 UnsafeIntrinsic(ModuleInternedTypeIndex, UnsafeIntrinsic),
270
271 Adapter(AdapterId),
280}
281
282impl<T> From<CoreExport<T>> for CoreDef
283where
284 EntityIndex: From<T>,
285{
286 fn from(export: CoreExport<T>) -> CoreDef {
287 CoreDef::Export(export.map_index(|i| i.into()))
288 }
289}
290
291#[derive(Debug, Clone, Hash, Eq, PartialEq)]
293#[expect(missing_docs, reason = "self-describing fields")]
294pub struct CoreExport<T> {
295 pub instance: InstanceId,
296 pub item: ExportItem<T>,
297}
298
299impl<T> CoreExport<T> {
300 #[expect(missing_docs, reason = "self-describing function")]
301 pub fn map_index<U>(self, f: impl FnOnce(T) -> U) -> CoreExport<U> {
302 CoreExport {
303 instance: self.instance,
304 item: match self.item {
305 ExportItem::Index(i) => ExportItem::Index(f(i)),
306 ExportItem::Name(s) => ExportItem::Name(s),
307 },
308 }
309 }
310}
311
312#[derive(Clone, PartialEq, Eq, Hash)]
314#[expect(missing_docs, reason = "self-describing fields")]
315pub enum Trampoline {
316 LowerImport {
317 import: RuntimeImportIndex,
318 options: OptionsId,
319 lower_ty: TypeFuncIndex,
320 },
321 Transcoder {
322 op: Transcode,
323 from: MemoryId,
324 from64: bool,
325 to: MemoryId,
326 to64: bool,
327 },
328 AlwaysTrap,
329 ResourceNew {
330 instance: RuntimeComponentInstanceIndex,
331 ty: TypeResourceTableIndex,
332 },
333 ResourceRep {
334 instance: RuntimeComponentInstanceIndex,
335 ty: TypeResourceTableIndex,
336 },
337 ResourceDrop {
338 instance: RuntimeComponentInstanceIndex,
339 ty: TypeResourceTableIndex,
340 },
341 BackpressureInc {
342 instance: RuntimeComponentInstanceIndex,
343 },
344 BackpressureDec {
345 instance: RuntimeComponentInstanceIndex,
346 },
347 TaskReturn {
348 instance: RuntimeComponentInstanceIndex,
349 results: TypeTupleIndex,
350 options: OptionsId,
351 },
352 TaskCancel {
353 instance: RuntimeComponentInstanceIndex,
354 },
355 WaitableSetNew {
356 instance: RuntimeComponentInstanceIndex,
357 },
358 WaitableSetWait {
359 instance: RuntimeComponentInstanceIndex,
360 options: OptionsId,
361 },
362 WaitableSetPoll {
363 instance: RuntimeComponentInstanceIndex,
364 options: OptionsId,
365 },
366 WaitableSetDrop {
367 instance: RuntimeComponentInstanceIndex,
368 },
369 WaitableJoin {
370 instance: RuntimeComponentInstanceIndex,
371 },
372 ThreadYield {
373 instance: RuntimeComponentInstanceIndex,
374 cancellable: bool,
375 },
376 SubtaskDrop {
377 instance: RuntimeComponentInstanceIndex,
378 },
379 SubtaskCancel {
380 instance: RuntimeComponentInstanceIndex,
381 async_: bool,
382 },
383 StreamNew {
384 instance: RuntimeComponentInstanceIndex,
385 ty: TypeStreamTableIndex,
386 },
387 StreamRead {
388 instance: RuntimeComponentInstanceIndex,
389 ty: TypeStreamTableIndex,
390 options: OptionsId,
391 },
392 StreamWrite {
393 instance: RuntimeComponentInstanceIndex,
394 ty: TypeStreamTableIndex,
395 options: OptionsId,
396 },
397 StreamCancelRead {
398 instance: RuntimeComponentInstanceIndex,
399 ty: TypeStreamTableIndex,
400 async_: bool,
401 },
402 StreamCancelWrite {
403 instance: RuntimeComponentInstanceIndex,
404 ty: TypeStreamTableIndex,
405 async_: bool,
406 },
407 StreamDropReadable {
408 instance: RuntimeComponentInstanceIndex,
409 ty: TypeStreamTableIndex,
410 },
411 StreamDropWritable {
412 instance: RuntimeComponentInstanceIndex,
413 ty: TypeStreamTableIndex,
414 },
415 FutureNew {
416 instance: RuntimeComponentInstanceIndex,
417 ty: TypeFutureTableIndex,
418 },
419 FutureRead {
420 instance: RuntimeComponentInstanceIndex,
421 ty: TypeFutureTableIndex,
422 options: OptionsId,
423 },
424 FutureWrite {
425 instance: RuntimeComponentInstanceIndex,
426 ty: TypeFutureTableIndex,
427 options: OptionsId,
428 },
429 FutureCancelRead {
430 instance: RuntimeComponentInstanceIndex,
431 ty: TypeFutureTableIndex,
432 async_: bool,
433 },
434 FutureCancelWrite {
435 instance: RuntimeComponentInstanceIndex,
436 ty: TypeFutureTableIndex,
437 async_: bool,
438 },
439 FutureDropReadable {
440 instance: RuntimeComponentInstanceIndex,
441 ty: TypeFutureTableIndex,
442 },
443 FutureDropWritable {
444 instance: RuntimeComponentInstanceIndex,
445 ty: TypeFutureTableIndex,
446 },
447 ErrorContextNew {
448 instance: RuntimeComponentInstanceIndex,
449 ty: TypeComponentLocalErrorContextTableIndex,
450 options: OptionsId,
451 },
452 ErrorContextDebugMessage {
453 instance: RuntimeComponentInstanceIndex,
454 ty: TypeComponentLocalErrorContextTableIndex,
455 options: OptionsId,
456 },
457 ErrorContextDrop {
458 instance: RuntimeComponentInstanceIndex,
459 ty: TypeComponentLocalErrorContextTableIndex,
460 },
461 ResourceTransferOwn,
462 ResourceTransferBorrow,
463 ResourceEnterCall,
464 ResourceExitCall,
465 PrepareCall {
466 memory: Option<MemoryId>,
467 },
468 SyncStartCall {
469 callback: Option<CallbackId>,
470 },
471 AsyncStartCall {
472 callback: Option<CallbackId>,
473 post_return: Option<PostReturnId>,
474 },
475 FutureTransfer,
476 StreamTransfer,
477 ErrorContextTransfer,
478 CheckBlocking,
479 ContextGet {
480 instance: RuntimeComponentInstanceIndex,
481 slot: u32,
482 },
483 ContextSet {
484 instance: RuntimeComponentInstanceIndex,
485 slot: u32,
486 },
487 ThreadIndex,
488 ThreadNewIndirect {
489 instance: RuntimeComponentInstanceIndex,
490 start_func_ty_idx: ComponentTypeIndex,
491 start_func_table_id: TableId,
492 },
493 ThreadSwitchTo {
494 instance: RuntimeComponentInstanceIndex,
495 cancellable: bool,
496 },
497 ThreadSuspend {
498 instance: RuntimeComponentInstanceIndex,
499 cancellable: bool,
500 },
501 ThreadResumeLater {
502 instance: RuntimeComponentInstanceIndex,
503 },
504 ThreadYieldTo {
505 instance: RuntimeComponentInstanceIndex,
506 cancellable: bool,
507 },
508}
509
510#[derive(Copy, Clone, Hash, Eq, PartialEq)]
511#[expect(missing_docs, reason = "self-describing fields")]
512pub struct FutureInfo {
513 pub instance: RuntimeComponentInstanceIndex,
514 pub payload_type: Option<InterfaceType>,
515}
516
517#[derive(Copy, Clone, Hash, Eq, PartialEq)]
518#[expect(missing_docs, reason = "self-describing fields")]
519pub struct StreamInfo {
520 pub instance: RuntimeComponentInstanceIndex,
521 pub payload_type: InterfaceType,
522}
523
524#[derive(Clone, Hash, Eq, PartialEq)]
526#[expect(missing_docs, reason = "self-describing fields")]
527pub enum CanonicalOptionsDataModel {
528 Gc {},
529 LinearMemory {
530 memory: Option<MemoryId>,
531 realloc: Option<ReallocId>,
532 },
533}
534
535#[derive(Clone, Hash, Eq, PartialEq)]
537#[expect(missing_docs, reason = "self-describing fields")]
538pub struct CanonicalOptions {
539 pub instance: RuntimeComponentInstanceIndex,
540 pub string_encoding: StringEncoding,
541 pub callback: Option<CallbackId>,
542 pub post_return: Option<PostReturnId>,
543 pub async_: bool,
544 pub cancellable: bool,
545 pub core_type: ModuleInternedTypeIndex,
546 pub data_model: CanonicalOptionsDataModel,
547}
548
549#[expect(missing_docs, reason = "self-describing fields")]
551pub struct Resource {
552 pub rep: WasmValType,
553 pub dtor: Option<CoreDef>,
554 pub instance: RuntimeComponentInstanceIndex,
555}
556
557pub struct Intern<K: EntityRef, V> {
563 intern_map: HashMap<V, K>,
564 key_map: PrimaryMap<K, V>,
565}
566
567impl<K, V> Intern<K, V>
568where
569 K: EntityRef,
570{
571 pub fn push(&mut self, value: V) -> K
578 where
579 V: Hash + Eq + Clone,
580 {
581 *self
582 .intern_map
583 .entry(value.clone())
584 .or_insert_with(|| self.key_map.push(value))
585 }
586
587 pub fn iter(&self) -> impl Iterator<Item = (K, &V)> {
589 self.key_map.iter()
590 }
591}
592
593impl<K: EntityRef, V> Index<K> for Intern<K, V> {
594 type Output = V;
595 fn index(&self, key: K) -> &V {
596 &self.key_map[key]
597 }
598}
599
600impl<K: EntityRef, V> Default for Intern<K, V> {
601 fn default() -> Intern<K, V> {
602 Intern {
603 intern_map: HashMap::new(),
604 key_map: PrimaryMap::new(),
605 }
606 }
607}
608
609impl ComponentDfg {
610 pub fn finish(
613 self,
614 wasmtime_types: &mut ComponentTypesBuilder,
615 wasmparser_types: wasmparser::types::TypesRef<'_>,
616 ) -> Result<ComponentTranslation> {
617 let mut linearize = LinearizeDfg {
618 dfg: &self,
619 initializers: Vec::new(),
620 runtime_memories: Default::default(),
621 runtime_tables: Default::default(),
622 runtime_post_return: Default::default(),
623 runtime_reallocs: Default::default(),
624 runtime_callbacks: Default::default(),
625 runtime_instances: Default::default(),
626 num_lowerings: 0,
627 unsafe_intrinsics: Default::default(),
628 trampolines: Default::default(),
629 trampoline_defs: Default::default(),
630 trampoline_map: Default::default(),
631 options: Default::default(),
632 options_map: Default::default(),
633 };
634
635 for item in linearize.dfg.side_effects.iter() {
639 linearize.side_effect(item);
640 }
641
642 let mut export_items = PrimaryMap::new();
645 let mut exports = NameMap::default();
646 for (name, export) in self.exports.iter() {
647 let export =
648 linearize.export(export, &mut export_items, wasmtime_types, wasmparser_types)?;
649 exports.insert(name, &mut NameMapNoIntern, false, export)?;
650 }
651
652 Ok(ComponentTranslation {
657 trampolines: linearize.trampoline_defs,
658 component: Component {
659 exports,
660 export_items,
661 initializers: linearize.initializers,
662 unsafe_intrinsics: linearize.unsafe_intrinsics,
663 trampolines: linearize.trampolines,
664 num_lowerings: linearize.num_lowerings,
665 options: linearize.options,
666
667 num_runtime_memories: linearize.runtime_memories.len() as u32,
668 num_runtime_tables: linearize.runtime_tables.len() as u32,
669 num_runtime_post_returns: linearize.runtime_post_return.len() as u32,
670 num_runtime_reallocs: linearize.runtime_reallocs.len() as u32,
671 num_runtime_callbacks: linearize.runtime_callbacks.len() as u32,
672 num_runtime_instances: linearize.runtime_instances.len() as u32,
673 imports: self.imports,
674 import_types: self.import_types,
675 num_runtime_component_instances: self.num_runtime_component_instances,
676 num_future_tables: self.num_future_tables,
677 num_stream_tables: self.num_stream_tables,
678 num_error_context_tables: self.num_error_context_tables,
679 num_resources: (self.resources.len() + self.imported_resources.len()) as u32,
680 imported_resources: self.imported_resources,
681 defined_resource_instances: self
682 .resources
683 .iter()
684 .map(|(_, r)| r.instance)
685 .collect(),
686 },
687 })
688 }
689
690 pub fn resource_index(&self, defined: DefinedResourceIndex) -> ResourceIndex {
693 ResourceIndex::from_u32(defined.as_u32() + (self.imported_resources.len() as u32))
694 }
695}
696
697struct LinearizeDfg<'a> {
698 dfg: &'a ComponentDfg,
699 initializers: Vec<GlobalInitializer>,
700 unsafe_intrinsics: [PackedOption<ModuleInternedTypeIndex>; UnsafeIntrinsic::len() as usize],
701 trampolines: PrimaryMap<TrampolineIndex, ModuleInternedTypeIndex>,
702 trampoline_defs: PrimaryMap<TrampolineIndex, info::Trampoline>,
703 options: PrimaryMap<OptionsIndex, info::CanonicalOptions>,
704 trampoline_map: HashMap<TrampolineIndex, TrampolineIndex>,
705 runtime_memories: HashMap<MemoryId, RuntimeMemoryIndex>,
706 runtime_tables: HashMap<TableId, RuntimeTableIndex>,
707 runtime_reallocs: HashMap<ReallocId, RuntimeReallocIndex>,
708 runtime_callbacks: HashMap<CallbackId, RuntimeCallbackIndex>,
709 runtime_post_return: HashMap<PostReturnId, RuntimePostReturnIndex>,
710 runtime_instances: HashMap<RuntimeInstance, RuntimeInstanceIndex>,
711 options_map: HashMap<OptionsId, OptionsIndex>,
712 num_lowerings: u32,
713}
714
715#[derive(Copy, Clone, Hash, Eq, PartialEq)]
716enum RuntimeInstance {
717 Normal(InstanceId),
718 Adapter(AdapterModuleId),
719}
720
721impl LinearizeDfg<'_> {
722 fn side_effect(&mut self, effect: &SideEffect) {
723 match effect {
724 SideEffect::Instance(i) => {
725 self.instantiate(*i, &self.dfg.instances[*i]);
726 }
727 SideEffect::Resource(i) => {
728 self.resource(*i, &self.dfg.resources[*i]);
729 }
730 }
731 }
732
733 fn instantiate(&mut self, instance: InstanceId, args: &Instance) {
734 log::trace!("creating instance {instance:?}");
735 let instantiation = match args {
736 Instance::Static(index, args) => InstantiateModule::Static(
737 *index,
738 args.iter().map(|def| self.core_def(def)).collect(),
739 ),
740 Instance::Import(index, args) => InstantiateModule::Import(
741 *index,
742 args.iter()
743 .map(|(module, values)| {
744 let values = values
745 .iter()
746 .map(|(name, def)| (name.clone(), self.core_def(def)))
747 .collect();
748 (module.clone(), values)
749 })
750 .collect(),
751 ),
752 };
753 let index = RuntimeInstanceIndex::new(self.runtime_instances.len());
754 self.initializers
755 .push(GlobalInitializer::InstantiateModule(instantiation));
756 let prev = self
757 .runtime_instances
758 .insert(RuntimeInstance::Normal(instance), index);
759 assert!(prev.is_none());
760 }
761
762 fn resource(&mut self, index: DefinedResourceIndex, resource: &Resource) {
763 let dtor = resource.dtor.as_ref().map(|dtor| self.core_def(dtor));
764 self.initializers
765 .push(GlobalInitializer::Resource(info::Resource {
766 dtor,
767 index,
768 rep: resource.rep,
769 instance: resource.instance,
770 }));
771 }
772
773 fn export(
774 &mut self,
775 export: &Export,
776 items: &mut PrimaryMap<ExportIndex, info::Export>,
777 wasmtime_types: &mut ComponentTypesBuilder,
778 wasmparser_types: wasmparser::types::TypesRef<'_>,
779 ) -> Result<ExportIndex> {
780 let item = match export {
781 Export::LiftedFunction { ty, func, options } => {
782 let func = self.core_def(func);
783 let options = self.options(*options);
784 info::Export::LiftedFunction {
785 ty: *ty,
786 func,
787 options,
788 }
789 }
790 Export::ModuleStatic { ty, index } => info::Export::ModuleStatic {
791 ty: wasmtime_types.convert_module(wasmparser_types, *ty)?,
792 index: *index,
793 },
794 Export::ModuleImport { ty, import } => info::Export::ModuleImport {
795 ty: *ty,
796 import: *import,
797 },
798 Export::Instance { ty, exports } => info::Export::Instance {
799 ty: *ty,
800 exports: {
801 let mut map = NameMap::default();
802 for (name, export) in exports {
803 let export =
804 self.export(export, items, wasmtime_types, wasmparser_types)?;
805 map.insert(name, &mut NameMapNoIntern, false, export)?;
806 }
807 map
808 },
809 },
810 Export::Type(def) => info::Export::Type(*def),
811 };
812 Ok(items.push(item))
813 }
814
815 fn options(&mut self, options: OptionsId) -> OptionsIndex {
816 self.intern_no_init(
817 options,
818 |me| &mut me.options_map,
819 |me, options| me.convert_options(options),
820 )
821 }
822
823 fn convert_options(&mut self, options: OptionsId) -> OptionsIndex {
824 let options = &self.dfg.options[options];
825 let data_model = match options.data_model {
826 CanonicalOptionsDataModel::Gc {} => info::CanonicalOptionsDataModel::Gc {},
827 CanonicalOptionsDataModel::LinearMemory { memory, realloc } => {
828 info::CanonicalOptionsDataModel::LinearMemory(LinearMemoryOptions {
829 memory: memory.map(|mem| self.runtime_memory(mem)),
830 realloc: realloc.map(|mem| self.runtime_realloc(mem)),
831 })
832 }
833 };
834 let callback = options.callback.map(|mem| self.runtime_callback(mem));
835 let post_return = options.post_return.map(|mem| self.runtime_post_return(mem));
836 let options = info::CanonicalOptions {
837 instance: options.instance,
838 string_encoding: options.string_encoding,
839 callback,
840 post_return,
841 async_: options.async_,
842 cancellable: options.cancellable,
843 core_type: options.core_type,
844 data_model,
845 };
846 self.options.push(options)
847 }
848
849 fn runtime_memory(&mut self, mem: MemoryId) -> RuntimeMemoryIndex {
850 self.intern(
851 mem,
852 |me| &mut me.runtime_memories,
853 |me, mem| me.core_export(&me.dfg.memories[mem]),
854 |index, export| GlobalInitializer::ExtractMemory(ExtractMemory { index, export }),
855 )
856 }
857
858 fn runtime_table(&mut self, table: TableId) -> RuntimeTableIndex {
859 self.intern(
860 table,
861 |me| &mut me.runtime_tables,
862 |me, table| me.core_export(&me.dfg.tables[table]),
863 |index, export| GlobalInitializer::ExtractTable(ExtractTable { index, export }),
864 )
865 }
866
867 fn runtime_realloc(&mut self, realloc: ReallocId) -> RuntimeReallocIndex {
868 self.intern(
869 realloc,
870 |me| &mut me.runtime_reallocs,
871 |me, realloc| me.core_def(&me.dfg.reallocs[realloc]),
872 |index, def| GlobalInitializer::ExtractRealloc(ExtractRealloc { index, def }),
873 )
874 }
875
876 fn runtime_callback(&mut self, callback: CallbackId) -> RuntimeCallbackIndex {
877 self.intern(
878 callback,
879 |me| &mut me.runtime_callbacks,
880 |me, callback| me.core_def(&me.dfg.callbacks[callback]),
881 |index, def| GlobalInitializer::ExtractCallback(ExtractCallback { index, def }),
882 )
883 }
884
885 fn runtime_post_return(&mut self, post_return: PostReturnId) -> RuntimePostReturnIndex {
886 self.intern(
887 post_return,
888 |me| &mut me.runtime_post_return,
889 |me, post_return| me.core_def(&me.dfg.post_returns[post_return]),
890 |index, def| GlobalInitializer::ExtractPostReturn(ExtractPostReturn { index, def }),
891 )
892 }
893
894 fn core_def(&mut self, def: &CoreDef) -> info::CoreDef {
895 match def {
896 CoreDef::Export(e) => info::CoreDef::Export(self.core_export(e)),
897 CoreDef::InstanceFlags(i) => info::CoreDef::InstanceFlags(*i),
898 CoreDef::Adapter(id) => info::CoreDef::Export(self.adapter(*id)),
899 CoreDef::Trampoline(index) => info::CoreDef::Trampoline(self.trampoline(*index)),
900 CoreDef::UnsafeIntrinsic(ty, i) => {
901 let index = usize::try_from(i.index()).unwrap();
902 if self.unsafe_intrinsics[index].is_none() {
903 self.unsafe_intrinsics[index] = Some(*ty).into();
904 }
905 info::CoreDef::UnsafeIntrinsic(*i)
906 }
907 }
908 }
909
910 fn trampoline(&mut self, index: TrampolineIndex) -> TrampolineIndex {
911 if let Some(idx) = self.trampoline_map.get(&index) {
912 return *idx;
913 }
914 let (signature, trampoline) = &self.dfg.trampolines[index];
915 let trampoline = match trampoline {
916 Trampoline::LowerImport {
917 import,
918 options,
919 lower_ty,
920 } => {
921 let index = LoweredIndex::from_u32(self.num_lowerings);
922 self.num_lowerings += 1;
923 self.initializers.push(GlobalInitializer::LowerImport {
924 index,
925 import: *import,
926 });
927 info::Trampoline::LowerImport {
928 index,
929 options: self.options(*options),
930 lower_ty: *lower_ty,
931 }
932 }
933 Trampoline::Transcoder {
934 op,
935 from,
936 from64,
937 to,
938 to64,
939 } => info::Trampoline::Transcoder {
940 op: *op,
941 from: self.runtime_memory(*from),
942 from64: *from64,
943 to: self.runtime_memory(*to),
944 to64: *to64,
945 },
946 Trampoline::AlwaysTrap => info::Trampoline::AlwaysTrap,
947 Trampoline::ResourceNew { instance, ty } => info::Trampoline::ResourceNew {
948 instance: *instance,
949 ty: *ty,
950 },
951 Trampoline::ResourceDrop { instance, ty } => info::Trampoline::ResourceDrop {
952 instance: *instance,
953 ty: *ty,
954 },
955 Trampoline::ResourceRep { instance, ty } => info::Trampoline::ResourceRep {
956 instance: *instance,
957 ty: *ty,
958 },
959 Trampoline::BackpressureInc { instance } => info::Trampoline::BackpressureInc {
960 instance: *instance,
961 },
962 Trampoline::BackpressureDec { instance } => info::Trampoline::BackpressureDec {
963 instance: *instance,
964 },
965 Trampoline::TaskReturn {
966 instance,
967 results,
968 options,
969 } => info::Trampoline::TaskReturn {
970 instance: *instance,
971 results: *results,
972 options: self.options(*options),
973 },
974 Trampoline::TaskCancel { instance } => info::Trampoline::TaskCancel {
975 instance: *instance,
976 },
977 Trampoline::WaitableSetNew { instance } => info::Trampoline::WaitableSetNew {
978 instance: *instance,
979 },
980 Trampoline::WaitableSetWait { instance, options } => {
981 info::Trampoline::WaitableSetWait {
982 instance: *instance,
983 options: self.options(*options),
984 }
985 }
986 Trampoline::WaitableSetPoll { instance, options } => {
987 info::Trampoline::WaitableSetPoll {
988 instance: *instance,
989 options: self.options(*options),
990 }
991 }
992 Trampoline::WaitableSetDrop { instance } => info::Trampoline::WaitableSetDrop {
993 instance: *instance,
994 },
995 Trampoline::WaitableJoin { instance } => info::Trampoline::WaitableJoin {
996 instance: *instance,
997 },
998 Trampoline::ThreadYield {
999 instance,
1000 cancellable,
1001 } => info::Trampoline::ThreadYield {
1002 instance: *instance,
1003 cancellable: *cancellable,
1004 },
1005 Trampoline::SubtaskDrop { instance } => info::Trampoline::SubtaskDrop {
1006 instance: *instance,
1007 },
1008 Trampoline::SubtaskCancel { instance, async_ } => info::Trampoline::SubtaskCancel {
1009 instance: *instance,
1010 async_: *async_,
1011 },
1012 Trampoline::StreamNew { instance, ty } => info::Trampoline::StreamNew {
1013 instance: *instance,
1014 ty: *ty,
1015 },
1016 Trampoline::StreamRead {
1017 instance,
1018 ty,
1019 options,
1020 } => info::Trampoline::StreamRead {
1021 instance: *instance,
1022 ty: *ty,
1023 options: self.options(*options),
1024 },
1025 Trampoline::StreamWrite {
1026 instance,
1027 ty,
1028 options,
1029 } => info::Trampoline::StreamWrite {
1030 instance: *instance,
1031 ty: *ty,
1032 options: self.options(*options),
1033 },
1034 Trampoline::StreamCancelRead {
1035 instance,
1036 ty,
1037 async_,
1038 } => info::Trampoline::StreamCancelRead {
1039 instance: *instance,
1040 ty: *ty,
1041 async_: *async_,
1042 },
1043 Trampoline::StreamCancelWrite {
1044 instance,
1045 ty,
1046 async_,
1047 } => info::Trampoline::StreamCancelWrite {
1048 instance: *instance,
1049 ty: *ty,
1050 async_: *async_,
1051 },
1052 Trampoline::StreamDropReadable { instance, ty } => {
1053 info::Trampoline::StreamDropReadable {
1054 instance: *instance,
1055 ty: *ty,
1056 }
1057 }
1058 Trampoline::StreamDropWritable { instance, ty } => {
1059 info::Trampoline::StreamDropWritable {
1060 instance: *instance,
1061 ty: *ty,
1062 }
1063 }
1064 Trampoline::FutureNew { instance, ty } => info::Trampoline::FutureNew {
1065 instance: *instance,
1066 ty: *ty,
1067 },
1068 Trampoline::FutureRead {
1069 instance,
1070 ty,
1071 options,
1072 } => info::Trampoline::FutureRead {
1073 instance: *instance,
1074 ty: *ty,
1075 options: self.options(*options),
1076 },
1077 Trampoline::FutureWrite {
1078 instance,
1079 ty,
1080 options,
1081 } => info::Trampoline::FutureWrite {
1082 instance: *instance,
1083 ty: *ty,
1084 options: self.options(*options),
1085 },
1086 Trampoline::FutureCancelRead {
1087 instance,
1088 ty,
1089 async_,
1090 } => info::Trampoline::FutureCancelRead {
1091 instance: *instance,
1092 ty: *ty,
1093 async_: *async_,
1094 },
1095 Trampoline::FutureCancelWrite {
1096 instance,
1097 ty,
1098 async_,
1099 } => info::Trampoline::FutureCancelWrite {
1100 instance: *instance,
1101 ty: *ty,
1102 async_: *async_,
1103 },
1104 Trampoline::FutureDropReadable { instance, ty } => {
1105 info::Trampoline::FutureDropReadable {
1106 instance: *instance,
1107 ty: *ty,
1108 }
1109 }
1110 Trampoline::FutureDropWritable { instance, ty } => {
1111 info::Trampoline::FutureDropWritable {
1112 instance: *instance,
1113 ty: *ty,
1114 }
1115 }
1116 Trampoline::ErrorContextNew {
1117 instance,
1118 ty,
1119 options,
1120 } => info::Trampoline::ErrorContextNew {
1121 instance: *instance,
1122 ty: *ty,
1123 options: self.options(*options),
1124 },
1125 Trampoline::ErrorContextDebugMessage {
1126 instance,
1127 ty,
1128 options,
1129 } => info::Trampoline::ErrorContextDebugMessage {
1130 instance: *instance,
1131 ty: *ty,
1132 options: self.options(*options),
1133 },
1134 Trampoline::ErrorContextDrop { instance, ty } => info::Trampoline::ErrorContextDrop {
1135 instance: *instance,
1136 ty: *ty,
1137 },
1138 Trampoline::ResourceTransferOwn => info::Trampoline::ResourceTransferOwn,
1139 Trampoline::ResourceTransferBorrow => info::Trampoline::ResourceTransferBorrow,
1140 Trampoline::ResourceEnterCall => info::Trampoline::ResourceEnterCall,
1141 Trampoline::ResourceExitCall => info::Trampoline::ResourceExitCall,
1142 Trampoline::PrepareCall { memory } => info::Trampoline::PrepareCall {
1143 memory: memory.map(|v| self.runtime_memory(v)),
1144 },
1145 Trampoline::SyncStartCall { callback } => info::Trampoline::SyncStartCall {
1146 callback: callback.map(|v| self.runtime_callback(v)),
1147 },
1148 Trampoline::AsyncStartCall {
1149 callback,
1150 post_return,
1151 } => info::Trampoline::AsyncStartCall {
1152 callback: callback.map(|v| self.runtime_callback(v)),
1153 post_return: post_return.map(|v| self.runtime_post_return(v)),
1154 },
1155 Trampoline::FutureTransfer => info::Trampoline::FutureTransfer,
1156 Trampoline::StreamTransfer => info::Trampoline::StreamTransfer,
1157 Trampoline::ErrorContextTransfer => info::Trampoline::ErrorContextTransfer,
1158 Trampoline::CheckBlocking => info::Trampoline::CheckBlocking,
1159 Trampoline::ContextGet { instance, slot } => info::Trampoline::ContextGet {
1160 instance: *instance,
1161 slot: *slot,
1162 },
1163 Trampoline::ContextSet { instance, slot } => info::Trampoline::ContextSet {
1164 instance: *instance,
1165 slot: *slot,
1166 },
1167 Trampoline::ThreadIndex => info::Trampoline::ThreadIndex,
1168 Trampoline::ThreadNewIndirect {
1169 instance,
1170 start_func_ty_idx,
1171 start_func_table_id,
1172 } => info::Trampoline::ThreadNewIndirect {
1173 instance: *instance,
1174 start_func_ty_idx: *start_func_ty_idx,
1175 start_func_table_idx: self.runtime_table(*start_func_table_id),
1176 },
1177 Trampoline::ThreadSwitchTo {
1178 instance,
1179 cancellable,
1180 } => info::Trampoline::ThreadSwitchTo {
1181 instance: *instance,
1182 cancellable: *cancellable,
1183 },
1184 Trampoline::ThreadSuspend {
1185 instance,
1186 cancellable,
1187 } => info::Trampoline::ThreadSuspend {
1188 instance: *instance,
1189 cancellable: *cancellable,
1190 },
1191 Trampoline::ThreadResumeLater { instance } => info::Trampoline::ThreadResumeLater {
1192 instance: *instance,
1193 },
1194 Trampoline::ThreadYieldTo {
1195 instance,
1196 cancellable,
1197 } => info::Trampoline::ThreadYieldTo {
1198 instance: *instance,
1199 cancellable: *cancellable,
1200 },
1201 };
1202 let i1 = self.trampolines.push(*signature);
1203 let i2 = self.trampoline_defs.push(trampoline);
1204 assert_eq!(i1, i2);
1205 self.trampoline_map.insert(index, i1);
1206 i1
1207 }
1208
1209 fn core_export<T>(&mut self, export: &CoreExport<T>) -> info::CoreExport<T>
1210 where
1211 T: Clone,
1212 {
1213 let instance = export.instance;
1214 log::trace!("referencing export of {instance:?}");
1215 info::CoreExport {
1216 instance: self.runtime_instances[&RuntimeInstance::Normal(instance)],
1217 item: export.item.clone(),
1218 }
1219 }
1220
1221 fn adapter(&mut self, adapter: AdapterId) -> info::CoreExport<EntityIndex> {
1222 let (adapter_module, entity_index) = self.dfg.adapter_partitionings[adapter];
1223
1224 let instance = self.adapter_module(adapter_module);
1228
1229 info::CoreExport {
1231 instance,
1232 item: ExportItem::Index(entity_index),
1233 }
1234 }
1235
1236 fn adapter_module(&mut self, adapter_module: AdapterModuleId) -> RuntimeInstanceIndex {
1237 self.intern(
1238 RuntimeInstance::Adapter(adapter_module),
1239 |me| &mut me.runtime_instances,
1240 |me, _| {
1241 log::debug!("instantiating {adapter_module:?}");
1242 let (module_index, args) = &me.dfg.adapter_modules[adapter_module];
1243 let args = args.iter().map(|arg| me.core_def(arg)).collect();
1244 let instantiate = InstantiateModule::Static(*module_index, args);
1245 GlobalInitializer::InstantiateModule(instantiate)
1246 },
1247 |_, init| init,
1248 )
1249 }
1250
1251 fn intern<K, V, T>(
1266 &mut self,
1267 key: K,
1268 map: impl Fn(&mut Self) -> &mut HashMap<K, V>,
1269 generate: impl FnOnce(&mut Self, K) -> T,
1270 init: impl FnOnce(V, T) -> GlobalInitializer,
1271 ) -> V
1272 where
1273 K: Hash + Eq + Copy,
1274 V: EntityRef,
1275 {
1276 self.intern_(key, map, generate, |me, key, val| {
1277 me.initializers.push(init(key, val));
1278 })
1279 }
1280
1281 fn intern_no_init<K, V, T>(
1282 &mut self,
1283 key: K,
1284 map: impl Fn(&mut Self) -> &mut HashMap<K, V>,
1285 generate: impl FnOnce(&mut Self, K) -> T,
1286 ) -> V
1287 where
1288 K: Hash + Eq + Copy,
1289 V: EntityRef,
1290 {
1291 self.intern_(key, map, generate, |_me, _key, _val| {})
1292 }
1293
1294 fn intern_<K, V, T>(
1295 &mut self,
1296 key: K,
1297 map: impl Fn(&mut Self) -> &mut HashMap<K, V>,
1298 generate: impl FnOnce(&mut Self, K) -> T,
1299 init: impl FnOnce(&mut Self, V, T),
1300 ) -> V
1301 where
1302 K: Hash + Eq + Copy,
1303 V: EntityRef,
1304 {
1305 if let Some(val) = map(self).get(&key) {
1306 return *val;
1307 }
1308 let tmp = generate(self, key);
1309 let index = V::new(map(self).len());
1310 init(self, index, tmp);
1311 let prev = map(self).insert(key, index);
1312 assert!(prev.is_none());
1313 index
1314 }
1315}