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