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