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