1use crate::component::*;
31use crate::error::Result;
32use crate::prelude::*;
33use crate::{EntityIndex, EntityRef, ModuleInternedTypeIndex, PrimaryMap, 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, 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, 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>,
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 TaskMayBlock,
271
272 Adapter(AdapterId),
281}
282
283impl<T> From<CoreExport<T>> for CoreDef
284where
285 EntityIndex: From<T>,
286{
287 fn from(export: CoreExport<T>) -> CoreDef {
288 CoreDef::Export(export.map_index(|i| i.into()))
289 }
290}
291
292#[derive(Debug, Clone, Hash, Eq, PartialEq)]
294#[expect(missing_docs, reason = "self-describing fields")]
295pub struct CoreExport<T> {
296 pub instance: InstanceId,
297 pub item: ExportItem<T>,
298}
299
300impl<T> CoreExport<T> {
301 #[expect(missing_docs, reason = "self-describing function")]
302 pub fn map_index<U>(self, f: impl FnOnce(T) -> U) -> CoreExport<U> {
303 CoreExport {
304 instance: self.instance,
305 item: match self.item {
306 ExportItem::Index(i) => ExportItem::Index(f(i)),
307 ExportItem::Name(s) => ExportItem::Name(s),
308 },
309 }
310 }
311}
312
313#[derive(Clone, PartialEq, Eq, Hash)]
315#[expect(missing_docs, reason = "self-describing fields")]
316pub enum Trampoline {
317 LowerImport {
318 import: RuntimeImportIndex,
319 options: OptionsId,
320 lower_ty: TypeFuncIndex,
321 },
322 Transcoder {
323 op: Transcode,
324 from: MemoryId,
325 from64: bool,
326 to: MemoryId,
327 to64: bool,
328 },
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 PrepareCall {
464 memory: Option<MemoryId>,
465 },
466 SyncStartCall {
467 callback: Option<CallbackId>,
468 },
469 AsyncStartCall {
470 callback: Option<CallbackId>,
471 post_return: Option<PostReturnId>,
472 },
473 FutureTransfer,
474 StreamTransfer,
475 ErrorContextTransfer,
476 Trap,
477 EnterSyncCall,
478 ExitSyncCall,
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 ThreadSuspendToSuspended {
494 instance: RuntimeComponentInstanceIndex,
495 cancellable: bool,
496 },
497 ThreadSuspend {
498 instance: RuntimeComponentInstanceIndex,
499 cancellable: bool,
500 },
501 ThreadSuspendTo {
502 instance: RuntimeComponentInstanceIndex,
503 cancellable: bool,
504 },
505 ThreadUnsuspend {
506 instance: RuntimeComponentInstanceIndex,
507 },
508 ThreadYieldToSuspended {
509 instance: RuntimeComponentInstanceIndex,
510 cancellable: bool,
511 },
512}
513
514#[derive(Copy, Clone, Hash, Eq, PartialEq)]
515#[expect(missing_docs, reason = "self-describing fields")]
516pub struct FutureInfo {
517 pub instance: RuntimeComponentInstanceIndex,
518 pub payload_type: Option<InterfaceType>,
519}
520
521#[derive(Copy, Clone, Hash, Eq, PartialEq)]
522#[expect(missing_docs, reason = "self-describing fields")]
523pub struct StreamInfo {
524 pub instance: RuntimeComponentInstanceIndex,
525 pub payload_type: InterfaceType,
526}
527
528#[derive(Clone, Hash, Eq, PartialEq)]
530#[expect(missing_docs, reason = "self-describing fields")]
531pub enum CanonicalOptionsDataModel {
532 Gc {},
533 LinearMemory {
534 memory: Option<MemoryId>,
535 realloc: Option<ReallocId>,
536 },
537}
538
539#[derive(Clone, Hash, Eq, PartialEq)]
541#[expect(missing_docs, reason = "self-describing fields")]
542pub struct CanonicalOptions {
543 pub instance: RuntimeComponentInstanceIndex,
544 pub string_encoding: StringEncoding,
545 pub callback: Option<CallbackId>,
546 pub post_return: Option<PostReturnId>,
547 pub async_: bool,
548 pub cancellable: bool,
549 pub core_type: ModuleInternedTypeIndex,
550 pub data_model: CanonicalOptionsDataModel,
551}
552
553#[expect(missing_docs, reason = "self-describing fields")]
555pub struct Resource {
556 pub rep: WasmValType,
557 pub dtor: Option<CoreDef>,
558 pub instance: RuntimeComponentInstanceIndex,
559}
560
561pub struct Intern<K: EntityRef, V> {
567 intern_map: HashMap<V, K>,
568 key_map: PrimaryMap<K, V>,
569}
570
571impl<K, V> Intern<K, V>
572where
573 K: EntityRef,
574{
575 pub fn push(&mut self, value: V) -> K
582 where
583 V: Hash + Eq + Clone,
584 {
585 *self
586 .intern_map
587 .entry(value.clone())
588 .or_insert_with(|| self.key_map.push(value))
589 }
590
591 pub fn iter(&self) -> impl Iterator<Item = (K, &V)> {
593 self.key_map.iter()
594 }
595}
596
597impl<K: EntityRef, V> Index<K> for Intern<K, V> {
598 type Output = V;
599 fn index(&self, key: K) -> &V {
600 &self.key_map[key]
601 }
602}
603
604impl<K: EntityRef, V> Default for Intern<K, V> {
605 fn default() -> Intern<K, V> {
606 Intern {
607 intern_map: HashMap::new(),
608 key_map: PrimaryMap::new(),
609 }
610 }
611}
612
613impl ComponentDfg {
614 pub fn finish(
617 self,
618 wasmtime_types: &mut ComponentTypesBuilder,
619 wasmparser_types: wasmparser::types::TypesRef<'_>,
620 ) -> Result<ComponentTranslation> {
621 let mut linearize = LinearizeDfg {
622 dfg: &self,
623 initializers: Vec::new(),
624 runtime_memories: Default::default(),
625 runtime_tables: Default::default(),
626 runtime_post_return: Default::default(),
627 runtime_reallocs: Default::default(),
628 runtime_callbacks: Default::default(),
629 runtime_instances: Default::default(),
630 num_lowerings: 0,
631 unsafe_intrinsics: Default::default(),
632 trampolines: Default::default(),
633 trampoline_defs: Default::default(),
634 trampoline_map: Default::default(),
635 options: Default::default(),
636 options_map: Default::default(),
637 };
638
639 for item in linearize.dfg.side_effects.iter() {
643 linearize.side_effect(item);
644 }
645
646 let mut export_items = PrimaryMap::new();
649 let mut exports = NameMap::default();
650 for (name, export) in self.exports.iter() {
651 let export =
652 linearize.export(export, &mut export_items, wasmtime_types, wasmparser_types)?;
653 exports.insert(name, &mut NameMapNoIntern, false, export)?;
654 }
655
656 Ok(ComponentTranslation {
661 trampolines: linearize.trampoline_defs,
662 component: Component {
663 exports,
664 export_items,
665 initializers: linearize.initializers,
666 unsafe_intrinsics: linearize.unsafe_intrinsics,
667 trampolines: linearize.trampolines,
668 num_lowerings: linearize.num_lowerings,
669 options: linearize.options,
670
671 num_runtime_memories: linearize.runtime_memories.len() as u32,
672 num_runtime_tables: linearize.runtime_tables.len() as u32,
673 num_runtime_post_returns: linearize.runtime_post_return.len() as u32,
674 num_runtime_reallocs: linearize.runtime_reallocs.len() as u32,
675 num_runtime_callbacks: linearize.runtime_callbacks.len() as u32,
676 num_runtime_instances: linearize.runtime_instances.len() as u32,
677 imports: self.imports,
678 import_types: self.import_types,
679 num_runtime_component_instances: self.num_runtime_component_instances,
680 num_future_tables: self.num_future_tables,
681 num_stream_tables: self.num_stream_tables,
682 num_error_context_tables: self.num_error_context_tables,
683 num_resources: (self.resources.len() + self.imported_resources.len()) as u32,
684 imported_resources: self.imported_resources,
685 defined_resource_instances: self
686 .resources
687 .iter()
688 .map(|(_, r)| r.instance)
689 .collect(),
690 },
691 })
692 }
693
694 pub fn resource_index(&self, defined: DefinedResourceIndex) -> ResourceIndex {
697 ResourceIndex::from_u32(defined.as_u32() + (self.imported_resources.len() as u32))
698 }
699}
700
701struct LinearizeDfg<'a> {
702 dfg: &'a ComponentDfg,
703 initializers: Vec<GlobalInitializer>,
704 unsafe_intrinsics: [PackedOption<ModuleInternedTypeIndex>; UnsafeIntrinsic::len() as usize],
705 trampolines: PrimaryMap<TrampolineIndex, ModuleInternedTypeIndex>,
706 trampoline_defs: PrimaryMap<TrampolineIndex, info::Trampoline>,
707 options: PrimaryMap<OptionsIndex, info::CanonicalOptions>,
708 trampoline_map: HashMap<TrampolineIndex, TrampolineIndex>,
709 runtime_memories: HashMap<MemoryId, RuntimeMemoryIndex>,
710 runtime_tables: HashMap<TableId, RuntimeTableIndex>,
711 runtime_reallocs: HashMap<ReallocId, RuntimeReallocIndex>,
712 runtime_callbacks: HashMap<CallbackId, RuntimeCallbackIndex>,
713 runtime_post_return: HashMap<PostReturnId, RuntimePostReturnIndex>,
714 runtime_instances: HashMap<RuntimeInstance, RuntimeInstanceIndex>,
715 options_map: HashMap<OptionsId, OptionsIndex>,
716 num_lowerings: u32,
717}
718
719#[derive(Copy, Clone, Hash, Eq, PartialEq)]
720enum RuntimeInstance {
721 Normal(InstanceId),
722 Adapter(AdapterModuleId),
723}
724
725impl LinearizeDfg<'_> {
726 fn side_effect(&mut self, effect: &SideEffect) {
727 match effect {
728 SideEffect::Instance(i, ci) => {
729 self.instantiate(*i, &self.dfg.instances[*i], *ci);
730 }
731 SideEffect::Resource(i) => {
732 self.resource(*i, &self.dfg.resources[*i]);
733 }
734 }
735 }
736
737 fn instantiate(
738 &mut self,
739 instance: InstanceId,
740 args: &Instance,
741 component_instance: RuntimeComponentInstanceIndex,
742 ) {
743 log::trace!("creating instance {instance:?}");
744 let instantiation = match args {
745 Instance::Static(index, args) => InstantiateModule::Static(
746 *index,
747 args.iter().map(|def| self.core_def(def)).collect(),
748 ),
749 Instance::Import(index, args) => InstantiateModule::Import(
750 *index,
751 args.iter()
752 .map(|(module, values)| {
753 let values = values
754 .iter()
755 .map(|(name, def)| (name.clone(), self.core_def(def)))
756 .collect();
757 (module.clone(), values)
758 })
759 .collect(),
760 ),
761 };
762 let index = RuntimeInstanceIndex::new(self.runtime_instances.len());
763 self.initializers.push(GlobalInitializer::InstantiateModule(
764 instantiation,
765 Some(component_instance),
766 ));
767 let prev = self
768 .runtime_instances
769 .insert(RuntimeInstance::Normal(instance), index);
770 assert!(prev.is_none());
771 }
772
773 fn resource(&mut self, index: DefinedResourceIndex, resource: &Resource) {
774 let dtor = resource.dtor.as_ref().map(|dtor| self.core_def(dtor));
775 self.initializers
776 .push(GlobalInitializer::Resource(info::Resource {
777 dtor,
778 index,
779 rep: resource.rep,
780 instance: resource.instance,
781 }));
782 }
783
784 fn export(
785 &mut self,
786 export: &Export,
787 items: &mut PrimaryMap<ExportIndex, info::Export>,
788 wasmtime_types: &mut ComponentTypesBuilder,
789 wasmparser_types: wasmparser::types::TypesRef<'_>,
790 ) -> Result<ExportIndex> {
791 let item = match export {
792 Export::LiftedFunction { ty, func, options } => {
793 let func = self.core_def(func);
794 let options = self.options(*options);
795 info::Export::LiftedFunction {
796 ty: *ty,
797 func,
798 options,
799 }
800 }
801 Export::ModuleStatic { ty, index } => info::Export::ModuleStatic {
802 ty: wasmtime_types.convert_module(wasmparser_types, *ty)?,
803 index: *index,
804 },
805 Export::ModuleImport { ty, import } => info::Export::ModuleImport {
806 ty: *ty,
807 import: *import,
808 },
809 Export::Instance { ty, exports } => info::Export::Instance {
810 ty: *ty,
811 exports: {
812 let mut map = NameMap::default();
813 for (name, export) in exports {
814 let export =
815 self.export(export, items, wasmtime_types, wasmparser_types)?;
816 map.insert(name, &mut NameMapNoIntern, false, export)?;
817 }
818 map
819 },
820 },
821 Export::Type(def) => info::Export::Type(*def),
822 };
823 Ok(items.push(item))
824 }
825
826 fn options(&mut self, options: OptionsId) -> OptionsIndex {
827 self.intern_no_init(
828 options,
829 |me| &mut me.options_map,
830 |me, options| me.convert_options(options),
831 )
832 }
833
834 fn convert_options(&mut self, options: OptionsId) -> OptionsIndex {
835 let options = &self.dfg.options[options];
836 let data_model = match options.data_model {
837 CanonicalOptionsDataModel::Gc {} => info::CanonicalOptionsDataModel::Gc {},
838 CanonicalOptionsDataModel::LinearMemory { memory, realloc } => {
839 info::CanonicalOptionsDataModel::LinearMemory(LinearMemoryOptions {
840 memory: memory.map(|mem| self.runtime_memory(mem)),
841 realloc: realloc.map(|mem| self.runtime_realloc(mem)),
842 })
843 }
844 };
845 let callback = options.callback.map(|mem| self.runtime_callback(mem));
846 let post_return = options.post_return.map(|mem| self.runtime_post_return(mem));
847 let options = info::CanonicalOptions {
848 instance: options.instance,
849 string_encoding: options.string_encoding,
850 callback,
851 post_return,
852 async_: options.async_,
853 cancellable: options.cancellable,
854 core_type: options.core_type,
855 data_model,
856 };
857 self.options.push(options)
858 }
859
860 fn runtime_memory(&mut self, mem: MemoryId) -> RuntimeMemoryIndex {
861 self.intern(
862 mem,
863 |me| &mut me.runtime_memories,
864 |me, mem| me.core_export(&me.dfg.memories[mem]),
865 |index, export| GlobalInitializer::ExtractMemory(ExtractMemory { index, export }),
866 )
867 }
868
869 fn runtime_table(&mut self, table: TableId) -> RuntimeTableIndex {
870 self.intern(
871 table,
872 |me| &mut me.runtime_tables,
873 |me, table| me.core_export(&me.dfg.tables[table]),
874 |index, export| GlobalInitializer::ExtractTable(ExtractTable { index, export }),
875 )
876 }
877
878 fn runtime_realloc(&mut self, realloc: ReallocId) -> RuntimeReallocIndex {
879 self.intern(
880 realloc,
881 |me| &mut me.runtime_reallocs,
882 |me, realloc| me.core_def(&me.dfg.reallocs[realloc]),
883 |index, def| GlobalInitializer::ExtractRealloc(ExtractRealloc { index, def }),
884 )
885 }
886
887 fn runtime_callback(&mut self, callback: CallbackId) -> RuntimeCallbackIndex {
888 self.intern(
889 callback,
890 |me| &mut me.runtime_callbacks,
891 |me, callback| me.core_def(&me.dfg.callbacks[callback]),
892 |index, def| GlobalInitializer::ExtractCallback(ExtractCallback { index, def }),
893 )
894 }
895
896 fn runtime_post_return(&mut self, post_return: PostReturnId) -> RuntimePostReturnIndex {
897 self.intern(
898 post_return,
899 |me| &mut me.runtime_post_return,
900 |me, post_return| me.core_def(&me.dfg.post_returns[post_return]),
901 |index, def| GlobalInitializer::ExtractPostReturn(ExtractPostReturn { index, def }),
902 )
903 }
904
905 fn core_def(&mut self, def: &CoreDef) -> info::CoreDef {
906 match def {
907 CoreDef::Export(e) => info::CoreDef::Export(self.core_export(e)),
908 CoreDef::InstanceFlags(i) => info::CoreDef::InstanceFlags(*i),
909 CoreDef::Adapter(id) => info::CoreDef::Export(self.adapter(*id)),
910 CoreDef::Trampoline(index) => info::CoreDef::Trampoline(self.trampoline(*index)),
911 CoreDef::UnsafeIntrinsic(ty, i) => {
912 let index = usize::try_from(i.index()).unwrap();
913 if self.unsafe_intrinsics[index].is_none() {
914 self.unsafe_intrinsics[index] = Some(*ty).into();
915 }
916 info::CoreDef::UnsafeIntrinsic(*i)
917 }
918 CoreDef::TaskMayBlock => info::CoreDef::TaskMayBlock,
919 }
920 }
921
922 fn trampoline(&mut self, index: TrampolineIndex) -> TrampolineIndex {
923 if let Some(idx) = self.trampoline_map.get(&index) {
924 return *idx;
925 }
926 let (signature, trampoline) = &self.dfg.trampolines[index];
927 let trampoline = match trampoline {
928 Trampoline::LowerImport {
929 import,
930 options,
931 lower_ty,
932 } => {
933 let index = LoweredIndex::from_u32(self.num_lowerings);
934 self.num_lowerings += 1;
935 self.initializers.push(GlobalInitializer::LowerImport {
936 index,
937 import: *import,
938 });
939 info::Trampoline::LowerImport {
940 index,
941 options: self.options(*options),
942 lower_ty: *lower_ty,
943 }
944 }
945 Trampoline::Transcoder {
946 op,
947 from,
948 from64,
949 to,
950 to64,
951 } => info::Trampoline::Transcoder {
952 op: *op,
953 from: self.runtime_memory(*from),
954 from64: *from64,
955 to: self.runtime_memory(*to),
956 to64: *to64,
957 },
958 Trampoline::ResourceNew { instance, ty } => info::Trampoline::ResourceNew {
959 instance: *instance,
960 ty: *ty,
961 },
962 Trampoline::ResourceDrop { instance, ty } => info::Trampoline::ResourceDrop {
963 instance: *instance,
964 ty: *ty,
965 },
966 Trampoline::ResourceRep { instance, ty } => info::Trampoline::ResourceRep {
967 instance: *instance,
968 ty: *ty,
969 },
970 Trampoline::BackpressureInc { instance } => info::Trampoline::BackpressureInc {
971 instance: *instance,
972 },
973 Trampoline::BackpressureDec { instance } => info::Trampoline::BackpressureDec {
974 instance: *instance,
975 },
976 Trampoline::TaskReturn {
977 instance,
978 results,
979 options,
980 } => info::Trampoline::TaskReturn {
981 instance: *instance,
982 results: *results,
983 options: self.options(*options),
984 },
985 Trampoline::TaskCancel { instance } => info::Trampoline::TaskCancel {
986 instance: *instance,
987 },
988 Trampoline::WaitableSetNew { instance } => info::Trampoline::WaitableSetNew {
989 instance: *instance,
990 },
991 Trampoline::WaitableSetWait { instance, options } => {
992 info::Trampoline::WaitableSetWait {
993 instance: *instance,
994 options: self.options(*options),
995 }
996 }
997 Trampoline::WaitableSetPoll { instance, options } => {
998 info::Trampoline::WaitableSetPoll {
999 instance: *instance,
1000 options: self.options(*options),
1001 }
1002 }
1003 Trampoline::WaitableSetDrop { instance } => info::Trampoline::WaitableSetDrop {
1004 instance: *instance,
1005 },
1006 Trampoline::WaitableJoin { instance } => info::Trampoline::WaitableJoin {
1007 instance: *instance,
1008 },
1009 Trampoline::ThreadYield {
1010 instance,
1011 cancellable,
1012 } => info::Trampoline::ThreadYield {
1013 instance: *instance,
1014 cancellable: *cancellable,
1015 },
1016 Trampoline::SubtaskDrop { instance } => info::Trampoline::SubtaskDrop {
1017 instance: *instance,
1018 },
1019 Trampoline::SubtaskCancel { instance, async_ } => info::Trampoline::SubtaskCancel {
1020 instance: *instance,
1021 async_: *async_,
1022 },
1023 Trampoline::StreamNew { instance, ty } => info::Trampoline::StreamNew {
1024 instance: *instance,
1025 ty: *ty,
1026 },
1027 Trampoline::StreamRead {
1028 instance,
1029 ty,
1030 options,
1031 } => info::Trampoline::StreamRead {
1032 instance: *instance,
1033 ty: *ty,
1034 options: self.options(*options),
1035 },
1036 Trampoline::StreamWrite {
1037 instance,
1038 ty,
1039 options,
1040 } => info::Trampoline::StreamWrite {
1041 instance: *instance,
1042 ty: *ty,
1043 options: self.options(*options),
1044 },
1045 Trampoline::StreamCancelRead {
1046 instance,
1047 ty,
1048 async_,
1049 } => info::Trampoline::StreamCancelRead {
1050 instance: *instance,
1051 ty: *ty,
1052 async_: *async_,
1053 },
1054 Trampoline::StreamCancelWrite {
1055 instance,
1056 ty,
1057 async_,
1058 } => info::Trampoline::StreamCancelWrite {
1059 instance: *instance,
1060 ty: *ty,
1061 async_: *async_,
1062 },
1063 Trampoline::StreamDropReadable { instance, ty } => {
1064 info::Trampoline::StreamDropReadable {
1065 instance: *instance,
1066 ty: *ty,
1067 }
1068 }
1069 Trampoline::StreamDropWritable { instance, ty } => {
1070 info::Trampoline::StreamDropWritable {
1071 instance: *instance,
1072 ty: *ty,
1073 }
1074 }
1075 Trampoline::FutureNew { instance, ty } => info::Trampoline::FutureNew {
1076 instance: *instance,
1077 ty: *ty,
1078 },
1079 Trampoline::FutureRead {
1080 instance,
1081 ty,
1082 options,
1083 } => info::Trampoline::FutureRead {
1084 instance: *instance,
1085 ty: *ty,
1086 options: self.options(*options),
1087 },
1088 Trampoline::FutureWrite {
1089 instance,
1090 ty,
1091 options,
1092 } => info::Trampoline::FutureWrite {
1093 instance: *instance,
1094 ty: *ty,
1095 options: self.options(*options),
1096 },
1097 Trampoline::FutureCancelRead {
1098 instance,
1099 ty,
1100 async_,
1101 } => info::Trampoline::FutureCancelRead {
1102 instance: *instance,
1103 ty: *ty,
1104 async_: *async_,
1105 },
1106 Trampoline::FutureCancelWrite {
1107 instance,
1108 ty,
1109 async_,
1110 } => info::Trampoline::FutureCancelWrite {
1111 instance: *instance,
1112 ty: *ty,
1113 async_: *async_,
1114 },
1115 Trampoline::FutureDropReadable { instance, ty } => {
1116 info::Trampoline::FutureDropReadable {
1117 instance: *instance,
1118 ty: *ty,
1119 }
1120 }
1121 Trampoline::FutureDropWritable { instance, ty } => {
1122 info::Trampoline::FutureDropWritable {
1123 instance: *instance,
1124 ty: *ty,
1125 }
1126 }
1127 Trampoline::ErrorContextNew {
1128 instance,
1129 ty,
1130 options,
1131 } => info::Trampoline::ErrorContextNew {
1132 instance: *instance,
1133 ty: *ty,
1134 options: self.options(*options),
1135 },
1136 Trampoline::ErrorContextDebugMessage {
1137 instance,
1138 ty,
1139 options,
1140 } => info::Trampoline::ErrorContextDebugMessage {
1141 instance: *instance,
1142 ty: *ty,
1143 options: self.options(*options),
1144 },
1145 Trampoline::ErrorContextDrop { instance, ty } => info::Trampoline::ErrorContextDrop {
1146 instance: *instance,
1147 ty: *ty,
1148 },
1149 Trampoline::ResourceTransferOwn => info::Trampoline::ResourceTransferOwn,
1150 Trampoline::ResourceTransferBorrow => info::Trampoline::ResourceTransferBorrow,
1151 Trampoline::PrepareCall { memory } => info::Trampoline::PrepareCall {
1152 memory: memory.map(|v| self.runtime_memory(v)),
1153 },
1154 Trampoline::SyncStartCall { callback } => info::Trampoline::SyncStartCall {
1155 callback: callback.map(|v| self.runtime_callback(v)),
1156 },
1157 Trampoline::AsyncStartCall {
1158 callback,
1159 post_return,
1160 } => info::Trampoline::AsyncStartCall {
1161 callback: callback.map(|v| self.runtime_callback(v)),
1162 post_return: post_return.map(|v| self.runtime_post_return(v)),
1163 },
1164 Trampoline::FutureTransfer => info::Trampoline::FutureTransfer,
1165 Trampoline::StreamTransfer => info::Trampoline::StreamTransfer,
1166 Trampoline::ErrorContextTransfer => info::Trampoline::ErrorContextTransfer,
1167 Trampoline::Trap => info::Trampoline::Trap,
1168 Trampoline::EnterSyncCall => info::Trampoline::EnterSyncCall,
1169 Trampoline::ExitSyncCall => info::Trampoline::ExitSyncCall,
1170 Trampoline::ContextGet { instance, slot } => info::Trampoline::ContextGet {
1171 instance: *instance,
1172 slot: *slot,
1173 },
1174 Trampoline::ContextSet { instance, slot } => info::Trampoline::ContextSet {
1175 instance: *instance,
1176 slot: *slot,
1177 },
1178 Trampoline::ThreadIndex => info::Trampoline::ThreadIndex,
1179 Trampoline::ThreadNewIndirect {
1180 instance,
1181 start_func_ty_idx,
1182 start_func_table_id,
1183 } => info::Trampoline::ThreadNewIndirect {
1184 instance: *instance,
1185 start_func_ty_idx: *start_func_ty_idx,
1186 start_func_table_idx: self.runtime_table(*start_func_table_id),
1187 },
1188 Trampoline::ThreadSuspendToSuspended {
1189 instance,
1190 cancellable,
1191 } => info::Trampoline::ThreadSuspendToSuspended {
1192 instance: *instance,
1193 cancellable: *cancellable,
1194 },
1195 Trampoline::ThreadSuspendTo {
1196 instance,
1197 cancellable,
1198 } => info::Trampoline::ThreadSuspendTo {
1199 instance: *instance,
1200 cancellable: *cancellable,
1201 },
1202 Trampoline::ThreadSuspend {
1203 instance,
1204 cancellable,
1205 } => info::Trampoline::ThreadSuspend {
1206 instance: *instance,
1207 cancellable: *cancellable,
1208 },
1209 Trampoline::ThreadUnsuspend { instance } => info::Trampoline::ThreadUnsuspend {
1210 instance: *instance,
1211 },
1212 Trampoline::ThreadYieldToSuspended {
1213 instance,
1214 cancellable,
1215 } => info::Trampoline::ThreadYieldToSuspended {
1216 instance: *instance,
1217 cancellable: *cancellable,
1218 },
1219 };
1220 let i1 = self.trampolines.push(*signature);
1221 let i2 = self.trampoline_defs.push(trampoline);
1222 assert_eq!(i1, i2);
1223 self.trampoline_map.insert(index, i1);
1224 i1
1225 }
1226
1227 fn core_export<T>(&mut self, export: &CoreExport<T>) -> info::CoreExport<T>
1228 where
1229 T: Clone,
1230 {
1231 let instance = export.instance;
1232 log::trace!("referencing export of {instance:?}");
1233 info::CoreExport {
1234 instance: self.runtime_instances[&RuntimeInstance::Normal(instance)],
1235 item: export.item.clone(),
1236 }
1237 }
1238
1239 fn adapter(&mut self, adapter: AdapterId) -> info::CoreExport<EntityIndex> {
1240 let (adapter_module, entity_index) = self.dfg.adapter_partitionings[adapter];
1241
1242 let instance = self.adapter_module(adapter_module);
1246
1247 info::CoreExport {
1249 instance,
1250 item: ExportItem::Index(entity_index),
1251 }
1252 }
1253
1254 fn adapter_module(&mut self, adapter_module: AdapterModuleId) -> RuntimeInstanceIndex {
1255 self.intern(
1256 RuntimeInstance::Adapter(adapter_module),
1257 |me| &mut me.runtime_instances,
1258 |me, _| {
1259 log::debug!("instantiating {adapter_module:?}");
1260 let (module_index, args) = &me.dfg.adapter_modules[adapter_module];
1261 let args = args.iter().map(|arg| me.core_def(arg)).collect();
1262 let instantiate = InstantiateModule::Static(*module_index, args);
1263 GlobalInitializer::InstantiateModule(instantiate, None)
1264 },
1265 |_, init| init,
1266 )
1267 }
1268
1269 fn intern<K, V, T>(
1284 &mut self,
1285 key: K,
1286 map: impl Fn(&mut Self) -> &mut HashMap<K, V>,
1287 generate: impl FnOnce(&mut Self, K) -> T,
1288 init: impl FnOnce(V, T) -> GlobalInitializer,
1289 ) -> V
1290 where
1291 K: Hash + Eq + Copy,
1292 V: EntityRef,
1293 {
1294 self.intern_(key, map, generate, |me, key, val| {
1295 me.initializers.push(init(key, val));
1296 })
1297 }
1298
1299 fn intern_no_init<K, V, T>(
1300 &mut self,
1301 key: K,
1302 map: impl Fn(&mut Self) -> &mut HashMap<K, V>,
1303 generate: impl FnOnce(&mut Self, K) -> T,
1304 ) -> V
1305 where
1306 K: Hash + Eq + Copy,
1307 V: EntityRef,
1308 {
1309 self.intern_(key, map, generate, |_me, _key, _val| {})
1310 }
1311
1312 fn intern_<K, V, T>(
1313 &mut self,
1314 key: K,
1315 map: impl Fn(&mut Self) -> &mut HashMap<K, V>,
1316 generate: impl FnOnce(&mut Self, K) -> T,
1317 init: impl FnOnce(&mut Self, V, T),
1318 ) -> V
1319 where
1320 K: Hash + Eq + Copy,
1321 V: EntityRef,
1322 {
1323 if let Some(val) = map(self).get(&key) {
1324 return *val;
1325 }
1326 let tmp = generate(self, key);
1327 let index = V::new(map(self).len());
1328 init(self, index, tmp);
1329 let prev = map(self).insert(key, index);
1330 assert!(prev.is_none());
1331 index
1332 }
1333}