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