1use crate::StringEncoding;
75use crate::metadata::{self, Bindgen, ModuleMetadata};
76use crate::validation::{
77 Export, ExportMap, Import, ImportInstance, ImportMap, PayloadInfo, PayloadType,
78};
79use anyhow::{Context, Result, anyhow, bail};
80use indexmap::{IndexMap, IndexSet};
81use std::borrow::Cow;
82use std::collections::HashMap;
83use std::hash::Hash;
84use std::mem;
85use wasm_encoder::*;
86use wasmparser::{Validator, WasmFeatures};
87use wit_parser::{
88 Function, FunctionKind, InterfaceId, LiveTypes, Param, Resolve, Stability, Type, TypeDefKind,
89 TypeId, TypeOwner, WorldItem, WorldKey,
90 abi::{AbiVariant, WasmSignature, WasmType},
91};
92
93const INDIRECT_TABLE_NAME: &str = "$imports";
94
95mod wit;
96pub use wit::{encode, encode_world};
97
98mod types;
99use types::{InstanceTypeEncoder, RootTypeEncoder, TypeEncodingMaps, ValtypeEncoder};
100mod world;
101use world::{ComponentWorld, ImportedInterface, Lowering};
102
103mod dedupe;
104pub(crate) use dedupe::ModuleImportMap;
105use wasm_metadata::AddMetadataField;
106
107fn to_val_type(ty: &WasmType) -> ValType {
108 match ty {
109 WasmType::I32 => ValType::I32,
110 WasmType::I64 => ValType::I64,
111 WasmType::F32 => ValType::F32,
112 WasmType::F64 => ValType::F64,
113 WasmType::Pointer => ValType::I32,
114 WasmType::PointerOrI64 => ValType::I64,
115 WasmType::Length => ValType::I32,
116 }
117}
118
119fn import_func_name(f: &Function) -> String {
120 match f.kind {
121 FunctionKind::Freestanding | FunctionKind::AsyncFreestanding => {
122 format!("import-func-{}", f.item_name())
123 }
124
125 FunctionKind::Method(_)
133 | FunctionKind::AsyncMethod(_)
134 | FunctionKind::Static(_)
135 | FunctionKind::AsyncStatic(_)
136 | FunctionKind::Constructor(_) => {
137 format!(
138 "import-{}",
139 f.name.replace('[', "").replace([']', '.', ' '], "-")
140 )
141 }
142 }
143}
144
145bitflags::bitflags! {
146 #[derive(Copy, Clone, Debug)]
149 pub struct RequiredOptions: u8 {
150 const MEMORY = 1 << 0;
153 const REALLOC = 1 << 1;
156 const STRING_ENCODING = 1 << 2;
159 const ASYNC = 1 << 3;
160 }
161}
162
163impl RequiredOptions {
164 fn for_import(resolve: &Resolve, func: &Function, abi: AbiVariant) -> RequiredOptions {
165 let sig = resolve.wasm_signature(abi, func);
166 let mut ret = RequiredOptions::empty();
167 ret.add_lift(TypeContents::for_types(
169 resolve,
170 func.params.iter().map(|p| &p.ty),
171 ));
172 ret.add_lower(TypeContents::for_types(resolve, &func.result));
173
174 if sig.retptr || sig.indirect_params {
177 ret |= RequiredOptions::MEMORY;
178 }
179 if abi == AbiVariant::GuestImportAsync {
180 ret |= RequiredOptions::ASYNC;
181 }
182 ret
183 }
184
185 fn for_export(resolve: &Resolve, func: &Function, abi: AbiVariant) -> RequiredOptions {
186 let sig = resolve.wasm_signature(abi, func);
187 let mut ret = RequiredOptions::empty();
188 ret.add_lower(TypeContents::for_types(
190 resolve,
191 func.params.iter().map(|p| &p.ty),
192 ));
193 ret.add_lift(TypeContents::for_types(resolve, &func.result));
194
195 if sig.retptr || sig.indirect_params {
199 ret |= RequiredOptions::MEMORY;
200 if sig.indirect_params {
201 ret |= RequiredOptions::REALLOC;
202 }
203 }
204 if let AbiVariant::GuestExportAsync | AbiVariant::GuestExportAsyncStackful = abi {
205 ret |= RequiredOptions::ASYNC;
206 ret |= task_return_options_and_type(resolve, func).0;
207 }
208 ret
209 }
210
211 fn add_lower(&mut self, types: TypeContents) {
212 if types.contains(TypeContents::NEEDS_MEMORY) {
216 *self |= RequiredOptions::MEMORY | RequiredOptions::REALLOC;
217 }
218 if types.contains(TypeContents::STRING) {
219 *self |= RequiredOptions::MEMORY
220 | RequiredOptions::STRING_ENCODING
221 | RequiredOptions::REALLOC;
222 }
223 }
224
225 fn add_lift(&mut self, types: TypeContents) {
226 if types.contains(TypeContents::NEEDS_MEMORY) {
230 *self |= RequiredOptions::MEMORY;
231 }
232 if types.contains(TypeContents::STRING) {
233 *self |= RequiredOptions::MEMORY | RequiredOptions::STRING_ENCODING;
234 }
235 }
236
237 fn into_iter(
238 self,
239 encoding: StringEncoding,
240 memory_index: Option<u32>,
241 realloc_index: Option<u32>,
242 ) -> Result<impl ExactSizeIterator<Item = CanonicalOption>> {
243 #[derive(Default)]
244 struct Iter {
245 options: [Option<CanonicalOption>; 5],
246 current: usize,
247 count: usize,
248 }
249
250 impl Iter {
251 fn push(&mut self, option: CanonicalOption) {
252 assert!(self.count < self.options.len());
253 self.options[self.count] = Some(option);
254 self.count += 1;
255 }
256 }
257
258 impl Iterator for Iter {
259 type Item = CanonicalOption;
260
261 fn next(&mut self) -> Option<Self::Item> {
262 if self.current == self.count {
263 return None;
264 }
265 let option = self.options[self.current];
266 self.current += 1;
267 option
268 }
269
270 fn size_hint(&self) -> (usize, Option<usize>) {
271 (self.count - self.current, Some(self.count - self.current))
272 }
273 }
274
275 impl ExactSizeIterator for Iter {}
276
277 let mut iter = Iter::default();
278
279 if self.contains(RequiredOptions::MEMORY) {
280 iter.push(CanonicalOption::Memory(memory_index.ok_or_else(|| {
281 anyhow!("module does not export a memory named `memory`")
282 })?));
283 }
284
285 if self.contains(RequiredOptions::REALLOC) {
286 iter.push(CanonicalOption::Realloc(realloc_index.ok_or_else(
287 || anyhow!("module does not export a function named `cabi_realloc`"),
288 )?));
289 }
290
291 if self.contains(RequiredOptions::STRING_ENCODING) {
292 iter.push(encoding.into());
293 }
294
295 if self.contains(RequiredOptions::ASYNC) {
296 iter.push(CanonicalOption::Async);
297 }
298
299 Ok(iter)
300 }
301}
302
303bitflags::bitflags! {
304 struct TypeContents: u8 {
307 const STRING = 1 << 0;
308 const NEEDS_MEMORY = 1 << 1;
309 }
310}
311
312impl TypeContents {
313 fn for_types<'a>(resolve: &Resolve, types: impl IntoIterator<Item = &'a Type>) -> Self {
314 let mut cur = TypeContents::empty();
315 for ty in types {
316 cur |= Self::for_type(resolve, ty);
317 }
318 cur
319 }
320
321 fn for_optional_types<'a>(
322 resolve: &Resolve,
323 types: impl Iterator<Item = Option<&'a Type>>,
324 ) -> Self {
325 Self::for_types(resolve, types.flatten())
326 }
327
328 fn for_optional_type(resolve: &Resolve, ty: Option<&Type>) -> Self {
329 match ty {
330 Some(ty) => Self::for_type(resolve, ty),
331 None => Self::empty(),
332 }
333 }
334
335 fn for_type(resolve: &Resolve, ty: &Type) -> Self {
336 match ty {
337 Type::Id(id) => match &resolve.types[*id].kind {
338 TypeDefKind::Handle(h) => match h {
339 wit_parser::Handle::Own(_) => Self::empty(),
340 wit_parser::Handle::Borrow(_) => Self::empty(),
341 },
342 TypeDefKind::Resource => Self::empty(),
343 TypeDefKind::Record(r) => Self::for_types(resolve, r.fields.iter().map(|f| &f.ty)),
344 TypeDefKind::Tuple(t) => Self::for_types(resolve, t.types.iter()),
345 TypeDefKind::Flags(_) => Self::empty(),
346 TypeDefKind::Option(t) => Self::for_type(resolve, t),
347 TypeDefKind::Result(r) => {
348 Self::for_optional_type(resolve, r.ok.as_ref())
349 | Self::for_optional_type(resolve, r.err.as_ref())
350 }
351 TypeDefKind::Variant(v) => {
352 Self::for_optional_types(resolve, v.cases.iter().map(|c| c.ty.as_ref()))
353 }
354 TypeDefKind::Enum(_) => Self::empty(),
355 TypeDefKind::List(t) => Self::for_type(resolve, t) | Self::NEEDS_MEMORY,
356 TypeDefKind::Map(k, v) => {
357 Self::for_type(resolve, k) | Self::for_type(resolve, v) | Self::NEEDS_MEMORY
358 }
359 TypeDefKind::FixedLengthList(t, _elements) => Self::for_type(resolve, t),
360 TypeDefKind::Type(t) => Self::for_type(resolve, t),
361 TypeDefKind::Future(_) => Self::empty(),
362 TypeDefKind::Stream(_) => Self::empty(),
363 TypeDefKind::Unknown => unreachable!(),
364 },
365 Type::String => Self::STRING,
366 _ => Self::empty(),
367 }
368 }
369}
370
371pub struct EncodingState<'a> {
373 component: ComponentBuilder,
375 module_index: Option<u32>,
379 instance_index: Option<u32>,
383 memory_index: Option<u32>,
387 shim_instance_index: Option<u32>,
391 fixups_module_index: Option<u32>,
395
396 adapter_modules: IndexMap<&'a str, u32>,
399 adapter_instances: IndexMap<&'a str, u32>,
401
402 instances: IndexMap<InterfaceId, u32>,
404 imported_funcs: IndexMap<String, u32>,
405
406 type_encoding_maps: TypeEncodingMaps<'a>,
411
412 aliased_core_items: HashMap<(u32, String), u32>,
418
419 info: &'a ComponentWorld<'a>,
421
422 export_task_initialization_wrappers: HashMap<String, u32>,
425}
426
427impl<'a> EncodingState<'a> {
428 fn encode_core_modules(&mut self) {
429 assert!(self.module_index.is_none());
430 let idx = self
431 .component
432 .core_module_raw(Some("main"), &self.info.encoder.module);
433 self.module_index = Some(idx);
434
435 for (name, adapter) in self.info.adapters.iter() {
436 let debug_name = if adapter.library_info.is_some() {
437 name.to_string()
438 } else {
439 format!("wit-component:adapter:{name}")
440 };
441 let idx = if self.info.encoder.debug_names {
442 let mut add_meta = wasm_metadata::AddMetadata::default();
443 add_meta.name = AddMetadataField::Set(debug_name.clone());
444 let wasm = add_meta
445 .to_wasm(&adapter.wasm)
446 .expect("core wasm can get name added");
447 self.component.core_module_raw(Some(&debug_name), &wasm)
448 } else {
449 self.component
450 .core_module_raw(Some(&debug_name), &adapter.wasm)
451 };
452 let prev = self.adapter_modules.insert(name, idx);
453 assert!(prev.is_none());
454 }
455 }
456
457 fn root_import_type_encoder(
458 &mut self,
459 interface: Option<InterfaceId>,
460 ) -> RootTypeEncoder<'_, 'a> {
461 RootTypeEncoder {
462 state: self,
463 interface,
464 import_types: true,
465 }
466 }
467
468 fn root_export_type_encoder(
469 &mut self,
470 interface: Option<InterfaceId>,
471 ) -> RootTypeEncoder<'_, 'a> {
472 RootTypeEncoder {
473 state: self,
474 interface,
475 import_types: false,
476 }
477 }
478
479 fn instance_type_encoder(&mut self, interface: InterfaceId) -> InstanceTypeEncoder<'_, 'a> {
480 InstanceTypeEncoder {
481 state: self,
482 interface,
483 type_encoding_maps: Default::default(),
484 ty: Default::default(),
485 }
486 }
487
488 fn encode_imports(&mut self, name_map: &HashMap<String, String>) -> Result<()> {
489 let mut has_funcs = false;
490 for (name, info) in self.info.import_map.iter() {
491 match name {
492 Some(name) => {
493 self.encode_interface_import(name_map.get(name).unwrap_or(name), info)?
494 }
495 None => has_funcs = true,
496 }
497 }
498
499 let resolve = &self.info.encoder.metadata.resolve;
500 let world = &resolve.worlds[self.info.encoder.metadata.world];
501
502 for (_name, item) in world.imports.iter() {
505 if let WorldItem::Type { id, .. } = item {
506 self.root_import_type_encoder(None)
507 .encode_valtype(resolve, &Type::Id(*id))?;
508 }
509 }
510
511 if has_funcs {
512 let info = &self.info.import_map[&None];
513 self.encode_root_import_funcs(info)?;
514 }
515 Ok(())
516 }
517
518 fn encode_interface_import(&mut self, name: &str, info: &ImportedInterface) -> Result<()> {
519 let resolve = &self.info.encoder.metadata.resolve;
520 let interface_id = info.interface.as_ref().unwrap();
521 let interface_id = *interface_id;
522 let interface = &resolve.interfaces[interface_id];
523 log::trace!("encoding imports for `{name}` as {interface_id:?}");
524 let mut encoder = self.instance_type_encoder(interface_id);
525
526 if let Some(live) = encoder.state.info.live_type_imports.get(&interface_id) {
528 for ty in live {
529 log::trace!(
530 "encoding extra type {ty:?} name={:?}",
531 resolve.types[*ty].name
532 );
533 encoder.encode_valtype(resolve, &Type::Id(*ty))?;
534 }
535 }
536
537 for (_, func) in interface.functions.iter() {
540 if !(info
541 .lowerings
542 .contains_key(&(func.name.clone(), AbiVariant::GuestImport))
543 || info
544 .lowerings
545 .contains_key(&(func.name.clone(), AbiVariant::GuestImportAsync)))
546 {
547 continue;
548 }
549 log::trace!("encoding function type for `{}`", func.name);
550 let idx = encoder.encode_func_type(resolve, func)?;
551
552 encoder.ty.export(
553 crate::encoding::types::extern_name(&func.name, func.external_id.as_deref()),
554 ComponentTypeRef::Func(idx),
555 );
556 }
557
558 let ty = encoder.ty;
559 if ty.is_empty() {
562 return Ok(());
563 }
564 let instance_type_idx = self
565 .component
566 .type_instance(Some(&format!("ty-{name}")), &ty);
567 let instance_idx = self.component.import(
568 wasm_encoder::ComponentExternName {
569 name: name.into(),
570 implements: info.implements.as_deref().map(|s| s.into()),
571 external_id: info.external_id.as_deref().map(|s| s.into()),
572 version_suffix: None,
573 },
574 ComponentTypeRef::Instance(instance_type_idx),
575 );
576 let prev = self.instances.insert(interface_id, instance_idx);
577 assert!(prev.is_none());
578 Ok(())
579 }
580
581 fn encode_root_import_funcs(&mut self, info: &ImportedInterface) -> Result<()> {
582 let resolve = &self.info.encoder.metadata.resolve;
583 let world = self.info.encoder.metadata.world;
584 for (name, item) in resolve.worlds[world].imports.iter() {
585 let func = match item {
586 WorldItem::Function(f) => f,
587 WorldItem::Interface { .. } | WorldItem::Type { .. } => continue,
588 };
589 let name = resolve.name_world_key(name);
590 if !(info
591 .lowerings
592 .contains_key(&(name.clone(), AbiVariant::GuestImport))
593 || info
594 .lowerings
595 .contains_key(&(name.clone(), AbiVariant::GuestImportAsync)))
596 {
597 continue;
598 }
599 log::trace!("encoding function type for `{}`", func.name);
600 let idx = self
601 .root_import_type_encoder(None)
602 .encode_func_type(resolve, func)?;
603 let func_idx = self.component.import(
604 crate::encoding::types::extern_name(name.as_str(), func.external_id.as_deref()),
605 ComponentTypeRef::Func(idx),
606 );
607 let prev = self.imported_funcs.insert(name, func_idx);
608 assert!(prev.is_none());
609 }
610 Ok(())
611 }
612
613 fn alias_instance_type_export(&mut self, interface: InterfaceId, id: TypeId) -> u32 {
614 let ty = &self.info.encoder.metadata.resolve.types[id];
615 let name = ty.name.as_ref().expect("type must have a name");
616 let instance = self.instances[&interface];
617 self.component
618 .alias_export(instance, name, ComponentExportKind::Type)
619 }
620
621 fn encode_core_instantiation(&mut self) -> Result<()> {
622 let shims = self.encode_shim_instantiation()?;
624
625 self.declare_types_for_imported_intrinsics(&shims)?;
629
630 self.instantiate_main_module(&shims)?;
634
635 self.create_export_task_initialization_wrappers()?;
638
639 let (before, after) = self
642 .info
643 .adapters
644 .iter()
645 .partition::<Vec<_>, _>(|(_, adapter)| {
646 !matches!(
647 adapter.library_info,
648 Some(LibraryInfo {
649 instantiate_after_shims: true,
650 ..
651 })
652 )
653 });
654
655 for (name, _adapter) in before {
656 self.instantiate_adapter_module(&shims, name)?;
657 }
658
659 self.encode_indirect_lowerings(&shims)?;
662
663 for (name, _adapter) in after {
664 self.instantiate_adapter_module(&shims, name)?;
665 }
666
667 self.encode_initialize_with_start()?;
668
669 Ok(())
670 }
671
672 fn lookup_resource_index(&mut self, id: TypeId) -> u32 {
673 let resolve = &self.info.encoder.metadata.resolve;
674 let ty = &resolve.types[id];
675 match ty.owner {
676 TypeOwner::World(_) => self.type_encoding_maps.id_to_index[&id],
680 TypeOwner::Interface(i) => {
681 let instance = self.instances[&i];
682 let name = ty.name.as_ref().expect("resources must be named");
683 self.component
684 .alias_export(instance, name, ComponentExportKind::Type)
685 }
686 TypeOwner::None => panic!("resources must have an owner"),
687 }
688 }
689
690 fn encode_exports(&mut self, module: CustomModule) -> Result<()> {
691 let resolve = &self.info.encoder.metadata.resolve;
692 let exports = match module {
693 CustomModule::Main => &self.info.encoder.main_module_exports,
694 CustomModule::Adapter(name) => &self.info.encoder.adapters[name].required_exports,
695 };
696
697 if exports.is_empty() {
698 return Ok(());
699 }
700
701 let mut interface_func_core_names = IndexMap::new();
702 let mut world_func_core_names = IndexMap::new();
703 for (core_name, export) in self.info.exports_for(module).iter() {
704 match export {
705 Export::WorldFunc(_, name, _) => {
706 let prev = world_func_core_names.insert(name, core_name);
707 assert!(prev.is_none());
708 }
709 Export::InterfaceFunc(key, _, name, _) => {
710 let prev = interface_func_core_names
711 .entry(key)
712 .or_insert(IndexMap::new())
713 .insert(name.as_str(), core_name);
714 assert!(prev.is_none());
715 }
716 Export::WorldFuncCallback(..)
717 | Export::InterfaceFuncCallback(..)
718 | Export::WorldFuncPostReturn(..)
719 | Export::InterfaceFuncPostReturn(..)
720 | Export::ResourceDtor(..)
721 | Export::Memory
722 | Export::GeneralPurposeRealloc
723 | Export::GeneralPurposeExportRealloc
724 | Export::GeneralPurposeImportRealloc
725 | Export::Initialize
726 | Export::ReallocForAdapter
727 | Export::IndirectFunctionTable
728 | Export::WasmInitTask
729 | Export::WasmInitAsyncTask => continue,
730 }
731 }
732
733 let world = &resolve.worlds[self.info.encoder.metadata.world];
734
735 for export_name in exports {
736 let export_string = resolve.name_world_key(export_name);
737 match &world.exports[export_name] {
738 WorldItem::Function(func) => {
739 let ty = self
740 .root_import_type_encoder(None)
741 .encode_func_type(resolve, func)?;
742 let core_name = world_func_core_names[&func.name];
743 let idx = self.encode_lift(module, &core_name, export_name, func, ty)?;
744 self.component.export(
745 crate::encoding::types::extern_name(
746 &export_string,
747 func.external_id.as_deref(),
748 ),
749 ComponentExportKind::Func,
750 idx,
751 None,
752 );
753 }
754 item @ WorldItem::Interface { id, .. } => {
755 let core_names = interface_func_core_names.get(export_name);
756 self.encode_interface_export(
757 &export_string,
758 module,
759 export_name,
760 item,
761 *id,
762 core_names,
763 )?;
764 }
765 WorldItem::Type { .. } => unreachable!(),
766 }
767 }
768
769 Ok(())
770 }
771
772 fn encode_interface_export(
773 &mut self,
774 export_name: &str,
775 module: CustomModule<'_>,
776 key: &WorldKey,
777 item: &WorldItem,
778 export: InterfaceId,
779 interface_func_core_names: Option<&IndexMap<&str, &str>>,
780 ) -> Result<()> {
781 log::trace!("encode interface export `{export_name}`");
782 let resolve = &self.info.encoder.metadata.resolve;
783
784 let mut imports = Vec::new();
791 let mut root = self.root_export_type_encoder(Some(export));
792 for (_, func) in &resolve.interfaces[export].functions {
793 let core_name = interface_func_core_names.unwrap()[func.name.as_str()];
794 let ty = root.encode_func_type(resolve, func)?;
795 let func_index = root.state.encode_lift(module, &core_name, key, func, ty)?;
796 imports.push((
797 import_func_name(func),
798 ComponentExportKind::Func,
799 func_index,
800 ));
801 }
802
803 let mut nested = NestedComponentTypeEncoder {
807 component: ComponentBuilder::default(),
808 type_encoding_maps: Default::default(),
809 export_types: false,
810 interface: export,
811 state: self,
812 imports: IndexMap::new(),
813 };
814
815 let mut types_to_import = LiveTypes::default();
825 types_to_import.add_interface(resolve, export);
826 let exports_used = &nested.state.info.exports_used[&export];
827 for ty in types_to_import.iter() {
828 if let TypeOwner::Interface(owner) = resolve.types[ty].owner {
829 if owner == export {
830 continue;
833 }
834
835 let mut encoder = if exports_used.contains(&owner) {
838 nested.state.root_export_type_encoder(Some(export))
839 } else {
840 nested.state.root_import_type_encoder(Some(export))
841 };
842 encoder.encode_valtype(resolve, &Type::Id(ty))?;
843
844 nested.interface = owner;
848 nested.encode_valtype(resolve, &Type::Id(ty))?;
849 }
850 }
851 nested.interface = export;
852
853 let imported_type_maps = nested.type_encoding_maps.clone();
857
858 let mut resources = HashMap::new();
864 for (_name, ty) in resolve.interfaces[export].types.iter() {
865 if !matches!(resolve.types[*ty].kind, TypeDefKind::Resource) {
866 continue;
867 }
868 let idx = match nested.encode_valtype(resolve, &Type::Id(*ty))? {
869 ComponentValType::Type(idx) => idx,
870 _ => unreachable!(),
871 };
872 resources.insert(*ty, idx);
873 }
874
875 for (_, func) in resolve.interfaces[export].functions.iter() {
879 let ty = nested.encode_func_type(resolve, func)?;
880 nested
881 .component
882 .import(&import_func_name(func), ComponentTypeRef::Func(ty));
883 }
884
885 let reverse_map = nested
892 .type_encoding_maps
893 .id_to_index
894 .drain()
895 .map(|p| (p.1, p.0))
896 .collect::<HashMap<_, _>>();
897 nested.type_encoding_maps.def_to_index.clear();
898 for (name, idx) in nested.imports.drain(..) {
899 let id = reverse_map[&idx];
900 let idx = nested.state.type_encoding_maps.id_to_index[&id];
901 imports.push((name, ComponentExportKind::Type, idx))
902 }
903
904 nested.type_encoding_maps = imported_type_maps;
909
910 nested.export_types = true;
917 nested.type_encoding_maps.func_type_map.clear();
918
919 for (_, id) in resolve.interfaces[export].types.iter() {
925 let ty = &resolve.types[*id];
926 match ty.kind {
927 TypeDefKind::Resource => {
928 let idx = nested.component.export(
929 crate::encoding::types::extern_name(
930 ty.name.as_ref().expect("resources must be named"),
931 ty.external_id.as_deref(),
932 ),
933 ComponentExportKind::Type,
934 resources[id],
935 None,
936 );
937 nested.type_encoding_maps.id_to_index.insert(*id, idx);
938 }
939 _ => {
940 nested.encode_valtype(resolve, &Type::Id(*id))?;
941 }
942 }
943 }
944
945 for (i, (_, func)) in resolve.interfaces[export].functions.iter().enumerate() {
946 let ty = nested.encode_func_type(resolve, func)?;
947 nested.component.export(
948 crate::encoding::types::extern_name(&func.name, func.external_id.as_deref()),
949 ComponentExportKind::Func,
950 i as u32,
951 Some(ComponentTypeRef::Func(ty)),
952 );
953 }
954
955 let component = nested.component;
959 let component_index = self
960 .component
961 .component(Some(&format!("{export_name}-shim-component")), component);
962 let instance_index = self.component.instantiate(
963 Some(&format!("{export_name}-shim-instance")),
964 component_index,
965 imports,
966 );
967 let idx = self.component.export(
968 wasm_encoder::ComponentExternName {
969 name: export_name.into(),
970 implements: resolve.implements_value(key, item).map(|s| s.into()),
971 external_id: resolve.external_id_value(key, item).map(|s| s.into()),
972 version_suffix: None,
973 },
974 ComponentExportKind::Instance,
975 instance_index,
976 None,
977 );
978 let prev = self.instances.insert(export, idx);
979 assert!(prev.is_none());
980
981 for (_name, id) in resolve.interfaces[export].types.iter() {
989 self.type_encoding_maps.id_to_index.remove(id);
990 self.type_encoding_maps
991 .def_to_index
992 .remove(&resolve.types[*id].kind);
993 }
994
995 return Ok(());
996
997 struct NestedComponentTypeEncoder<'state, 'a> {
998 component: ComponentBuilder,
999 type_encoding_maps: TypeEncodingMaps<'a>,
1000 export_types: bool,
1001 interface: InterfaceId,
1002 state: &'state mut EncodingState<'a>,
1003 imports: IndexMap<String, u32>,
1004 }
1005
1006 impl<'a> ValtypeEncoder<'a> for NestedComponentTypeEncoder<'_, 'a> {
1007 fn defined_type(&mut self) -> (u32, ComponentDefinedTypeEncoder<'_>) {
1008 self.component.type_defined(None)
1009 }
1010 fn define_function_type(&mut self) -> (u32, ComponentFuncTypeEncoder<'_>) {
1011 self.component.type_function(None)
1012 }
1013 fn export_type(
1014 &mut self,
1015 idx: u32,
1016 name: wasm_encoder::ComponentExternName<'a>,
1017 ) -> Option<u32> {
1018 if self.export_types {
1019 Some(
1020 self.component
1021 .export(name, ComponentExportKind::Type, idx, None),
1022 )
1023 } else {
1024 let name = self.unique_import_name(&name.name);
1025 let ret = self
1026 .component
1027 .import(&name, ComponentTypeRef::Type(TypeBounds::Eq(idx)));
1028 self.imports.insert(name, ret);
1029 Some(ret)
1030 }
1031 }
1032 fn export_resource(&mut self, name: wasm_encoder::ComponentExternName<'a>) -> u32 {
1033 if self.export_types {
1034 panic!("resources should already be exported")
1035 } else {
1036 let name = self.unique_import_name(&name.name);
1037 let ret = self
1038 .component
1039 .import(&name, ComponentTypeRef::Type(TypeBounds::SubResource));
1040 self.imports.insert(name, ret);
1041 ret
1042 }
1043 }
1044 fn import_type(&mut self, _: InterfaceId, _id: TypeId) -> u32 {
1045 unreachable!()
1046 }
1047 fn type_encoding_maps(&mut self) -> &mut TypeEncodingMaps<'a> {
1048 &mut self.type_encoding_maps
1049 }
1050 fn interface(&self) -> Option<InterfaceId> {
1051 Some(self.interface)
1052 }
1053 }
1054
1055 impl NestedComponentTypeEncoder<'_, '_> {
1056 fn unique_import_name(&mut self, name: &str) -> String {
1057 let mut name = format!("import-type-{name}");
1058 let mut n = 0;
1059 while self.imports.contains_key(&name) {
1060 name = format!("{name}{n}");
1061 n += 1;
1062 }
1063 name
1064 }
1065 }
1066 }
1067
1068 fn encode_lift(
1069 &mut self,
1070 module: CustomModule<'_>,
1071 core_name: &str,
1072 key: &WorldKey,
1073 func: &Function,
1074 ty: u32,
1075 ) -> Result<u32> {
1076 let resolve = &self.info.encoder.metadata.resolve;
1077 let metadata = self.info.module_metadata_for(module);
1078 let instance_index = self.instance_for(module);
1079 let core_func_index =
1082 if let Some(&wrapper_idx) = self.export_task_initialization_wrappers.get(core_name) {
1083 wrapper_idx
1084 } else {
1085 self.core_alias_export(Some(core_name), instance_index, core_name, ExportKind::Func)
1086 };
1087 let exports = self.info.exports_for(module);
1088
1089 let options = RequiredOptions::for_export(
1090 resolve,
1091 func,
1092 exports
1093 .abi(key, func)
1094 .ok_or_else(|| anyhow!("no ABI found for {}", func.name))?,
1095 );
1096
1097 let encoding = metadata
1098 .export_encodings
1099 .get(resolve, key, &func.name)
1100 .unwrap();
1101 let exports = self.info.exports_for(module);
1102 let realloc_index = exports
1103 .export_realloc_for(key, &func.name)
1104 .map(|name| self.core_alias_export(Some(name), instance_index, name, ExportKind::Func));
1105 let mut options = options
1106 .into_iter(encoding, self.memory_index, realloc_index)?
1107 .collect::<Vec<_>>();
1108
1109 if let Some(post_return) = exports.post_return(key, func) {
1110 let post_return = self.core_alias_export(
1111 Some(post_return),
1112 instance_index,
1113 post_return,
1114 ExportKind::Func,
1115 );
1116 options.push(CanonicalOption::PostReturn(post_return));
1117 }
1118 if let Some(callback) = exports.callback(key, func) {
1119 let callback =
1120 self.core_alias_export(Some(callback), instance_index, callback, ExportKind::Func);
1121 options.push(CanonicalOption::Callback(callback));
1122 }
1123 let func_index = self
1124 .component
1125 .lift_func(Some(&func.name), core_func_index, ty, options);
1126 Ok(func_index)
1127 }
1128
1129 fn encode_shim_instantiation(&mut self) -> Result<Shims<'a>> {
1130 let mut ret = Shims::default();
1131
1132 ret.append_indirect(self.info, CustomModule::Main)
1133 .context("failed to register indirect shims for main module")?;
1134
1135 for (adapter_name, _adapter) in self.info.adapters.iter() {
1139 ret.append_indirect(self.info, CustomModule::Adapter(adapter_name))
1140 .with_context(|| {
1141 format!("failed to register indirect shims for adapter {adapter_name}")
1142 })?;
1143 }
1144
1145 if ret.shims.is_empty() {
1146 return Ok(ret);
1147 }
1148
1149 assert!(self.shim_instance_index.is_none());
1150 assert!(self.fixups_module_index.is_none());
1151
1152 let mut types = TypeSection::new();
1161 let mut tables = TableSection::new();
1162 let mut functions = FunctionSection::new();
1163 let mut exports = ExportSection::new();
1164 let mut code = CodeSection::new();
1165 let mut sigs = IndexMap::new();
1166 let mut imports_section = ImportSection::new();
1167 let mut elements = ElementSection::new();
1168 let mut func_indexes = Vec::new();
1169 let mut func_names = NameMap::new();
1170
1171 for (i, shim) in ret.shims.values().enumerate() {
1172 let i = i as u32;
1173 let type_index = *sigs.entry(&shim.sig).or_insert_with(|| {
1174 let index = types.len();
1175 types.ty().function(
1176 shim.sig.params.iter().map(to_val_type),
1177 shim.sig.results.iter().map(to_val_type),
1178 );
1179 index
1180 });
1181
1182 functions.function(type_index);
1183 Self::encode_shim_function(type_index, i, &mut code, shim.sig.params.len() as u32);
1184 exports.export(&shim.name, ExportKind::Func, i);
1185
1186 imports_section.import("", &shim.name, EntityType::Function(type_index));
1187 func_indexes.push(i);
1188 func_names.append(i, &shim.debug_name);
1189 }
1190 let mut names = NameSection::new();
1191 names.module("wit-component:shim");
1192 names.functions(&func_names);
1193
1194 let table_type = TableType {
1195 element_type: RefType::FUNCREF,
1196 minimum: ret.shims.len() as u64,
1197 maximum: Some(ret.shims.len() as u64),
1198 table64: false,
1199 shared: false,
1200 };
1201
1202 tables.table(table_type);
1203
1204 exports.export(INDIRECT_TABLE_NAME, ExportKind::Table, 0);
1205 imports_section.import("", INDIRECT_TABLE_NAME, table_type);
1206
1207 elements.active(
1208 None,
1209 &ConstExpr::i32_const(0),
1210 Elements::Functions(func_indexes.into()),
1211 );
1212
1213 let mut shim = Module::new();
1214 shim.section(&types);
1215 shim.section(&functions);
1216 shim.section(&tables);
1217 shim.section(&exports);
1218 shim.section(&code);
1219 shim.section(&RawCustomSection(
1220 &crate::base_producers().raw_custom_section(),
1221 ));
1222 if self.info.encoder.debug_names {
1223 shim.section(&names);
1224 }
1225
1226 let mut fixups = Module::default();
1227 fixups.section(&types);
1228 fixups.section(&imports_section);
1229 fixups.section(&elements);
1230 fixups.section(&RawCustomSection(
1231 &crate::base_producers().raw_custom_section(),
1232 ));
1233
1234 if self.info.encoder.debug_names {
1235 let mut names = NameSection::new();
1236 names.module("wit-component:fixups");
1237 fixups.section(&names);
1238 }
1239
1240 let shim_module_index = self
1241 .component
1242 .core_module(Some("wit-component-shim-module"), &shim);
1243 let fixup_index = self
1244 .component
1245 .core_module(Some("wit-component-fixup"), &fixups);
1246 self.fixups_module_index = Some(fixup_index);
1247 let shim_instance = self.component.core_instantiate(
1248 Some("wit-component-shim-instance"),
1249 shim_module_index,
1250 [],
1251 );
1252 self.shim_instance_index = Some(shim_instance);
1253
1254 return Ok(ret);
1255 }
1256
1257 fn encode_shim_function(
1258 type_index: u32,
1259 func_index: u32,
1260 code: &mut CodeSection,
1261 param_count: u32,
1262 ) {
1263 let mut func = wasm_encoder::Function::new(std::iter::empty());
1264 for i in 0..param_count {
1265 func.instructions().local_get(i);
1266 }
1267 func.instructions().i32_const(func_index as i32);
1268 func.instructions().call_indirect(0, type_index);
1269 func.instructions().end();
1270 code.function(&func);
1271 }
1272
1273 fn encode_indirect_lowerings(&mut self, shims: &Shims<'_>) -> Result<()> {
1274 if shims.shims.is_empty() {
1275 return Ok(());
1276 }
1277
1278 let shim_instance_index = self
1279 .shim_instance_index
1280 .expect("must have an instantiated shim");
1281
1282 let table_index = self.core_alias_export(
1283 Some("shim table"),
1284 shim_instance_index,
1285 INDIRECT_TABLE_NAME,
1286 ExportKind::Table,
1287 );
1288
1289 let resolve = &self.info.encoder.metadata.resolve;
1290
1291 let mut exports = Vec::new();
1292 exports.push((INDIRECT_TABLE_NAME, ExportKind::Table, table_index));
1293
1294 for shim in shims.shims.values() {
1295 let core_func_index = match &shim.kind {
1296 ShimKind::IndirectLowering {
1303 interface,
1304 index,
1305 realloc,
1306 encoding,
1307 } => {
1308 let interface = &self.info.import_map[interface];
1309 let ((name, _), _) = interface.lowerings.get_index(*index).unwrap();
1310 let func_index = match &interface.interface {
1311 Some(interface_id) => {
1312 let instance_index = self.instances[interface_id];
1313 self.component.alias_export(
1314 instance_index,
1315 name,
1316 ComponentExportKind::Func,
1317 )
1318 }
1319 None => self.imported_funcs[name],
1320 };
1321
1322 let realloc = self
1323 .info
1324 .exports_for(*realloc)
1325 .import_realloc_for(interface.interface, name)
1326 .map(|name| {
1327 let instance = self.instance_for(*realloc);
1328 self.core_alias_export(
1329 Some("realloc"),
1330 instance,
1331 name,
1332 ExportKind::Func,
1333 )
1334 });
1335
1336 self.component.lower_func(
1337 Some(&shim.debug_name),
1338 func_index,
1339 shim.options
1340 .into_iter(*encoding, self.memory_index, realloc)?,
1341 )
1342 }
1343
1344 ShimKind::Adapter { adapter, func } => self.core_alias_export(
1349 Some(func),
1350 self.adapter_instances[adapter],
1351 func,
1352 ExportKind::Func,
1353 ),
1354
1355 ShimKind::ResourceDtor { module, export } => self.core_alias_export(
1360 Some(export),
1361 self.instance_for(*module),
1362 export,
1363 ExportKind::Func,
1364 ),
1365
1366 ShimKind::PayloadFunc {
1367 for_module,
1368 info,
1369 kind,
1370 } => {
1371 let metadata = self.info.module_metadata_for(*for_module);
1372 let exports = self.info.exports_for(*for_module);
1373 let instance_index = self.instance_for(*for_module);
1374 let (encoding, realloc) = match &info.ty {
1375 PayloadType::Type { function, .. } => {
1376 if info.imported {
1377 (
1378 metadata.import_encodings.get(resolve, &info.key, function),
1379 exports.import_realloc_for(info.interface, function),
1380 )
1381 } else {
1382 (
1383 metadata.export_encodings.get(resolve, &info.key, function),
1384 exports.export_realloc_for(&info.key, function),
1385 )
1386 }
1387 }
1388 PayloadType::UnitFuture | PayloadType::UnitStream => (None, None),
1389 };
1390 let encoding = encoding.unwrap_or(StringEncoding::UTF8);
1391 let realloc_index = realloc.map(|name| {
1392 self.core_alias_export(
1393 Some("realloc"),
1394 instance_index,
1395 name,
1396 ExportKind::Func,
1397 )
1398 });
1399 let type_index = self.payload_type_index(info)?;
1400 let options =
1401 shim.options
1402 .into_iter(encoding, self.memory_index, realloc_index)?;
1403
1404 match kind {
1405 PayloadFuncKind::FutureWrite => {
1406 self.component.future_write(type_index, options)
1407 }
1408 PayloadFuncKind::FutureRead => {
1409 self.component.future_read(type_index, options)
1410 }
1411 PayloadFuncKind::StreamWrite => {
1412 self.component.stream_write(type_index, options)
1413 }
1414 PayloadFuncKind::StreamRead => {
1415 self.component.stream_read(type_index, options)
1416 }
1417 }
1418 }
1419
1420 ShimKind::WaitableSetWait { cancellable } => self
1421 .component
1422 .waitable_set_wait(*cancellable, self.memory_index.unwrap()),
1423 ShimKind::WaitableSetPoll { cancellable } => self
1424 .component
1425 .waitable_set_poll(*cancellable, self.memory_index.unwrap()),
1426 ShimKind::ErrorContextNew { encoding } => self.component.error_context_new(
1427 shim.options.into_iter(*encoding, self.memory_index, None)?,
1428 ),
1429 ShimKind::ErrorContextDebugMessage {
1430 for_module,
1431 encoding,
1432 } => {
1433 let instance_index = self.instance_for(*for_module);
1434 let realloc = self.info.exports_for(*for_module).import_realloc_fallback();
1435 let realloc_index = realloc.map(|r| {
1436 self.core_alias_export(Some("realloc"), instance_index, r, ExportKind::Func)
1437 });
1438
1439 self.component
1440 .error_context_debug_message(shim.options.into_iter(
1441 *encoding,
1442 self.memory_index,
1443 realloc_index,
1444 )?)
1445 }
1446 ShimKind::TaskReturn {
1447 interface,
1448 func,
1449 result,
1450 encoding,
1451 for_module,
1452 } => {
1453 let mut encoder = if interface.is_none() {
1456 self.root_import_type_encoder(*interface)
1457 } else {
1458 self.root_export_type_encoder(*interface)
1459 };
1460 let result = match result {
1461 Some(ty) => Some(encoder.encode_valtype(resolve, ty)?),
1462 None => None,
1463 };
1464
1465 let exports = self.info.exports_for(*for_module);
1466 let realloc = exports.import_realloc_for(*interface, func);
1467
1468 let instance_index = self.instance_for(*for_module);
1469 let realloc_index = realloc.map(|r| {
1470 self.core_alias_export(Some("realloc"), instance_index, r, ExportKind::Func)
1471 });
1472 let options =
1473 shim.options
1474 .into_iter(*encoding, self.memory_index, realloc_index)?;
1475 self.component.task_return(result, options)
1476 }
1477 ShimKind::ThreadNewIndirect {
1478 for_module,
1479 func_ty,
1480 } => {
1481 let (func_ty_idx, f) = self.component.core_type(Some("thread-start"));
1483 f.core().func_type(func_ty);
1484
1485 let exports = self.info.exports_for(*for_module);
1488 let instance_index = self.instance_for(*for_module);
1489 let table_idx = exports.indirect_function_table().map(|table| {
1490 self.core_alias_export(
1491 Some("indirect-function-table"),
1492 instance_index,
1493 table,
1494 ExportKind::Table,
1495 )
1496 }).ok_or_else(|| {
1497 anyhow!(
1498 "table __indirect_function_table must be an exported funcref table for thread.new-indirect"
1499 )
1500 })?;
1501
1502 self.component.thread_new_indirect(func_ty_idx, table_idx)
1503 }
1504 };
1505
1506 exports.push((shim.name.as_str(), ExportKind::Func, core_func_index));
1507 }
1508
1509 let instance_index = self
1510 .component
1511 .core_instantiate_exports(Some("fixup-args"), exports);
1512 self.component.core_instantiate(
1513 Some("fixup"),
1514 self.fixups_module_index.expect("must have fixup module"),
1515 [("", ModuleArg::Instance(instance_index))],
1516 );
1517 Ok(())
1518 }
1519
1520 fn payload_type_index(&mut self, info: &PayloadInfo) -> Result<u32> {
1528 let resolve = &self.info.encoder.metadata.resolve;
1529 let mut encoder = if info.imported || info.interface.is_none() {
1545 self.root_import_type_encoder(None)
1546 } else {
1547 self.root_export_type_encoder(info.interface)
1548 };
1549 match info.ty {
1550 PayloadType::Type { id, .. } => match encoder.encode_valtype(resolve, &Type::Id(id))? {
1551 ComponentValType::Type(index) => Ok(index),
1552 ComponentValType::Primitive(_) => unreachable!(),
1553 },
1554 PayloadType::UnitFuture => Ok(encoder.encode_unit_future()),
1555 PayloadType::UnitStream => Ok(encoder.encode_unit_stream()),
1556 }
1557 }
1558
1559 fn declare_types_for_imported_intrinsics(&mut self, shims: &Shims<'_>) -> Result<()> {
1566 let resolve = &self.info.encoder.metadata.resolve;
1567 let world = &resolve.worlds[self.info.encoder.metadata.world];
1568
1569 let main_module_keys = self.info.encoder.main_module_exports.iter();
1572 let main_module_keys = main_module_keys.map(|key| (CustomModule::Main, key));
1573 let adapter_keys = self.info.encoder.adapters.iter().flat_map(|(name, info)| {
1574 info.required_exports
1575 .iter()
1576 .map(move |key| (CustomModule::Adapter(name), key))
1577 });
1578 for (for_module, key) in main_module_keys.chain(adapter_keys) {
1579 let id = match &world.exports[key] {
1580 WorldItem::Interface { id, .. } => *id,
1581 WorldItem::Type { .. } => unreachable!(),
1582 WorldItem::Function(_) => continue,
1583 };
1584
1585 for ty in resolve.interfaces[id].types.values() {
1586 let def = &resolve.types[*ty];
1587 match &def.kind {
1588 TypeDefKind::Resource => {
1592 let exports = self.info.exports_for(for_module);
1595 let dtor = exports.resource_dtor(*ty).map(|name| {
1596 let shim = &shims.shims[&ShimKind::ResourceDtor {
1597 module: for_module,
1598 export: name,
1599 }];
1600 let index = self.shim_instance_index.unwrap();
1601 self.core_alias_export(
1602 Some(&shim.debug_name),
1603 index,
1604 &shim.name,
1605 ExportKind::Func,
1606 )
1607 });
1608
1609 let resource_idx = self.component.type_resource(
1613 Some(def.name.as_ref().unwrap()),
1614 ValType::I32,
1615 dtor,
1616 );
1617 let prev = self
1618 .type_encoding_maps
1619 .id_to_index
1620 .insert(*ty, resource_idx);
1621 assert!(prev.is_none());
1622 }
1623 _other => {
1624 self.root_export_type_encoder(Some(id))
1625 .encode_valtype(resolve, &Type::Id(*ty))?;
1626 }
1627 }
1628 }
1629 }
1630 Ok(())
1631 }
1632
1633 fn instantiate_main_module(&mut self, shims: &Shims<'_>) -> Result<()> {
1636 assert!(self.instance_index.is_none());
1637
1638 let instance_index = self.instantiate_core_module(shims, CustomModule::Main)?;
1639
1640 if let Some(memory) = self.info.info.exports.memory() {
1641 self.memory_index = Some(self.core_alias_export(
1642 Some("memory"),
1643 instance_index,
1644 memory,
1645 ExportKind::Memory,
1646 ));
1647 }
1648
1649 self.instance_index = Some(instance_index);
1650 Ok(())
1651 }
1652
1653 fn instantiate_adapter_module(&mut self, shims: &Shims<'_>, name: &'a str) -> Result<()> {
1656 let instance = self.instantiate_core_module(shims, CustomModule::Adapter(name))?;
1657 self.adapter_instances.insert(name, instance);
1658 Ok(())
1659 }
1660
1661 fn instantiate_core_module(
1668 &mut self,
1669 shims: &Shims,
1670 for_module: CustomModule<'_>,
1671 ) -> Result<u32> {
1672 let module = self.module_for(for_module);
1673
1674 let mut args = Vec::new();
1675 for (core_wasm_name, instance) in self.info.imports_for(for_module).modules() {
1676 match instance {
1677 ImportInstance::Names(names) => {
1683 let mut exports = Vec::new();
1684 for (name, import) in names {
1685 log::trace!(
1686 "attempting to materialize import of `{core_wasm_name}::{name}` for {for_module:?}"
1687 );
1688 let (kind, index) = self
1689 .materialize_import(&shims, for_module, import)
1690 .with_context(|| {
1691 format!("failed to satisfy import `{core_wasm_name}::{name}`")
1692 })?;
1693 exports.push((name.as_str(), kind, index));
1694 }
1695 let index = self
1696 .component
1697 .core_instantiate_exports(Some(core_wasm_name), exports);
1698 args.push((core_wasm_name.as_str(), ModuleArg::Instance(index)));
1699 }
1700
1701 ImportInstance::Whole(which) => {
1704 let instance = self.instance_for(which.to_custom_module());
1705 args.push((core_wasm_name.as_str(), ModuleArg::Instance(instance)));
1706 }
1707 }
1708 }
1709
1710 Ok(self
1712 .component
1713 .core_instantiate(Some(for_module.debug_name()), module, args))
1714 }
1715
1716 fn materialize_import(
1723 &mut self,
1724 shims: &Shims<'_>,
1725 for_module: CustomModule<'_>,
1726 import: &'a Import,
1727 ) -> Result<(ExportKind, u32)> {
1728 let resolve = &self.info.encoder.metadata.resolve;
1729 match import {
1730 Import::AdapterExport {
1733 adapter,
1734 func,
1735 ty: _,
1736 } => {
1737 assert!(self.info.encoder.adapters.contains_key(adapter));
1738 Ok(self.materialize_shim_import(shims, &ShimKind::Adapter { adapter, func }))
1739 }
1740
1741 Import::MainModuleMemory => {
1744 let index = self
1745 .memory_index
1746 .ok_or_else(|| anyhow!("main module cannot import memory"))?;
1747 Ok((ExportKind::Memory, index))
1748 }
1749
1750 Import::MainModuleExport { name, kind } => {
1752 let instance = self.instance_index.unwrap();
1753 let index = self.core_alias_export(Some(name), instance, name, *kind);
1754 Ok((*kind, index))
1755 }
1756
1757 Import::Item(item) => {
1761 let instance = self.instance_for(item.which.to_custom_module());
1762 let index =
1763 self.core_alias_export(Some(&item.name), instance, &item.name, item.kind);
1764 Ok((item.kind, index))
1765 }
1766
1767 Import::ExportedResourceDrop(_key, id) => {
1773 let index = self
1774 .component
1775 .resource_drop(self.type_encoding_maps.id_to_index[id]);
1776 Ok((ExportKind::Func, index))
1777 }
1778 Import::ExportedResourceRep(_key, id) => {
1779 let index = self
1780 .component
1781 .resource_rep(self.type_encoding_maps.id_to_index[id]);
1782 Ok((ExportKind::Func, index))
1783 }
1784 Import::ExportedResourceNew(_key, id) => {
1785 let index = self
1786 .component
1787 .resource_new(self.type_encoding_maps.id_to_index[id]);
1788 Ok((ExportKind::Func, index))
1789 }
1790
1791 Import::ImportedResourceDrop(key, iface, id) => {
1796 let ty = &resolve.types[*id];
1797 let name = ty.name.as_ref().unwrap();
1798 self.materialize_wit_import(
1799 shims,
1800 for_module,
1801 iface.map(|_| resolve.name_world_key(key)),
1802 &format!("{name}_drop"),
1803 key,
1804 AbiVariant::GuestImport,
1805 )
1806 }
1807 Import::ExportedTaskReturn(key, interface, func) => {
1808 let (options, _sig) = task_return_options_and_type(resolve, func);
1809 let result_ty = func.result;
1810 if options.is_empty() {
1811 let mut encoder = if interface.is_none() {
1817 self.root_import_type_encoder(*interface)
1818 } else {
1819 self.root_export_type_encoder(*interface)
1820 };
1821
1822 let result = match result_ty.as_ref() {
1823 Some(ty) => Some(encoder.encode_valtype(resolve, ty)?),
1824 None => None,
1825 };
1826 let index = self.component.task_return(result, []);
1827 Ok((ExportKind::Func, index))
1828 } else {
1829 let metadata = &self.info.module_metadata_for(for_module);
1830 let encoding = metadata
1831 .export_encodings
1832 .get(resolve, key, &func.name)
1833 .unwrap();
1834 Ok(self.materialize_shim_import(
1835 shims,
1836 &ShimKind::TaskReturn {
1837 for_module,
1838 interface: *interface,
1839 func: &func.name,
1840 result: result_ty,
1841 encoding,
1842 },
1843 ))
1844 }
1845 }
1846 Import::BackpressureInc => {
1847 let index = self.component.backpressure_inc();
1848 Ok((ExportKind::Func, index))
1849 }
1850 Import::BackpressureDec => {
1851 let index = self.component.backpressure_dec();
1852 Ok((ExportKind::Func, index))
1853 }
1854 Import::WaitableSetWait { cancellable } => Ok(self.materialize_shim_import(
1855 shims,
1856 &ShimKind::WaitableSetWait {
1857 cancellable: *cancellable,
1858 },
1859 )),
1860 Import::WaitableSetPoll { cancellable } => Ok(self.materialize_shim_import(
1861 shims,
1862 &ShimKind::WaitableSetPoll {
1863 cancellable: *cancellable,
1864 },
1865 )),
1866 Import::SubtaskDrop => {
1867 let index = self.component.subtask_drop();
1868 Ok((ExportKind::Func, index))
1869 }
1870 Import::SubtaskCancel { async_ } => {
1871 let index = self.component.subtask_cancel(*async_);
1872 Ok((ExportKind::Func, index))
1873 }
1874 Import::StreamNew(info) => {
1875 let ty = self.payload_type_index(info)?;
1876 let index = self.component.stream_new(ty);
1877 Ok((ExportKind::Func, index))
1878 }
1879 Import::StreamRead { info, .. } => Ok(self.materialize_payload_import(
1880 shims,
1881 for_module,
1882 info,
1883 PayloadFuncKind::StreamRead,
1884 )),
1885 Import::StreamWrite { info, .. } => Ok(self.materialize_payload_import(
1886 shims,
1887 for_module,
1888 info,
1889 PayloadFuncKind::StreamWrite,
1890 )),
1891 Import::StreamCancelRead { info, async_ } => {
1892 let ty = self.payload_type_index(info)?;
1893 let index = self.component.stream_cancel_read(ty, *async_);
1894 Ok((ExportKind::Func, index))
1895 }
1896 Import::StreamCancelWrite { info, async_ } => {
1897 let ty = self.payload_type_index(info)?;
1898 let index = self.component.stream_cancel_write(ty, *async_);
1899 Ok((ExportKind::Func, index))
1900 }
1901 Import::StreamDropReadable(info) => {
1902 let type_index = self.payload_type_index(info)?;
1903 let index = self.component.stream_drop_readable(type_index);
1904 Ok((ExportKind::Func, index))
1905 }
1906 Import::StreamDropWritable(info) => {
1907 let type_index = self.payload_type_index(info)?;
1908 let index = self.component.stream_drop_writable(type_index);
1909 Ok((ExportKind::Func, index))
1910 }
1911 Import::FutureNew(info) => {
1912 let ty = self.payload_type_index(info)?;
1913 let index = self.component.future_new(ty);
1914 Ok((ExportKind::Func, index))
1915 }
1916 Import::FutureRead { info, .. } => Ok(self.materialize_payload_import(
1917 shims,
1918 for_module,
1919 info,
1920 PayloadFuncKind::FutureRead,
1921 )),
1922 Import::FutureWrite { info, .. } => Ok(self.materialize_payload_import(
1923 shims,
1924 for_module,
1925 info,
1926 PayloadFuncKind::FutureWrite,
1927 )),
1928 Import::FutureCancelRead { info, async_ } => {
1929 let ty = self.payload_type_index(info)?;
1930 let index = self.component.future_cancel_read(ty, *async_);
1931 Ok((ExportKind::Func, index))
1932 }
1933 Import::FutureCancelWrite { info, async_ } => {
1934 let ty = self.payload_type_index(info)?;
1935 let index = self.component.future_cancel_write(ty, *async_);
1936 Ok((ExportKind::Func, index))
1937 }
1938 Import::FutureDropReadable(info) => {
1939 let type_index = self.payload_type_index(info)?;
1940 let index = self.component.future_drop_readable(type_index);
1941 Ok((ExportKind::Func, index))
1942 }
1943 Import::FutureDropWritable(info) => {
1944 let type_index = self.payload_type_index(info)?;
1945 let index = self.component.future_drop_writable(type_index);
1946 Ok((ExportKind::Func, index))
1947 }
1948 Import::ErrorContextNew { encoding } => Ok(self.materialize_shim_import(
1949 shims,
1950 &ShimKind::ErrorContextNew {
1951 encoding: *encoding,
1952 },
1953 )),
1954 Import::ErrorContextDebugMessage { encoding } => Ok(self.materialize_shim_import(
1955 shims,
1956 &ShimKind::ErrorContextDebugMessage {
1957 for_module,
1958 encoding: *encoding,
1959 },
1960 )),
1961 Import::ErrorContextDrop => {
1962 let index = self.component.error_context_drop();
1963 Ok((ExportKind::Func, index))
1964 }
1965 Import::WorldFunc(key, name, abi) => {
1966 self.materialize_wit_import(shims, for_module, None, name, key, *abi)
1967 }
1968 Import::InterfaceFunc(key, _, name, abi) => self.materialize_wit_import(
1969 shims,
1970 for_module,
1971 Some(resolve.name_world_key(key)),
1972 name,
1973 key,
1974 *abi,
1975 ),
1976
1977 Import::WaitableSetNew => {
1978 let index = self.component.waitable_set_new();
1979 Ok((ExportKind::Func, index))
1980 }
1981 Import::WaitableSetDrop => {
1982 let index = self.component.waitable_set_drop();
1983 Ok((ExportKind::Func, index))
1984 }
1985 Import::WaitableJoin => {
1986 let index = self.component.waitable_join();
1987 Ok((ExportKind::Func, index))
1988 }
1989 Import::ContextGet { ty, slot } => {
1990 let index = self.component.context_get((*ty).try_into()?, *slot);
1991 Ok((ExportKind::Func, index))
1992 }
1993 Import::ContextSet { ty, slot } => {
1994 let index = self.component.context_set((*ty).try_into()?, *slot);
1995 Ok((ExportKind::Func, index))
1996 }
1997 Import::ExportedTaskCancel => {
1998 let index = self.component.task_cancel();
1999 Ok((ExportKind::Func, index))
2000 }
2001 Import::ThreadIndex => {
2002 let index = self.component.thread_index();
2003 Ok((ExportKind::Func, index))
2004 }
2005 Import::ThreadNewIndirect => Ok(self.materialize_shim_import(
2006 shims,
2007 &ShimKind::ThreadNewIndirect {
2008 for_module,
2009 func_ty: FuncType::new([ValType::I32], []),
2011 },
2012 )),
2013 Import::ThreadResumeLater => {
2014 let index = self.component.thread_resume_later();
2015 Ok((ExportKind::Func, index))
2016 }
2017 Import::ThreadSuspend { cancellable } => {
2018 let index = self.component.thread_suspend(*cancellable);
2019 Ok((ExportKind::Func, index))
2020 }
2021 Import::ThreadYield { cancellable } => {
2022 let index = self.component.thread_yield(*cancellable);
2023 Ok((ExportKind::Func, index))
2024 }
2025 Import::ThreadSuspendThenResume { cancellable } => {
2026 let index = self.component.thread_suspend_then_resume(*cancellable);
2027 Ok((ExportKind::Func, index))
2028 }
2029 Import::ThreadYieldThenResume { cancellable } => {
2030 let index = self.component.thread_yield_then_resume(*cancellable);
2031 Ok((ExportKind::Func, index))
2032 }
2033 Import::ThreadSuspendThenPromote { cancellable } => {
2034 let index = self.component.thread_suspend_then_promote(*cancellable);
2035 Ok((ExportKind::Func, index))
2036 }
2037 Import::ThreadYieldThenPromote { cancellable } => {
2038 let index = self.component.thread_yield_then_promote(*cancellable);
2039 Ok((ExportKind::Func, index))
2040 }
2041 }
2042 }
2043
2044 fn materialize_shim_import(&mut self, shims: &Shims<'_>, kind: &ShimKind) -> (ExportKind, u32) {
2047 let index = self.core_alias_export(
2048 Some(&shims.shims[kind].debug_name),
2049 self.shim_instance_index
2050 .expect("shim should be instantiated"),
2051 &shims.shims[kind].name,
2052 ExportKind::Func,
2053 );
2054 (ExportKind::Func, index)
2055 }
2056
2057 fn materialize_payload_import(
2060 &mut self,
2061 shims: &Shims<'_>,
2062 for_module: CustomModule<'_>,
2063 info: &PayloadInfo,
2064 kind: PayloadFuncKind,
2065 ) -> (ExportKind, u32) {
2066 self.materialize_shim_import(
2067 shims,
2068 &ShimKind::PayloadFunc {
2069 for_module,
2070 info,
2071 kind,
2072 },
2073 )
2074 }
2075
2076 fn materialize_wit_import(
2079 &mut self,
2080 shims: &Shims<'_>,
2081 for_module: CustomModule<'_>,
2082 interface_key: Option<String>,
2083 name: &String,
2084 key: &WorldKey,
2085 abi: AbiVariant,
2086 ) -> Result<(ExportKind, u32)> {
2087 let resolve = &self.info.encoder.metadata.resolve;
2088 let import = &self.info.import_map[&interface_key];
2089 let (index, _, lowering) = import.lowerings.get_full(&(name.clone(), abi)).unwrap();
2090 let metadata = self.info.module_metadata_for(for_module);
2091
2092 let index = match lowering {
2093 Lowering::Direct => {
2096 let func_index = match &import.interface {
2097 Some(interface) => {
2098 let instance_index = self.instances[interface];
2099 self.component
2100 .alias_export(instance_index, name, ComponentExportKind::Func)
2101 }
2102 None => self.imported_funcs[name],
2103 };
2104 self.component.lower_func(
2105 Some(name),
2106 func_index,
2107 if let AbiVariant::GuestImportAsync = abi {
2108 vec![CanonicalOption::Async]
2109 } else {
2110 Vec::new()
2111 },
2112 )
2113 }
2114
2115 Lowering::Indirect { .. } => {
2119 let encoding = metadata.import_encodings.get(resolve, key, name).unwrap();
2120 return Ok(self.materialize_shim_import(
2121 shims,
2122 &ShimKind::IndirectLowering {
2123 interface: interface_key,
2124 index,
2125 realloc: for_module,
2126 encoding,
2127 },
2128 ));
2129 }
2130
2131 Lowering::ResourceDrop(id) => {
2134 let resource_idx = self.lookup_resource_index(*id);
2135 self.component.resource_drop(resource_idx)
2136 }
2137 };
2138 Ok((ExportKind::Func, index))
2139 }
2140
2141 fn encode_initialize_with_start(&mut self) -> Result<()> {
2160 let initialize = match self.info.info.exports.initialize() {
2161 Some(name) => name,
2162 None => return Ok(()),
2165 };
2166 let initialize_index = self.core_alias_export(
2167 Some("start"),
2168 self.instance_index.unwrap(),
2169 initialize,
2170 ExportKind::Func,
2171 );
2172 let mut shim = Module::default();
2173 let mut section = TypeSection::new();
2174 section.ty().function([], []);
2175 shim.section(§ion);
2176 let mut section = ImportSection::new();
2177 section.import("", "", EntityType::Function(0));
2178 shim.section(§ion);
2179 shim.section(&StartSection { function_index: 0 });
2180
2181 let shim_module_index = self.component.core_module(Some("start-shim-module"), &shim);
2186 let shim_args_instance_index = self.component.core_instantiate_exports(
2187 Some("start-shim-args"),
2188 [("", ExportKind::Func, initialize_index)],
2189 );
2190 self.component.core_instantiate(
2191 Some("start-shim-instance"),
2192 shim_module_index,
2193 [("", ModuleArg::Instance(shim_args_instance_index))],
2194 );
2195 Ok(())
2196 }
2197
2198 fn instance_for(&self, module: CustomModule) -> u32 {
2201 match module {
2202 CustomModule::Main => self.instance_index.expect("instantiated by now"),
2203 CustomModule::Adapter(name) => self.adapter_instances[name],
2204 }
2205 }
2206
2207 fn module_for(&self, module: CustomModule) -> u32 {
2210 match module {
2211 CustomModule::Main => self.module_index.unwrap(),
2212 CustomModule::Adapter(name) => self.adapter_modules[name],
2213 }
2214 }
2215
2216 fn core_alias_export(
2219 &mut self,
2220 debug_name: Option<&str>,
2221 instance: u32,
2222 name: &str,
2223 kind: ExportKind,
2224 ) -> u32 {
2225 *self
2226 .aliased_core_items
2227 .entry((instance, name.to_string()))
2228 .or_insert_with(|| {
2229 self.component
2230 .core_alias_export(debug_name, instance, name, kind)
2231 })
2232 }
2233
2234 fn create_export_task_initialization_wrappers(&mut self) -> Result<()> {
2244 let instance_index = self.instance_index.unwrap();
2245 let resolve = &self.info.encoder.metadata.resolve;
2246 let world = &resolve.worlds[self.info.encoder.metadata.world];
2247 let exports = self.info.exports_for(CustomModule::Main);
2248
2249 let wasm_init_task_export = exports.wasm_init_task();
2250 let wasm_init_async_task_export = exports.wasm_init_async_task();
2251 if wasm_init_task_export.is_none() || wasm_init_async_task_export.is_none() {
2252 return Ok(());
2255 }
2256 let wasm_init_task = wasm_init_task_export.unwrap();
2257 let wasm_init_async_task = wasm_init_async_task_export.unwrap();
2258
2259 let funcs_to_wrap: Vec<_> = exports
2262 .iter()
2263 .flat_map(|(core_name, export)| match export {
2264 Export::WorldFunc(key, _, abi) => match &world.exports[key] {
2265 WorldItem::Function(f) => Some((core_name, f, abi)),
2266 _ => None,
2267 },
2268 Export::InterfaceFunc(_, id, func_name, abi) => {
2269 let func = &resolve.interfaces[*id].functions[func_name.as_str()];
2270 Some((core_name, func, abi))
2271 }
2272 _ => None,
2273 })
2274 .collect();
2275
2276 if funcs_to_wrap.is_empty() {
2277 return Ok(());
2279 }
2280
2281 let mut types = TypeSection::new();
2283 let mut imports = ImportSection::new();
2284 let mut functions = FunctionSection::new();
2285 let mut exports_section = ExportSection::new();
2286 let mut code = CodeSection::new();
2287
2288 types.ty().function([], []);
2290 let wasm_init_task_type_idx = 0;
2291
2292 imports.import(
2294 "",
2295 wasm_init_task,
2296 EntityType::Function(wasm_init_task_type_idx),
2297 );
2298 imports.import(
2299 "",
2300 wasm_init_async_task,
2301 EntityType::Function(wasm_init_task_type_idx),
2302 );
2303 let wasm_init_task_func_idx = 0u32;
2304 let wasm_init_async_task_func_idx = 1u32;
2305
2306 let mut type_indices = HashMap::new();
2307 let mut next_type_idx = 1u32;
2308 let mut next_func_idx = 2u32;
2309
2310 struct FuncInfo<'a> {
2312 name: &'a str,
2313 type_idx: u32,
2314 orig_func_idx: u32,
2315 is_async: bool,
2316 n_params: usize,
2317 }
2318 let mut func_info = Vec::new();
2319 for &(name, func, abi) in funcs_to_wrap.iter() {
2320 let sig = resolve.wasm_signature(*abi, func);
2321 let type_idx = *type_indices.entry(sig.clone()).or_insert_with(|| {
2322 let idx = next_type_idx;
2323 types.ty().function(
2324 sig.params.iter().map(to_val_type),
2325 sig.results.iter().map(to_val_type),
2326 );
2327 next_type_idx += 1;
2328 idx
2329 });
2330
2331 imports.import("", &import_func_name(func), EntityType::Function(type_idx));
2332 let orig_func_idx = next_func_idx;
2333 next_func_idx += 1;
2334
2335 func_info.push(FuncInfo {
2336 name,
2337 type_idx,
2338 orig_func_idx,
2339 is_async: abi.is_async(),
2340 n_params: sig.params.len(),
2341 });
2342 }
2343
2344 for info in func_info.iter() {
2346 let wrapper_func_idx = next_func_idx;
2347 functions.function(info.type_idx);
2348
2349 let mut func = wasm_encoder::Function::new([]);
2350 if info.is_async {
2351 func.instruction(&Instruction::Call(wasm_init_async_task_func_idx));
2352 } else {
2353 func.instruction(&Instruction::Call(wasm_init_task_func_idx));
2354 }
2355 for i in 0..info.n_params as u32 {
2356 func.instruction(&Instruction::LocalGet(i));
2357 }
2358 func.instruction(&Instruction::Call(info.orig_func_idx));
2359 func.instruction(&Instruction::End);
2360 code.function(&func);
2361
2362 exports_section.export(info.name, ExportKind::Func, wrapper_func_idx);
2363 next_func_idx += 1;
2364 }
2365
2366 let mut wrapper_module = Module::new();
2367 wrapper_module.section(&types);
2368 wrapper_module.section(&imports);
2369 wrapper_module.section(&functions);
2370 wrapper_module.section(&exports_section);
2371 wrapper_module.section(&code);
2372
2373 let wrapper_module_idx = self
2374 .component
2375 .core_module(Some("init-task-wrappers"), &wrapper_module);
2376
2377 let mut wrapper_imports = Vec::new();
2379 let init_idx = self.core_alias_export(
2380 Some(wasm_init_task),
2381 instance_index,
2382 wasm_init_task,
2383 ExportKind::Func,
2384 );
2385 let init_async_idx = self.core_alias_export(
2386 Some(wasm_init_async_task),
2387 instance_index,
2388 wasm_init_async_task,
2389 ExportKind::Func,
2390 );
2391 wrapper_imports.push((wasm_init_task.into(), ExportKind::Func, init_idx));
2392 wrapper_imports.push((
2393 wasm_init_async_task.into(),
2394 ExportKind::Func,
2395 init_async_idx,
2396 ));
2397
2398 for (name, func, _) in &funcs_to_wrap {
2400 let orig_idx =
2401 self.core_alias_export(Some(name), instance_index, name, ExportKind::Func);
2402 wrapper_imports.push((import_func_name(func), ExportKind::Func, orig_idx));
2403 }
2404
2405 let wrapper_args_idx = self.component.core_instantiate_exports(
2406 Some("init-task-wrappers-args"),
2407 wrapper_imports.iter().map(|(n, k, i)| (n.as_str(), *k, *i)),
2408 );
2409
2410 let wrapper_instance = self.component.core_instantiate(
2411 Some("init-task-wrappers-instance"),
2412 wrapper_module_idx,
2413 [("", ModuleArg::Instance(wrapper_args_idx))],
2414 );
2415
2416 for (name, _, _) in funcs_to_wrap {
2418 let wrapper_idx =
2419 self.core_alias_export(Some(&name), wrapper_instance, &name, ExportKind::Func);
2420 self.export_task_initialization_wrappers
2421 .insert(name.into(), wrapper_idx);
2422 }
2423
2424 Ok(())
2425 }
2426}
2427
2428#[derive(Default)]
2446struct Shims<'a> {
2447 shims: IndexMap<ShimKind<'a>, Shim<'a>>,
2449}
2450
2451struct Shim<'a> {
2452 options: RequiredOptions,
2455
2456 name: String,
2460
2461 debug_name: String,
2464
2465 kind: ShimKind<'a>,
2467
2468 sig: WasmSignature,
2470}
2471
2472#[derive(Debug, Clone, Hash, Eq, PartialEq)]
2475enum PayloadFuncKind {
2476 FutureWrite,
2477 FutureRead,
2478 StreamWrite,
2479 StreamRead,
2480}
2481
2482#[derive(Debug, Clone, Hash, Eq, PartialEq)]
2483enum ShimKind<'a> {
2484 IndirectLowering {
2488 interface: Option<String>,
2490 index: usize,
2492 realloc: CustomModule<'a>,
2494 encoding: StringEncoding,
2496 },
2497 Adapter {
2500 adapter: &'a str,
2502 func: &'a str,
2504 },
2505 ResourceDtor {
2508 module: CustomModule<'a>,
2510 export: &'a str,
2512 },
2513 PayloadFunc {
2517 for_module: CustomModule<'a>,
2520 info: &'a PayloadInfo,
2525 kind: PayloadFuncKind,
2527 },
2528 WaitableSetWait { cancellable: bool },
2532 WaitableSetPoll { cancellable: bool },
2536 TaskReturn {
2538 interface: Option<InterfaceId>,
2541 func: &'a str,
2544 result: Option<Type>,
2546 for_module: CustomModule<'a>,
2548 encoding: StringEncoding,
2550 },
2551 ErrorContextNew {
2555 encoding: StringEncoding,
2557 },
2558 ErrorContextDebugMessage {
2562 for_module: CustomModule<'a>,
2564 encoding: StringEncoding,
2566 },
2567 ThreadNewIndirect {
2570 for_module: CustomModule<'a>,
2572 func_ty: FuncType,
2574 },
2575}
2576
2577#[derive(Debug, Copy, Clone, Hash, Eq, PartialEq)]
2587enum CustomModule<'a> {
2588 Main,
2591 Adapter(&'a str),
2594}
2595
2596impl<'a> CustomModule<'a> {
2597 fn debug_name(&self) -> &'a str {
2598 match self {
2599 CustomModule::Main => "main",
2600 CustomModule::Adapter(s) => s,
2601 }
2602 }
2603}
2604
2605impl<'a> Shims<'a> {
2606 fn append_indirect(
2611 &mut self,
2612 world: &'a ComponentWorld<'a>,
2613 for_module: CustomModule<'a>,
2614 ) -> Result<()> {
2615 let module_imports = world.imports_for(for_module);
2616 let module_exports = world.exports_for(for_module);
2617 let resolve = &world.encoder.metadata.resolve;
2618
2619 for (module, field, import) in module_imports.imports() {
2620 match import {
2621 Import::ImportedResourceDrop(..)
2624 | Import::MainModuleMemory
2625 | Import::MainModuleExport { .. }
2626 | Import::Item(_)
2627 | Import::ExportedResourceDrop(..)
2628 | Import::ExportedResourceRep(..)
2629 | Import::ExportedResourceNew(..)
2630 | Import::ExportedTaskCancel
2631 | Import::ErrorContextDrop
2632 | Import::BackpressureInc
2633 | Import::BackpressureDec
2634 | Import::SubtaskDrop
2635 | Import::SubtaskCancel { .. }
2636 | Import::FutureNew(..)
2637 | Import::StreamNew(..)
2638 | Import::FutureCancelRead { .. }
2639 | Import::FutureCancelWrite { .. }
2640 | Import::FutureDropWritable { .. }
2641 | Import::FutureDropReadable { .. }
2642 | Import::StreamCancelRead { .. }
2643 | Import::StreamCancelWrite { .. }
2644 | Import::StreamDropWritable { .. }
2645 | Import::StreamDropReadable { .. }
2646 | Import::WaitableSetNew
2647 | Import::WaitableSetDrop
2648 | Import::WaitableJoin
2649 | Import::ContextGet { .. }
2650 | Import::ContextSet { .. }
2651 | Import::ThreadIndex
2652 | Import::ThreadResumeLater
2653 | Import::ThreadSuspend { .. }
2654 | Import::ThreadYield { .. }
2655 | Import::ThreadSuspendThenResume { .. }
2656 | Import::ThreadYieldThenResume { .. }
2657 | Import::ThreadSuspendThenPromote { .. }
2658 | Import::ThreadYieldThenPromote { .. } => {}
2659
2660 Import::ExportedTaskReturn(key, interface, func) => {
2664 let (options, sig) = task_return_options_and_type(resolve, func);
2665 if options.is_empty() {
2666 continue;
2667 }
2668 let name = self.shims.len().to_string();
2669 let encoding = world
2670 .module_metadata_for(for_module)
2671 .export_encodings
2672 .get(resolve, key, &func.name)
2673 .ok_or_else(|| {
2674 anyhow::anyhow!(
2675 "missing component metadata for export of \
2676 `{module}::{field}`"
2677 )
2678 })?;
2679 self.push(Shim {
2680 name,
2681 debug_name: format!("task-return-{}", func.name),
2682 options,
2683 kind: ShimKind::TaskReturn {
2684 interface: *interface,
2685 func: &func.name,
2686 result: func.result,
2687 for_module,
2688 encoding,
2689 },
2690 sig,
2691 });
2692 }
2693
2694 Import::FutureWrite { async_, info } => {
2695 self.append_indirect_payload_push(
2696 resolve,
2697 for_module,
2698 module,
2699 *async_,
2700 info,
2701 PayloadFuncKind::FutureWrite,
2702 vec![WasmType::I32; 2],
2703 vec![WasmType::I32],
2704 );
2705 }
2706 Import::FutureRead { async_, info } => {
2707 self.append_indirect_payload_push(
2708 resolve,
2709 for_module,
2710 module,
2711 *async_,
2712 info,
2713 PayloadFuncKind::FutureRead,
2714 vec![WasmType::I32; 2],
2715 vec![WasmType::I32],
2716 );
2717 }
2718 Import::StreamWrite { async_, info } => {
2719 self.append_indirect_payload_push(
2720 resolve,
2721 for_module,
2722 module,
2723 *async_,
2724 info,
2725 PayloadFuncKind::StreamWrite,
2726 vec![WasmType::I32; 3],
2727 vec![WasmType::I32],
2728 );
2729 }
2730 Import::StreamRead { async_, info } => {
2731 self.append_indirect_payload_push(
2732 resolve,
2733 for_module,
2734 module,
2735 *async_,
2736 info,
2737 PayloadFuncKind::StreamRead,
2738 vec![WasmType::I32; 3],
2739 vec![WasmType::I32],
2740 );
2741 }
2742
2743 Import::WaitableSetWait { cancellable } => {
2744 let name = self.shims.len().to_string();
2745 self.push(Shim {
2746 name,
2747 debug_name: "waitable-set.wait".to_string(),
2748 options: RequiredOptions::empty(),
2749 kind: ShimKind::WaitableSetWait {
2750 cancellable: *cancellable,
2751 },
2752 sig: WasmSignature {
2753 params: vec![WasmType::I32; 2],
2754 results: vec![WasmType::I32],
2755 indirect_params: false,
2756 retptr: false,
2757 },
2758 });
2759 }
2760
2761 Import::WaitableSetPoll { cancellable } => {
2762 let name = self.shims.len().to_string();
2763 self.push(Shim {
2764 name,
2765 debug_name: "waitable-set.poll".to_string(),
2766 options: RequiredOptions::empty(),
2767 kind: ShimKind::WaitableSetPoll {
2768 cancellable: *cancellable,
2769 },
2770 sig: WasmSignature {
2771 params: vec![WasmType::I32; 2],
2772 results: vec![WasmType::I32],
2773 indirect_params: false,
2774 retptr: false,
2775 },
2776 });
2777 }
2778
2779 Import::ErrorContextNew { encoding } => {
2780 let name = self.shims.len().to_string();
2781 self.push(Shim {
2782 name,
2783 debug_name: "error-new".to_string(),
2784 options: RequiredOptions::MEMORY | RequiredOptions::STRING_ENCODING,
2785 kind: ShimKind::ErrorContextNew {
2786 encoding: *encoding,
2787 },
2788 sig: WasmSignature {
2789 params: vec![WasmType::I32; 2],
2790 results: vec![WasmType::I32],
2791 indirect_params: false,
2792 retptr: false,
2793 },
2794 });
2795 }
2796
2797 Import::ErrorContextDebugMessage { encoding } => {
2798 let name = self.shims.len().to_string();
2799 self.push(Shim {
2800 name,
2801 debug_name: "error-debug-message".to_string(),
2802 options: RequiredOptions::MEMORY
2803 | RequiredOptions::STRING_ENCODING
2804 | RequiredOptions::REALLOC,
2805 kind: ShimKind::ErrorContextDebugMessage {
2806 for_module,
2807 encoding: *encoding,
2808 },
2809 sig: WasmSignature {
2810 params: vec![WasmType::I32; 2],
2811 results: vec![],
2812 indirect_params: false,
2813 retptr: false,
2814 },
2815 });
2816 }
2817
2818 Import::ThreadNewIndirect => {
2819 let name = self.shims.len().to_string();
2820 self.push(Shim {
2821 name,
2822 debug_name: "thread.new-indirect".to_string(),
2823 options: RequiredOptions::empty(),
2824 kind: ShimKind::ThreadNewIndirect {
2825 for_module,
2826 func_ty: FuncType::new([ValType::I32], vec![]),
2828 },
2829 sig: WasmSignature {
2830 params: vec![WasmType::I32; 2],
2831 results: vec![WasmType::I32],
2832 indirect_params: false,
2833 retptr: false,
2834 },
2835 });
2836 }
2837
2838 Import::AdapterExport { adapter, func, ty } => {
2841 let name = self.shims.len().to_string();
2842 log::debug!("shim {name} is adapter `{module}::{field}`");
2843 self.push(Shim {
2844 name,
2845 debug_name: format!("adapt-{module}-{field}"),
2846 options: RequiredOptions::MEMORY,
2850 kind: ShimKind::Adapter { adapter, func },
2851 sig: WasmSignature {
2852 params: ty.params().iter().map(to_wasm_type).collect(),
2853 results: ty.results().iter().map(to_wasm_type).collect(),
2854 indirect_params: false,
2855 retptr: false,
2856 },
2857 });
2858
2859 fn to_wasm_type(ty: &wasmparser::ValType) -> WasmType {
2860 match ty {
2861 wasmparser::ValType::I32 => WasmType::I32,
2862 wasmparser::ValType::I64 => WasmType::I64,
2863 wasmparser::ValType::F32 => WasmType::F32,
2864 wasmparser::ValType::F64 => WasmType::F64,
2865 _ => unreachable!(),
2866 }
2867 }
2868 }
2869
2870 Import::InterfaceFunc(key, _, name, abi) => {
2874 self.append_indirect_wit_func(
2875 world,
2876 for_module,
2877 module,
2878 field,
2879 key,
2880 name,
2881 Some(resolve.name_world_key(key)),
2882 *abi,
2883 )?;
2884 }
2885 Import::WorldFunc(key, name, abi) => {
2886 self.append_indirect_wit_func(
2887 world, for_module, module, field, key, name, None, *abi,
2888 )?;
2889 }
2890 }
2891 }
2892
2893 for (export_name, export) in module_exports.iter() {
2899 let id = match export {
2900 Export::ResourceDtor(id) => id,
2901 _ => continue,
2902 };
2903 let resource = resolve.types[*id].name.as_ref().unwrap();
2904 let name = self.shims.len().to_string();
2905 self.push(Shim {
2906 name,
2907 debug_name: format!("dtor-{resource}"),
2908 options: RequiredOptions::empty(),
2909 kind: ShimKind::ResourceDtor {
2910 module: for_module,
2911 export: export_name,
2912 },
2913 sig: WasmSignature {
2914 params: vec![WasmType::I32],
2915 results: Vec::new(),
2916 indirect_params: false,
2917 retptr: false,
2918 },
2919 });
2920 }
2921
2922 Ok(())
2923 }
2924
2925 fn append_indirect_payload_push(
2928 &mut self,
2929 resolve: &Resolve,
2930 for_module: CustomModule<'a>,
2931 module: &str,
2932 async_: bool,
2933 info: &'a PayloadInfo,
2934 kind: PayloadFuncKind,
2935 params: Vec<WasmType>,
2936 results: Vec<WasmType>,
2937 ) {
2938 let debug_name = format!("{module}-{}", info.name);
2939 let name = self.shims.len().to_string();
2940
2941 let payload = info.payload(resolve);
2942 let (wit_param, wit_result) = match kind {
2943 PayloadFuncKind::StreamRead | PayloadFuncKind::FutureRead => (None, payload),
2944 PayloadFuncKind::StreamWrite | PayloadFuncKind::FutureWrite => (payload, None),
2945 };
2946 self.push(Shim {
2947 name,
2948 debug_name,
2949 options: RequiredOptions::MEMORY
2950 | RequiredOptions::for_import(
2951 resolve,
2952 &Function {
2953 name: String::new(),
2954 kind: FunctionKind::Freestanding,
2955 params: match wit_param {
2956 Some(ty) => vec![Param {
2957 name: "a".to_string(),
2958 ty,
2959 span: Default::default(),
2960 }],
2961 None => Vec::new(),
2962 },
2963 result: wit_result,
2964 docs: Default::default(),
2965 stability: Stability::Unknown,
2966 span: Default::default(),
2967 external_id: None,
2968 },
2969 if async_ {
2970 AbiVariant::GuestImportAsync
2971 } else {
2972 AbiVariant::GuestImport
2973 },
2974 ),
2975 kind: ShimKind::PayloadFunc {
2976 for_module,
2977 info,
2978 kind,
2979 },
2980 sig: WasmSignature {
2981 params,
2982 results,
2983 indirect_params: false,
2984 retptr: false,
2985 },
2986 });
2987 }
2988
2989 fn append_indirect_wit_func(
2992 &mut self,
2993 world: &'a ComponentWorld<'a>,
2994 for_module: CustomModule<'a>,
2995 module: &str,
2996 field: &str,
2997 key: &WorldKey,
2998 name: &String,
2999 interface_key: Option<String>,
3000 abi: AbiVariant,
3001 ) -> Result<()> {
3002 let resolve = &world.encoder.metadata.resolve;
3003 let metadata = world.module_metadata_for(for_module);
3004 let interface = &world.import_map[&interface_key];
3005 let (index, _, lowering) = interface.lowerings.get_full(&(name.clone(), abi)).unwrap();
3006 let shim_name = self.shims.len().to_string();
3007 match lowering {
3008 Lowering::Direct | Lowering::ResourceDrop(_) => {}
3009
3010 Lowering::Indirect { sig, options } => {
3011 log::debug!(
3012 "shim {shim_name} is import `{module}::{field}` lowering {index} `{name}`",
3013 );
3014 let encoding = metadata
3015 .import_encodings
3016 .get(resolve, key, name)
3017 .ok_or_else(|| {
3018 anyhow::anyhow!(
3019 "missing component metadata for import of \
3020 `{module}::{field}`"
3021 )
3022 })?;
3023 self.push(Shim {
3024 name: shim_name,
3025 debug_name: format!("indirect-{module}-{field}"),
3026 options: *options,
3027 kind: ShimKind::IndirectLowering {
3028 interface: interface_key,
3029 index,
3030 realloc: for_module,
3031 encoding,
3032 },
3033 sig: sig.clone(),
3034 });
3035 }
3036 }
3037
3038 Ok(())
3039 }
3040
3041 fn push(&mut self, shim: Shim<'a>) {
3042 if !self.shims.contains_key(&shim.kind) {
3046 self.shims.insert(shim.kind.clone(), shim);
3047 }
3048 }
3049}
3050
3051fn task_return_options_and_type(
3052 resolve: &Resolve,
3053 func: &Function,
3054) -> (RequiredOptions, WasmSignature) {
3055 let func_tmp = Function {
3056 name: String::new(),
3057 kind: FunctionKind::Freestanding,
3058 params: match &func.result {
3059 Some(ty) => vec![Param {
3060 name: "a".to_string(),
3061 ty: *ty,
3062 span: Default::default(),
3063 }],
3064 None => Vec::new(),
3065 },
3066 result: None,
3067 docs: Default::default(),
3068 stability: Stability::Unknown,
3069 span: Default::default(),
3070 external_id: None,
3071 };
3072 let abi = AbiVariant::GuestImport;
3073 let mut options = RequiredOptions::for_import(resolve, func, abi);
3074 options.remove(RequiredOptions::REALLOC);
3076 let sig = resolve.wasm_signature(abi, &func_tmp);
3077 (options, sig)
3078}
3079
3080#[derive(Clone, Debug)]
3082pub struct Item {
3083 pub alias: String,
3084 pub kind: ExportKind,
3085 pub which: MainOrAdapter,
3086 pub name: String,
3087}
3088
3089#[derive(Debug, PartialEq, Clone)]
3091pub enum MainOrAdapter {
3092 Main,
3093 Adapter(String),
3094}
3095
3096impl MainOrAdapter {
3097 fn to_custom_module(&self) -> CustomModule<'_> {
3098 match self {
3099 MainOrAdapter::Main => CustomModule::Main,
3100 MainOrAdapter::Adapter(s) => CustomModule::Adapter(s),
3101 }
3102 }
3103}
3104
3105#[derive(Clone)]
3107pub enum Instance {
3108 MainOrAdapter(MainOrAdapter),
3110
3111 Items(Vec<Item>),
3113}
3114
3115#[derive(Clone)]
3118pub struct LibraryInfo {
3119 pub instantiate_after_shims: bool,
3121
3122 pub arguments: Vec<(String, Instance)>,
3124}
3125
3126pub(super) struct Adapter {
3128 wasm: Vec<u8>,
3130
3131 metadata: ModuleMetadata,
3133
3134 required_exports: IndexSet<WorldKey>,
3137
3138 library_info: Option<LibraryInfo>,
3143}
3144
3145#[derive(Default)]
3147pub struct ComponentEncoder {
3148 module: Vec<u8>,
3149 module_import_map: Option<ModuleImportMap>,
3150 pub(super) metadata: Bindgen,
3151 validate: bool,
3152 pub(super) main_module_exports: IndexSet<WorldKey>,
3153 pub(super) adapters: IndexMap<String, Adapter>,
3154 import_name_map: HashMap<String, String>,
3155 realloc_via_memory_grow: bool,
3156 merge_imports_based_on_semver: Option<bool>,
3157 pub(super) reject_legacy_names: bool,
3158 debug_names: bool,
3159}
3160
3161impl ComponentEncoder {
3162 pub fn module(mut self, module: &[u8]) -> Result<Self> {
3168 let (wasm, metadata) = self.decode(module.as_ref())?;
3169 let (wasm, module_import_map) = ModuleImportMap::new(wasm)?;
3170 let exports = self
3171 .merge_metadata(metadata)
3172 .context("failed merge WIT metadata for module with previous metadata")?;
3173 self.main_module_exports.extend(exports);
3174 self.module = if let Some(producers) = &self.metadata.producers {
3175 producers.add_to_wasm(&wasm)?
3176 } else {
3177 wasm.to_vec()
3178 };
3179 self.module_import_map = module_import_map;
3180 Ok(self)
3181 }
3182
3183 fn decode<'a>(&self, wasm: &'a [u8]) -> Result<(Cow<'a, [u8]>, Bindgen)> {
3184 let (bytes, metadata) = metadata::decode(wasm)?;
3185 match bytes {
3186 Some(wasm) => Ok((Cow::Owned(wasm), metadata)),
3187 None => Ok((Cow::Borrowed(wasm), metadata)),
3188 }
3189 }
3190
3191 fn merge_metadata(&mut self, metadata: Bindgen) -> Result<IndexSet<WorldKey>> {
3192 self.metadata.merge(metadata)
3193 }
3194
3195 pub fn validate(mut self, validate: bool) -> Self {
3197 self.validate = validate;
3198 self
3199 }
3200
3201 pub fn debug_names(mut self, debug_names: bool) -> Self {
3203 self.debug_names = debug_names;
3204 self
3205 }
3206
3207 pub fn merge_imports_based_on_semver(mut self, merge: bool) -> Self {
3215 self.merge_imports_based_on_semver = Some(merge);
3216 self
3217 }
3218
3219 pub fn reject_legacy_names(mut self, reject: bool) -> Self {
3228 self.reject_legacy_names = reject;
3229 self
3230 }
3231
3232 pub fn adapter(self, name: &str, bytes: &[u8]) -> Result<Self> {
3250 self.library_or_adapter(name, bytes, None)
3251 }
3252
3253 pub fn library(self, name: &str, bytes: &[u8], library_info: LibraryInfo) -> Result<Self> {
3266 self.library_or_adapter(name, bytes, Some(library_info))
3267 }
3268
3269 fn library_or_adapter(
3270 mut self,
3271 name: &str,
3272 bytes: &[u8],
3273 library_info: Option<LibraryInfo>,
3274 ) -> Result<Self> {
3275 let (wasm, mut metadata) = self.decode(bytes)?;
3276 let adapter_metadata = mem::take(&mut metadata.metadata);
3284 let exports = self.merge_metadata(metadata).with_context(|| {
3285 format!("failed to merge WIT packages of adapter `{name}` into main packages")
3286 })?;
3287 if let Some(library_info) = &library_info {
3288 for (_, instance) in &library_info.arguments {
3290 let resolve = |which: &_| match which {
3291 MainOrAdapter::Main => Ok(()),
3292 MainOrAdapter::Adapter(name) => {
3293 if self.adapters.contains_key(name.as_str()) {
3294 Ok(())
3295 } else {
3296 Err(anyhow!("instance refers to unknown adapter `{name}`"))
3297 }
3298 }
3299 };
3300
3301 match instance {
3302 Instance::MainOrAdapter(which) => resolve(which)?,
3303 Instance::Items(items) => {
3304 for item in items {
3305 resolve(&item.which)?;
3306 }
3307 }
3308 }
3309 }
3310 }
3311 self.adapters.insert(
3312 name.to_string(),
3313 Adapter {
3314 wasm: wasm.to_vec(),
3315 metadata: adapter_metadata,
3316 required_exports: exports,
3317 library_info,
3318 },
3319 );
3320 Ok(self)
3321 }
3322
3323 pub fn realloc_via_memory_grow(mut self, value: bool) -> Self {
3328 self.realloc_via_memory_grow = value;
3329 self
3330 }
3331
3332 pub fn import_name_map(mut self, map: HashMap<String, String>) -> Self {
3343 self.import_name_map = map;
3344 self
3345 }
3346
3347 pub fn encode(&mut self) -> Result<Vec<u8>> {
3349 if self.module.is_empty() {
3350 bail!("a module is required when encoding a component");
3351 }
3352
3353 if self.merge_imports_based_on_semver.unwrap_or(true) {
3354 self.metadata
3355 .resolve
3356 .merge_world_imports_based_on_semver(self.metadata.world)?;
3357 }
3358
3359 self.finalize_resolve_with_nominal_ids();
3360
3361 let world = ComponentWorld::new(self).context("failed to decode world from module")?;
3362 let mut state = EncodingState {
3363 component: ComponentBuilder::default(),
3364 module_index: None,
3365 instance_index: None,
3366 memory_index: None,
3367 shim_instance_index: None,
3368 fixups_module_index: None,
3369 adapter_modules: IndexMap::new(),
3370 adapter_instances: IndexMap::new(),
3371 type_encoding_maps: Default::default(),
3372 instances: Default::default(),
3373 imported_funcs: Default::default(),
3374 aliased_core_items: Default::default(),
3375 info: &world,
3376 export_task_initialization_wrappers: HashMap::new(),
3377 };
3378 state.encode_imports(&self.import_name_map)?;
3379 state.encode_core_modules();
3380 state.encode_core_instantiation()?;
3381 state.encode_exports(CustomModule::Main)?;
3382 for name in self.adapters.keys() {
3383 state.encode_exports(CustomModule::Adapter(name))?;
3384 }
3385 state.component.append_names();
3386 state
3387 .component
3388 .raw_custom_section(&crate::base_producers().raw_custom_section());
3389 let bytes = state.component.finish();
3390
3391 if self.validate {
3392 Validator::new_with_features(WasmFeatures::all())
3393 .validate_all(&bytes)
3394 .context("failed to validate component output")?;
3395 }
3396
3397 Ok(bytes)
3398 }
3399
3400 fn finalize_resolve_with_nominal_ids(&mut self) {
3409 let world = &self.metadata.resolve.worlds[self.metadata.world];
3416 let main_module_exports = self
3417 .main_module_exports
3418 .iter()
3419 .map(|i| world.exports.get_index_of(i).unwrap())
3420 .collect::<Vec<_>>();
3421 let adapter_exports = self
3422 .adapters
3423 .values()
3424 .map(|adapter| {
3425 adapter
3426 .required_exports
3427 .iter()
3428 .map(|i| world.exports.get_index_of(i).unwrap())
3429 .collect::<Vec<_>>()
3430 })
3431 .collect::<Vec<_>>();
3432
3433 self.metadata
3437 .resolve
3438 .generate_nominal_type_ids(self.metadata.world);
3439
3440 self.main_module_exports.clear();
3443 let world = &self.metadata.resolve.worlds[self.metadata.world];
3444 for index in main_module_exports {
3445 let (key, _) = world.exports.get_index(index).unwrap();
3446 self.main_module_exports.insert(key.clone());
3447 }
3448 for (exports, adapter) in adapter_exports.into_iter().zip(self.adapters.values_mut()) {
3449 adapter.required_exports.clear();
3450 for index in exports {
3451 let (key, _) = world.exports.get_index(index).unwrap();
3452 adapter.required_exports.insert(key.clone());
3453 }
3454 }
3455 }
3456}
3457
3458impl ComponentWorld<'_> {
3459 fn imports_for(&self, module: CustomModule) -> &ImportMap {
3461 match module {
3462 CustomModule::Main => &self.info.imports,
3463 CustomModule::Adapter(name) => &self.adapters[name].info.imports,
3464 }
3465 }
3466
3467 fn exports_for(&self, module: CustomModule) -> &ExportMap {
3469 match module {
3470 CustomModule::Main => &self.info.exports,
3471 CustomModule::Adapter(name) => &self.adapters[name].info.exports,
3472 }
3473 }
3474
3475 fn module_metadata_for(&self, module: CustomModule) -> &ModuleMetadata {
3477 match module {
3478 CustomModule::Main => &self.encoder.metadata.metadata,
3479 CustomModule::Adapter(name) => &self.encoder.adapters[name].metadata,
3480 }
3481 }
3482}
3483
3484#[cfg(all(test, feature = "dummy-module"))]
3485mod test {
3486 use super::*;
3487 use crate::{dummy_module, embed_component_metadata};
3488 use wit_parser::ManglingAndAbi;
3489
3490 #[test]
3491 fn it_renames_imports() {
3492 let mut resolve = Resolve::new();
3493 let pkg = resolve
3494 .push_str(
3495 "test.wit",
3496 r#"
3497package test:wit;
3498
3499interface i {
3500 f: func();
3501}
3502
3503world test {
3504 import i;
3505 import foo: interface {
3506 f: func();
3507 }
3508}
3509"#,
3510 )
3511 .unwrap();
3512 let world = resolve.select_world(&[pkg], None).unwrap();
3513
3514 let mut module = dummy_module(&resolve, world, ManglingAndAbi::Standard32);
3515
3516 embed_component_metadata(&mut module, &resolve, world, StringEncoding::UTF8).unwrap();
3517
3518 let encoded = ComponentEncoder::default()
3519 .import_name_map(HashMap::from([
3520 (
3521 "foo".to_string(),
3522 "unlocked-dep=<foo:bar/foo@{>=1.0.0 <1.1.0}>".to_string(),
3523 ),
3524 (
3525 "test:wit/i".to_string(),
3526 "locked-dep=<foo:bar/i@1.2.3>".to_string(),
3527 ),
3528 ]))
3529 .module(&module)
3530 .unwrap()
3531 .validate(true)
3532 .encode()
3533 .unwrap();
3534
3535 let wat = wasmprinter::print_bytes(encoded).unwrap();
3536 assert!(wat.contains("unlocked-dep=<foo:bar/foo@{>=1.0.0 <1.1.0}>"));
3537 assert!(wat.contains("locked-dep=<foo:bar/i@1.2.3>"));
3538 }
3539}