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