1use crate::component::*;
31use crate::error::Result;
32use crate::prelude::*;
33use crate::{EntityIndex, EntityRef, ModuleInternedTypeIndex, PrimaryMap, Trap, WasmValType};
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, ComponentExtern)>,
47
48 pub imports: PrimaryMap<RuntimeImportIndex, (ImportIndex, Vec<String>)>,
50
51 pub exports: IndexMap<String, (Export, ComponentExternData)>,
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, RuntimeComponentInstanceIndex),
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, ComponentExternData)>,
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 ResourceNew {
329 instance: RuntimeComponentInstanceIndex,
330 ty: TypeResourceTableIndex,
331 },
332 ResourceRep {
333 instance: RuntimeComponentInstanceIndex,
334 ty: TypeResourceTableIndex,
335 },
336 ResourceDrop {
337 instance: RuntimeComponentInstanceIndex,
338 ty: TypeResourceTableIndex,
339 },
340 BackpressureInc {
341 instance: RuntimeComponentInstanceIndex,
342 },
343 BackpressureDec {
344 instance: RuntimeComponentInstanceIndex,
345 },
346 TaskReturn {
347 instance: RuntimeComponentInstanceIndex,
348 results: TypeTupleIndex,
349 options: OptionsId,
350 },
351 TaskCancel {
352 instance: RuntimeComponentInstanceIndex,
353 },
354 WaitableSetNew {
355 instance: RuntimeComponentInstanceIndex,
356 },
357 WaitableSetWait {
358 instance: RuntimeComponentInstanceIndex,
359 options: OptionsId,
360 },
361 WaitableSetPoll {
362 instance: RuntimeComponentInstanceIndex,
363 options: OptionsId,
364 },
365 WaitableSetDrop {
366 instance: RuntimeComponentInstanceIndex,
367 },
368 WaitableJoin {
369 instance: RuntimeComponentInstanceIndex,
370 },
371 SubtaskDrop {
372 instance: RuntimeComponentInstanceIndex,
373 },
374 SubtaskCancel {
375 instance: RuntimeComponentInstanceIndex,
376 async_: bool,
377 },
378 StreamNew {
379 instance: RuntimeComponentInstanceIndex,
380 ty: TypeStreamTableIndex,
381 },
382 StreamRead {
383 instance: RuntimeComponentInstanceIndex,
384 ty: TypeStreamTableIndex,
385 options: OptionsId,
386 },
387 StreamWrite {
388 instance: RuntimeComponentInstanceIndex,
389 ty: TypeStreamTableIndex,
390 options: OptionsId,
391 },
392 StreamCancelRead {
393 instance: RuntimeComponentInstanceIndex,
394 ty: TypeStreamTableIndex,
395 async_: bool,
396 },
397 StreamCancelWrite {
398 instance: RuntimeComponentInstanceIndex,
399 ty: TypeStreamTableIndex,
400 async_: bool,
401 },
402 StreamDropReadable {
403 instance: RuntimeComponentInstanceIndex,
404 ty: TypeStreamTableIndex,
405 },
406 StreamDropWritable {
407 instance: RuntimeComponentInstanceIndex,
408 ty: TypeStreamTableIndex,
409 },
410 FutureNew {
411 instance: RuntimeComponentInstanceIndex,
412 ty: TypeFutureTableIndex,
413 },
414 FutureRead {
415 instance: RuntimeComponentInstanceIndex,
416 ty: TypeFutureTableIndex,
417 options: OptionsId,
418 },
419 FutureWrite {
420 instance: RuntimeComponentInstanceIndex,
421 ty: TypeFutureTableIndex,
422 options: OptionsId,
423 },
424 FutureCancelRead {
425 instance: RuntimeComponentInstanceIndex,
426 ty: TypeFutureTableIndex,
427 async_: bool,
428 },
429 FutureCancelWrite {
430 instance: RuntimeComponentInstanceIndex,
431 ty: TypeFutureTableIndex,
432 async_: bool,
433 },
434 FutureDropReadable {
435 instance: RuntimeComponentInstanceIndex,
436 ty: TypeFutureTableIndex,
437 },
438 FutureDropWritable {
439 instance: RuntimeComponentInstanceIndex,
440 ty: TypeFutureTableIndex,
441 },
442 ErrorContextNew {
443 instance: RuntimeComponentInstanceIndex,
444 ty: TypeComponentLocalErrorContextTableIndex,
445 options: OptionsId,
446 },
447 ErrorContextDebugMessage {
448 instance: RuntimeComponentInstanceIndex,
449 ty: TypeComponentLocalErrorContextTableIndex,
450 options: OptionsId,
451 },
452 ErrorContextDrop {
453 instance: RuntimeComponentInstanceIndex,
454 ty: TypeComponentLocalErrorContextTableIndex,
455 },
456 ResourceTransferOwn,
457 ResourceTransferBorrow,
458 PrepareCall {
459 memory: Option<MemoryId>,
460 },
461 SyncStartCall {
462 callback: Option<CallbackId>,
463 },
464 AsyncStartCall {
465 callback: Option<CallbackId>,
466 post_return: Option<PostReturnId>,
467 },
468 FutureTransfer,
469 StreamTransfer,
470 ErrorContextTransfer,
471 Trap(Trap),
472 EnterSyncCall,
473 ExitSyncCall,
474 ThreadIndex {
475 instance: RuntimeComponentInstanceIndex,
476 },
477 ThreadNewIndirect {
478 instance: RuntimeComponentInstanceIndex,
479 start_func_ty_idx: ComponentTypeIndex,
480 start_func_table_id: TableId,
481 },
482 ThreadResumeLater {
483 instance: RuntimeComponentInstanceIndex,
484 },
485 ThreadSuspend {
486 instance: RuntimeComponentInstanceIndex,
487 cancellable: bool,
488 },
489 ThreadYield {
490 instance: RuntimeComponentInstanceIndex,
491 cancellable: bool,
492 },
493 ThreadSuspendThenResume {
494 instance: RuntimeComponentInstanceIndex,
495 cancellable: bool,
496 },
497 ThreadYieldThenResume {
498 instance: RuntimeComponentInstanceIndex,
499 cancellable: bool,
500 },
501 ThreadSuspendThenPromote {
502 instance: RuntimeComponentInstanceIndex,
503 cancellable: bool,
504 },
505 ThreadYieldThenPromote {
506 instance: RuntimeComponentInstanceIndex,
507 cancellable: bool,
508 },
509}
510
511#[derive(Copy, Clone, Hash, Eq, PartialEq)]
512#[expect(missing_docs, reason = "self-describing fields")]
513pub struct FutureInfo {
514 pub instance: RuntimeComponentInstanceIndex,
515 pub payload_type: Option<InterfaceType>,
516}
517
518#[derive(Copy, Clone, Hash, Eq, PartialEq)]
519#[expect(missing_docs, reason = "self-describing fields")]
520pub struct StreamInfo {
521 pub instance: RuntimeComponentInstanceIndex,
522 pub payload_type: InterfaceType,
523}
524
525#[derive(Clone, Hash, Eq, PartialEq)]
527#[expect(missing_docs, reason = "self-describing fields")]
528pub enum CanonicalOptionsDataModel {
529 Gc {},
530 LinearMemory {
531 memory: Option<MemoryId>,
532 realloc: Option<ReallocId>,
533 },
534}
535
536#[derive(Clone, Hash, Eq, PartialEq)]
538#[expect(missing_docs, reason = "self-describing fields")]
539pub struct CanonicalOptions {
540 pub instance: RuntimeComponentInstanceIndex,
541 pub string_encoding: StringEncoding,
542 pub callback: Option<CallbackId>,
543 pub post_return: Option<PostReturnId>,
544 pub async_: bool,
545 pub cancellable: bool,
546 pub core_type: ModuleInternedTypeIndex,
547 pub data_model: CanonicalOptionsDataModel,
548}
549
550#[expect(missing_docs, reason = "self-describing fields")]
552pub struct Resource {
553 pub rep: WasmValType,
554 pub dtor: Option<CoreDef>,
555 pub instance: RuntimeComponentInstanceIndex,
556}
557
558pub struct Intern<K: EntityRef, V> {
564 intern_map: HashMap<V, K>,
565 key_map: PrimaryMap<K, V>,
566}
567
568impl<K, V> Intern<K, V>
569where
570 K: EntityRef,
571{
572 pub fn push(&mut self, value: V) -> K
579 where
580 V: Hash + Eq + Clone,
581 {
582 *self
583 .intern_map
584 .entry(value.clone())
585 .or_insert_with(|| self.key_map.push(value))
586 }
587
588 pub fn iter(&self) -> impl Iterator<Item = (K, &V)> {
590 self.key_map.iter()
591 }
592}
593
594impl<K: EntityRef, V> Index<K> for Intern<K, V> {
595 type Output = V;
596 fn index(&self, key: K) -> &V {
597 &self.key_map[key]
598 }
599}
600
601impl<K: EntityRef, V> Default for Intern<K, V> {
602 fn default() -> Intern<K, V> {
603 Intern {
604 intern_map: HashMap::new(),
605 key_map: PrimaryMap::new(),
606 }
607 }
608}
609
610impl ComponentDfg {
611 pub fn finish(
614 self,
615 wasmtime_types: &mut ComponentTypesBuilder,
616 wasmparser_types: wasmparser::types::TypesRef<'_>,
617 ) -> Result<ComponentTranslation> {
618 let mut linearize = LinearizeDfg {
619 dfg: &self,
620 initializers: Vec::new(),
621 runtime_memories: Default::default(),
622 runtime_tables: Default::default(),
623 runtime_post_return: Default::default(),
624 runtime_reallocs: Default::default(),
625 runtime_callbacks: Default::default(),
626 runtime_instances: Default::default(),
627 num_lowerings: 0,
628 unsafe_intrinsics: Default::default(),
629 trampolines: Default::default(),
630 trampoline_defs: Default::default(),
631 trampoline_map: Default::default(),
632 options: Default::default(),
633 options_map: Default::default(),
634 };
635
636 for item in linearize.dfg.side_effects.iter() {
640 linearize.side_effect(item);
641 }
642
643 let mut export_items = PrimaryMap::new();
646 let mut exports = NameMap::default();
647 for (name, (export, data)) in self.exports.iter() {
648 let export =
649 linearize.export(export, &mut export_items, wasmtime_types, wasmparser_types)?;
650 exports.insert(name, &mut NameMapNoIntern, false, (export, data.clone()))?;
651 }
652
653 Ok(ComponentTranslation {
658 trampolines: linearize.trampoline_defs,
659 component: Component {
660 exports,
661 export_items,
662 initializers: linearize.initializers,
663 unsafe_intrinsics: linearize.unsafe_intrinsics,
664 trampolines: linearize.trampolines,
665 num_lowerings: linearize.num_lowerings,
666 options: linearize.options,
667
668 num_runtime_memories: linearize.runtime_memories.len() as u32,
669 num_runtime_tables: linearize.runtime_tables.len() as u32,
670 num_runtime_post_returns: linearize.runtime_post_return.len() as u32,
671 num_runtime_reallocs: linearize.runtime_reallocs.len() as u32,
672 num_runtime_callbacks: linearize.runtime_callbacks.len() as u32,
673 num_runtime_instances: linearize.runtime_instances.len() as u32,
674 imports: self.imports,
675 import_types: self.import_types,
676 num_runtime_component_instances: self.num_runtime_component_instances,
677 num_future_tables: self.num_future_tables,
678 num_stream_tables: self.num_stream_tables,
679 num_error_context_tables: self.num_error_context_tables,
680 num_resources: (self.resources.len() + self.imported_resources.len()) as u32,
681 imported_resources: self.imported_resources,
682 defined_resource_instances: self
683 .resources
684 .iter()
685 .map(|(_, r)| r.instance)
686 .collect(),
687 },
688 })
689 }
690
691 pub fn resource_index(&self, defined: DefinedResourceIndex) -> ResourceIndex {
694 ResourceIndex::from_u32(defined.as_u32() + (self.imported_resources.len() as u32))
695 }
696}
697
698struct LinearizeDfg<'a> {
699 dfg: &'a ComponentDfg,
700 initializers: Vec<GlobalInitializer>,
701 unsafe_intrinsics: [PackedOption<ModuleInternedTypeIndex>; UnsafeIntrinsic::len() as usize],
702 trampolines: PrimaryMap<TrampolineIndex, ModuleInternedTypeIndex>,
703 trampoline_defs: PrimaryMap<TrampolineIndex, info::Trampoline>,
704 options: PrimaryMap<OptionsIndex, info::CanonicalOptions>,
705 trampoline_map: HashMap<TrampolineIndex, TrampolineIndex>,
706 runtime_memories: HashMap<MemoryId, RuntimeMemoryIndex>,
707 runtime_tables: HashMap<TableId, RuntimeTableIndex>,
708 runtime_reallocs: HashMap<ReallocId, RuntimeReallocIndex>,
709 runtime_callbacks: HashMap<CallbackId, RuntimeCallbackIndex>,
710 runtime_post_return: HashMap<PostReturnId, RuntimePostReturnIndex>,
711 runtime_instances: HashMap<RuntimeInstance, RuntimeInstanceIndex>,
712 options_map: HashMap<OptionsId, OptionsIndex>,
713 num_lowerings: u32,
714}
715
716#[derive(Copy, Clone, Hash, Eq, PartialEq)]
717enum RuntimeInstance {
718 Normal(InstanceId),
719 Adapter(AdapterModuleId),
720}
721
722impl LinearizeDfg<'_> {
723 fn side_effect(&mut self, effect: &SideEffect) {
724 match effect {
725 SideEffect::Instance(i, ci) => {
726 self.instantiate(*i, &self.dfg.instances[*i], *ci);
727 }
728 SideEffect::Resource(i) => {
729 self.resource(*i, &self.dfg.resources[*i]);
730 }
731 }
732 }
733
734 fn instantiate(
735 &mut self,
736 instance: InstanceId,
737 args: &Instance,
738 component_instance: RuntimeComponentInstanceIndex,
739 ) {
740 log::trace!("creating instance {instance:?}");
741 let instantiation = match args {
742 Instance::Static(index, args) => InstantiateModule::Static(
743 *index,
744 args.iter().map(|def| self.core_def(def)).collect(),
745 ),
746 Instance::Import(index, args) => InstantiateModule::Import(
747 *index,
748 args.iter()
749 .map(|(module, values)| {
750 let values = values
751 .iter()
752 .map(|(name, def)| (name.clone(), self.core_def(def)))
753 .collect();
754 (module.clone(), values)
755 })
756 .collect(),
757 ),
758 };
759 let index = RuntimeInstanceIndex::new(self.runtime_instances.len());
760 self.initializers.push(GlobalInitializer::InstantiateModule(
761 instantiation,
762 Some(component_instance),
763 ));
764 let prev = self
765 .runtime_instances
766 .insert(RuntimeInstance::Normal(instance), index);
767 assert!(prev.is_none());
768 }
769
770 fn resource(&mut self, index: DefinedResourceIndex, resource: &Resource) {
771 let dtor = resource.dtor.as_ref().map(|dtor| self.core_def(dtor));
772 self.initializers
773 .push(GlobalInitializer::Resource(info::Resource {
774 dtor,
775 index,
776 rep: resource.rep,
777 instance: resource.instance,
778 }));
779 }
780
781 fn export(
782 &mut self,
783 export: &Export,
784 items: &mut PrimaryMap<ExportIndex, info::Export>,
785 wasmtime_types: &mut ComponentTypesBuilder,
786 wasmparser_types: wasmparser::types::TypesRef<'_>,
787 ) -> Result<ExportIndex> {
788 let item = match export {
789 Export::LiftedFunction { ty, func, options } => {
790 let func = self.core_def(func);
791 let options = self.options(*options);
792 info::Export::LiftedFunction {
793 ty: *ty,
794 func,
795 options,
796 }
797 }
798 Export::ModuleStatic { ty, index } => info::Export::ModuleStatic {
799 ty: wasmtime_types.convert_module(wasmparser_types, *ty)?,
800 index: *index,
801 },
802 Export::ModuleImport { ty, import } => info::Export::ModuleImport {
803 ty: *ty,
804 import: *import,
805 },
806 Export::Instance { ty, exports } => info::Export::Instance {
807 ty: *ty,
808 exports: {
809 let mut map = NameMap::default();
810 for (name, (export, data)) in exports {
811 let export =
812 self.export(export, items, wasmtime_types, wasmparser_types)?;
813 map.insert(name, &mut NameMapNoIntern, false, (export, data.clone()))?;
814 }
815 map
816 },
817 },
818 Export::Type(def) => info::Export::Type(*def),
819 };
820 Ok(items.push(item))
821 }
822
823 fn options(&mut self, options: OptionsId) -> OptionsIndex {
824 self.intern_no_init(
825 options,
826 |me| &mut me.options_map,
827 |me, options| me.convert_options(options),
828 )
829 }
830
831 fn convert_options(&mut self, options: OptionsId) -> OptionsIndex {
832 let options = &self.dfg.options[options];
833 let data_model = match options.data_model {
834 CanonicalOptionsDataModel::Gc {} => info::CanonicalOptionsDataModel::Gc {},
835 CanonicalOptionsDataModel::LinearMemory { memory, realloc } => {
836 info::CanonicalOptionsDataModel::LinearMemory(LinearMemoryOptions {
837 memory: memory.map(|mem| self.runtime_memory(mem)),
838 realloc: realloc.map(|mem| self.runtime_realloc(mem)),
839 })
840 }
841 };
842 let callback = options.callback.map(|mem| self.runtime_callback(mem));
843 let post_return = options.post_return.map(|mem| self.runtime_post_return(mem));
844 let options = info::CanonicalOptions {
845 instance: options.instance,
846 string_encoding: options.string_encoding,
847 callback,
848 post_return,
849 async_: options.async_,
850 cancellable: options.cancellable,
851 core_type: options.core_type,
852 data_model,
853 };
854 self.options.push(options)
855 }
856
857 fn runtime_memory(&mut self, mem: MemoryId) -> RuntimeMemoryIndex {
858 self.intern(
859 mem,
860 |me| &mut me.runtime_memories,
861 |me, mem| me.core_export(&me.dfg.memories[mem]),
862 |index, export| GlobalInitializer::ExtractMemory(ExtractMemory { index, export }),
863 )
864 }
865
866 fn runtime_table(&mut self, table: TableId) -> RuntimeTableIndex {
867 self.intern(
868 table,
869 |me| &mut me.runtime_tables,
870 |me, table| me.core_export(&me.dfg.tables[table]),
871 |index, export| GlobalInitializer::ExtractTable(ExtractTable { index, export }),
872 )
873 }
874
875 fn runtime_realloc(&mut self, realloc: ReallocId) -> RuntimeReallocIndex {
876 self.intern(
877 realloc,
878 |me| &mut me.runtime_reallocs,
879 |me, realloc| me.core_def(&me.dfg.reallocs[realloc]),
880 |index, def| GlobalInitializer::ExtractRealloc(ExtractRealloc { index, def }),
881 )
882 }
883
884 fn runtime_callback(&mut self, callback: CallbackId) -> RuntimeCallbackIndex {
885 self.intern(
886 callback,
887 |me| &mut me.runtime_callbacks,
888 |me, callback| me.core_def(&me.dfg.callbacks[callback]),
889 |index, def| GlobalInitializer::ExtractCallback(ExtractCallback { index, def }),
890 )
891 }
892
893 fn runtime_post_return(&mut self, post_return: PostReturnId) -> RuntimePostReturnIndex {
894 self.intern(
895 post_return,
896 |me| &mut me.runtime_post_return,
897 |me, post_return| me.core_def(&me.dfg.post_returns[post_return]),
898 |index, def| GlobalInitializer::ExtractPostReturn(ExtractPostReturn { index, def }),
899 )
900 }
901
902 fn core_def(&mut self, def: &CoreDef) -> info::CoreDef {
903 match def {
904 CoreDef::Export(e) => info::CoreDef::Export(self.core_export(e)),
905 CoreDef::InstanceFlags(i) => info::CoreDef::InstanceFlags(*i),
906 CoreDef::Adapter(id) => info::CoreDef::Export(self.adapter(*id)),
907 CoreDef::Trampoline(index) => info::CoreDef::Trampoline(self.trampoline(*index)),
908 CoreDef::UnsafeIntrinsic(ty, i) => {
909 let index = usize::try_from(i.index()).unwrap();
910 if self.unsafe_intrinsics[index].is_none() {
911 self.unsafe_intrinsics[index] = Some(*ty).into();
912 }
913 info::CoreDef::UnsafeIntrinsic(*i)
914 }
915 }
916 }
917
918 fn trampoline(&mut self, index: TrampolineIndex) -> TrampolineIndex {
919 if let Some(idx) = self.trampoline_map.get(&index) {
920 return *idx;
921 }
922 let (signature, trampoline) = &self.dfg.trampolines[index];
923 let trampoline = match trampoline {
924 Trampoline::LowerImport {
925 import,
926 options,
927 lower_ty,
928 } => {
929 let index = LoweredIndex::from_u32(self.num_lowerings);
930 self.num_lowerings += 1;
931 self.initializers.push(GlobalInitializer::LowerImport {
932 index,
933 import: *import,
934 });
935 info::Trampoline::LowerImport {
936 index,
937 options: self.options(*options),
938 lower_ty: *lower_ty,
939 }
940 }
941 Trampoline::Transcoder {
942 op,
943 from,
944 from64,
945 to,
946 to64,
947 } => info::Trampoline::Transcoder {
948 op: *op,
949 from: self.runtime_memory(*from),
950 from64: *from64,
951 to: self.runtime_memory(*to),
952 to64: *to64,
953 },
954 Trampoline::ResourceNew { instance, ty } => info::Trampoline::ResourceNew {
955 instance: *instance,
956 ty: *ty,
957 },
958 Trampoline::ResourceDrop { instance, ty } => info::Trampoline::ResourceDrop {
959 instance: *instance,
960 ty: *ty,
961 },
962 Trampoline::ResourceRep { instance, ty } => info::Trampoline::ResourceRep {
963 instance: *instance,
964 ty: *ty,
965 },
966 Trampoline::BackpressureInc { instance } => info::Trampoline::BackpressureInc {
967 instance: *instance,
968 },
969 Trampoline::BackpressureDec { instance } => info::Trampoline::BackpressureDec {
970 instance: *instance,
971 },
972 Trampoline::TaskReturn {
973 instance,
974 results,
975 options,
976 } => info::Trampoline::TaskReturn {
977 instance: *instance,
978 results: *results,
979 options: self.options(*options),
980 },
981 Trampoline::TaskCancel { instance } => info::Trampoline::TaskCancel {
982 instance: *instance,
983 },
984 Trampoline::WaitableSetNew { instance } => info::Trampoline::WaitableSetNew {
985 instance: *instance,
986 },
987 Trampoline::WaitableSetWait { instance, options } => {
988 info::Trampoline::WaitableSetWait {
989 instance: *instance,
990 options: self.options(*options),
991 }
992 }
993 Trampoline::WaitableSetPoll { instance, options } => {
994 info::Trampoline::WaitableSetPoll {
995 instance: *instance,
996 options: self.options(*options),
997 }
998 }
999 Trampoline::WaitableSetDrop { instance } => info::Trampoline::WaitableSetDrop {
1000 instance: *instance,
1001 },
1002 Trampoline::WaitableJoin { instance } => info::Trampoline::WaitableJoin {
1003 instance: *instance,
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::PrepareCall { memory } => info::Trampoline::PrepareCall {
1141 memory: memory.map(|v| self.runtime_memory(v)),
1142 },
1143 Trampoline::SyncStartCall { callback } => info::Trampoline::SyncStartCall {
1144 callback: callback.map(|v| self.runtime_callback(v)),
1145 },
1146 Trampoline::AsyncStartCall {
1147 callback,
1148 post_return,
1149 } => info::Trampoline::AsyncStartCall {
1150 callback: callback.map(|v| self.runtime_callback(v)),
1151 post_return: post_return.map(|v| self.runtime_post_return(v)),
1152 },
1153 Trampoline::FutureTransfer => info::Trampoline::FutureTransfer,
1154 Trampoline::StreamTransfer => info::Trampoline::StreamTransfer,
1155 Trampoline::ErrorContextTransfer => info::Trampoline::ErrorContextTransfer,
1156 Trampoline::Trap(trap) => info::Trampoline::Trap(*trap),
1157 Trampoline::EnterSyncCall => info::Trampoline::EnterSyncCall,
1158 Trampoline::ExitSyncCall => info::Trampoline::ExitSyncCall,
1159 Trampoline::ThreadIndex { instance } => info::Trampoline::ThreadIndex {
1160 instance: *instance,
1161 },
1162 Trampoline::ThreadNewIndirect {
1163 instance,
1164 start_func_ty_idx,
1165 start_func_table_id,
1166 } => info::Trampoline::ThreadNewIndirect {
1167 instance: *instance,
1168 start_func_ty_idx: *start_func_ty_idx,
1169 start_func_table_idx: self.runtime_table(*start_func_table_id),
1170 },
1171 Trampoline::ThreadResumeLater { instance } => info::Trampoline::ThreadResumeLater {
1172 instance: *instance,
1173 },
1174 Trampoline::ThreadSuspend {
1175 instance,
1176 cancellable,
1177 } => info::Trampoline::ThreadSuspend {
1178 instance: *instance,
1179 cancellable: *cancellable,
1180 },
1181 Trampoline::ThreadYield {
1182 instance,
1183 cancellable,
1184 } => info::Trampoline::ThreadYield {
1185 instance: *instance,
1186 cancellable: *cancellable,
1187 },
1188 Trampoline::ThreadSuspendThenResume {
1189 instance,
1190 cancellable,
1191 } => info::Trampoline::ThreadSuspendThenResume {
1192 instance: *instance,
1193 cancellable: *cancellable,
1194 },
1195 Trampoline::ThreadYieldThenResume {
1196 instance,
1197 cancellable,
1198 } => info::Trampoline::ThreadYieldThenResume {
1199 instance: *instance,
1200 cancellable: *cancellable,
1201 },
1202 Trampoline::ThreadSuspendThenPromote {
1203 instance,
1204 cancellable,
1205 } => info::Trampoline::ThreadSuspendThenPromote {
1206 instance: *instance,
1207 cancellable: *cancellable,
1208 },
1209 Trampoline::ThreadYieldThenPromote {
1210 instance,
1211 cancellable,
1212 } => info::Trampoline::ThreadYieldThenPromote {
1213 instance: *instance,
1214 cancellable: *cancellable,
1215 },
1216 };
1217 let i1 = self.trampolines.push(*signature);
1218 let i2 = self.trampoline_defs.push(trampoline);
1219 assert_eq!(i1, i2);
1220 self.trampoline_map.insert(index, i1);
1221 i1
1222 }
1223
1224 fn core_export<T>(&mut self, export: &CoreExport<T>) -> info::CoreExport<T>
1225 where
1226 T: Clone,
1227 {
1228 let instance = export.instance;
1229 log::trace!("referencing export of {instance:?}");
1230 info::CoreExport {
1231 instance: self.runtime_instances[&RuntimeInstance::Normal(instance)],
1232 item: export.item.clone(),
1233 }
1234 }
1235
1236 fn adapter(&mut self, adapter: AdapterId) -> info::CoreExport<EntityIndex> {
1237 let (adapter_module, entity_index) = self.dfg.adapter_partitionings[adapter];
1238
1239 let instance = self.adapter_module(adapter_module);
1243
1244 info::CoreExport {
1246 instance,
1247 item: ExportItem::Index(entity_index),
1248 }
1249 }
1250
1251 fn adapter_module(&mut self, adapter_module: AdapterModuleId) -> RuntimeInstanceIndex {
1252 self.intern(
1253 RuntimeInstance::Adapter(adapter_module),
1254 |me| &mut me.runtime_instances,
1255 |me, _| {
1256 log::debug!("instantiating {adapter_module:?}");
1257 let (module_index, args) = &me.dfg.adapter_modules[adapter_module];
1258 let args = args.iter().map(|arg| me.core_def(arg)).collect();
1259 let instantiate = InstantiateModule::Static(*module_index, args);
1260 GlobalInitializer::InstantiateModule(instantiate, None)
1261 },
1262 |_, init| init,
1263 )
1264 }
1265
1266 fn intern<K, V, T>(
1281 &mut self,
1282 key: K,
1283 map: impl Fn(&mut Self) -> &mut HashMap<K, V>,
1284 generate: impl FnOnce(&mut Self, K) -> T,
1285 init: impl FnOnce(V, T) -> GlobalInitializer,
1286 ) -> V
1287 where
1288 K: Hash + Eq + Copy,
1289 V: EntityRef,
1290 {
1291 self.intern_(key, map, generate, |me, key, val| {
1292 me.initializers.push(init(key, val));
1293 })
1294 }
1295
1296 fn intern_no_init<K, V, T>(
1297 &mut self,
1298 key: K,
1299 map: impl Fn(&mut Self) -> &mut HashMap<K, V>,
1300 generate: impl FnOnce(&mut Self, K) -> T,
1301 ) -> V
1302 where
1303 K: Hash + Eq + Copy,
1304 V: EntityRef,
1305 {
1306 self.intern_(key, map, generate, |_me, _key, _val| {})
1307 }
1308
1309 fn intern_<K, V, T>(
1310 &mut self,
1311 key: K,
1312 map: impl Fn(&mut Self) -> &mut HashMap<K, V>,
1313 generate: impl FnOnce(&mut Self, K) -> T,
1314 init: impl FnOnce(&mut Self, V, T),
1315 ) -> V
1316 where
1317 K: Hash + Eq + Copy,
1318 V: EntityRef,
1319 {
1320 if let Some(val) = map(self).get(&key) {
1321 return *val;
1322 }
1323 let tmp = generate(self, key);
1324 let index = V::new(map(self).len());
1325 init(self, index, tmp);
1326 let prev = map(self).insert(key, index);
1327 assert!(prev.is_none());
1328 index
1329 }
1330}