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 StartCall {
467 callback: Option<CallbackId>,
468 post_return: Option<PostReturnId>,
469 },
470 FutureTransfer,
471 StreamTransfer,
472 ErrorContextTransfer,
473 Trap(Trap),
474 EnterSyncCall,
475 ExitSyncCall,
476 ThreadIndex {
477 instance: RuntimeComponentInstanceIndex,
478 },
479 ThreadNewIndirect {
480 instance: RuntimeComponentInstanceIndex,
481 start_func_ty_idx: ModuleInternedTypeIndex,
482 start_func_table_id: TableId,
483 },
484 ThreadResumeLater {
485 instance: RuntimeComponentInstanceIndex,
486 },
487 ThreadSuspend {
488 instance: RuntimeComponentInstanceIndex,
489 },
490 ThreadYield {
491 instance: RuntimeComponentInstanceIndex,
492 },
493 ThreadSuspendThenResume {
494 instance: RuntimeComponentInstanceIndex,
495 },
496 ThreadYieldThenResume {
497 instance: RuntimeComponentInstanceIndex,
498 },
499 ThreadSuspendThenPromote {
500 instance: RuntimeComponentInstanceIndex,
501 },
502 ThreadYieldThenPromote {
503 instance: RuntimeComponentInstanceIndex,
504 },
505}
506
507#[derive(Copy, Clone, Hash, Eq, PartialEq)]
508#[expect(missing_docs, reason = "self-describing fields")]
509pub struct FutureInfo {
510 pub instance: RuntimeComponentInstanceIndex,
511 pub payload_type: Option<InterfaceType>,
512}
513
514#[derive(Copy, Clone, Hash, Eq, PartialEq)]
515#[expect(missing_docs, reason = "self-describing fields")]
516pub struct StreamInfo {
517 pub instance: RuntimeComponentInstanceIndex,
518 pub payload_type: InterfaceType,
519}
520
521#[derive(Clone, Hash, Eq, PartialEq)]
523#[expect(missing_docs, reason = "self-describing fields")]
524pub enum CanonicalOptionsDataModel {
525 Gc {},
526 LinearMemory {
527 memory: Option<MemoryId>,
528 realloc: Option<ReallocId>,
529 },
530}
531
532#[derive(Clone, Hash, Eq, PartialEq)]
534#[expect(missing_docs, reason = "self-describing fields")]
535pub struct CanonicalOptions {
536 pub instance: RuntimeComponentInstanceIndex,
537 pub string_encoding: StringEncoding,
538 pub callback: Option<CallbackId>,
539 pub post_return: Option<PostReturnId>,
540 pub async_: bool,
541 pub core_type: ModuleInternedTypeIndex,
542 pub data_model: CanonicalOptionsDataModel,
543}
544
545#[expect(missing_docs, reason = "self-describing fields")]
547pub struct Resource {
548 pub rep: WasmValType,
549 pub dtor: Option<CoreDef>,
550 pub instance: RuntimeComponentInstanceIndex,
551}
552
553pub struct Intern<K: EntityRef, V> {
559 intern_map: HashMap<V, K>,
560 key_map: PrimaryMap<K, V>,
561}
562
563impl<K, V> Intern<K, V>
564where
565 K: EntityRef,
566{
567 pub fn push(&mut self, value: V) -> K
574 where
575 V: Hash + Eq + Clone,
576 {
577 *self
578 .intern_map
579 .entry(value.clone())
580 .or_insert_with(|| self.key_map.push(value))
581 }
582
583 pub fn iter(&self) -> impl Iterator<Item = (K, &V)> {
585 self.key_map.iter()
586 }
587}
588
589impl<K: EntityRef, V> Index<K> for Intern<K, V> {
590 type Output = V;
591 fn index(&self, key: K) -> &V {
592 &self.key_map[key]
593 }
594}
595
596impl<K: EntityRef, V> Default for Intern<K, V> {
597 fn default() -> Intern<K, V> {
598 Intern {
599 intern_map: HashMap::new(),
600 key_map: PrimaryMap::new(),
601 }
602 }
603}
604
605impl ComponentDfg {
606 pub fn finish(
609 self,
610 wasmtime_types: &mut ComponentTypesBuilder,
611 wasmparser_types: wasmparser::types::TypesRef<'_>,
612 ) -> Result<ComponentTranslation> {
613 let mut linearize = LinearizeDfg {
614 dfg: &self,
615 initializers: Vec::new(),
616 runtime_memories: Default::default(),
617 runtime_tables: Default::default(),
618 runtime_post_return: Default::default(),
619 runtime_reallocs: Default::default(),
620 runtime_callbacks: Default::default(),
621 runtime_instances: Default::default(),
622 num_lowerings: 0,
623 unsafe_intrinsics: Default::default(),
624 trampolines: Default::default(),
625 trampoline_defs: Default::default(),
626 trampoline_map: Default::default(),
627 options: Default::default(),
628 options_map: Default::default(),
629 };
630
631 for item in linearize.dfg.side_effects.iter() {
635 linearize.side_effect(item);
636 }
637
638 let mut export_items = PrimaryMap::new();
641 let mut exports = NameMap::default();
642 for (name, (export, data)) in self.exports.iter() {
643 let export =
644 linearize.export(export, &mut export_items, wasmtime_types, wasmparser_types)?;
645 exports.insert(name, &mut NameMapNoIntern, false, (export, data.clone()))?;
646 }
647
648 Ok(ComponentTranslation {
653 trampolines: linearize.trampoline_defs,
654 component: Component {
655 exports,
656 export_items,
657 initializers: linearize.initializers,
658 unsafe_intrinsics: linearize.unsafe_intrinsics,
659 trampolines: linearize.trampolines,
660 num_lowerings: linearize.num_lowerings,
661 options: linearize.options,
662
663 num_runtime_memories: linearize.runtime_memories.len() as u32,
664 num_runtime_tables: linearize.runtime_tables.len() as u32,
665 num_runtime_post_returns: linearize.runtime_post_return.len() as u32,
666 num_runtime_reallocs: linearize.runtime_reallocs.len() as u32,
667 num_runtime_callbacks: linearize.runtime_callbacks.len() as u32,
668 num_runtime_instances: linearize.runtime_instances.len() as u32,
669 imports: self.imports,
670 import_types: self.import_types,
671 num_runtime_component_instances: self.num_runtime_component_instances,
672 num_future_tables: self.num_future_tables,
673 num_stream_tables: self.num_stream_tables,
674 num_error_context_tables: self.num_error_context_tables,
675 num_resources: (self.resources.len() + self.imported_resources.len()) as u32,
676 imported_resources: self.imported_resources,
677 defined_resource_instances: self
678 .resources
679 .iter()
680 .map(|(_, r)| r.instance)
681 .collect(),
682 },
683 })
684 }
685
686 pub fn resource_index(&self, defined: DefinedResourceIndex) -> ResourceIndex {
689 ResourceIndex::from_u32(defined.as_u32() + (self.imported_resources.len() as u32))
690 }
691}
692
693struct LinearizeDfg<'a> {
694 dfg: &'a ComponentDfg,
695 initializers: Vec<GlobalInitializer>,
696 unsafe_intrinsics: [PackedOption<ModuleInternedTypeIndex>; UnsafeIntrinsic::len() as usize],
697 trampolines: PrimaryMap<TrampolineIndex, ModuleInternedTypeIndex>,
698 trampoline_defs: PrimaryMap<TrampolineIndex, info::Trampoline>,
699 options: PrimaryMap<OptionsIndex, info::CanonicalOptions>,
700 trampoline_map: HashMap<TrampolineIndex, TrampolineIndex>,
701 runtime_memories: HashMap<MemoryId, RuntimeMemoryIndex>,
702 runtime_tables: HashMap<TableId, RuntimeTableIndex>,
703 runtime_reallocs: HashMap<ReallocId, RuntimeReallocIndex>,
704 runtime_callbacks: HashMap<CallbackId, RuntimeCallbackIndex>,
705 runtime_post_return: HashMap<PostReturnId, RuntimePostReturnIndex>,
706 runtime_instances: HashMap<RuntimeInstance, RuntimeInstanceIndex>,
707 options_map: HashMap<OptionsId, OptionsIndex>,
708 num_lowerings: u32,
709}
710
711#[derive(Copy, Clone, Hash, Eq, PartialEq)]
712enum RuntimeInstance {
713 Normal(InstanceId),
714 Adapter(AdapterModuleId),
715}
716
717impl LinearizeDfg<'_> {
718 fn side_effect(&mut self, effect: &SideEffect) {
719 match effect {
720 SideEffect::Instance(i, ci) => {
721 self.instantiate(*i, &self.dfg.instances[*i], *ci);
722 }
723 SideEffect::Resource(i) => {
724 self.resource(*i, &self.dfg.resources[*i]);
725 }
726 }
727 }
728
729 fn instantiate(
730 &mut self,
731 instance: InstanceId,
732 args: &Instance,
733 component_instance: RuntimeComponentInstanceIndex,
734 ) {
735 log::trace!("creating instance {instance:?}");
736 let instantiation = match args {
737 Instance::Static(index, args) => InstantiateModule::Static(
738 *index,
739 args.iter().map(|def| self.core_def(def)).collect(),
740 ),
741 Instance::Import(index, args) => InstantiateModule::Import(
742 *index,
743 args.iter()
744 .map(|(module, values)| {
745 let values = values
746 .iter()
747 .map(|(name, def)| (name.clone(), self.core_def(def)))
748 .collect();
749 (module.clone(), values)
750 })
751 .collect(),
752 ),
753 };
754 let index = RuntimeInstanceIndex::new(self.runtime_instances.len());
755 self.initializers.push(GlobalInitializer::InstantiateModule(
756 instantiation,
757 Some(component_instance),
758 ));
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, data)) in exports {
806 let export =
807 self.export(export, items, wasmtime_types, wasmparser_types)?;
808 map.insert(name, &mut NameMapNoIntern, false, (export, data.clone()))?;
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 core_type: options.core_type,
846 data_model,
847 };
848 self.options.push(options)
849 }
850
851 fn runtime_memory(&mut self, mem: MemoryId) -> RuntimeMemoryIndex {
852 self.intern(
853 mem,
854 |me| &mut me.runtime_memories,
855 |me, mem| me.core_export(&me.dfg.memories[mem]),
856 |index, export| GlobalInitializer::ExtractMemory(ExtractMemory { index, export }),
857 )
858 }
859
860 fn runtime_table(&mut self, table: TableId) -> RuntimeTableIndex {
861 self.intern(
862 table,
863 |me| &mut me.runtime_tables,
864 |me, table| me.core_export(&me.dfg.tables[table]),
865 |index, export| GlobalInitializer::ExtractTable(ExtractTable { index, export }),
866 )
867 }
868
869 fn runtime_realloc(&mut self, realloc: ReallocId) -> RuntimeReallocIndex {
870 self.intern(
871 realloc,
872 |me| &mut me.runtime_reallocs,
873 |me, realloc| me.core_def(&me.dfg.reallocs[realloc]),
874 |index, def| GlobalInitializer::ExtractRealloc(ExtractRealloc { index, def }),
875 )
876 }
877
878 fn runtime_callback(&mut self, callback: CallbackId) -> RuntimeCallbackIndex {
879 self.intern(
880 callback,
881 |me| &mut me.runtime_callbacks,
882 |me, callback| me.core_def(&me.dfg.callbacks[callback]),
883 |index, def| GlobalInitializer::ExtractCallback(ExtractCallback { index, def }),
884 )
885 }
886
887 fn runtime_post_return(&mut self, post_return: PostReturnId) -> RuntimePostReturnIndex {
888 self.intern(
889 post_return,
890 |me| &mut me.runtime_post_return,
891 |me, post_return| me.core_def(&me.dfg.post_returns[post_return]),
892 |index, def| GlobalInitializer::ExtractPostReturn(ExtractPostReturn { index, def }),
893 )
894 }
895
896 fn core_def(&mut self, def: &CoreDef) -> info::CoreDef {
897 match def {
898 CoreDef::Export(e) => info::CoreDef::Export(self.core_export(e)),
899 CoreDef::InstanceFlags(i) => info::CoreDef::InstanceFlags(*i),
900 CoreDef::Adapter(id) => info::CoreDef::Export(self.adapter(*id)),
901 CoreDef::Trampoline(index) => info::CoreDef::Trampoline(self.trampoline(*index)),
902 CoreDef::UnsafeIntrinsic(ty, i) => {
903 let index = usize::try_from(i.index()).unwrap();
904 if self.unsafe_intrinsics[index].is_none() {
905 self.unsafe_intrinsics[index] = Some(*ty).into();
906 }
907 info::CoreDef::UnsafeIntrinsic(*i)
908 }
909 }
910 }
911
912 fn trampoline(&mut self, index: TrampolineIndex) -> TrampolineIndex {
913 if let Some(idx) = self.trampoline_map.get(&index) {
914 return *idx;
915 }
916 let (signature, trampoline) = &self.dfg.trampolines[index];
917 let trampoline = match trampoline {
918 Trampoline::LowerImport {
919 import,
920 options,
921 lower_ty,
922 } => {
923 let index = LoweredIndex::from_u32(self.num_lowerings);
924 self.num_lowerings += 1;
925 self.initializers.push(GlobalInitializer::LowerImport {
926 index,
927 import: *import,
928 });
929 info::Trampoline::LowerImport {
930 index,
931 options: self.options(*options),
932 lower_ty: *lower_ty,
933 }
934 }
935 Trampoline::Transcoder {
936 op,
937 from,
938 from64,
939 to,
940 to64,
941 } => info::Trampoline::Transcoder {
942 op: *op,
943 from: self.runtime_memory(*from),
944 from64: *from64,
945 to: self.runtime_memory(*to),
946 to64: *to64,
947 },
948 Trampoline::ResourceNew { instance, ty } => info::Trampoline::ResourceNew {
949 instance: *instance,
950 ty: *ty,
951 },
952 Trampoline::ResourceDrop { instance, ty } => info::Trampoline::ResourceDrop {
953 instance: *instance,
954 ty: *ty,
955 },
956 Trampoline::ResourceRep { instance, ty } => info::Trampoline::ResourceRep {
957 instance: *instance,
958 ty: *ty,
959 },
960 Trampoline::BackpressureInc { instance } => info::Trampoline::BackpressureInc {
961 instance: *instance,
962 },
963 Trampoline::BackpressureDec { instance } => info::Trampoline::BackpressureDec {
964 instance: *instance,
965 },
966 Trampoline::TaskReturn {
967 instance,
968 results,
969 options,
970 } => info::Trampoline::TaskReturn {
971 instance: *instance,
972 results: *results,
973 options: self.options(*options),
974 },
975 Trampoline::TaskCancel { instance } => info::Trampoline::TaskCancel {
976 instance: *instance,
977 },
978 Trampoline::WaitableSetNew { instance } => info::Trampoline::WaitableSetNew {
979 instance: *instance,
980 },
981 Trampoline::WaitableSetWait { instance, options } => {
982 info::Trampoline::WaitableSetWait {
983 instance: *instance,
984 options: self.options(*options),
985 }
986 }
987 Trampoline::WaitableSetPoll { instance, options } => {
988 info::Trampoline::WaitableSetPoll {
989 instance: *instance,
990 options: self.options(*options),
991 }
992 }
993 Trampoline::WaitableSetDrop { instance } => info::Trampoline::WaitableSetDrop {
994 instance: *instance,
995 },
996 Trampoline::WaitableJoin { instance } => info::Trampoline::WaitableJoin {
997 instance: *instance,
998 },
999 Trampoline::SubtaskDrop { instance } => info::Trampoline::SubtaskDrop {
1000 instance: *instance,
1001 },
1002 Trampoline::SubtaskCancel { instance, async_ } => info::Trampoline::SubtaskCancel {
1003 instance: *instance,
1004 async_: *async_,
1005 },
1006 Trampoline::StreamNew { instance, ty } => info::Trampoline::StreamNew {
1007 instance: *instance,
1008 ty: *ty,
1009 },
1010 Trampoline::StreamRead {
1011 instance,
1012 ty,
1013 options,
1014 } => info::Trampoline::StreamRead {
1015 instance: *instance,
1016 ty: *ty,
1017 options: self.options(*options),
1018 },
1019 Trampoline::StreamWrite {
1020 instance,
1021 ty,
1022 options,
1023 } => info::Trampoline::StreamWrite {
1024 instance: *instance,
1025 ty: *ty,
1026 options: self.options(*options),
1027 },
1028 Trampoline::StreamCancelRead {
1029 instance,
1030 ty,
1031 async_,
1032 } => info::Trampoline::StreamCancelRead {
1033 instance: *instance,
1034 ty: *ty,
1035 async_: *async_,
1036 },
1037 Trampoline::StreamCancelWrite {
1038 instance,
1039 ty,
1040 async_,
1041 } => info::Trampoline::StreamCancelWrite {
1042 instance: *instance,
1043 ty: *ty,
1044 async_: *async_,
1045 },
1046 Trampoline::StreamDropReadable { instance, ty } => {
1047 info::Trampoline::StreamDropReadable {
1048 instance: *instance,
1049 ty: *ty,
1050 }
1051 }
1052 Trampoline::StreamDropWritable { instance, ty } => {
1053 info::Trampoline::StreamDropWritable {
1054 instance: *instance,
1055 ty: *ty,
1056 }
1057 }
1058 Trampoline::FutureNew { instance, ty } => info::Trampoline::FutureNew {
1059 instance: *instance,
1060 ty: *ty,
1061 },
1062 Trampoline::FutureRead {
1063 instance,
1064 ty,
1065 options,
1066 } => info::Trampoline::FutureRead {
1067 instance: *instance,
1068 ty: *ty,
1069 options: self.options(*options),
1070 },
1071 Trampoline::FutureWrite {
1072 instance,
1073 ty,
1074 options,
1075 } => info::Trampoline::FutureWrite {
1076 instance: *instance,
1077 ty: *ty,
1078 options: self.options(*options),
1079 },
1080 Trampoline::FutureCancelRead {
1081 instance,
1082 ty,
1083 async_,
1084 } => info::Trampoline::FutureCancelRead {
1085 instance: *instance,
1086 ty: *ty,
1087 async_: *async_,
1088 },
1089 Trampoline::FutureCancelWrite {
1090 instance,
1091 ty,
1092 async_,
1093 } => info::Trampoline::FutureCancelWrite {
1094 instance: *instance,
1095 ty: *ty,
1096 async_: *async_,
1097 },
1098 Trampoline::FutureDropReadable { instance, ty } => {
1099 info::Trampoline::FutureDropReadable {
1100 instance: *instance,
1101 ty: *ty,
1102 }
1103 }
1104 Trampoline::FutureDropWritable { instance, ty } => {
1105 info::Trampoline::FutureDropWritable {
1106 instance: *instance,
1107 ty: *ty,
1108 }
1109 }
1110 Trampoline::ErrorContextNew {
1111 instance,
1112 ty,
1113 options,
1114 } => info::Trampoline::ErrorContextNew {
1115 instance: *instance,
1116 ty: *ty,
1117 options: self.options(*options),
1118 },
1119 Trampoline::ErrorContextDebugMessage {
1120 instance,
1121 ty,
1122 options,
1123 } => info::Trampoline::ErrorContextDebugMessage {
1124 instance: *instance,
1125 ty: *ty,
1126 options: self.options(*options),
1127 },
1128 Trampoline::ErrorContextDrop { instance, ty } => info::Trampoline::ErrorContextDrop {
1129 instance: *instance,
1130 ty: *ty,
1131 },
1132 Trampoline::ResourceTransferOwn => info::Trampoline::ResourceTransferOwn,
1133 Trampoline::ResourceTransferBorrow => info::Trampoline::ResourceTransferBorrow,
1134 Trampoline::PrepareCall { memory } => info::Trampoline::PrepareCall {
1135 memory: memory.map(|v| self.runtime_memory(v)),
1136 },
1137 Trampoline::StartCall {
1138 callback,
1139 post_return,
1140 } => info::Trampoline::StartCall {
1141 callback: callback.map(|v| self.runtime_callback(v)),
1142 post_return: post_return.map(|v| self.runtime_post_return(v)),
1143 },
1144 Trampoline::FutureTransfer => info::Trampoline::FutureTransfer,
1145 Trampoline::StreamTransfer => info::Trampoline::StreamTransfer,
1146 Trampoline::ErrorContextTransfer => info::Trampoline::ErrorContextTransfer,
1147 Trampoline::Trap(trap) => info::Trampoline::Trap(*trap),
1148 Trampoline::EnterSyncCall => info::Trampoline::EnterSyncCall,
1149 Trampoline::ExitSyncCall => info::Trampoline::ExitSyncCall,
1150 Trampoline::ThreadIndex { instance } => info::Trampoline::ThreadIndex {
1151 instance: *instance,
1152 },
1153 Trampoline::ThreadNewIndirect {
1154 instance,
1155 start_func_ty_idx,
1156 start_func_table_id,
1157 } => info::Trampoline::ThreadNewIndirect {
1158 instance: *instance,
1159 start_func_ty_idx: *start_func_ty_idx,
1160 start_func_table_idx: self.runtime_table(*start_func_table_id),
1161 },
1162 Trampoline::ThreadResumeLater { instance } => info::Trampoline::ThreadResumeLater {
1163 instance: *instance,
1164 },
1165 Trampoline::ThreadSuspend { instance } => info::Trampoline::ThreadSuspend {
1166 instance: *instance,
1167 },
1168 Trampoline::ThreadYield { instance } => info::Trampoline::ThreadYield {
1169 instance: *instance,
1170 },
1171 Trampoline::ThreadSuspendThenResume { instance } => {
1172 info::Trampoline::ThreadSuspendThenResume {
1173 instance: *instance,
1174 }
1175 }
1176 Trampoline::ThreadYieldThenResume { instance } => {
1177 info::Trampoline::ThreadYieldThenResume {
1178 instance: *instance,
1179 }
1180 }
1181 Trampoline::ThreadSuspendThenPromote { instance } => {
1182 info::Trampoline::ThreadSuspendThenPromote {
1183 instance: *instance,
1184 }
1185 }
1186 Trampoline::ThreadYieldThenPromote { instance } => {
1187 info::Trampoline::ThreadYieldThenPromote {
1188 instance: *instance,
1189 }
1190 }
1191 };
1192 let i1 = self.trampolines.push(*signature);
1193 let i2 = self.trampoline_defs.push(trampoline);
1194 assert_eq!(i1, i2);
1195 self.trampoline_map.insert(index, i1);
1196 i1
1197 }
1198
1199 fn core_export<T>(&mut self, export: &CoreExport<T>) -> info::CoreExport<T>
1200 where
1201 T: Clone,
1202 {
1203 let instance = export.instance;
1204 log::trace!("referencing export of {instance:?}");
1205 info::CoreExport {
1206 instance: self.runtime_instances[&RuntimeInstance::Normal(instance)],
1207 item: export.item.clone(),
1208 }
1209 }
1210
1211 fn adapter(&mut self, adapter: AdapterId) -> info::CoreExport<EntityIndex> {
1212 let (adapter_module, entity_index) = self.dfg.adapter_partitionings[adapter];
1213
1214 let instance = self.adapter_module(adapter_module);
1218
1219 info::CoreExport {
1221 instance,
1222 item: ExportItem::Index(entity_index),
1223 }
1224 }
1225
1226 fn adapter_module(&mut self, adapter_module: AdapterModuleId) -> RuntimeInstanceIndex {
1227 self.intern(
1228 RuntimeInstance::Adapter(adapter_module),
1229 |me| &mut me.runtime_instances,
1230 |me, _| {
1231 log::debug!("instantiating {adapter_module:?}");
1232 let (module_index, args) = &me.dfg.adapter_modules[adapter_module];
1233 let args = args.iter().map(|arg| me.core_def(arg)).collect();
1234 let instantiate = InstantiateModule::Static(*module_index, args);
1235 GlobalInitializer::InstantiateModule(instantiate, None)
1236 },
1237 |_, init| init,
1238 )
1239 }
1240
1241 fn intern<K, V, T>(
1256 &mut self,
1257 key: K,
1258 map: impl Fn(&mut Self) -> &mut HashMap<K, V>,
1259 generate: impl FnOnce(&mut Self, K) -> T,
1260 init: impl FnOnce(V, T) -> GlobalInitializer,
1261 ) -> V
1262 where
1263 K: Hash + Eq + Copy,
1264 V: EntityRef,
1265 {
1266 self.intern_(key, map, generate, |me, key, val| {
1267 me.initializers.push(init(key, val));
1268 })
1269 }
1270
1271 fn intern_no_init<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 ) -> V
1277 where
1278 K: Hash + Eq + Copy,
1279 V: EntityRef,
1280 {
1281 self.intern_(key, map, generate, |_me, _key, _val| {})
1282 }
1283
1284 fn intern_<K, V, T>(
1285 &mut self,
1286 key: K,
1287 map: impl Fn(&mut Self) -> &mut HashMap<K, V>,
1288 generate: impl FnOnce(&mut Self, K) -> T,
1289 init: impl FnOnce(&mut Self, V, T),
1290 ) -> V
1291 where
1292 K: Hash + Eq + Copy,
1293 V: EntityRef,
1294 {
1295 if let Some(val) = map(self).get(&key) {
1296 return *val;
1297 }
1298 let tmp = generate(self, key);
1299 let index = V::new(map(self).len());
1300 init(self, index, tmp);
1301 let prev = map(self).insert(key, index);
1302 assert!(prev.is_none());
1303 index
1304 }
1305}