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
143pub enum SideEffect {
145 Instance(InstanceId),
152
153 Resource(DefinedResourceIndex),
160}
161
162macro_rules! id {
163 ($(pub struct $name:ident(u32);)*) => ($(
164 #[derive(Debug, Copy, Clone, Hash, Eq, PartialEq)]
165 #[expect(missing_docs, reason = "tedious to document")]
166 pub struct $name(u32);
167 cranelift_entity::entity_impl!($name);
168 )*)
169}
170
171id! {
172 pub struct InstanceId(u32);
173 pub struct MemoryId(u32);
174 pub struct TableId(u32);
175 pub struct ReallocId(u32);
176 pub struct CallbackId(u32);
177 pub struct AdapterId(u32);
178 pub struct PostReturnId(u32);
179 pub struct AdapterModuleId(u32);
180}
181
182#[expect(missing_docs, reason = "tedious to document variants")]
184pub enum Instance {
185 Static(StaticModuleIndex, Box<[CoreDef]>),
186 Import(
187 RuntimeImportIndex,
188 IndexMap<String, IndexMap<String, CoreDef>>,
189 ),
190}
191
192#[expect(missing_docs, reason = "tedious to document variants")]
194pub enum Export {
195 LiftedFunction {
196 ty: TypeFuncIndex,
197 func: CoreDef,
198 options: CanonicalOptions,
199 },
200 ModuleStatic {
201 ty: ComponentCoreModuleTypeId,
202 index: StaticModuleIndex,
203 },
204 ModuleImport {
205 ty: TypeModuleIndex,
206 import: RuntimeImportIndex,
207 },
208 Instance {
209 ty: TypeComponentInstanceIndex,
210 exports: IndexMap<String, Export>,
211 },
212 Type(TypeDef),
213}
214
215#[derive(Debug, Clone, Hash, Eq, PartialEq)]
217#[expect(missing_docs, reason = "tedious to document variants")]
218pub enum CoreDef {
219 Export(CoreExport<EntityIndex>),
220 InstanceFlags(RuntimeComponentInstanceIndex),
221 Trampoline(TrampolineIndex),
222 Adapter(AdapterId),
231}
232
233impl<T> From<CoreExport<T>> for CoreDef
234where
235 EntityIndex: From<T>,
236{
237 fn from(export: CoreExport<T>) -> CoreDef {
238 CoreDef::Export(export.map_index(|i| i.into()))
239 }
240}
241
242#[derive(Debug, Clone, Hash, Eq, PartialEq)]
244#[expect(missing_docs, reason = "self-describing fields")]
245pub struct CoreExport<T> {
246 pub instance: InstanceId,
247 pub item: ExportItem<T>,
248}
249
250impl<T> CoreExport<T> {
251 #[expect(missing_docs, reason = "self-describing function")]
252 pub fn map_index<U>(self, f: impl FnOnce(T) -> U) -> CoreExport<U> {
253 CoreExport {
254 instance: self.instance,
255 item: match self.item {
256 ExportItem::Index(i) => ExportItem::Index(f(i)),
257 ExportItem::Name(s) => ExportItem::Name(s),
258 },
259 }
260 }
261}
262
263#[derive(Clone, PartialEq, Eq, Hash)]
265#[expect(missing_docs, reason = "self-describing fields")]
266pub enum Trampoline {
267 LowerImport {
268 import: RuntimeImportIndex,
269 options: CanonicalOptions,
270 lower_ty: TypeFuncIndex,
271 },
272 Transcoder {
273 op: Transcode,
274 from: MemoryId,
275 from64: bool,
276 to: MemoryId,
277 to64: bool,
278 },
279 AlwaysTrap,
280 ResourceNew(TypeResourceTableIndex),
281 ResourceRep(TypeResourceTableIndex),
282 ResourceDrop(TypeResourceTableIndex),
283 BackpressureSet {
284 instance: RuntimeComponentInstanceIndex,
285 },
286 TaskReturn {
287 results: TypeTupleIndex,
288 options: CanonicalOptions,
289 },
290 TaskCancel {
291 instance: RuntimeComponentInstanceIndex,
292 },
293 WaitableSetNew {
294 instance: RuntimeComponentInstanceIndex,
295 },
296 WaitableSetWait {
297 instance: RuntimeComponentInstanceIndex,
298 async_: bool,
299 memory: MemoryId,
300 },
301 WaitableSetPoll {
302 instance: RuntimeComponentInstanceIndex,
303 async_: bool,
304 memory: MemoryId,
305 },
306 WaitableSetDrop {
307 instance: RuntimeComponentInstanceIndex,
308 },
309 WaitableJoin {
310 instance: RuntimeComponentInstanceIndex,
311 },
312 Yield {
313 async_: bool,
314 },
315 SubtaskDrop {
316 instance: RuntimeComponentInstanceIndex,
317 },
318 SubtaskCancel {
319 instance: RuntimeComponentInstanceIndex,
320 async_: bool,
321 },
322 StreamNew {
323 ty: TypeStreamTableIndex,
324 },
325 StreamRead {
326 ty: TypeStreamTableIndex,
327 options: CanonicalOptions,
328 },
329 StreamWrite {
330 ty: TypeStreamTableIndex,
331 options: CanonicalOptions,
332 },
333 StreamCancelRead {
334 ty: TypeStreamTableIndex,
335 async_: bool,
336 },
337 StreamCancelWrite {
338 ty: TypeStreamTableIndex,
339 async_: bool,
340 },
341 StreamDropReadable {
342 ty: TypeStreamTableIndex,
343 },
344 StreamDropWritable {
345 ty: TypeStreamTableIndex,
346 },
347 FutureNew {
348 ty: TypeFutureTableIndex,
349 },
350 FutureRead {
351 ty: TypeFutureTableIndex,
352 options: CanonicalOptions,
353 },
354 FutureWrite {
355 ty: TypeFutureTableIndex,
356 options: CanonicalOptions,
357 },
358 FutureCancelRead {
359 ty: TypeFutureTableIndex,
360 async_: bool,
361 },
362 FutureCancelWrite {
363 ty: TypeFutureTableIndex,
364 async_: bool,
365 },
366 FutureDropReadable {
367 ty: TypeFutureTableIndex,
368 },
369 FutureDropWritable {
370 ty: TypeFutureTableIndex,
371 },
372 ErrorContextNew {
373 ty: TypeComponentLocalErrorContextTableIndex,
374 options: CanonicalOptions,
375 },
376 ErrorContextDebugMessage {
377 ty: TypeComponentLocalErrorContextTableIndex,
378 options: CanonicalOptions,
379 },
380 ErrorContextDrop {
381 ty: TypeComponentLocalErrorContextTableIndex,
382 },
383 ResourceTransferOwn,
384 ResourceTransferBorrow,
385 ResourceEnterCall,
386 ResourceExitCall,
387 PrepareCall {
388 memory: Option<MemoryId>,
389 },
390 SyncStartCall {
391 callback: Option<CallbackId>,
392 },
393 AsyncStartCall {
394 callback: Option<CallbackId>,
395 post_return: Option<PostReturnId>,
396 },
397 FutureTransfer,
398 StreamTransfer,
399 ErrorContextTransfer,
400 ContextGet(u32),
401 ContextSet(u32),
402}
403
404#[derive(Copy, Clone, Hash, Eq, PartialEq)]
405#[expect(missing_docs, reason = "self-describing fields")]
406pub struct FutureInfo {
407 pub instance: RuntimeComponentInstanceIndex,
408 pub payload_type: Option<InterfaceType>,
409}
410
411#[derive(Copy, Clone, Hash, Eq, PartialEq)]
412#[expect(missing_docs, reason = "self-describing fields")]
413pub struct StreamInfo {
414 pub instance: RuntimeComponentInstanceIndex,
415 pub payload_type: InterfaceType,
416}
417
418#[derive(Clone, Hash, Eq, PartialEq)]
420#[expect(missing_docs, reason = "self-describing fields")]
421pub enum CanonicalOptionsDataModel {
422 Gc {},
423 LinearMemory {
424 memory: Option<MemoryId>,
425 realloc: Option<ReallocId>,
426 },
427}
428
429#[derive(Clone, Hash, Eq, PartialEq)]
431#[expect(missing_docs, reason = "self-describing fields")]
432pub struct CanonicalOptions {
433 pub instance: RuntimeComponentInstanceIndex,
434 pub string_encoding: StringEncoding,
435 pub callback: Option<CallbackId>,
436 pub post_return: Option<PostReturnId>,
437 pub async_: bool,
438 pub core_type: ModuleInternedTypeIndex,
439 pub data_model: CanonicalOptionsDataModel,
440}
441
442#[expect(missing_docs, reason = "self-describing fields")]
444pub struct Resource {
445 pub rep: WasmValType,
446 pub dtor: Option<CoreDef>,
447 pub instance: RuntimeComponentInstanceIndex,
448}
449
450pub struct Intern<K: EntityRef, V> {
456 intern_map: HashMap<V, K>,
457 key_map: PrimaryMap<K, V>,
458}
459
460impl<K, V> Intern<K, V>
461where
462 K: EntityRef,
463{
464 pub fn push(&mut self, value: V) -> K
471 where
472 V: Hash + Eq + Clone,
473 {
474 *self
475 .intern_map
476 .entry(value.clone())
477 .or_insert_with(|| self.key_map.push(value))
478 }
479
480 pub fn iter(&self) -> impl Iterator<Item = (K, &V)> {
482 self.key_map.iter()
483 }
484}
485
486impl<K: EntityRef, V> Index<K> for Intern<K, V> {
487 type Output = V;
488 fn index(&self, key: K) -> &V {
489 &self.key_map[key]
490 }
491}
492
493impl<K: EntityRef, V> Default for Intern<K, V> {
494 fn default() -> Intern<K, V> {
495 Intern {
496 intern_map: HashMap::new(),
497 key_map: PrimaryMap::new(),
498 }
499 }
500}
501
502impl ComponentDfg {
503 pub fn finish(
506 self,
507 wasmtime_types: &mut ComponentTypesBuilder,
508 wasmparser_types: wasmparser::types::TypesRef<'_>,
509 ) -> Result<ComponentTranslation> {
510 let mut linearize = LinearizeDfg {
511 dfg: &self,
512 initializers: Vec::new(),
513 runtime_memories: Default::default(),
514 runtime_tables: Default::default(),
515 runtime_post_return: Default::default(),
516 runtime_reallocs: Default::default(),
517 runtime_callbacks: Default::default(),
518 runtime_instances: Default::default(),
519 num_lowerings: 0,
520 trampolines: Default::default(),
521 trampoline_defs: Default::default(),
522 trampoline_map: Default::default(),
523 };
524
525 for item in linearize.dfg.side_effects.iter() {
529 linearize.side_effect(item);
530 }
531
532 let mut export_items = PrimaryMap::new();
535 let mut exports = NameMap::default();
536 for (name, export) in self.exports.iter() {
537 let export =
538 linearize.export(export, &mut export_items, wasmtime_types, wasmparser_types)?;
539 exports.insert(name, &mut NameMapNoIntern, false, export)?;
540 }
541
542 Ok(ComponentTranslation {
547 trampolines: linearize.trampoline_defs,
548 component: Component {
549 exports,
550 export_items,
551 initializers: linearize.initializers,
552 trampolines: linearize.trampolines,
553 num_lowerings: linearize.num_lowerings,
554
555 num_runtime_memories: linearize.runtime_memories.len() as u32,
556 num_runtime_tables: linearize.runtime_tables.len() as u32,
557 num_runtime_post_returns: linearize.runtime_post_return.len() as u32,
558 num_runtime_reallocs: linearize.runtime_reallocs.len() as u32,
559 num_runtime_callbacks: linearize.runtime_callbacks.len() as u32,
560 num_runtime_instances: linearize.runtime_instances.len() as u32,
561 imports: self.imports,
562 import_types: self.import_types,
563 num_runtime_component_instances: self.num_runtime_component_instances,
564 num_future_tables: self.num_future_tables,
565 num_stream_tables: self.num_stream_tables,
566 num_error_context_tables: self.num_error_context_tables,
567 num_resources: (self.resources.len() + self.imported_resources.len()) as u32,
568 imported_resources: self.imported_resources,
569 defined_resource_instances: self
570 .resources
571 .iter()
572 .map(|(_, r)| r.instance)
573 .collect(),
574 },
575 })
576 }
577
578 pub fn resource_index(&self, defined: DefinedResourceIndex) -> ResourceIndex {
581 ResourceIndex::from_u32(defined.as_u32() + (self.imported_resources.len() as u32))
582 }
583}
584
585struct LinearizeDfg<'a> {
586 dfg: &'a ComponentDfg,
587 initializers: Vec<GlobalInitializer>,
588 trampolines: PrimaryMap<TrampolineIndex, ModuleInternedTypeIndex>,
589 trampoline_defs: PrimaryMap<TrampolineIndex, info::Trampoline>,
590 trampoline_map: HashMap<TrampolineIndex, TrampolineIndex>,
591 runtime_memories: HashMap<MemoryId, RuntimeMemoryIndex>,
592 runtime_tables: HashMap<TableId, RuntimeTableIndex>,
593 runtime_reallocs: HashMap<ReallocId, RuntimeReallocIndex>,
594 runtime_callbacks: HashMap<CallbackId, RuntimeCallbackIndex>,
595 runtime_post_return: HashMap<PostReturnId, RuntimePostReturnIndex>,
596 runtime_instances: HashMap<RuntimeInstance, RuntimeInstanceIndex>,
597 num_lowerings: u32,
598}
599
600#[derive(Copy, Clone, Hash, Eq, PartialEq)]
601enum RuntimeInstance {
602 Normal(InstanceId),
603 Adapter(AdapterModuleId),
604}
605
606impl LinearizeDfg<'_> {
607 fn side_effect(&mut self, effect: &SideEffect) {
608 match effect {
609 SideEffect::Instance(i) => {
610 self.instantiate(*i, &self.dfg.instances[*i]);
611 }
612 SideEffect::Resource(i) => {
613 self.resource(*i, &self.dfg.resources[*i]);
614 }
615 }
616 }
617
618 fn instantiate(&mut self, instance: InstanceId, args: &Instance) {
619 log::trace!("creating instance {instance:?}");
620 let instantiation = match args {
621 Instance::Static(index, args) => InstantiateModule::Static(
622 *index,
623 args.iter().map(|def| self.core_def(def)).collect(),
624 ),
625 Instance::Import(index, args) => InstantiateModule::Import(
626 *index,
627 args.iter()
628 .map(|(module, values)| {
629 let values = values
630 .iter()
631 .map(|(name, def)| (name.clone(), self.core_def(def)))
632 .collect();
633 (module.clone(), values)
634 })
635 .collect(),
636 ),
637 };
638 let index = RuntimeInstanceIndex::new(self.runtime_instances.len());
639 self.initializers
640 .push(GlobalInitializer::InstantiateModule(instantiation));
641 let prev = self
642 .runtime_instances
643 .insert(RuntimeInstance::Normal(instance), index);
644 assert!(prev.is_none());
645 }
646
647 fn resource(&mut self, index: DefinedResourceIndex, resource: &Resource) {
648 let dtor = resource.dtor.as_ref().map(|dtor| self.core_def(dtor));
649 self.initializers
650 .push(GlobalInitializer::Resource(info::Resource {
651 dtor,
652 index,
653 rep: resource.rep,
654 instance: resource.instance,
655 }));
656 }
657
658 fn export(
659 &mut self,
660 export: &Export,
661 items: &mut PrimaryMap<ExportIndex, info::Export>,
662 wasmtime_types: &mut ComponentTypesBuilder,
663 wasmparser_types: wasmparser::types::TypesRef<'_>,
664 ) -> Result<ExportIndex> {
665 let item = match export {
666 Export::LiftedFunction { ty, func, options } => {
667 let func = self.core_def(func);
668 let options = self.options(options);
669 info::Export::LiftedFunction {
670 ty: *ty,
671 func,
672 options,
673 }
674 }
675 Export::ModuleStatic { ty, index } => info::Export::ModuleStatic {
676 ty: wasmtime_types.convert_module(wasmparser_types, *ty)?,
677 index: *index,
678 },
679 Export::ModuleImport { ty, import } => info::Export::ModuleImport {
680 ty: *ty,
681 import: *import,
682 },
683 Export::Instance { ty, exports } => info::Export::Instance {
684 ty: *ty,
685 exports: {
686 let mut map = NameMap::default();
687 for (name, export) in exports {
688 let export =
689 self.export(export, items, wasmtime_types, wasmparser_types)?;
690 map.insert(name, &mut NameMapNoIntern, false, export)?;
691 }
692 map
693 },
694 },
695 Export::Type(def) => info::Export::Type(*def),
696 };
697 Ok(items.push(item))
698 }
699
700 fn options(&mut self, options: &CanonicalOptions) -> info::CanonicalOptions {
701 let data_model = match options.data_model {
702 CanonicalOptionsDataModel::Gc {} => info::CanonicalOptionsDataModel::Gc {},
703 CanonicalOptionsDataModel::LinearMemory { memory, realloc } => {
704 info::CanonicalOptionsDataModel::LinearMemory(LinearMemoryOptions {
705 memory: memory.map(|mem| self.runtime_memory(mem)),
706 realloc: realloc.map(|mem| self.runtime_realloc(mem)),
707 })
708 }
709 };
710 let callback = options.callback.map(|mem| self.runtime_callback(mem));
711 let post_return = options.post_return.map(|mem| self.runtime_post_return(mem));
712 info::CanonicalOptions {
713 instance: options.instance,
714 string_encoding: options.string_encoding,
715 callback,
716 post_return,
717 async_: options.async_,
718 core_type: options.core_type,
719 data_model,
720 }
721 }
722
723 fn runtime_memory(&mut self, mem: MemoryId) -> RuntimeMemoryIndex {
724 self.intern(
725 mem,
726 |me| &mut me.runtime_memories,
727 |me, mem| me.core_export(&me.dfg.memories[mem]),
728 |index, export| GlobalInitializer::ExtractMemory(ExtractMemory { index, export }),
729 )
730 }
731
732 fn runtime_realloc(&mut self, realloc: ReallocId) -> RuntimeReallocIndex {
733 self.intern(
734 realloc,
735 |me| &mut me.runtime_reallocs,
736 |me, realloc| me.core_def(&me.dfg.reallocs[realloc]),
737 |index, def| GlobalInitializer::ExtractRealloc(ExtractRealloc { index, def }),
738 )
739 }
740
741 fn runtime_callback(&mut self, callback: CallbackId) -> RuntimeCallbackIndex {
742 self.intern(
743 callback,
744 |me| &mut me.runtime_callbacks,
745 |me, callback| me.core_def(&me.dfg.callbacks[callback]),
746 |index, def| GlobalInitializer::ExtractCallback(ExtractCallback { index, def }),
747 )
748 }
749
750 fn runtime_post_return(&mut self, post_return: PostReturnId) -> RuntimePostReturnIndex {
751 self.intern(
752 post_return,
753 |me| &mut me.runtime_post_return,
754 |me, post_return| me.core_def(&me.dfg.post_returns[post_return]),
755 |index, def| GlobalInitializer::ExtractPostReturn(ExtractPostReturn { index, def }),
756 )
757 }
758
759 fn core_def(&mut self, def: &CoreDef) -> info::CoreDef {
760 match def {
761 CoreDef::Export(e) => info::CoreDef::Export(self.core_export(e)),
762 CoreDef::InstanceFlags(i) => info::CoreDef::InstanceFlags(*i),
763 CoreDef::Adapter(id) => info::CoreDef::Export(self.adapter(*id)),
764 CoreDef::Trampoline(index) => info::CoreDef::Trampoline(self.trampoline(*index)),
765 }
766 }
767
768 fn trampoline(&mut self, index: TrampolineIndex) -> TrampolineIndex {
769 if let Some(idx) = self.trampoline_map.get(&index) {
770 return *idx;
771 }
772 let (signature, trampoline) = &self.dfg.trampolines[index];
773 let trampoline = match trampoline {
774 Trampoline::LowerImport {
775 import,
776 options,
777 lower_ty,
778 } => {
779 let index = LoweredIndex::from_u32(self.num_lowerings);
780 self.num_lowerings += 1;
781 self.initializers.push(GlobalInitializer::LowerImport {
782 index,
783 import: *import,
784 });
785 info::Trampoline::LowerImport {
786 index,
787 options: self.options(options),
788 lower_ty: *lower_ty,
789 }
790 }
791 Trampoline::Transcoder {
792 op,
793 from,
794 from64,
795 to,
796 to64,
797 } => info::Trampoline::Transcoder {
798 op: *op,
799 from: self.runtime_memory(*from),
800 from64: *from64,
801 to: self.runtime_memory(*to),
802 to64: *to64,
803 },
804 Trampoline::AlwaysTrap => info::Trampoline::AlwaysTrap,
805 Trampoline::ResourceNew(ty) => info::Trampoline::ResourceNew(*ty),
806 Trampoline::ResourceDrop(ty) => info::Trampoline::ResourceDrop(*ty),
807 Trampoline::ResourceRep(ty) => info::Trampoline::ResourceRep(*ty),
808 Trampoline::BackpressureSet { instance } => info::Trampoline::BackpressureSet {
809 instance: *instance,
810 },
811 Trampoline::TaskReturn { results, options } => info::Trampoline::TaskReturn {
812 results: *results,
813 options: self.options(options),
814 },
815 Trampoline::TaskCancel { instance } => info::Trampoline::TaskCancel {
816 instance: *instance,
817 },
818 Trampoline::WaitableSetNew { instance } => info::Trampoline::WaitableSetNew {
819 instance: *instance,
820 },
821 Trampoline::WaitableSetWait {
822 instance,
823 async_,
824 memory,
825 } => info::Trampoline::WaitableSetWait {
826 instance: *instance,
827 async_: *async_,
828 memory: self.runtime_memory(*memory),
829 },
830 Trampoline::WaitableSetPoll {
831 instance,
832 async_,
833 memory,
834 } => info::Trampoline::WaitableSetPoll {
835 instance: *instance,
836 async_: *async_,
837 memory: self.runtime_memory(*memory),
838 },
839 Trampoline::WaitableSetDrop { instance } => info::Trampoline::WaitableSetDrop {
840 instance: *instance,
841 },
842 Trampoline::WaitableJoin { instance } => info::Trampoline::WaitableJoin {
843 instance: *instance,
844 },
845 Trampoline::Yield { async_ } => info::Trampoline::Yield { async_: *async_ },
846 Trampoline::SubtaskDrop { instance } => info::Trampoline::SubtaskDrop {
847 instance: *instance,
848 },
849 Trampoline::SubtaskCancel { instance, async_ } => info::Trampoline::SubtaskCancel {
850 instance: *instance,
851 async_: *async_,
852 },
853 Trampoline::StreamNew { ty } => info::Trampoline::StreamNew { ty: *ty },
854 Trampoline::StreamRead { ty, options } => info::Trampoline::StreamRead {
855 ty: *ty,
856 options: self.options(options),
857 },
858 Trampoline::StreamWrite { ty, options } => info::Trampoline::StreamWrite {
859 ty: *ty,
860 options: self.options(options),
861 },
862 Trampoline::StreamCancelRead { ty, async_ } => info::Trampoline::StreamCancelRead {
863 ty: *ty,
864 async_: *async_,
865 },
866 Trampoline::StreamCancelWrite { ty, async_ } => info::Trampoline::StreamCancelWrite {
867 ty: *ty,
868 async_: *async_,
869 },
870 Trampoline::StreamDropReadable { ty } => {
871 info::Trampoline::StreamDropReadable { ty: *ty }
872 }
873 Trampoline::StreamDropWritable { ty } => {
874 info::Trampoline::StreamDropWritable { ty: *ty }
875 }
876 Trampoline::FutureNew { ty } => info::Trampoline::FutureNew { ty: *ty },
877 Trampoline::FutureRead { ty, options } => info::Trampoline::FutureRead {
878 ty: *ty,
879 options: self.options(options),
880 },
881 Trampoline::FutureWrite { ty, options } => info::Trampoline::FutureWrite {
882 ty: *ty,
883 options: self.options(options),
884 },
885 Trampoline::FutureCancelRead { ty, async_ } => info::Trampoline::FutureCancelRead {
886 ty: *ty,
887 async_: *async_,
888 },
889 Trampoline::FutureCancelWrite { ty, async_ } => info::Trampoline::FutureCancelWrite {
890 ty: *ty,
891 async_: *async_,
892 },
893 Trampoline::FutureDropReadable { ty } => {
894 info::Trampoline::FutureDropReadable { ty: *ty }
895 }
896 Trampoline::FutureDropWritable { ty } => {
897 info::Trampoline::FutureDropWritable { ty: *ty }
898 }
899 Trampoline::ErrorContextNew { ty, options } => info::Trampoline::ErrorContextNew {
900 ty: *ty,
901 options: self.options(options),
902 },
903 Trampoline::ErrorContextDebugMessage { ty, options } => {
904 info::Trampoline::ErrorContextDebugMessage {
905 ty: *ty,
906 options: self.options(options),
907 }
908 }
909 Trampoline::ErrorContextDrop { ty } => info::Trampoline::ErrorContextDrop { ty: *ty },
910 Trampoline::ResourceTransferOwn => info::Trampoline::ResourceTransferOwn,
911 Trampoline::ResourceTransferBorrow => info::Trampoline::ResourceTransferBorrow,
912 Trampoline::ResourceEnterCall => info::Trampoline::ResourceEnterCall,
913 Trampoline::ResourceExitCall => info::Trampoline::ResourceExitCall,
914 Trampoline::PrepareCall { memory } => info::Trampoline::PrepareCall {
915 memory: memory.map(|v| self.runtime_memory(v)),
916 },
917 Trampoline::SyncStartCall { callback } => info::Trampoline::SyncStartCall {
918 callback: callback.map(|v| self.runtime_callback(v)),
919 },
920 Trampoline::AsyncStartCall {
921 callback,
922 post_return,
923 } => info::Trampoline::AsyncStartCall {
924 callback: callback.map(|v| self.runtime_callback(v)),
925 post_return: post_return.map(|v| self.runtime_post_return(v)),
926 },
927 Trampoline::FutureTransfer => info::Trampoline::FutureTransfer,
928 Trampoline::StreamTransfer => info::Trampoline::StreamTransfer,
929 Trampoline::ErrorContextTransfer => info::Trampoline::ErrorContextTransfer,
930 Trampoline::ContextGet(i) => info::Trampoline::ContextGet(*i),
931 Trampoline::ContextSet(i) => info::Trampoline::ContextSet(*i),
932 };
933 let i1 = self.trampolines.push(*signature);
934 let i2 = self.trampoline_defs.push(trampoline);
935 assert_eq!(i1, i2);
936 self.trampoline_map.insert(index, i1);
937 i1
938 }
939
940 fn core_export<T>(&mut self, export: &CoreExport<T>) -> info::CoreExport<T>
941 where
942 T: Clone,
943 {
944 let instance = export.instance;
945 log::trace!("referencing export of {instance:?}");
946 info::CoreExport {
947 instance: self.runtime_instances[&RuntimeInstance::Normal(instance)],
948 item: export.item.clone(),
949 }
950 }
951
952 fn adapter(&mut self, adapter: AdapterId) -> info::CoreExport<EntityIndex> {
953 let (adapter_module, entity_index) = self.dfg.adapter_partitionings[adapter];
954
955 let instance = self.adapter_module(adapter_module);
959
960 info::CoreExport {
962 instance,
963 item: ExportItem::Index(entity_index),
964 }
965 }
966
967 fn adapter_module(&mut self, adapter_module: AdapterModuleId) -> RuntimeInstanceIndex {
968 self.intern(
969 RuntimeInstance::Adapter(adapter_module),
970 |me| &mut me.runtime_instances,
971 |me, _| {
972 log::debug!("instantiating {adapter_module:?}");
973 let (module_index, args) = &me.dfg.adapter_modules[adapter_module];
974 let args = args.iter().map(|arg| me.core_def(arg)).collect();
975 let instantiate = InstantiateModule::Static(*module_index, args);
976 GlobalInitializer::InstantiateModule(instantiate)
977 },
978 |_, init| init,
979 )
980 }
981
982 fn intern<K, V, T>(
997 &mut self,
998 key: K,
999 map: impl Fn(&mut Self) -> &mut HashMap<K, V>,
1000 generate: impl FnOnce(&mut Self, K) -> T,
1001 init: impl FnOnce(V, T) -> GlobalInitializer,
1002 ) -> V
1003 where
1004 K: Hash + Eq + Copy,
1005 V: EntityRef,
1006 {
1007 if let Some(val) = map(self).get(&key) {
1008 return *val;
1009 }
1010 let tmp = generate(self, key);
1011 let index = V::new(map(self).len());
1012 self.initializers.push(init(index, tmp));
1013 let prev = map(self).insert(key, index);
1014 assert!(prev.is_none());
1015 index
1016 }
1017}