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 imported_instances: IndexMap<InterfaceId, u32>,
404 imported_funcs: IndexMap<String, u32>,
405 exported_instances: IndexMap<InterfaceId, u32>,
406
407 import_type_encoding_maps: TypeEncodingMaps<'a>,
412 export_type_encoding_maps: TypeEncodingMaps<'a>,
413
414 aliased_core_items: HashMap<(u32, String), u32>,
420
421 info: &'a ComponentWorld<'a>,
423
424 export_task_initialization_wrappers: HashMap<String, u32>,
427}
428
429impl<'a> EncodingState<'a> {
430 fn encode_core_modules(&mut self) {
431 assert!(self.module_index.is_none());
432 let idx = self
433 .component
434 .core_module_raw(Some("main"), &self.info.encoder.module);
435 self.module_index = Some(idx);
436
437 for (name, adapter) in self.info.adapters.iter() {
438 let debug_name = if adapter.library_info.is_some() {
439 name.to_string()
440 } else {
441 format!("wit-component:adapter:{name}")
442 };
443 let idx = if self.info.encoder.debug_names {
444 let mut add_meta = wasm_metadata::AddMetadata::default();
445 add_meta.name = AddMetadataField::Set(debug_name.clone());
446 let wasm = add_meta
447 .to_wasm(&adapter.wasm)
448 .expect("core wasm can get name added");
449 self.component.core_module_raw(Some(&debug_name), &wasm)
450 } else {
451 self.component
452 .core_module_raw(Some(&debug_name), &adapter.wasm)
453 };
454 let prev = self.adapter_modules.insert(name, idx);
455 assert!(prev.is_none());
456 }
457 }
458
459 fn root_import_type_encoder(
460 &mut self,
461 interface: Option<InterfaceId>,
462 ) -> RootTypeEncoder<'_, 'a> {
463 RootTypeEncoder {
464 state: self,
465 interface,
466 import_types: true,
467 }
468 }
469
470 fn root_export_type_encoder(
471 &mut self,
472 interface: Option<InterfaceId>,
473 ) -> RootTypeEncoder<'_, 'a> {
474 RootTypeEncoder {
475 state: self,
476 interface,
477 import_types: false,
478 }
479 }
480
481 fn instance_type_encoder(&mut self, interface: InterfaceId) -> InstanceTypeEncoder<'_, 'a> {
482 InstanceTypeEncoder {
483 state: self,
484 interface,
485 type_encoding_maps: Default::default(),
486 ty: Default::default(),
487 }
488 }
489
490 fn encode_imports(&mut self, name_map: &HashMap<String, String>) -> Result<()> {
491 let mut has_funcs = false;
492 for (name, info) in self.info.import_map.iter() {
493 match name {
494 Some(name) => {
495 self.encode_interface_import(name_map.get(name).unwrap_or(name), info)?
496 }
497 None => has_funcs = true,
498 }
499 }
500
501 let resolve = &self.info.encoder.metadata.resolve;
502 let world = &resolve.worlds[self.info.encoder.metadata.world];
503
504 for (_name, item) in world.imports.iter() {
507 if let WorldItem::Type { id, .. } = item {
508 self.root_import_type_encoder(None)
509 .encode_valtype(resolve, &Type::Id(*id))?;
510 }
511 }
512
513 if has_funcs {
514 let info = &self.info.import_map[&None];
515 self.encode_root_import_funcs(info)?;
516 }
517 Ok(())
518 }
519
520 fn encode_interface_import(&mut self, name: &str, info: &ImportedInterface) -> Result<()> {
521 let resolve = &self.info.encoder.metadata.resolve;
522 let interface_id = info.interface.as_ref().unwrap();
523 let interface_id = *interface_id;
524 let interface = &resolve.interfaces[interface_id];
525 log::trace!("encoding imports for `{name}` as {interface_id:?}");
526 let mut encoder = self.instance_type_encoder(interface_id);
527
528 if let Some(live) = encoder.state.info.live_type_imports.get(&interface_id) {
530 for ty in live {
531 log::trace!(
532 "encoding extra type {ty:?} name={:?}",
533 resolve.types[*ty].name
534 );
535 encoder.encode_valtype(resolve, &Type::Id(*ty))?;
536 }
537 }
538
539 for (_, func) in interface.functions.iter() {
542 if !(info
543 .lowerings
544 .contains_key(&(func.name.clone(), AbiVariant::GuestImport))
545 || info
546 .lowerings
547 .contains_key(&(func.name.clone(), AbiVariant::GuestImportAsync)))
548 {
549 continue;
550 }
551 log::trace!("encoding function type for `{}`", func.name);
552 let idx = encoder.encode_func_type(resolve, func)?;
553
554 encoder.ty.export(&func.name, ComponentTypeRef::Func(idx));
555 }
556
557 let ty = encoder.ty;
558 if ty.is_empty() {
561 return Ok(());
562 }
563 let instance_type_idx = self
564 .component
565 .type_instance(Some(&format!("ty-{name}")), &ty);
566 let instance_idx = self
567 .component
568 .import(name, ComponentTypeRef::Instance(instance_type_idx));
569 let prev = self.imported_instances.insert(interface_id, instance_idx);
570 assert!(prev.is_none());
571 Ok(())
572 }
573
574 fn encode_root_import_funcs(&mut self, info: &ImportedInterface) -> Result<()> {
575 let resolve = &self.info.encoder.metadata.resolve;
576 let world = self.info.encoder.metadata.world;
577 for (name, item) in resolve.worlds[world].imports.iter() {
578 let func = match item {
579 WorldItem::Function(f) => f,
580 WorldItem::Interface { .. } | WorldItem::Type { .. } => continue,
581 };
582 let name = resolve.name_world_key(name);
583 if !(info
584 .lowerings
585 .contains_key(&(name.clone(), AbiVariant::GuestImport))
586 || info
587 .lowerings
588 .contains_key(&(name.clone(), AbiVariant::GuestImportAsync)))
589 {
590 continue;
591 }
592 log::trace!("encoding function type for `{}`", func.name);
593 let idx = self
594 .root_import_type_encoder(None)
595 .encode_func_type(resolve, func)?;
596 let func_idx = self.component.import(&name, ComponentTypeRef::Func(idx));
597 let prev = self.imported_funcs.insert(name, func_idx);
598 assert!(prev.is_none());
599 }
600 Ok(())
601 }
602
603 fn alias_imported_type(&mut self, interface: InterfaceId, id: TypeId) -> u32 {
604 let ty = &self.info.encoder.metadata.resolve.types[id];
605 let name = ty.name.as_ref().expect("type must have a name");
606 let instance = self.imported_instances[&interface];
607 self.component
608 .alias_export(instance, name, ComponentExportKind::Type)
609 }
610
611 fn alias_exported_type(&mut self, interface: InterfaceId, id: TypeId) -> u32 {
612 let ty = &self.info.encoder.metadata.resolve.types[id];
613 let name = ty.name.as_ref().expect("type must have a name");
614 let instance = self.exported_instances[&interface];
615 self.component
616 .alias_export(instance, name, ComponentExportKind::Type)
617 }
618
619 fn encode_core_instantiation(&mut self) -> Result<()> {
620 let shims = self.encode_shim_instantiation()?;
622
623 self.declare_types_for_imported_intrinsics(&shims)?;
627
628 self.instantiate_main_module(&shims)?;
632
633 self.create_export_task_initialization_wrappers()?;
636
637 let (before, after) = self
640 .info
641 .adapters
642 .iter()
643 .partition::<Vec<_>, _>(|(_, adapter)| {
644 !matches!(
645 adapter.library_info,
646 Some(LibraryInfo {
647 instantiate_after_shims: true,
648 ..
649 })
650 )
651 });
652
653 for (name, _adapter) in before {
654 self.instantiate_adapter_module(&shims, name)?;
655 }
656
657 self.encode_indirect_lowerings(&shims)?;
660
661 for (name, _adapter) in after {
662 self.instantiate_adapter_module(&shims, name)?;
663 }
664
665 self.encode_initialize_with_start()?;
666
667 Ok(())
668 }
669
670 fn lookup_resource_index(&mut self, id: TypeId) -> u32 {
671 let resolve = &self.info.encoder.metadata.resolve;
672 let ty = &resolve.types[id];
673 match ty.owner {
674 TypeOwner::World(_) => self.import_type_encoding_maps.id_to_index[&id],
678 TypeOwner::Interface(i) => {
679 let instance = self.imported_instances[&i];
680 let name = ty.name.as_ref().expect("resources must be named");
681 self.component
682 .alias_export(instance, name, ComponentExportKind::Type)
683 }
684 TypeOwner::None => panic!("resources must have an owner"),
685 }
686 }
687
688 fn encode_exports(&mut self, module: CustomModule) -> Result<()> {
689 let resolve = &self.info.encoder.metadata.resolve;
690 let exports = match module {
691 CustomModule::Main => &self.info.encoder.main_module_exports,
692 CustomModule::Adapter(name) => &self.info.encoder.adapters[name].required_exports,
693 };
694
695 if exports.is_empty() {
696 return Ok(());
697 }
698
699 let mut interface_func_core_names = IndexMap::new();
700 let mut world_func_core_names = IndexMap::new();
701 for (core_name, export) in self.info.exports_for(module).iter() {
702 match export {
703 Export::WorldFunc(_, name, _) => {
704 let prev = world_func_core_names.insert(name, core_name);
705 assert!(prev.is_none());
706 }
707 Export::InterfaceFunc(_, id, name, _) => {
708 let prev = interface_func_core_names
709 .entry(id)
710 .or_insert(IndexMap::new())
711 .insert(name.as_str(), core_name);
712 assert!(prev.is_none());
713 }
714 Export::WorldFuncCallback(..)
715 | Export::InterfaceFuncCallback(..)
716 | Export::WorldFuncPostReturn(..)
717 | Export::InterfaceFuncPostReturn(..)
718 | Export::ResourceDtor(..)
719 | Export::Memory
720 | Export::GeneralPurposeRealloc
721 | Export::GeneralPurposeExportRealloc
722 | Export::GeneralPurposeImportRealloc
723 | Export::Initialize
724 | Export::ReallocForAdapter
725 | Export::IndirectFunctionTable
726 | Export::WasmInitTask
727 | Export::WasmInitAsyncTask => continue,
728 }
729 }
730
731 let world = &resolve.worlds[self.info.encoder.metadata.world];
732
733 for export_name in exports {
734 let export_string = resolve.name_world_key(export_name);
735 match &world.exports[export_name] {
736 WorldItem::Function(func) => {
737 let ty = self
738 .root_import_type_encoder(None)
739 .encode_func_type(resolve, func)?;
740 let core_name = world_func_core_names[&func.name];
741 let idx = self.encode_lift(module, &core_name, export_name, func, ty)?;
742 self.component
743 .export(&export_string, ComponentExportKind::Func, idx, None);
744 }
745 WorldItem::Interface { id, .. } => {
746 let core_names = interface_func_core_names.get(id);
747 self.encode_interface_export(
748 &export_string,
749 module,
750 export_name,
751 *id,
752 core_names,
753 )?;
754 }
755 WorldItem::Type { .. } => unreachable!(),
756 }
757 }
758
759 Ok(())
760 }
761
762 fn encode_interface_export(
763 &mut self,
764 export_name: &str,
765 module: CustomModule<'_>,
766 key: &WorldKey,
767 export: InterfaceId,
768 interface_func_core_names: Option<&IndexMap<&str, &str>>,
769 ) -> Result<()> {
770 log::trace!("encode interface export `{export_name}`");
771 let resolve = &self.info.encoder.metadata.resolve;
772
773 let mut imports = Vec::new();
780 let mut root = self.root_export_type_encoder(Some(export));
781 for (_, func) in &resolve.interfaces[export].functions {
782 let core_name = interface_func_core_names.unwrap()[func.name.as_str()];
783 let ty = root.encode_func_type(resolve, func)?;
784 let func_index = root.state.encode_lift(module, &core_name, key, func, ty)?;
785 imports.push((
786 import_func_name(func),
787 ComponentExportKind::Func,
788 func_index,
789 ));
790 }
791
792 let mut nested = NestedComponentTypeEncoder {
796 component: ComponentBuilder::default(),
797 type_encoding_maps: Default::default(),
798 export_types: false,
799 interface: export,
800 state: self,
801 imports: IndexMap::new(),
802 };
803
804 let mut types_to_import = LiveTypes::default();
814 types_to_import.add_interface(resolve, export);
815 let exports_used = &nested.state.info.exports_used[&export];
816 for ty in types_to_import.iter() {
817 if let TypeOwner::Interface(owner) = resolve.types[ty].owner {
818 if owner == export {
819 continue;
822 }
823
824 let mut encoder = if exports_used.contains(&owner) {
827 nested.state.root_export_type_encoder(Some(export))
828 } else {
829 nested.state.root_import_type_encoder(Some(export))
830 };
831 encoder.encode_valtype(resolve, &Type::Id(ty))?;
832
833 nested.interface = owner;
837 nested.encode_valtype(resolve, &Type::Id(ty))?;
838 }
839 }
840 nested.interface = export;
841
842 let imported_type_maps = nested.type_encoding_maps.clone();
846
847 let mut resources = HashMap::new();
853 for (_name, ty) in resolve.interfaces[export].types.iter() {
854 if !matches!(resolve.types[*ty].kind, TypeDefKind::Resource) {
855 continue;
856 }
857 let idx = match nested.encode_valtype(resolve, &Type::Id(*ty))? {
858 ComponentValType::Type(idx) => idx,
859 _ => unreachable!(),
860 };
861 resources.insert(*ty, idx);
862 }
863
864 for (_, func) in resolve.interfaces[export].functions.iter() {
868 let ty = nested.encode_func_type(resolve, func)?;
869 nested
870 .component
871 .import(&import_func_name(func), ComponentTypeRef::Func(ty));
872 }
873
874 let reverse_map = nested
881 .type_encoding_maps
882 .id_to_index
883 .drain()
884 .map(|p| (p.1, p.0))
885 .collect::<HashMap<_, _>>();
886 nested.type_encoding_maps.def_to_index.clear();
887 for (name, idx) in nested.imports.drain(..) {
888 let id = reverse_map[&idx];
889 let owner = match resolve.types[id].owner {
890 TypeOwner::Interface(id) => id,
891 _ => unreachable!(),
892 };
893 let idx = if owner == export || exports_used.contains(&owner) {
894 log::trace!("consulting exports for {id:?}");
895 nested.state.export_type_encoding_maps.id_to_index[&id]
896 } else {
897 log::trace!("consulting imports for {id:?}");
898 nested.state.import_type_encoding_maps.id_to_index[&id]
899 };
900 imports.push((name, ComponentExportKind::Type, idx))
901 }
902
903 nested.type_encoding_maps = imported_type_maps;
908
909 nested.export_types = true;
916 nested.type_encoding_maps.func_type_map.clear();
917
918 for (_, id) in resolve.interfaces[export].types.iter() {
924 let ty = &resolve.types[*id];
925 match ty.kind {
926 TypeDefKind::Resource => {
927 let idx = nested.component.export(
928 ty.name.as_ref().expect("resources must be named"),
929 ComponentExportKind::Type,
930 resources[id],
931 None,
932 );
933 nested.type_encoding_maps.id_to_index.insert(*id, idx);
934 }
935 _ => {
936 nested.encode_valtype(resolve, &Type::Id(*id))?;
937 }
938 }
939 }
940
941 for (i, (_, func)) in resolve.interfaces[export].functions.iter().enumerate() {
942 let ty = nested.encode_func_type(resolve, func)?;
943 nested.component.export(
944 &func.name,
945 ComponentExportKind::Func,
946 i as u32,
947 Some(ComponentTypeRef::Func(ty)),
948 );
949 }
950
951 let component = nested.component;
955 let component_index = self
956 .component
957 .component(Some(&format!("{export_name}-shim-component")), component);
958 let instance_index = self.component.instantiate(
959 Some(&format!("{export_name}-shim-instance")),
960 component_index,
961 imports,
962 );
963 let idx = self.component.export(
964 export_name,
965 ComponentExportKind::Instance,
966 instance_index,
967 None,
968 );
969 let prev = self.exported_instances.insert(export, idx);
970 assert!(prev.is_none());
971
972 for (_name, id) in resolve.interfaces[export].types.iter() {
980 self.export_type_encoding_maps.id_to_index.remove(id);
981 self.export_type_encoding_maps
982 .def_to_index
983 .remove(&resolve.types[*id].kind);
984 }
985
986 return Ok(());
987
988 struct NestedComponentTypeEncoder<'state, 'a> {
989 component: ComponentBuilder,
990 type_encoding_maps: TypeEncodingMaps<'a>,
991 export_types: bool,
992 interface: InterfaceId,
993 state: &'state mut EncodingState<'a>,
994 imports: IndexMap<String, u32>,
995 }
996
997 impl<'a> ValtypeEncoder<'a> for NestedComponentTypeEncoder<'_, 'a> {
998 fn defined_type(&mut self) -> (u32, ComponentDefinedTypeEncoder<'_>) {
999 self.component.type_defined(None)
1000 }
1001 fn define_function_type(&mut self) -> (u32, ComponentFuncTypeEncoder<'_>) {
1002 self.component.type_function(None)
1003 }
1004 fn export_type(&mut self, idx: u32, name: &'a str) -> Option<u32> {
1005 if self.export_types {
1006 Some(
1007 self.component
1008 .export(name, ComponentExportKind::Type, idx, None),
1009 )
1010 } else {
1011 let name = self.unique_import_name(name);
1012 let ret = self
1013 .component
1014 .import(&name, ComponentTypeRef::Type(TypeBounds::Eq(idx)));
1015 self.imports.insert(name, ret);
1016 Some(ret)
1017 }
1018 }
1019 fn export_resource(&mut self, name: &'a str) -> u32 {
1020 if self.export_types {
1021 panic!("resources should already be exported")
1022 } else {
1023 let name = self.unique_import_name(name);
1024 let ret = self
1025 .component
1026 .import(&name, ComponentTypeRef::Type(TypeBounds::SubResource));
1027 self.imports.insert(name, ret);
1028 ret
1029 }
1030 }
1031 fn import_type(&mut self, _: InterfaceId, _id: TypeId) -> u32 {
1032 unreachable!()
1033 }
1034 fn type_encoding_maps(&mut self) -> &mut TypeEncodingMaps<'a> {
1035 &mut self.type_encoding_maps
1036 }
1037 fn interface(&self) -> Option<InterfaceId> {
1038 Some(self.interface)
1039 }
1040 }
1041
1042 impl NestedComponentTypeEncoder<'_, '_> {
1043 fn unique_import_name(&mut self, name: &str) -> String {
1044 let mut name = format!("import-type-{name}");
1045 let mut n = 0;
1046 while self.imports.contains_key(&name) {
1047 name = format!("{name}{n}");
1048 n += 1;
1049 }
1050 name
1051 }
1052 }
1053 }
1054
1055 fn encode_lift(
1056 &mut self,
1057 module: CustomModule<'_>,
1058 core_name: &str,
1059 key: &WorldKey,
1060 func: &Function,
1061 ty: u32,
1062 ) -> Result<u32> {
1063 let resolve = &self.info.encoder.metadata.resolve;
1064 let metadata = self.info.module_metadata_for(module);
1065 let instance_index = self.instance_for(module);
1066 let core_func_index =
1069 if let Some(&wrapper_idx) = self.export_task_initialization_wrappers.get(core_name) {
1070 wrapper_idx
1071 } else {
1072 self.core_alias_export(Some(core_name), instance_index, core_name, ExportKind::Func)
1073 };
1074 let exports = self.info.exports_for(module);
1075
1076 let options = RequiredOptions::for_export(
1077 resolve,
1078 func,
1079 exports
1080 .abi(key, func)
1081 .ok_or_else(|| anyhow!("no ABI found for {}", func.name))?,
1082 );
1083
1084 let encoding = metadata
1085 .export_encodings
1086 .get(resolve, key, &func.name)
1087 .unwrap();
1088 let exports = self.info.exports_for(module);
1089 let realloc_index = exports
1090 .export_realloc_for(key, &func.name)
1091 .map(|name| self.core_alias_export(Some(name), instance_index, name, ExportKind::Func));
1092 let mut options = options
1093 .into_iter(encoding, self.memory_index, realloc_index)?
1094 .collect::<Vec<_>>();
1095
1096 if let Some(post_return) = exports.post_return(key, func) {
1097 let post_return = self.core_alias_export(
1098 Some(post_return),
1099 instance_index,
1100 post_return,
1101 ExportKind::Func,
1102 );
1103 options.push(CanonicalOption::PostReturn(post_return));
1104 }
1105 if let Some(callback) = exports.callback(key, func) {
1106 let callback =
1107 self.core_alias_export(Some(callback), instance_index, callback, ExportKind::Func);
1108 options.push(CanonicalOption::Callback(callback));
1109 }
1110 let func_index = self
1111 .component
1112 .lift_func(Some(&func.name), core_func_index, ty, options);
1113 Ok(func_index)
1114 }
1115
1116 fn encode_shim_instantiation(&mut self) -> Result<Shims<'a>> {
1117 let mut ret = Shims::default();
1118
1119 ret.append_indirect(self.info, CustomModule::Main)
1120 .context("failed to register indirect shims for main module")?;
1121
1122 for (adapter_name, _adapter) in self.info.adapters.iter() {
1126 ret.append_indirect(self.info, CustomModule::Adapter(adapter_name))
1127 .with_context(|| {
1128 format!("failed to register indirect shims for adapter {adapter_name}")
1129 })?;
1130 }
1131
1132 if ret.shims.is_empty() {
1133 return Ok(ret);
1134 }
1135
1136 assert!(self.shim_instance_index.is_none());
1137 assert!(self.fixups_module_index.is_none());
1138
1139 let mut types = TypeSection::new();
1148 let mut tables = TableSection::new();
1149 let mut functions = FunctionSection::new();
1150 let mut exports = ExportSection::new();
1151 let mut code = CodeSection::new();
1152 let mut sigs = IndexMap::new();
1153 let mut imports_section = ImportSection::new();
1154 let mut elements = ElementSection::new();
1155 let mut func_indexes = Vec::new();
1156 let mut func_names = NameMap::new();
1157
1158 for (i, shim) in ret.shims.values().enumerate() {
1159 let i = i as u32;
1160 let type_index = *sigs.entry(&shim.sig).or_insert_with(|| {
1161 let index = types.len();
1162 types.ty().function(
1163 shim.sig.params.iter().map(to_val_type),
1164 shim.sig.results.iter().map(to_val_type),
1165 );
1166 index
1167 });
1168
1169 functions.function(type_index);
1170 Self::encode_shim_function(type_index, i, &mut code, shim.sig.params.len() as u32);
1171 exports.export(&shim.name, ExportKind::Func, i);
1172
1173 imports_section.import("", &shim.name, EntityType::Function(type_index));
1174 func_indexes.push(i);
1175 func_names.append(i, &shim.debug_name);
1176 }
1177 let mut names = NameSection::new();
1178 names.module("wit-component:shim");
1179 names.functions(&func_names);
1180
1181 let table_type = TableType {
1182 element_type: RefType::FUNCREF,
1183 minimum: ret.shims.len() as u64,
1184 maximum: Some(ret.shims.len() as u64),
1185 table64: false,
1186 shared: false,
1187 };
1188
1189 tables.table(table_type);
1190
1191 exports.export(INDIRECT_TABLE_NAME, ExportKind::Table, 0);
1192 imports_section.import("", INDIRECT_TABLE_NAME, table_type);
1193
1194 elements.active(
1195 None,
1196 &ConstExpr::i32_const(0),
1197 Elements::Functions(func_indexes.into()),
1198 );
1199
1200 let mut shim = Module::new();
1201 shim.section(&types);
1202 shim.section(&functions);
1203 shim.section(&tables);
1204 shim.section(&exports);
1205 shim.section(&code);
1206 shim.section(&RawCustomSection(
1207 &crate::base_producers().raw_custom_section(),
1208 ));
1209 if self.info.encoder.debug_names {
1210 shim.section(&names);
1211 }
1212
1213 let mut fixups = Module::default();
1214 fixups.section(&types);
1215 fixups.section(&imports_section);
1216 fixups.section(&elements);
1217 fixups.section(&RawCustomSection(
1218 &crate::base_producers().raw_custom_section(),
1219 ));
1220
1221 if self.info.encoder.debug_names {
1222 let mut names = NameSection::new();
1223 names.module("wit-component:fixups");
1224 fixups.section(&names);
1225 }
1226
1227 let shim_module_index = self
1228 .component
1229 .core_module(Some("wit-component-shim-module"), &shim);
1230 let fixup_index = self
1231 .component
1232 .core_module(Some("wit-component-fixup"), &fixups);
1233 self.fixups_module_index = Some(fixup_index);
1234 let shim_instance = self.component.core_instantiate(
1235 Some("wit-component-shim-instance"),
1236 shim_module_index,
1237 [],
1238 );
1239 self.shim_instance_index = Some(shim_instance);
1240
1241 return Ok(ret);
1242 }
1243
1244 fn encode_shim_function(
1245 type_index: u32,
1246 func_index: u32,
1247 code: &mut CodeSection,
1248 param_count: u32,
1249 ) {
1250 let mut func = wasm_encoder::Function::new(std::iter::empty());
1251 for i in 0..param_count {
1252 func.instructions().local_get(i);
1253 }
1254 func.instructions().i32_const(func_index as i32);
1255 func.instructions().call_indirect(0, type_index);
1256 func.instructions().end();
1257 code.function(&func);
1258 }
1259
1260 fn encode_indirect_lowerings(&mut self, shims: &Shims<'_>) -> Result<()> {
1261 if shims.shims.is_empty() {
1262 return Ok(());
1263 }
1264
1265 let shim_instance_index = self
1266 .shim_instance_index
1267 .expect("must have an instantiated shim");
1268
1269 let table_index = self.core_alias_export(
1270 Some("shim table"),
1271 shim_instance_index,
1272 INDIRECT_TABLE_NAME,
1273 ExportKind::Table,
1274 );
1275
1276 let resolve = &self.info.encoder.metadata.resolve;
1277
1278 let mut exports = Vec::new();
1279 exports.push((INDIRECT_TABLE_NAME, ExportKind::Table, table_index));
1280
1281 for shim in shims.shims.values() {
1282 let core_func_index = match &shim.kind {
1283 ShimKind::IndirectLowering {
1290 interface,
1291 index,
1292 realloc,
1293 encoding,
1294 } => {
1295 let interface = &self.info.import_map[interface];
1296 let ((name, _), _) = interface.lowerings.get_index(*index).unwrap();
1297 let func_index = match &interface.interface {
1298 Some(interface_id) => {
1299 let instance_index = self.imported_instances[interface_id];
1300 self.component.alias_export(
1301 instance_index,
1302 name,
1303 ComponentExportKind::Func,
1304 )
1305 }
1306 None => self.imported_funcs[name],
1307 };
1308
1309 let realloc = self
1310 .info
1311 .exports_for(*realloc)
1312 .import_realloc_for(interface.interface, name)
1313 .map(|name| {
1314 let instance = self.instance_for(*realloc);
1315 self.core_alias_export(
1316 Some("realloc"),
1317 instance,
1318 name,
1319 ExportKind::Func,
1320 )
1321 });
1322
1323 self.component.lower_func(
1324 Some(&shim.debug_name),
1325 func_index,
1326 shim.options
1327 .into_iter(*encoding, self.memory_index, realloc)?,
1328 )
1329 }
1330
1331 ShimKind::Adapter { adapter, func } => self.core_alias_export(
1336 Some(func),
1337 self.adapter_instances[adapter],
1338 func,
1339 ExportKind::Func,
1340 ),
1341
1342 ShimKind::ResourceDtor { module, export } => self.core_alias_export(
1347 Some(export),
1348 self.instance_for(*module),
1349 export,
1350 ExportKind::Func,
1351 ),
1352
1353 ShimKind::PayloadFunc {
1354 for_module,
1355 info,
1356 kind,
1357 } => {
1358 let metadata = self.info.module_metadata_for(*for_module);
1359 let exports = self.info.exports_for(*for_module);
1360 let instance_index = self.instance_for(*for_module);
1361 let (encoding, realloc) = match &info.ty {
1362 PayloadType::Type { function, .. } => {
1363 if info.imported {
1364 (
1365 metadata.import_encodings.get(resolve, &info.key, function),
1366 exports.import_realloc_for(info.interface, function),
1367 )
1368 } else {
1369 (
1370 metadata.export_encodings.get(resolve, &info.key, function),
1371 exports.export_realloc_for(&info.key, function),
1372 )
1373 }
1374 }
1375 PayloadType::UnitFuture | PayloadType::UnitStream => (None, None),
1376 };
1377 let encoding = encoding.unwrap_or(StringEncoding::UTF8);
1378 let realloc_index = realloc.map(|name| {
1379 self.core_alias_export(
1380 Some("realloc"),
1381 instance_index,
1382 name,
1383 ExportKind::Func,
1384 )
1385 });
1386 let type_index = self.payload_type_index(info)?;
1387 let options =
1388 shim.options
1389 .into_iter(encoding, self.memory_index, realloc_index)?;
1390
1391 match kind {
1392 PayloadFuncKind::FutureWrite => {
1393 self.component.future_write(type_index, options)
1394 }
1395 PayloadFuncKind::FutureRead => {
1396 self.component.future_read(type_index, options)
1397 }
1398 PayloadFuncKind::StreamWrite => {
1399 self.component.stream_write(type_index, options)
1400 }
1401 PayloadFuncKind::StreamRead => {
1402 self.component.stream_read(type_index, options)
1403 }
1404 }
1405 }
1406
1407 ShimKind::WaitableSetWait { cancellable } => self
1408 .component
1409 .waitable_set_wait(*cancellable, self.memory_index.unwrap()),
1410 ShimKind::WaitableSetPoll { cancellable } => self
1411 .component
1412 .waitable_set_poll(*cancellable, self.memory_index.unwrap()),
1413 ShimKind::ErrorContextNew { encoding } => self.component.error_context_new(
1414 shim.options.into_iter(*encoding, self.memory_index, None)?,
1415 ),
1416 ShimKind::ErrorContextDebugMessage {
1417 for_module,
1418 encoding,
1419 } => {
1420 let instance_index = self.instance_for(*for_module);
1421 let realloc = self.info.exports_for(*for_module).import_realloc_fallback();
1422 let realloc_index = realloc.map(|r| {
1423 self.core_alias_export(Some("realloc"), instance_index, r, ExportKind::Func)
1424 });
1425
1426 self.component
1427 .error_context_debug_message(shim.options.into_iter(
1428 *encoding,
1429 self.memory_index,
1430 realloc_index,
1431 )?)
1432 }
1433 ShimKind::TaskReturn {
1434 interface,
1435 func,
1436 result,
1437 encoding,
1438 for_module,
1439 } => {
1440 let mut encoder = if interface.is_none() {
1443 self.root_import_type_encoder(*interface)
1444 } else {
1445 self.root_export_type_encoder(*interface)
1446 };
1447 let result = match result {
1448 Some(ty) => Some(encoder.encode_valtype(resolve, ty)?),
1449 None => None,
1450 };
1451
1452 let exports = self.info.exports_for(*for_module);
1453 let realloc = exports.import_realloc_for(*interface, func);
1454
1455 let instance_index = self.instance_for(*for_module);
1456 let realloc_index = realloc.map(|r| {
1457 self.core_alias_export(Some("realloc"), instance_index, r, ExportKind::Func)
1458 });
1459 let options =
1460 shim.options
1461 .into_iter(*encoding, self.memory_index, realloc_index)?;
1462 self.component.task_return(result, options)
1463 }
1464 ShimKind::ThreadNewIndirect {
1465 for_module,
1466 func_ty,
1467 } => {
1468 let (func_ty_idx, f) = self.component.core_type(Some("thread-start"));
1470 f.core().func_type(func_ty);
1471
1472 let exports = self.info.exports_for(*for_module);
1475 let instance_index = self.instance_for(*for_module);
1476 let table_idx = exports.indirect_function_table().map(|table| {
1477 self.core_alias_export(
1478 Some("indirect-function-table"),
1479 instance_index,
1480 table,
1481 ExportKind::Table,
1482 )
1483 }).ok_or_else(|| {
1484 anyhow!(
1485 "table __indirect_function_table must be an exported funcref table for thread.new-indirect"
1486 )
1487 })?;
1488
1489 self.component.thread_new_indirect(func_ty_idx, table_idx)
1490 }
1491 };
1492
1493 exports.push((shim.name.as_str(), ExportKind::Func, core_func_index));
1494 }
1495
1496 let instance_index = self
1497 .component
1498 .core_instantiate_exports(Some("fixup-args"), exports);
1499 self.component.core_instantiate(
1500 Some("fixup"),
1501 self.fixups_module_index.expect("must have fixup module"),
1502 [("", ModuleArg::Instance(instance_index))],
1503 );
1504 Ok(())
1505 }
1506
1507 fn payload_type_index(&mut self, info: &PayloadInfo) -> Result<u32> {
1515 let resolve = &self.info.encoder.metadata.resolve;
1516 let mut encoder = if info.imported || info.interface.is_none() {
1532 self.root_import_type_encoder(None)
1533 } else {
1534 self.root_export_type_encoder(info.interface)
1535 };
1536 match info.ty {
1537 PayloadType::Type { id, .. } => match encoder.encode_valtype(resolve, &Type::Id(id))? {
1538 ComponentValType::Type(index) => Ok(index),
1539 ComponentValType::Primitive(_) => unreachable!(),
1540 },
1541 PayloadType::UnitFuture => Ok(encoder.encode_unit_future()),
1542 PayloadType::UnitStream => Ok(encoder.encode_unit_stream()),
1543 }
1544 }
1545
1546 fn declare_types_for_imported_intrinsics(&mut self, shims: &Shims<'_>) -> Result<()> {
1553 let resolve = &self.info.encoder.metadata.resolve;
1554 let world = &resolve.worlds[self.info.encoder.metadata.world];
1555
1556 let main_module_keys = self.info.encoder.main_module_exports.iter();
1559 let main_module_keys = main_module_keys.map(|key| (CustomModule::Main, key));
1560 let adapter_keys = self.info.encoder.adapters.iter().flat_map(|(name, info)| {
1561 info.required_exports
1562 .iter()
1563 .map(move |key| (CustomModule::Adapter(name), key))
1564 });
1565 for (for_module, key) in main_module_keys.chain(adapter_keys) {
1566 let id = match &world.exports[key] {
1567 WorldItem::Interface { id, .. } => *id,
1568 WorldItem::Type { .. } => unreachable!(),
1569 WorldItem::Function(_) => continue,
1570 };
1571
1572 for ty in resolve.interfaces[id].types.values() {
1573 let def = &resolve.types[*ty];
1574 match &def.kind {
1575 TypeDefKind::Resource => {
1579 let exports = self.info.exports_for(for_module);
1582 let dtor = exports.resource_dtor(*ty).map(|name| {
1583 let shim = &shims.shims[&ShimKind::ResourceDtor {
1584 module: for_module,
1585 export: name,
1586 }];
1587 let index = self.shim_instance_index.unwrap();
1588 self.core_alias_export(
1589 Some(&shim.debug_name),
1590 index,
1591 &shim.name,
1592 ExportKind::Func,
1593 )
1594 });
1595
1596 let resource_idx = self.component.type_resource(
1600 Some(def.name.as_ref().unwrap()),
1601 ValType::I32,
1602 dtor,
1603 );
1604 let prev = self
1605 .export_type_encoding_maps
1606 .id_to_index
1607 .insert(*ty, resource_idx);
1608 assert!(prev.is_none());
1609 }
1610 _other => {
1611 self.root_export_type_encoder(Some(id))
1612 .encode_valtype(resolve, &Type::Id(*ty))?;
1613 }
1614 }
1615 }
1616 }
1617 Ok(())
1618 }
1619
1620 fn instantiate_main_module(&mut self, shims: &Shims<'_>) -> Result<()> {
1623 assert!(self.instance_index.is_none());
1624
1625 let instance_index = self.instantiate_core_module(shims, CustomModule::Main)?;
1626
1627 if let Some(memory) = self.info.info.exports.memory() {
1628 self.memory_index = Some(self.core_alias_export(
1629 Some("memory"),
1630 instance_index,
1631 memory,
1632 ExportKind::Memory,
1633 ));
1634 }
1635
1636 self.instance_index = Some(instance_index);
1637 Ok(())
1638 }
1639
1640 fn instantiate_adapter_module(&mut self, shims: &Shims<'_>, name: &'a str) -> Result<()> {
1643 let instance = self.instantiate_core_module(shims, CustomModule::Adapter(name))?;
1644 self.adapter_instances.insert(name, instance);
1645 Ok(())
1646 }
1647
1648 fn instantiate_core_module(
1655 &mut self,
1656 shims: &Shims,
1657 for_module: CustomModule<'_>,
1658 ) -> Result<u32> {
1659 let module = self.module_for(for_module);
1660
1661 let mut args = Vec::new();
1662 for (core_wasm_name, instance) in self.info.imports_for(for_module).modules() {
1663 match instance {
1664 ImportInstance::Names(names) => {
1670 let mut exports = Vec::new();
1671 for (name, import) in names {
1672 log::trace!(
1673 "attempting to materialize import of `{core_wasm_name}::{name}` for {for_module:?}"
1674 );
1675 let (kind, index) = self
1676 .materialize_import(&shims, for_module, import)
1677 .with_context(|| {
1678 format!("failed to satisfy import `{core_wasm_name}::{name}`")
1679 })?;
1680 exports.push((name.as_str(), kind, index));
1681 }
1682 let index = self
1683 .component
1684 .core_instantiate_exports(Some(core_wasm_name), exports);
1685 args.push((core_wasm_name.as_str(), ModuleArg::Instance(index)));
1686 }
1687
1688 ImportInstance::Whole(which) => {
1691 let instance = self.instance_for(which.to_custom_module());
1692 args.push((core_wasm_name.as_str(), ModuleArg::Instance(instance)));
1693 }
1694 }
1695 }
1696
1697 Ok(self
1699 .component
1700 .core_instantiate(Some(for_module.debug_name()), module, args))
1701 }
1702
1703 fn materialize_import(
1710 &mut self,
1711 shims: &Shims<'_>,
1712 for_module: CustomModule<'_>,
1713 import: &'a Import,
1714 ) -> Result<(ExportKind, u32)> {
1715 let resolve = &self.info.encoder.metadata.resolve;
1716 match import {
1717 Import::AdapterExport {
1720 adapter,
1721 func,
1722 ty: _,
1723 } => {
1724 assert!(self.info.encoder.adapters.contains_key(adapter));
1725 Ok(self.materialize_shim_import(shims, &ShimKind::Adapter { adapter, func }))
1726 }
1727
1728 Import::MainModuleMemory => {
1731 let index = self
1732 .memory_index
1733 .ok_or_else(|| anyhow!("main module cannot import memory"))?;
1734 Ok((ExportKind::Memory, index))
1735 }
1736
1737 Import::MainModuleExport { name, kind } => {
1739 let instance = self.instance_index.unwrap();
1740 let index = self.core_alias_export(Some(name), instance, name, *kind);
1741 Ok((*kind, index))
1742 }
1743
1744 Import::Item(item) => {
1748 let instance = self.instance_for(item.which.to_custom_module());
1749 let index =
1750 self.core_alias_export(Some(&item.name), instance, &item.name, item.kind);
1751 Ok((item.kind, index))
1752 }
1753
1754 Import::ExportedResourceDrop(_key, id) => {
1760 let index = self
1761 .component
1762 .resource_drop(self.export_type_encoding_maps.id_to_index[id]);
1763 Ok((ExportKind::Func, index))
1764 }
1765 Import::ExportedResourceRep(_key, id) => {
1766 let index = self
1767 .component
1768 .resource_rep(self.export_type_encoding_maps.id_to_index[id]);
1769 Ok((ExportKind::Func, index))
1770 }
1771 Import::ExportedResourceNew(_key, id) => {
1772 let index = self
1773 .component
1774 .resource_new(self.export_type_encoding_maps.id_to_index[id]);
1775 Ok((ExportKind::Func, index))
1776 }
1777
1778 Import::ImportedResourceDrop(key, iface, id) => {
1783 let ty = &resolve.types[*id];
1784 let name = ty.name.as_ref().unwrap();
1785 self.materialize_wit_import(
1786 shims,
1787 for_module,
1788 iface.map(|_| resolve.name_world_key(key)),
1789 &format!("{name}_drop"),
1790 key,
1791 AbiVariant::GuestImport,
1792 )
1793 }
1794 Import::ExportedTaskReturn(key, interface, func) => {
1795 let (options, _sig) = task_return_options_and_type(resolve, func);
1796 let result_ty = func.result;
1797 if options.is_empty() {
1798 let mut encoder = if interface.is_none() {
1804 self.root_import_type_encoder(*interface)
1805 } else {
1806 self.root_export_type_encoder(*interface)
1807 };
1808
1809 let result = match result_ty.as_ref() {
1810 Some(ty) => Some(encoder.encode_valtype(resolve, ty)?),
1811 None => None,
1812 };
1813 let index = self.component.task_return(result, []);
1814 Ok((ExportKind::Func, index))
1815 } else {
1816 let metadata = &self.info.module_metadata_for(for_module);
1817 let encoding = metadata
1818 .export_encodings
1819 .get(resolve, key, &func.name)
1820 .unwrap();
1821 Ok(self.materialize_shim_import(
1822 shims,
1823 &ShimKind::TaskReturn {
1824 for_module,
1825 interface: *interface,
1826 func: &func.name,
1827 result: result_ty,
1828 encoding,
1829 },
1830 ))
1831 }
1832 }
1833 Import::BackpressureInc => {
1834 let index = self.component.backpressure_inc();
1835 Ok((ExportKind::Func, index))
1836 }
1837 Import::BackpressureDec => {
1838 let index = self.component.backpressure_dec();
1839 Ok((ExportKind::Func, index))
1840 }
1841 Import::WaitableSetWait { cancellable } => Ok(self.materialize_shim_import(
1842 shims,
1843 &ShimKind::WaitableSetWait {
1844 cancellable: *cancellable,
1845 },
1846 )),
1847 Import::WaitableSetPoll { cancellable } => Ok(self.materialize_shim_import(
1848 shims,
1849 &ShimKind::WaitableSetPoll {
1850 cancellable: *cancellable,
1851 },
1852 )),
1853 Import::ThreadYield { cancellable } => {
1854 let index = self.component.thread_yield(*cancellable);
1855 Ok((ExportKind::Func, index))
1856 }
1857 Import::SubtaskDrop => {
1858 let index = self.component.subtask_drop();
1859 Ok((ExportKind::Func, index))
1860 }
1861 Import::SubtaskCancel { async_ } => {
1862 let index = self.component.subtask_cancel(*async_);
1863 Ok((ExportKind::Func, index))
1864 }
1865 Import::StreamNew(info) => {
1866 let ty = self.payload_type_index(info)?;
1867 let index = self.component.stream_new(ty);
1868 Ok((ExportKind::Func, index))
1869 }
1870 Import::StreamRead { info, .. } => Ok(self.materialize_payload_import(
1871 shims,
1872 for_module,
1873 info,
1874 PayloadFuncKind::StreamRead,
1875 )),
1876 Import::StreamWrite { info, .. } => Ok(self.materialize_payload_import(
1877 shims,
1878 for_module,
1879 info,
1880 PayloadFuncKind::StreamWrite,
1881 )),
1882 Import::StreamCancelRead { info, async_ } => {
1883 let ty = self.payload_type_index(info)?;
1884 let index = self.component.stream_cancel_read(ty, *async_);
1885 Ok((ExportKind::Func, index))
1886 }
1887 Import::StreamCancelWrite { info, async_ } => {
1888 let ty = self.payload_type_index(info)?;
1889 let index = self.component.stream_cancel_write(ty, *async_);
1890 Ok((ExportKind::Func, index))
1891 }
1892 Import::StreamDropReadable(info) => {
1893 let type_index = self.payload_type_index(info)?;
1894 let index = self.component.stream_drop_readable(type_index);
1895 Ok((ExportKind::Func, index))
1896 }
1897 Import::StreamDropWritable(info) => {
1898 let type_index = self.payload_type_index(info)?;
1899 let index = self.component.stream_drop_writable(type_index);
1900 Ok((ExportKind::Func, index))
1901 }
1902 Import::FutureNew(info) => {
1903 let ty = self.payload_type_index(info)?;
1904 let index = self.component.future_new(ty);
1905 Ok((ExportKind::Func, index))
1906 }
1907 Import::FutureRead { info, .. } => Ok(self.materialize_payload_import(
1908 shims,
1909 for_module,
1910 info,
1911 PayloadFuncKind::FutureRead,
1912 )),
1913 Import::FutureWrite { info, .. } => Ok(self.materialize_payload_import(
1914 shims,
1915 for_module,
1916 info,
1917 PayloadFuncKind::FutureWrite,
1918 )),
1919 Import::FutureCancelRead { info, async_ } => {
1920 let ty = self.payload_type_index(info)?;
1921 let index = self.component.future_cancel_read(ty, *async_);
1922 Ok((ExportKind::Func, index))
1923 }
1924 Import::FutureCancelWrite { info, async_ } => {
1925 let ty = self.payload_type_index(info)?;
1926 let index = self.component.future_cancel_write(ty, *async_);
1927 Ok((ExportKind::Func, index))
1928 }
1929 Import::FutureDropReadable(info) => {
1930 let type_index = self.payload_type_index(info)?;
1931 let index = self.component.future_drop_readable(type_index);
1932 Ok((ExportKind::Func, index))
1933 }
1934 Import::FutureDropWritable(info) => {
1935 let type_index = self.payload_type_index(info)?;
1936 let index = self.component.future_drop_writable(type_index);
1937 Ok((ExportKind::Func, index))
1938 }
1939 Import::ErrorContextNew { encoding } => Ok(self.materialize_shim_import(
1940 shims,
1941 &ShimKind::ErrorContextNew {
1942 encoding: *encoding,
1943 },
1944 )),
1945 Import::ErrorContextDebugMessage { encoding } => Ok(self.materialize_shim_import(
1946 shims,
1947 &ShimKind::ErrorContextDebugMessage {
1948 for_module,
1949 encoding: *encoding,
1950 },
1951 )),
1952 Import::ErrorContextDrop => {
1953 let index = self.component.error_context_drop();
1954 Ok((ExportKind::Func, index))
1955 }
1956 Import::WorldFunc(key, name, abi) => {
1957 self.materialize_wit_import(shims, for_module, None, name, key, *abi)
1958 }
1959 Import::InterfaceFunc(key, _, name, abi) => self.materialize_wit_import(
1960 shims,
1961 for_module,
1962 Some(resolve.name_world_key(key)),
1963 name,
1964 key,
1965 *abi,
1966 ),
1967
1968 Import::WaitableSetNew => {
1969 let index = self.component.waitable_set_new();
1970 Ok((ExportKind::Func, index))
1971 }
1972 Import::WaitableSetDrop => {
1973 let index = self.component.waitable_set_drop();
1974 Ok((ExportKind::Func, index))
1975 }
1976 Import::WaitableJoin => {
1977 let index = self.component.waitable_join();
1978 Ok((ExportKind::Func, index))
1979 }
1980 Import::ContextGet(n) => {
1981 let index = self.component.context_get(*n);
1982 Ok((ExportKind::Func, index))
1983 }
1984 Import::ContextSet(n) => {
1985 let index = self.component.context_set(*n);
1986 Ok((ExportKind::Func, index))
1987 }
1988 Import::ExportedTaskCancel => {
1989 let index = self.component.task_cancel();
1990 Ok((ExportKind::Func, index))
1991 }
1992 Import::ThreadIndex => {
1993 let index = self.component.thread_index();
1994 Ok((ExportKind::Func, index))
1995 }
1996 Import::ThreadNewIndirect => Ok(self.materialize_shim_import(
1997 shims,
1998 &ShimKind::ThreadNewIndirect {
1999 for_module,
2000 func_ty: FuncType::new([ValType::I32], []),
2002 },
2003 )),
2004 Import::ThreadSuspendToSuspended { cancellable } => {
2005 let index = self.component.thread_suspend_to_suspended(*cancellable);
2006 Ok((ExportKind::Func, index))
2007 }
2008 Import::ThreadSuspend { cancellable } => {
2009 let index = self.component.thread_suspend(*cancellable);
2010 Ok((ExportKind::Func, index))
2011 }
2012 Import::ThreadSuspendTo { cancellable } => {
2013 let index = self.component.thread_suspend_to(*cancellable);
2014 Ok((ExportKind::Func, index))
2015 }
2016 Import::ThreadUnsuspend => {
2017 let index = self.component.thread_unsuspend();
2018 Ok((ExportKind::Func, index))
2019 }
2020 Import::ThreadYieldToSuspended { cancellable } => {
2021 let index = self.component.thread_yield_to_suspended(*cancellable);
2022 Ok((ExportKind::Func, index))
2023 }
2024 }
2025 }
2026
2027 fn materialize_shim_import(&mut self, shims: &Shims<'_>, kind: &ShimKind) -> (ExportKind, u32) {
2030 let index = self.core_alias_export(
2031 Some(&shims.shims[kind].debug_name),
2032 self.shim_instance_index
2033 .expect("shim should be instantiated"),
2034 &shims.shims[kind].name,
2035 ExportKind::Func,
2036 );
2037 (ExportKind::Func, index)
2038 }
2039
2040 fn materialize_payload_import(
2043 &mut self,
2044 shims: &Shims<'_>,
2045 for_module: CustomModule<'_>,
2046 info: &PayloadInfo,
2047 kind: PayloadFuncKind,
2048 ) -> (ExportKind, u32) {
2049 self.materialize_shim_import(
2050 shims,
2051 &ShimKind::PayloadFunc {
2052 for_module,
2053 info,
2054 kind,
2055 },
2056 )
2057 }
2058
2059 fn materialize_wit_import(
2062 &mut self,
2063 shims: &Shims<'_>,
2064 for_module: CustomModule<'_>,
2065 interface_key: Option<String>,
2066 name: &String,
2067 key: &WorldKey,
2068 abi: AbiVariant,
2069 ) -> Result<(ExportKind, u32)> {
2070 let resolve = &self.info.encoder.metadata.resolve;
2071 let import = &self.info.import_map[&interface_key];
2072 let (index, _, lowering) = import.lowerings.get_full(&(name.clone(), abi)).unwrap();
2073 let metadata = self.info.module_metadata_for(for_module);
2074
2075 let index = match lowering {
2076 Lowering::Direct => {
2079 let func_index = match &import.interface {
2080 Some(interface) => {
2081 let instance_index = self.imported_instances[interface];
2082 self.component
2083 .alias_export(instance_index, name, ComponentExportKind::Func)
2084 }
2085 None => self.imported_funcs[name],
2086 };
2087 self.component.lower_func(
2088 Some(name),
2089 func_index,
2090 if let AbiVariant::GuestImportAsync = abi {
2091 vec![CanonicalOption::Async]
2092 } else {
2093 Vec::new()
2094 },
2095 )
2096 }
2097
2098 Lowering::Indirect { .. } => {
2102 let encoding = metadata.import_encodings.get(resolve, key, name).unwrap();
2103 return Ok(self.materialize_shim_import(
2104 shims,
2105 &ShimKind::IndirectLowering {
2106 interface: interface_key,
2107 index,
2108 realloc: for_module,
2109 encoding,
2110 },
2111 ));
2112 }
2113
2114 Lowering::ResourceDrop(id) => {
2117 let resource_idx = self.lookup_resource_index(*id);
2118 self.component.resource_drop(resource_idx)
2119 }
2120 };
2121 Ok((ExportKind::Func, index))
2122 }
2123
2124 fn encode_initialize_with_start(&mut self) -> Result<()> {
2143 let initialize = match self.info.info.exports.initialize() {
2144 Some(name) => name,
2145 None => return Ok(()),
2148 };
2149 let initialize_index = self.core_alias_export(
2150 Some("start"),
2151 self.instance_index.unwrap(),
2152 initialize,
2153 ExportKind::Func,
2154 );
2155 let mut shim = Module::default();
2156 let mut section = TypeSection::new();
2157 section.ty().function([], []);
2158 shim.section(§ion);
2159 let mut section = ImportSection::new();
2160 section.import("", "", EntityType::Function(0));
2161 shim.section(§ion);
2162 shim.section(&StartSection { function_index: 0 });
2163
2164 let shim_module_index = self.component.core_module(Some("start-shim-module"), &shim);
2169 let shim_args_instance_index = self.component.core_instantiate_exports(
2170 Some("start-shim-args"),
2171 [("", ExportKind::Func, initialize_index)],
2172 );
2173 self.component.core_instantiate(
2174 Some("start-shim-instance"),
2175 shim_module_index,
2176 [("", ModuleArg::Instance(shim_args_instance_index))],
2177 );
2178 Ok(())
2179 }
2180
2181 fn instance_for(&self, module: CustomModule) -> u32 {
2184 match module {
2185 CustomModule::Main => self.instance_index.expect("instantiated by now"),
2186 CustomModule::Adapter(name) => self.adapter_instances[name],
2187 }
2188 }
2189
2190 fn module_for(&self, module: CustomModule) -> u32 {
2193 match module {
2194 CustomModule::Main => self.module_index.unwrap(),
2195 CustomModule::Adapter(name) => self.adapter_modules[name],
2196 }
2197 }
2198
2199 fn core_alias_export(
2202 &mut self,
2203 debug_name: Option<&str>,
2204 instance: u32,
2205 name: &str,
2206 kind: ExportKind,
2207 ) -> u32 {
2208 *self
2209 .aliased_core_items
2210 .entry((instance, name.to_string()))
2211 .or_insert_with(|| {
2212 self.component
2213 .core_alias_export(debug_name, instance, name, kind)
2214 })
2215 }
2216
2217 fn create_export_task_initialization_wrappers(&mut self) -> Result<()> {
2227 let instance_index = self.instance_index.unwrap();
2228 let resolve = &self.info.encoder.metadata.resolve;
2229 let world = &resolve.worlds[self.info.encoder.metadata.world];
2230 let exports = self.info.exports_for(CustomModule::Main);
2231
2232 let wasm_init_task_export = exports.wasm_init_task();
2233 let wasm_init_async_task_export = exports.wasm_init_async_task();
2234 if wasm_init_task_export.is_none() || wasm_init_async_task_export.is_none() {
2235 return Ok(());
2238 }
2239 let wasm_init_task = wasm_init_task_export.unwrap();
2240 let wasm_init_async_task = wasm_init_async_task_export.unwrap();
2241
2242 let funcs_to_wrap: Vec<_> = exports
2245 .iter()
2246 .flat_map(|(core_name, export)| match export {
2247 Export::WorldFunc(key, _, abi) => match &world.exports[key] {
2248 WorldItem::Function(f) => Some((core_name, f, abi)),
2249 _ => None,
2250 },
2251 Export::InterfaceFunc(_, id, func_name, abi) => {
2252 let func = &resolve.interfaces[*id].functions[func_name.as_str()];
2253 Some((core_name, func, abi))
2254 }
2255 _ => None,
2256 })
2257 .collect();
2258
2259 if funcs_to_wrap.is_empty() {
2260 return Ok(());
2262 }
2263
2264 let mut types = TypeSection::new();
2266 let mut imports = ImportSection::new();
2267 let mut functions = FunctionSection::new();
2268 let mut exports_section = ExportSection::new();
2269 let mut code = CodeSection::new();
2270
2271 types.ty().function([], []);
2273 let wasm_init_task_type_idx = 0;
2274
2275 imports.import(
2277 "",
2278 wasm_init_task,
2279 EntityType::Function(wasm_init_task_type_idx),
2280 );
2281 imports.import(
2282 "",
2283 wasm_init_async_task,
2284 EntityType::Function(wasm_init_task_type_idx),
2285 );
2286 let wasm_init_task_func_idx = 0u32;
2287 let wasm_init_async_task_func_idx = 1u32;
2288
2289 let mut type_indices = HashMap::new();
2290 let mut next_type_idx = 1u32;
2291 let mut next_func_idx = 2u32;
2292
2293 struct FuncInfo<'a> {
2295 name: &'a str,
2296 type_idx: u32,
2297 orig_func_idx: u32,
2298 is_async: bool,
2299 n_params: usize,
2300 }
2301 let mut func_info = Vec::new();
2302 for &(name, func, abi) in funcs_to_wrap.iter() {
2303 let sig = resolve.wasm_signature(*abi, func);
2304 let type_idx = *type_indices.entry(sig.clone()).or_insert_with(|| {
2305 let idx = next_type_idx;
2306 types.ty().function(
2307 sig.params.iter().map(to_val_type),
2308 sig.results.iter().map(to_val_type),
2309 );
2310 next_type_idx += 1;
2311 idx
2312 });
2313
2314 imports.import("", &import_func_name(func), EntityType::Function(type_idx));
2315 let orig_func_idx = next_func_idx;
2316 next_func_idx += 1;
2317
2318 func_info.push(FuncInfo {
2319 name,
2320 type_idx,
2321 orig_func_idx,
2322 is_async: abi.is_async(),
2323 n_params: sig.params.len(),
2324 });
2325 }
2326
2327 for info in func_info.iter() {
2329 let wrapper_func_idx = next_func_idx;
2330 functions.function(info.type_idx);
2331
2332 let mut func = wasm_encoder::Function::new([]);
2333 if info.is_async {
2334 func.instruction(&Instruction::Call(wasm_init_async_task_func_idx));
2335 } else {
2336 func.instruction(&Instruction::Call(wasm_init_task_func_idx));
2337 }
2338 for i in 0..info.n_params as u32 {
2339 func.instruction(&Instruction::LocalGet(i));
2340 }
2341 func.instruction(&Instruction::Call(info.orig_func_idx));
2342 func.instruction(&Instruction::End);
2343 code.function(&func);
2344
2345 exports_section.export(info.name, ExportKind::Func, wrapper_func_idx);
2346 next_func_idx += 1;
2347 }
2348
2349 let mut wrapper_module = Module::new();
2350 wrapper_module.section(&types);
2351 wrapper_module.section(&imports);
2352 wrapper_module.section(&functions);
2353 wrapper_module.section(&exports_section);
2354 wrapper_module.section(&code);
2355
2356 let wrapper_module_idx = self
2357 .component
2358 .core_module(Some("init-task-wrappers"), &wrapper_module);
2359
2360 let mut wrapper_imports = Vec::new();
2362 let init_idx = self.core_alias_export(
2363 Some(wasm_init_task),
2364 instance_index,
2365 wasm_init_task,
2366 ExportKind::Func,
2367 );
2368 let init_async_idx = self.core_alias_export(
2369 Some(wasm_init_async_task),
2370 instance_index,
2371 wasm_init_async_task,
2372 ExportKind::Func,
2373 );
2374 wrapper_imports.push((wasm_init_task.into(), ExportKind::Func, init_idx));
2375 wrapper_imports.push((
2376 wasm_init_async_task.into(),
2377 ExportKind::Func,
2378 init_async_idx,
2379 ));
2380
2381 for (name, func, _) in &funcs_to_wrap {
2383 let orig_idx =
2384 self.core_alias_export(Some(name), instance_index, name, ExportKind::Func);
2385 wrapper_imports.push((import_func_name(func), ExportKind::Func, orig_idx));
2386 }
2387
2388 let wrapper_args_idx = self.component.core_instantiate_exports(
2389 Some("init-task-wrappers-args"),
2390 wrapper_imports.iter().map(|(n, k, i)| (n.as_str(), *k, *i)),
2391 );
2392
2393 let wrapper_instance = self.component.core_instantiate(
2394 Some("init-task-wrappers-instance"),
2395 wrapper_module_idx,
2396 [("", ModuleArg::Instance(wrapper_args_idx))],
2397 );
2398
2399 for (name, _, _) in funcs_to_wrap {
2401 let wrapper_idx =
2402 self.core_alias_export(Some(&name), wrapper_instance, &name, ExportKind::Func);
2403 self.export_task_initialization_wrappers
2404 .insert(name.into(), wrapper_idx);
2405 }
2406
2407 Ok(())
2408 }
2409}
2410
2411#[derive(Default)]
2429struct Shims<'a> {
2430 shims: IndexMap<ShimKind<'a>, Shim<'a>>,
2432}
2433
2434struct Shim<'a> {
2435 options: RequiredOptions,
2438
2439 name: String,
2443
2444 debug_name: String,
2447
2448 kind: ShimKind<'a>,
2450
2451 sig: WasmSignature,
2453}
2454
2455#[derive(Debug, Clone, Hash, Eq, PartialEq)]
2458enum PayloadFuncKind {
2459 FutureWrite,
2460 FutureRead,
2461 StreamWrite,
2462 StreamRead,
2463}
2464
2465#[derive(Debug, Clone, Hash, Eq, PartialEq)]
2466enum ShimKind<'a> {
2467 IndirectLowering {
2471 interface: Option<String>,
2473 index: usize,
2475 realloc: CustomModule<'a>,
2477 encoding: StringEncoding,
2479 },
2480 Adapter {
2483 adapter: &'a str,
2485 func: &'a str,
2487 },
2488 ResourceDtor {
2491 module: CustomModule<'a>,
2493 export: &'a str,
2495 },
2496 PayloadFunc {
2500 for_module: CustomModule<'a>,
2503 info: &'a PayloadInfo,
2508 kind: PayloadFuncKind,
2510 },
2511 WaitableSetWait { cancellable: bool },
2515 WaitableSetPoll { cancellable: bool },
2519 TaskReturn {
2521 interface: Option<InterfaceId>,
2524 func: &'a str,
2527 result: Option<Type>,
2529 for_module: CustomModule<'a>,
2531 encoding: StringEncoding,
2533 },
2534 ErrorContextNew {
2538 encoding: StringEncoding,
2540 },
2541 ErrorContextDebugMessage {
2545 for_module: CustomModule<'a>,
2547 encoding: StringEncoding,
2549 },
2550 ThreadNewIndirect {
2553 for_module: CustomModule<'a>,
2555 func_ty: FuncType,
2557 },
2558}
2559
2560#[derive(Debug, Copy, Clone, Hash, Eq, PartialEq)]
2570enum CustomModule<'a> {
2571 Main,
2574 Adapter(&'a str),
2577}
2578
2579impl<'a> CustomModule<'a> {
2580 fn debug_name(&self) -> &'a str {
2581 match self {
2582 CustomModule::Main => "main",
2583 CustomModule::Adapter(s) => s,
2584 }
2585 }
2586}
2587
2588impl<'a> Shims<'a> {
2589 fn append_indirect(
2594 &mut self,
2595 world: &'a ComponentWorld<'a>,
2596 for_module: CustomModule<'a>,
2597 ) -> Result<()> {
2598 let module_imports = world.imports_for(for_module);
2599 let module_exports = world.exports_for(for_module);
2600 let resolve = &world.encoder.metadata.resolve;
2601
2602 for (module, field, import) in module_imports.imports() {
2603 match import {
2604 Import::ImportedResourceDrop(..)
2607 | Import::MainModuleMemory
2608 | Import::MainModuleExport { .. }
2609 | Import::Item(_)
2610 | Import::ExportedResourceDrop(..)
2611 | Import::ExportedResourceRep(..)
2612 | Import::ExportedResourceNew(..)
2613 | Import::ExportedTaskCancel
2614 | Import::ErrorContextDrop
2615 | Import::BackpressureInc
2616 | Import::BackpressureDec
2617 | Import::ThreadYield { .. }
2618 | Import::SubtaskDrop
2619 | Import::SubtaskCancel { .. }
2620 | Import::FutureNew(..)
2621 | Import::StreamNew(..)
2622 | Import::FutureCancelRead { .. }
2623 | Import::FutureCancelWrite { .. }
2624 | Import::FutureDropWritable { .. }
2625 | Import::FutureDropReadable { .. }
2626 | Import::StreamCancelRead { .. }
2627 | Import::StreamCancelWrite { .. }
2628 | Import::StreamDropWritable { .. }
2629 | Import::StreamDropReadable { .. }
2630 | Import::WaitableSetNew
2631 | Import::WaitableSetDrop
2632 | Import::WaitableJoin
2633 | Import::ContextGet(_)
2634 | Import::ContextSet(_)
2635 | Import::ThreadIndex
2636 | Import::ThreadSuspendToSuspended { .. }
2637 | Import::ThreadSuspend { .. }
2638 | Import::ThreadSuspendTo { .. }
2639 | Import::ThreadUnsuspend
2640 | Import::ThreadYieldToSuspended { .. } => {}
2641
2642 Import::ExportedTaskReturn(key, interface, func) => {
2646 let (options, sig) = task_return_options_and_type(resolve, func);
2647 if options.is_empty() {
2648 continue;
2649 }
2650 let name = self.shims.len().to_string();
2651 let encoding = world
2652 .module_metadata_for(for_module)
2653 .export_encodings
2654 .get(resolve, key, &func.name)
2655 .ok_or_else(|| {
2656 anyhow::anyhow!(
2657 "missing component metadata for export of \
2658 `{module}::{field}`"
2659 )
2660 })?;
2661 self.push(Shim {
2662 name,
2663 debug_name: format!("task-return-{}", func.name),
2664 options,
2665 kind: ShimKind::TaskReturn {
2666 interface: *interface,
2667 func: &func.name,
2668 result: func.result,
2669 for_module,
2670 encoding,
2671 },
2672 sig,
2673 });
2674 }
2675
2676 Import::FutureWrite { async_, info } => {
2677 self.append_indirect_payload_push(
2678 resolve,
2679 for_module,
2680 module,
2681 *async_,
2682 info,
2683 PayloadFuncKind::FutureWrite,
2684 vec![WasmType::I32; 2],
2685 vec![WasmType::I32],
2686 );
2687 }
2688 Import::FutureRead { async_, info } => {
2689 self.append_indirect_payload_push(
2690 resolve,
2691 for_module,
2692 module,
2693 *async_,
2694 info,
2695 PayloadFuncKind::FutureRead,
2696 vec![WasmType::I32; 2],
2697 vec![WasmType::I32],
2698 );
2699 }
2700 Import::StreamWrite { async_, info } => {
2701 self.append_indirect_payload_push(
2702 resolve,
2703 for_module,
2704 module,
2705 *async_,
2706 info,
2707 PayloadFuncKind::StreamWrite,
2708 vec![WasmType::I32; 3],
2709 vec![WasmType::I32],
2710 );
2711 }
2712 Import::StreamRead { async_, info } => {
2713 self.append_indirect_payload_push(
2714 resolve,
2715 for_module,
2716 module,
2717 *async_,
2718 info,
2719 PayloadFuncKind::StreamRead,
2720 vec![WasmType::I32; 3],
2721 vec![WasmType::I32],
2722 );
2723 }
2724
2725 Import::WaitableSetWait { cancellable } => {
2726 let name = self.shims.len().to_string();
2727 self.push(Shim {
2728 name,
2729 debug_name: "waitable-set.wait".to_string(),
2730 options: RequiredOptions::empty(),
2731 kind: ShimKind::WaitableSetWait {
2732 cancellable: *cancellable,
2733 },
2734 sig: WasmSignature {
2735 params: vec![WasmType::I32; 2],
2736 results: vec![WasmType::I32],
2737 indirect_params: false,
2738 retptr: false,
2739 },
2740 });
2741 }
2742
2743 Import::WaitableSetPoll { cancellable } => {
2744 let name = self.shims.len().to_string();
2745 self.push(Shim {
2746 name,
2747 debug_name: "waitable-set.poll".to_string(),
2748 options: RequiredOptions::empty(),
2749 kind: ShimKind::WaitableSetPoll {
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::ErrorContextNew { encoding } => {
2762 let name = self.shims.len().to_string();
2763 self.push(Shim {
2764 name,
2765 debug_name: "error-new".to_string(),
2766 options: RequiredOptions::MEMORY | RequiredOptions::STRING_ENCODING,
2767 kind: ShimKind::ErrorContextNew {
2768 encoding: *encoding,
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::ErrorContextDebugMessage { encoding } => {
2780 let name = self.shims.len().to_string();
2781 self.push(Shim {
2782 name,
2783 debug_name: "error-debug-message".to_string(),
2784 options: RequiredOptions::MEMORY
2785 | RequiredOptions::STRING_ENCODING
2786 | RequiredOptions::REALLOC,
2787 kind: ShimKind::ErrorContextDebugMessage {
2788 for_module,
2789 encoding: *encoding,
2790 },
2791 sig: WasmSignature {
2792 params: vec![WasmType::I32; 2],
2793 results: vec![],
2794 indirect_params: false,
2795 retptr: false,
2796 },
2797 });
2798 }
2799
2800 Import::ThreadNewIndirect => {
2801 let name = self.shims.len().to_string();
2802 self.push(Shim {
2803 name,
2804 debug_name: "thread.new-indirect".to_string(),
2805 options: RequiredOptions::empty(),
2806 kind: ShimKind::ThreadNewIndirect {
2807 for_module,
2808 func_ty: FuncType::new([ValType::I32], vec![]),
2810 },
2811 sig: WasmSignature {
2812 params: vec![WasmType::I32; 2],
2813 results: vec![WasmType::I32],
2814 indirect_params: false,
2815 retptr: false,
2816 },
2817 });
2818 }
2819
2820 Import::AdapterExport { adapter, func, ty } => {
2823 let name = self.shims.len().to_string();
2824 log::debug!("shim {name} is adapter `{module}::{field}`");
2825 self.push(Shim {
2826 name,
2827 debug_name: format!("adapt-{module}-{field}"),
2828 options: RequiredOptions::MEMORY,
2832 kind: ShimKind::Adapter { adapter, func },
2833 sig: WasmSignature {
2834 params: ty.params().iter().map(to_wasm_type).collect(),
2835 results: ty.results().iter().map(to_wasm_type).collect(),
2836 indirect_params: false,
2837 retptr: false,
2838 },
2839 });
2840
2841 fn to_wasm_type(ty: &wasmparser::ValType) -> WasmType {
2842 match ty {
2843 wasmparser::ValType::I32 => WasmType::I32,
2844 wasmparser::ValType::I64 => WasmType::I64,
2845 wasmparser::ValType::F32 => WasmType::F32,
2846 wasmparser::ValType::F64 => WasmType::F64,
2847 _ => unreachable!(),
2848 }
2849 }
2850 }
2851
2852 Import::InterfaceFunc(key, _, name, abi) => {
2856 self.append_indirect_wit_func(
2857 world,
2858 for_module,
2859 module,
2860 field,
2861 key,
2862 name,
2863 Some(resolve.name_world_key(key)),
2864 *abi,
2865 )?;
2866 }
2867 Import::WorldFunc(key, name, abi) => {
2868 self.append_indirect_wit_func(
2869 world, for_module, module, field, key, name, None, *abi,
2870 )?;
2871 }
2872 }
2873 }
2874
2875 for (export_name, export) in module_exports.iter() {
2881 let id = match export {
2882 Export::ResourceDtor(id) => id,
2883 _ => continue,
2884 };
2885 let resource = resolve.types[*id].name.as_ref().unwrap();
2886 let name = self.shims.len().to_string();
2887 self.push(Shim {
2888 name,
2889 debug_name: format!("dtor-{resource}"),
2890 options: RequiredOptions::empty(),
2891 kind: ShimKind::ResourceDtor {
2892 module: for_module,
2893 export: export_name,
2894 },
2895 sig: WasmSignature {
2896 params: vec![WasmType::I32],
2897 results: Vec::new(),
2898 indirect_params: false,
2899 retptr: false,
2900 },
2901 });
2902 }
2903
2904 Ok(())
2905 }
2906
2907 fn append_indirect_payload_push(
2910 &mut self,
2911 resolve: &Resolve,
2912 for_module: CustomModule<'a>,
2913 module: &str,
2914 async_: bool,
2915 info: &'a PayloadInfo,
2916 kind: PayloadFuncKind,
2917 params: Vec<WasmType>,
2918 results: Vec<WasmType>,
2919 ) {
2920 let debug_name = format!("{module}-{}", info.name);
2921 let name = self.shims.len().to_string();
2922
2923 let payload = info.payload(resolve);
2924 let (wit_param, wit_result) = match kind {
2925 PayloadFuncKind::StreamRead | PayloadFuncKind::FutureRead => (None, payload),
2926 PayloadFuncKind::StreamWrite | PayloadFuncKind::FutureWrite => (payload, None),
2927 };
2928 self.push(Shim {
2929 name,
2930 debug_name,
2931 options: RequiredOptions::MEMORY
2932 | RequiredOptions::for_import(
2933 resolve,
2934 &Function {
2935 name: String::new(),
2936 kind: FunctionKind::Freestanding,
2937 params: match wit_param {
2938 Some(ty) => vec![Param {
2939 name: "a".to_string(),
2940 ty,
2941 span: Default::default(),
2942 }],
2943 None => Vec::new(),
2944 },
2945 result: wit_result,
2946 docs: Default::default(),
2947 stability: Stability::Unknown,
2948 span: Default::default(),
2949 },
2950 if async_ {
2951 AbiVariant::GuestImportAsync
2952 } else {
2953 AbiVariant::GuestImport
2954 },
2955 ),
2956 kind: ShimKind::PayloadFunc {
2957 for_module,
2958 info,
2959 kind,
2960 },
2961 sig: WasmSignature {
2962 params,
2963 results,
2964 indirect_params: false,
2965 retptr: false,
2966 },
2967 });
2968 }
2969
2970 fn append_indirect_wit_func(
2973 &mut self,
2974 world: &'a ComponentWorld<'a>,
2975 for_module: CustomModule<'a>,
2976 module: &str,
2977 field: &str,
2978 key: &WorldKey,
2979 name: &String,
2980 interface_key: Option<String>,
2981 abi: AbiVariant,
2982 ) -> Result<()> {
2983 let resolve = &world.encoder.metadata.resolve;
2984 let metadata = world.module_metadata_for(for_module);
2985 let interface = &world.import_map[&interface_key];
2986 let (index, _, lowering) = interface.lowerings.get_full(&(name.clone(), abi)).unwrap();
2987 let shim_name = self.shims.len().to_string();
2988 match lowering {
2989 Lowering::Direct | Lowering::ResourceDrop(_) => {}
2990
2991 Lowering::Indirect { sig, options } => {
2992 log::debug!(
2993 "shim {shim_name} is import `{module}::{field}` lowering {index} `{name}`",
2994 );
2995 let encoding = metadata
2996 .import_encodings
2997 .get(resolve, key, name)
2998 .ok_or_else(|| {
2999 anyhow::anyhow!(
3000 "missing component metadata for import of \
3001 `{module}::{field}`"
3002 )
3003 })?;
3004 self.push(Shim {
3005 name: shim_name,
3006 debug_name: format!("indirect-{module}-{field}"),
3007 options: *options,
3008 kind: ShimKind::IndirectLowering {
3009 interface: interface_key,
3010 index,
3011 realloc: for_module,
3012 encoding,
3013 },
3014 sig: sig.clone(),
3015 });
3016 }
3017 }
3018
3019 Ok(())
3020 }
3021
3022 fn push(&mut self, shim: Shim<'a>) {
3023 if !self.shims.contains_key(&shim.kind) {
3027 self.shims.insert(shim.kind.clone(), shim);
3028 }
3029 }
3030}
3031
3032fn task_return_options_and_type(
3033 resolve: &Resolve,
3034 func: &Function,
3035) -> (RequiredOptions, WasmSignature) {
3036 let func_tmp = Function {
3037 name: String::new(),
3038 kind: FunctionKind::Freestanding,
3039 params: match &func.result {
3040 Some(ty) => vec![Param {
3041 name: "a".to_string(),
3042 ty: *ty,
3043 span: Default::default(),
3044 }],
3045 None => Vec::new(),
3046 },
3047 result: None,
3048 docs: Default::default(),
3049 stability: Stability::Unknown,
3050 span: Default::default(),
3051 };
3052 let abi = AbiVariant::GuestImport;
3053 let mut options = RequiredOptions::for_import(resolve, func, abi);
3054 options.remove(RequiredOptions::REALLOC);
3056 let sig = resolve.wasm_signature(abi, &func_tmp);
3057 (options, sig)
3058}
3059
3060#[derive(Clone, Debug)]
3062pub struct Item {
3063 pub alias: String,
3064 pub kind: ExportKind,
3065 pub which: MainOrAdapter,
3066 pub name: String,
3067}
3068
3069#[derive(Debug, PartialEq, Clone)]
3071pub enum MainOrAdapter {
3072 Main,
3073 Adapter(String),
3074}
3075
3076impl MainOrAdapter {
3077 fn to_custom_module(&self) -> CustomModule<'_> {
3078 match self {
3079 MainOrAdapter::Main => CustomModule::Main,
3080 MainOrAdapter::Adapter(s) => CustomModule::Adapter(s),
3081 }
3082 }
3083}
3084
3085#[derive(Clone)]
3087pub enum Instance {
3088 MainOrAdapter(MainOrAdapter),
3090
3091 Items(Vec<Item>),
3093}
3094
3095#[derive(Clone)]
3098pub struct LibraryInfo {
3099 pub instantiate_after_shims: bool,
3101
3102 pub arguments: Vec<(String, Instance)>,
3104}
3105
3106pub(super) struct Adapter {
3108 wasm: Vec<u8>,
3110
3111 metadata: ModuleMetadata,
3113
3114 required_exports: IndexSet<WorldKey>,
3117
3118 library_info: Option<LibraryInfo>,
3123}
3124
3125#[derive(Default)]
3127pub struct ComponentEncoder {
3128 module: Vec<u8>,
3129 module_import_map: Option<ModuleImportMap>,
3130 pub(super) metadata: Bindgen,
3131 validate: bool,
3132 pub(super) main_module_exports: IndexSet<WorldKey>,
3133 pub(super) adapters: IndexMap<String, Adapter>,
3134 import_name_map: HashMap<String, String>,
3135 realloc_via_memory_grow: bool,
3136 merge_imports_based_on_semver: Option<bool>,
3137 pub(super) reject_legacy_names: bool,
3138 debug_names: bool,
3139}
3140
3141impl ComponentEncoder {
3142 pub fn module(mut self, module: &[u8]) -> Result<Self> {
3148 let (wasm, metadata) = self.decode(module.as_ref())?;
3149 let (wasm, module_import_map) = ModuleImportMap::new(wasm)?;
3150 let exports = self
3151 .merge_metadata(metadata)
3152 .context("failed merge WIT metadata for module with previous metadata")?;
3153 self.main_module_exports.extend(exports);
3154 self.module = if let Some(producers) = &self.metadata.producers {
3155 producers.add_to_wasm(&wasm)?
3156 } else {
3157 wasm.to_vec()
3158 };
3159 self.module_import_map = module_import_map;
3160 Ok(self)
3161 }
3162
3163 fn decode<'a>(&self, wasm: &'a [u8]) -> Result<(Cow<'a, [u8]>, Bindgen)> {
3164 let (bytes, metadata) = metadata::decode(wasm)?;
3165 match bytes {
3166 Some(wasm) => Ok((Cow::Owned(wasm), metadata)),
3167 None => Ok((Cow::Borrowed(wasm), metadata)),
3168 }
3169 }
3170
3171 fn merge_metadata(&mut self, metadata: Bindgen) -> Result<IndexSet<WorldKey>> {
3172 self.metadata.merge(metadata)
3173 }
3174
3175 pub fn validate(mut self, validate: bool) -> Self {
3177 self.validate = validate;
3178 self
3179 }
3180
3181 pub fn debug_names(mut self, debug_names: bool) -> Self {
3183 self.debug_names = debug_names;
3184 self
3185 }
3186
3187 pub fn merge_imports_based_on_semver(mut self, merge: bool) -> Self {
3195 self.merge_imports_based_on_semver = Some(merge);
3196 self
3197 }
3198
3199 pub fn reject_legacy_names(mut self, reject: bool) -> Self {
3208 self.reject_legacy_names = reject;
3209 self
3210 }
3211
3212 pub fn adapter(self, name: &str, bytes: &[u8]) -> Result<Self> {
3230 self.library_or_adapter(name, bytes, None)
3231 }
3232
3233 pub fn library(self, name: &str, bytes: &[u8], library_info: LibraryInfo) -> Result<Self> {
3246 self.library_or_adapter(name, bytes, Some(library_info))
3247 }
3248
3249 fn library_or_adapter(
3250 mut self,
3251 name: &str,
3252 bytes: &[u8],
3253 library_info: Option<LibraryInfo>,
3254 ) -> Result<Self> {
3255 let (wasm, mut metadata) = self.decode(bytes)?;
3256 let adapter_metadata = mem::take(&mut metadata.metadata);
3264 let exports = self.merge_metadata(metadata).with_context(|| {
3265 format!("failed to merge WIT packages of adapter `{name}` into main packages")
3266 })?;
3267 if let Some(library_info) = &library_info {
3268 for (_, instance) in &library_info.arguments {
3270 let resolve = |which: &_| match which {
3271 MainOrAdapter::Main => Ok(()),
3272 MainOrAdapter::Adapter(name) => {
3273 if self.adapters.contains_key(name.as_str()) {
3274 Ok(())
3275 } else {
3276 Err(anyhow!("instance refers to unknown adapter `{name}`"))
3277 }
3278 }
3279 };
3280
3281 match instance {
3282 Instance::MainOrAdapter(which) => resolve(which)?,
3283 Instance::Items(items) => {
3284 for item in items {
3285 resolve(&item.which)?;
3286 }
3287 }
3288 }
3289 }
3290 }
3291 self.adapters.insert(
3292 name.to_string(),
3293 Adapter {
3294 wasm: wasm.to_vec(),
3295 metadata: adapter_metadata,
3296 required_exports: exports,
3297 library_info,
3298 },
3299 );
3300 Ok(self)
3301 }
3302
3303 pub fn realloc_via_memory_grow(mut self, value: bool) -> Self {
3308 self.realloc_via_memory_grow = value;
3309 self
3310 }
3311
3312 pub fn import_name_map(mut self, map: HashMap<String, String>) -> Self {
3323 self.import_name_map = map;
3324 self
3325 }
3326
3327 pub fn encode(&mut self) -> Result<Vec<u8>> {
3329 if self.module.is_empty() {
3330 bail!("a module is required when encoding a component");
3331 }
3332
3333 if self.merge_imports_based_on_semver.unwrap_or(true) {
3334 self.metadata
3335 .resolve
3336 .merge_world_imports_based_on_semver(self.metadata.world)?;
3337 }
3338
3339 let world = ComponentWorld::new(self).context("failed to decode world from module")?;
3340 let mut state = EncodingState {
3341 component: ComponentBuilder::default(),
3342 module_index: None,
3343 instance_index: None,
3344 memory_index: None,
3345 shim_instance_index: None,
3346 fixups_module_index: None,
3347 adapter_modules: IndexMap::new(),
3348 adapter_instances: IndexMap::new(),
3349 import_type_encoding_maps: Default::default(),
3350 export_type_encoding_maps: Default::default(),
3351 imported_instances: Default::default(),
3352 imported_funcs: Default::default(),
3353 exported_instances: Default::default(),
3354 aliased_core_items: Default::default(),
3355 info: &world,
3356 export_task_initialization_wrappers: HashMap::new(),
3357 };
3358 state.encode_imports(&self.import_name_map)?;
3359 state.encode_core_modules();
3360 state.encode_core_instantiation()?;
3361 state.encode_exports(CustomModule::Main)?;
3362 for name in self.adapters.keys() {
3363 state.encode_exports(CustomModule::Adapter(name))?;
3364 }
3365 state.component.append_names();
3366 state
3367 .component
3368 .raw_custom_section(&crate::base_producers().raw_custom_section());
3369 let bytes = state.component.finish();
3370
3371 if self.validate {
3372 Validator::new_with_features(WasmFeatures::all())
3373 .validate_all(&bytes)
3374 .context("failed to validate component output")?;
3375 }
3376
3377 Ok(bytes)
3378 }
3379}
3380
3381impl ComponentWorld<'_> {
3382 fn imports_for(&self, module: CustomModule) -> &ImportMap {
3384 match module {
3385 CustomModule::Main => &self.info.imports,
3386 CustomModule::Adapter(name) => &self.adapters[name].info.imports,
3387 }
3388 }
3389
3390 fn exports_for(&self, module: CustomModule) -> &ExportMap {
3392 match module {
3393 CustomModule::Main => &self.info.exports,
3394 CustomModule::Adapter(name) => &self.adapters[name].info.exports,
3395 }
3396 }
3397
3398 fn module_metadata_for(&self, module: CustomModule) -> &ModuleMetadata {
3400 match module {
3401 CustomModule::Main => &self.encoder.metadata.metadata,
3402 CustomModule::Adapter(name) => &self.encoder.adapters[name].metadata,
3403 }
3404 }
3405}
3406
3407#[cfg(all(test, feature = "dummy-module"))]
3408mod test {
3409 use super::*;
3410 use crate::{dummy_module, embed_component_metadata};
3411 use wit_parser::ManglingAndAbi;
3412
3413 #[test]
3414 fn it_renames_imports() {
3415 let mut resolve = Resolve::new();
3416 let pkg = resolve
3417 .push_str(
3418 "test.wit",
3419 r#"
3420package test:wit;
3421
3422interface i {
3423 f: func();
3424}
3425
3426world test {
3427 import i;
3428 import foo: interface {
3429 f: func();
3430 }
3431}
3432"#,
3433 )
3434 .unwrap();
3435 let world = resolve.select_world(&[pkg], None).unwrap();
3436
3437 let mut module = dummy_module(&resolve, world, ManglingAndAbi::Standard32);
3438
3439 embed_component_metadata(&mut module, &resolve, world, StringEncoding::UTF8).unwrap();
3440
3441 let encoded = ComponentEncoder::default()
3442 .import_name_map(HashMap::from([
3443 (
3444 "foo".to_string(),
3445 "unlocked-dep=<foo:bar/foo@{>=1.0.0 <1.1.0}>".to_string(),
3446 ),
3447 (
3448 "test:wit/i".to_string(),
3449 "locked-dep=<foo:bar/i@1.2.3>".to_string(),
3450 ),
3451 ]))
3452 .module(&module)
3453 .unwrap()
3454 .validate(true)
3455 .encode()
3456 .unwrap();
3457
3458 let wat = wasmprinter::print_bytes(encoded).unwrap();
3459 assert!(wat.contains("unlocked-dep=<foo:bar/foo@{>=1.0.0 <1.1.0}>"));
3460 assert!(wat.contains("locked-dep=<foo:bar/i@1.2.3>"));
3461 }
3462}