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.result).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, result) => {
1795 let (options, _sig) = task_return_options_and_type(resolve, *result);
1796 if options.is_empty() {
1797 let mut encoder = if interface.is_none() {
1803 self.root_import_type_encoder(*interface)
1804 } else {
1805 self.root_export_type_encoder(*interface)
1806 };
1807
1808 let result = match result {
1809 Some(ty) => Some(encoder.encode_valtype(resolve, ty)?),
1810 None => None,
1811 };
1812 let index = self.component.task_return(result, []);
1813 Ok((ExportKind::Func, index))
1814 } else {
1815 let metadata = &self.info.module_metadata_for(for_module);
1816 let encoding = metadata.export_encodings.get(resolve, key, func).unwrap();
1817 Ok(self.materialize_shim_import(
1818 shims,
1819 &ShimKind::TaskReturn {
1820 for_module,
1821 interface: *interface,
1822 func,
1823 result: *result,
1824 encoding,
1825 },
1826 ))
1827 }
1828 }
1829 Import::BackpressureInc => {
1830 let index = self.component.backpressure_inc();
1831 Ok((ExportKind::Func, index))
1832 }
1833 Import::BackpressureDec => {
1834 let index = self.component.backpressure_dec();
1835 Ok((ExportKind::Func, index))
1836 }
1837 Import::WaitableSetWait { cancellable } => Ok(self.materialize_shim_import(
1838 shims,
1839 &ShimKind::WaitableSetWait {
1840 cancellable: *cancellable,
1841 },
1842 )),
1843 Import::WaitableSetPoll { cancellable } => Ok(self.materialize_shim_import(
1844 shims,
1845 &ShimKind::WaitableSetPoll {
1846 cancellable: *cancellable,
1847 },
1848 )),
1849 Import::ThreadYield { cancellable } => {
1850 let index = self.component.thread_yield(*cancellable);
1851 Ok((ExportKind::Func, index))
1852 }
1853 Import::SubtaskDrop => {
1854 let index = self.component.subtask_drop();
1855 Ok((ExportKind::Func, index))
1856 }
1857 Import::SubtaskCancel { async_ } => {
1858 let index = self.component.subtask_cancel(*async_);
1859 Ok((ExportKind::Func, index))
1860 }
1861 Import::StreamNew(info) => {
1862 let ty = self.payload_type_index(info)?;
1863 let index = self.component.stream_new(ty);
1864 Ok((ExportKind::Func, index))
1865 }
1866 Import::StreamRead { info, .. } => Ok(self.materialize_payload_import(
1867 shims,
1868 for_module,
1869 info,
1870 PayloadFuncKind::StreamRead,
1871 )),
1872 Import::StreamWrite { info, .. } => Ok(self.materialize_payload_import(
1873 shims,
1874 for_module,
1875 info,
1876 PayloadFuncKind::StreamWrite,
1877 )),
1878 Import::StreamCancelRead { info, async_ } => {
1879 let ty = self.payload_type_index(info)?;
1880 let index = self.component.stream_cancel_read(ty, *async_);
1881 Ok((ExportKind::Func, index))
1882 }
1883 Import::StreamCancelWrite { info, async_ } => {
1884 let ty = self.payload_type_index(info)?;
1885 let index = self.component.stream_cancel_write(ty, *async_);
1886 Ok((ExportKind::Func, index))
1887 }
1888 Import::StreamDropReadable(info) => {
1889 let type_index = self.payload_type_index(info)?;
1890 let index = self.component.stream_drop_readable(type_index);
1891 Ok((ExportKind::Func, index))
1892 }
1893 Import::StreamDropWritable(info) => {
1894 let type_index = self.payload_type_index(info)?;
1895 let index = self.component.stream_drop_writable(type_index);
1896 Ok((ExportKind::Func, index))
1897 }
1898 Import::FutureNew(info) => {
1899 let ty = self.payload_type_index(info)?;
1900 let index = self.component.future_new(ty);
1901 Ok((ExportKind::Func, index))
1902 }
1903 Import::FutureRead { info, .. } => Ok(self.materialize_payload_import(
1904 shims,
1905 for_module,
1906 info,
1907 PayloadFuncKind::FutureRead,
1908 )),
1909 Import::FutureWrite { info, .. } => Ok(self.materialize_payload_import(
1910 shims,
1911 for_module,
1912 info,
1913 PayloadFuncKind::FutureWrite,
1914 )),
1915 Import::FutureCancelRead { info, async_ } => {
1916 let ty = self.payload_type_index(info)?;
1917 let index = self.component.future_cancel_read(ty, *async_);
1918 Ok((ExportKind::Func, index))
1919 }
1920 Import::FutureCancelWrite { info, async_ } => {
1921 let ty = self.payload_type_index(info)?;
1922 let index = self.component.future_cancel_write(ty, *async_);
1923 Ok((ExportKind::Func, index))
1924 }
1925 Import::FutureDropReadable(info) => {
1926 let type_index = self.payload_type_index(info)?;
1927 let index = self.component.future_drop_readable(type_index);
1928 Ok((ExportKind::Func, index))
1929 }
1930 Import::FutureDropWritable(info) => {
1931 let type_index = self.payload_type_index(info)?;
1932 let index = self.component.future_drop_writable(type_index);
1933 Ok((ExportKind::Func, index))
1934 }
1935 Import::ErrorContextNew { encoding } => Ok(self.materialize_shim_import(
1936 shims,
1937 &ShimKind::ErrorContextNew {
1938 encoding: *encoding,
1939 },
1940 )),
1941 Import::ErrorContextDebugMessage { encoding } => Ok(self.materialize_shim_import(
1942 shims,
1943 &ShimKind::ErrorContextDebugMessage {
1944 for_module,
1945 encoding: *encoding,
1946 },
1947 )),
1948 Import::ErrorContextDrop => {
1949 let index = self.component.error_context_drop();
1950 Ok((ExportKind::Func, index))
1951 }
1952 Import::WorldFunc(key, name, abi) => {
1953 self.materialize_wit_import(shims, for_module, None, name, key, *abi)
1954 }
1955 Import::InterfaceFunc(key, _, name, abi) => self.materialize_wit_import(
1956 shims,
1957 for_module,
1958 Some(resolve.name_world_key(key)),
1959 name,
1960 key,
1961 *abi,
1962 ),
1963
1964 Import::WaitableSetNew => {
1965 let index = self.component.waitable_set_new();
1966 Ok((ExportKind::Func, index))
1967 }
1968 Import::WaitableSetDrop => {
1969 let index = self.component.waitable_set_drop();
1970 Ok((ExportKind::Func, index))
1971 }
1972 Import::WaitableJoin => {
1973 let index = self.component.waitable_join();
1974 Ok((ExportKind::Func, index))
1975 }
1976 Import::ContextGet(n) => {
1977 let index = self.component.context_get(*n);
1978 Ok((ExportKind::Func, index))
1979 }
1980 Import::ContextSet(n) => {
1981 let index = self.component.context_set(*n);
1982 Ok((ExportKind::Func, index))
1983 }
1984 Import::ExportedTaskCancel => {
1985 let index = self.component.task_cancel();
1986 Ok((ExportKind::Func, index))
1987 }
1988 Import::ThreadIndex => {
1989 let index = self.component.thread_index();
1990 Ok((ExportKind::Func, index))
1991 }
1992 Import::ThreadNewIndirect => Ok(self.materialize_shim_import(
1993 shims,
1994 &ShimKind::ThreadNewIndirect {
1995 for_module,
1996 func_ty: FuncType::new([ValType::I32], []),
1998 },
1999 )),
2000 Import::ThreadSuspendToSuspended { cancellable } => {
2001 let index = self.component.thread_suspend_to_suspended(*cancellable);
2002 Ok((ExportKind::Func, index))
2003 }
2004 Import::ThreadSuspend { cancellable } => {
2005 let index = self.component.thread_suspend(*cancellable);
2006 Ok((ExportKind::Func, index))
2007 }
2008 Import::ThreadSuspendTo { cancellable } => {
2009 let index = self.component.thread_suspend_to(*cancellable);
2010 Ok((ExportKind::Func, index))
2011 }
2012 Import::ThreadUnsuspend => {
2013 let index = self.component.thread_unsuspend();
2014 Ok((ExportKind::Func, index))
2015 }
2016 Import::ThreadYieldToSuspended { cancellable } => {
2017 let index = self.component.thread_yield_to_suspended(*cancellable);
2018 Ok((ExportKind::Func, index))
2019 }
2020 }
2021 }
2022
2023 fn materialize_shim_import(&mut self, shims: &Shims<'_>, kind: &ShimKind) -> (ExportKind, u32) {
2026 let index = self.core_alias_export(
2027 Some(&shims.shims[kind].debug_name),
2028 self.shim_instance_index
2029 .expect("shim should be instantiated"),
2030 &shims.shims[kind].name,
2031 ExportKind::Func,
2032 );
2033 (ExportKind::Func, index)
2034 }
2035
2036 fn materialize_payload_import(
2039 &mut self,
2040 shims: &Shims<'_>,
2041 for_module: CustomModule<'_>,
2042 info: &PayloadInfo,
2043 kind: PayloadFuncKind,
2044 ) -> (ExportKind, u32) {
2045 self.materialize_shim_import(
2046 shims,
2047 &ShimKind::PayloadFunc {
2048 for_module,
2049 info,
2050 kind,
2051 },
2052 )
2053 }
2054
2055 fn materialize_wit_import(
2058 &mut self,
2059 shims: &Shims<'_>,
2060 for_module: CustomModule<'_>,
2061 interface_key: Option<String>,
2062 name: &String,
2063 key: &WorldKey,
2064 abi: AbiVariant,
2065 ) -> Result<(ExportKind, u32)> {
2066 let resolve = &self.info.encoder.metadata.resolve;
2067 let import = &self.info.import_map[&interface_key];
2068 let (index, _, lowering) = import.lowerings.get_full(&(name.clone(), abi)).unwrap();
2069 let metadata = self.info.module_metadata_for(for_module);
2070
2071 let index = match lowering {
2072 Lowering::Direct => {
2075 let func_index = match &import.interface {
2076 Some(interface) => {
2077 let instance_index = self.imported_instances[interface];
2078 self.component
2079 .alias_export(instance_index, name, ComponentExportKind::Func)
2080 }
2081 None => self.imported_funcs[name],
2082 };
2083 self.component.lower_func(
2084 Some(name),
2085 func_index,
2086 if let AbiVariant::GuestImportAsync = abi {
2087 vec![CanonicalOption::Async]
2088 } else {
2089 Vec::new()
2090 },
2091 )
2092 }
2093
2094 Lowering::Indirect { .. } => {
2098 let encoding = metadata.import_encodings.get(resolve, key, name).unwrap();
2099 return Ok(self.materialize_shim_import(
2100 shims,
2101 &ShimKind::IndirectLowering {
2102 interface: interface_key,
2103 index,
2104 realloc: for_module,
2105 encoding,
2106 },
2107 ));
2108 }
2109
2110 Lowering::ResourceDrop(id) => {
2113 let resource_idx = self.lookup_resource_index(*id);
2114 self.component.resource_drop(resource_idx)
2115 }
2116 };
2117 Ok((ExportKind::Func, index))
2118 }
2119
2120 fn encode_initialize_with_start(&mut self) -> Result<()> {
2139 let initialize = match self.info.info.exports.initialize() {
2140 Some(name) => name,
2141 None => return Ok(()),
2144 };
2145 let initialize_index = self.core_alias_export(
2146 Some("start"),
2147 self.instance_index.unwrap(),
2148 initialize,
2149 ExportKind::Func,
2150 );
2151 let mut shim = Module::default();
2152 let mut section = TypeSection::new();
2153 section.ty().function([], []);
2154 shim.section(§ion);
2155 let mut section = ImportSection::new();
2156 section.import("", "", EntityType::Function(0));
2157 shim.section(§ion);
2158 shim.section(&StartSection { function_index: 0 });
2159
2160 let shim_module_index = self.component.core_module(Some("start-shim-module"), &shim);
2165 let shim_args_instance_index = self.component.core_instantiate_exports(
2166 Some("start-shim-args"),
2167 [("", ExportKind::Func, initialize_index)],
2168 );
2169 self.component.core_instantiate(
2170 Some("start-shim-instance"),
2171 shim_module_index,
2172 [("", ModuleArg::Instance(shim_args_instance_index))],
2173 );
2174 Ok(())
2175 }
2176
2177 fn instance_for(&self, module: CustomModule) -> u32 {
2180 match module {
2181 CustomModule::Main => self.instance_index.expect("instantiated by now"),
2182 CustomModule::Adapter(name) => self.adapter_instances[name],
2183 }
2184 }
2185
2186 fn module_for(&self, module: CustomModule) -> u32 {
2189 match module {
2190 CustomModule::Main => self.module_index.unwrap(),
2191 CustomModule::Adapter(name) => self.adapter_modules[name],
2192 }
2193 }
2194
2195 fn core_alias_export(
2198 &mut self,
2199 debug_name: Option<&str>,
2200 instance: u32,
2201 name: &str,
2202 kind: ExportKind,
2203 ) -> u32 {
2204 *self
2205 .aliased_core_items
2206 .entry((instance, name.to_string()))
2207 .or_insert_with(|| {
2208 self.component
2209 .core_alias_export(debug_name, instance, name, kind)
2210 })
2211 }
2212
2213 fn create_export_task_initialization_wrappers(&mut self) -> Result<()> {
2223 let instance_index = self.instance_index.unwrap();
2224 let resolve = &self.info.encoder.metadata.resolve;
2225 let world = &resolve.worlds[self.info.encoder.metadata.world];
2226 let exports = self.info.exports_for(CustomModule::Main);
2227
2228 let wasm_init_task_export = exports.wasm_init_task();
2229 let wasm_init_async_task_export = exports.wasm_init_async_task();
2230 if wasm_init_task_export.is_none() || wasm_init_async_task_export.is_none() {
2231 return Ok(());
2234 }
2235 let wasm_init_task = wasm_init_task_export.unwrap();
2236 let wasm_init_async_task = wasm_init_async_task_export.unwrap();
2237
2238 let funcs_to_wrap: Vec<_> = exports
2241 .iter()
2242 .flat_map(|(core_name, export)| match export {
2243 Export::WorldFunc(key, _, abi) => match &world.exports[key] {
2244 WorldItem::Function(f) => Some((core_name, f, abi)),
2245 _ => None,
2246 },
2247 Export::InterfaceFunc(_, id, func_name, abi) => {
2248 let func = &resolve.interfaces[*id].functions[func_name.as_str()];
2249 Some((core_name, func, abi))
2250 }
2251 _ => None,
2252 })
2253 .collect();
2254
2255 if funcs_to_wrap.is_empty() {
2256 return Ok(());
2258 }
2259
2260 let mut types = TypeSection::new();
2262 let mut imports = ImportSection::new();
2263 let mut functions = FunctionSection::new();
2264 let mut exports_section = ExportSection::new();
2265 let mut code = CodeSection::new();
2266
2267 types.ty().function([], []);
2269 let wasm_init_task_type_idx = 0;
2270
2271 imports.import(
2273 "",
2274 wasm_init_task,
2275 EntityType::Function(wasm_init_task_type_idx),
2276 );
2277 imports.import(
2278 "",
2279 wasm_init_async_task,
2280 EntityType::Function(wasm_init_task_type_idx),
2281 );
2282 let wasm_init_task_func_idx = 0u32;
2283 let wasm_init_async_task_func_idx = 1u32;
2284
2285 let mut type_indices = HashMap::new();
2286 let mut next_type_idx = 1u32;
2287 let mut next_func_idx = 2u32;
2288
2289 struct FuncInfo<'a> {
2291 name: &'a str,
2292 type_idx: u32,
2293 orig_func_idx: u32,
2294 is_async: bool,
2295 n_params: usize,
2296 }
2297 let mut func_info = Vec::new();
2298 for &(name, func, abi) in funcs_to_wrap.iter() {
2299 let sig = resolve.wasm_signature(*abi, func);
2300 let type_idx = *type_indices.entry(sig.clone()).or_insert_with(|| {
2301 let idx = next_type_idx;
2302 types.ty().function(
2303 sig.params.iter().map(to_val_type),
2304 sig.results.iter().map(to_val_type),
2305 );
2306 next_type_idx += 1;
2307 idx
2308 });
2309
2310 imports.import("", &import_func_name(func), EntityType::Function(type_idx));
2311 let orig_func_idx = next_func_idx;
2312 next_func_idx += 1;
2313
2314 func_info.push(FuncInfo {
2315 name,
2316 type_idx,
2317 orig_func_idx,
2318 is_async: abi.is_async(),
2319 n_params: sig.params.len(),
2320 });
2321 }
2322
2323 for info in func_info.iter() {
2325 let wrapper_func_idx = next_func_idx;
2326 functions.function(info.type_idx);
2327
2328 let mut func = wasm_encoder::Function::new([]);
2329 if info.is_async {
2330 func.instruction(&Instruction::Call(wasm_init_async_task_func_idx));
2331 } else {
2332 func.instruction(&Instruction::Call(wasm_init_task_func_idx));
2333 }
2334 for i in 0..info.n_params as u32 {
2335 func.instruction(&Instruction::LocalGet(i));
2336 }
2337 func.instruction(&Instruction::Call(info.orig_func_idx));
2338 func.instruction(&Instruction::End);
2339 code.function(&func);
2340
2341 exports_section.export(info.name, ExportKind::Func, wrapper_func_idx);
2342 next_func_idx += 1;
2343 }
2344
2345 let mut wrapper_module = Module::new();
2346 wrapper_module.section(&types);
2347 wrapper_module.section(&imports);
2348 wrapper_module.section(&functions);
2349 wrapper_module.section(&exports_section);
2350 wrapper_module.section(&code);
2351
2352 let wrapper_module_idx = self
2353 .component
2354 .core_module(Some("init-task-wrappers"), &wrapper_module);
2355
2356 let mut wrapper_imports = Vec::new();
2358 let init_idx = self.core_alias_export(
2359 Some(wasm_init_task),
2360 instance_index,
2361 wasm_init_task,
2362 ExportKind::Func,
2363 );
2364 let init_async_idx = self.core_alias_export(
2365 Some(wasm_init_async_task),
2366 instance_index,
2367 wasm_init_async_task,
2368 ExportKind::Func,
2369 );
2370 wrapper_imports.push((wasm_init_task.into(), ExportKind::Func, init_idx));
2371 wrapper_imports.push((
2372 wasm_init_async_task.into(),
2373 ExportKind::Func,
2374 init_async_idx,
2375 ));
2376
2377 for (name, func, _) in &funcs_to_wrap {
2379 let orig_idx =
2380 self.core_alias_export(Some(name), instance_index, name, ExportKind::Func);
2381 wrapper_imports.push((import_func_name(func), ExportKind::Func, orig_idx));
2382 }
2383
2384 let wrapper_args_idx = self.component.core_instantiate_exports(
2385 Some("init-task-wrappers-args"),
2386 wrapper_imports.iter().map(|(n, k, i)| (n.as_str(), *k, *i)),
2387 );
2388
2389 let wrapper_instance = self.component.core_instantiate(
2390 Some("init-task-wrappers-instance"),
2391 wrapper_module_idx,
2392 [("", ModuleArg::Instance(wrapper_args_idx))],
2393 );
2394
2395 for (name, _, _) in funcs_to_wrap {
2397 let wrapper_idx =
2398 self.core_alias_export(Some(&name), wrapper_instance, &name, ExportKind::Func);
2399 self.export_task_initialization_wrappers
2400 .insert(name.into(), wrapper_idx);
2401 }
2402
2403 Ok(())
2404 }
2405}
2406
2407#[derive(Default)]
2425struct Shims<'a> {
2426 shims: IndexMap<ShimKind<'a>, Shim<'a>>,
2428}
2429
2430struct Shim<'a> {
2431 options: RequiredOptions,
2434
2435 name: String,
2439
2440 debug_name: String,
2443
2444 kind: ShimKind<'a>,
2446
2447 sig: WasmSignature,
2449}
2450
2451#[derive(Debug, Clone, Hash, Eq, PartialEq)]
2454enum PayloadFuncKind {
2455 FutureWrite,
2456 FutureRead,
2457 StreamWrite,
2458 StreamRead,
2459}
2460
2461#[derive(Debug, Clone, Hash, Eq, PartialEq)]
2462enum ShimKind<'a> {
2463 IndirectLowering {
2467 interface: Option<String>,
2469 index: usize,
2471 realloc: CustomModule<'a>,
2473 encoding: StringEncoding,
2475 },
2476 Adapter {
2479 adapter: &'a str,
2481 func: &'a str,
2483 },
2484 ResourceDtor {
2487 module: CustomModule<'a>,
2489 export: &'a str,
2491 },
2492 PayloadFunc {
2496 for_module: CustomModule<'a>,
2499 info: &'a PayloadInfo,
2504 kind: PayloadFuncKind,
2506 },
2507 WaitableSetWait { cancellable: bool },
2511 WaitableSetPoll { cancellable: bool },
2515 TaskReturn {
2517 interface: Option<InterfaceId>,
2520 func: &'a str,
2523 result: Option<Type>,
2525 for_module: CustomModule<'a>,
2527 encoding: StringEncoding,
2529 },
2530 ErrorContextNew {
2534 encoding: StringEncoding,
2536 },
2537 ErrorContextDebugMessage {
2541 for_module: CustomModule<'a>,
2543 encoding: StringEncoding,
2545 },
2546 ThreadNewIndirect {
2549 for_module: CustomModule<'a>,
2551 func_ty: FuncType,
2553 },
2554}
2555
2556#[derive(Debug, Copy, Clone, Hash, Eq, PartialEq)]
2566enum CustomModule<'a> {
2567 Main,
2570 Adapter(&'a str),
2573}
2574
2575impl<'a> CustomModule<'a> {
2576 fn debug_name(&self) -> &'a str {
2577 match self {
2578 CustomModule::Main => "main",
2579 CustomModule::Adapter(s) => s,
2580 }
2581 }
2582}
2583
2584impl<'a> Shims<'a> {
2585 fn append_indirect(
2590 &mut self,
2591 world: &'a ComponentWorld<'a>,
2592 for_module: CustomModule<'a>,
2593 ) -> Result<()> {
2594 let module_imports = world.imports_for(for_module);
2595 let module_exports = world.exports_for(for_module);
2596 let resolve = &world.encoder.metadata.resolve;
2597
2598 for (module, field, import) in module_imports.imports() {
2599 match import {
2600 Import::ImportedResourceDrop(..)
2603 | Import::MainModuleMemory
2604 | Import::MainModuleExport { .. }
2605 | Import::Item(_)
2606 | Import::ExportedResourceDrop(..)
2607 | Import::ExportedResourceRep(..)
2608 | Import::ExportedResourceNew(..)
2609 | Import::ExportedTaskCancel
2610 | Import::ErrorContextDrop
2611 | Import::BackpressureInc
2612 | Import::BackpressureDec
2613 | Import::ThreadYield { .. }
2614 | Import::SubtaskDrop
2615 | Import::SubtaskCancel { .. }
2616 | Import::FutureNew(..)
2617 | Import::StreamNew(..)
2618 | Import::FutureCancelRead { .. }
2619 | Import::FutureCancelWrite { .. }
2620 | Import::FutureDropWritable { .. }
2621 | Import::FutureDropReadable { .. }
2622 | Import::StreamCancelRead { .. }
2623 | Import::StreamCancelWrite { .. }
2624 | Import::StreamDropWritable { .. }
2625 | Import::StreamDropReadable { .. }
2626 | Import::WaitableSetNew
2627 | Import::WaitableSetDrop
2628 | Import::WaitableJoin
2629 | Import::ContextGet(_)
2630 | Import::ContextSet(_)
2631 | Import::ThreadIndex
2632 | Import::ThreadSuspendToSuspended { .. }
2633 | Import::ThreadSuspend { .. }
2634 | Import::ThreadSuspendTo { .. }
2635 | Import::ThreadUnsuspend
2636 | Import::ThreadYieldToSuspended { .. } => {}
2637
2638 Import::ExportedTaskReturn(key, interface, func, ty) => {
2642 let (options, sig) = task_return_options_and_type(resolve, *ty);
2643 if options.is_empty() {
2644 continue;
2645 }
2646 let name = self.shims.len().to_string();
2647 let encoding = world
2648 .module_metadata_for(for_module)
2649 .export_encodings
2650 .get(resolve, key, func)
2651 .ok_or_else(|| {
2652 anyhow::anyhow!(
2653 "missing component metadata for export of \
2654 `{module}::{field}`"
2655 )
2656 })?;
2657 self.push(Shim {
2658 name,
2659 debug_name: format!("task-return-{func}"),
2660 options,
2661 kind: ShimKind::TaskReturn {
2662 interface: *interface,
2663 func,
2664 result: *ty,
2665 for_module,
2666 encoding,
2667 },
2668 sig,
2669 });
2670 }
2671
2672 Import::FutureWrite { async_, info } => {
2673 self.append_indirect_payload_push(
2674 resolve,
2675 for_module,
2676 module,
2677 *async_,
2678 info,
2679 PayloadFuncKind::FutureWrite,
2680 vec![WasmType::I32; 2],
2681 vec![WasmType::I32],
2682 );
2683 }
2684 Import::FutureRead { async_, info } => {
2685 self.append_indirect_payload_push(
2686 resolve,
2687 for_module,
2688 module,
2689 *async_,
2690 info,
2691 PayloadFuncKind::FutureRead,
2692 vec![WasmType::I32; 2],
2693 vec![WasmType::I32],
2694 );
2695 }
2696 Import::StreamWrite { async_, info } => {
2697 self.append_indirect_payload_push(
2698 resolve,
2699 for_module,
2700 module,
2701 *async_,
2702 info,
2703 PayloadFuncKind::StreamWrite,
2704 vec![WasmType::I32; 3],
2705 vec![WasmType::I32],
2706 );
2707 }
2708 Import::StreamRead { async_, info } => {
2709 self.append_indirect_payload_push(
2710 resolve,
2711 for_module,
2712 module,
2713 *async_,
2714 info,
2715 PayloadFuncKind::StreamRead,
2716 vec![WasmType::I32; 3],
2717 vec![WasmType::I32],
2718 );
2719 }
2720
2721 Import::WaitableSetWait { cancellable } => {
2722 let name = self.shims.len().to_string();
2723 self.push(Shim {
2724 name,
2725 debug_name: "waitable-set.wait".to_string(),
2726 options: RequiredOptions::empty(),
2727 kind: ShimKind::WaitableSetWait {
2728 cancellable: *cancellable,
2729 },
2730 sig: WasmSignature {
2731 params: vec![WasmType::I32; 2],
2732 results: vec![WasmType::I32],
2733 indirect_params: false,
2734 retptr: false,
2735 },
2736 });
2737 }
2738
2739 Import::WaitableSetPoll { cancellable } => {
2740 let name = self.shims.len().to_string();
2741 self.push(Shim {
2742 name,
2743 debug_name: "waitable-set.poll".to_string(),
2744 options: RequiredOptions::empty(),
2745 kind: ShimKind::WaitableSetPoll {
2746 cancellable: *cancellable,
2747 },
2748 sig: WasmSignature {
2749 params: vec![WasmType::I32; 2],
2750 results: vec![WasmType::I32],
2751 indirect_params: false,
2752 retptr: false,
2753 },
2754 });
2755 }
2756
2757 Import::ErrorContextNew { encoding } => {
2758 let name = self.shims.len().to_string();
2759 self.push(Shim {
2760 name,
2761 debug_name: "error-new".to_string(),
2762 options: RequiredOptions::MEMORY | RequiredOptions::STRING_ENCODING,
2763 kind: ShimKind::ErrorContextNew {
2764 encoding: *encoding,
2765 },
2766 sig: WasmSignature {
2767 params: vec![WasmType::I32; 2],
2768 results: vec![WasmType::I32],
2769 indirect_params: false,
2770 retptr: false,
2771 },
2772 });
2773 }
2774
2775 Import::ErrorContextDebugMessage { encoding } => {
2776 let name = self.shims.len().to_string();
2777 self.push(Shim {
2778 name,
2779 debug_name: "error-debug-message".to_string(),
2780 options: RequiredOptions::MEMORY
2781 | RequiredOptions::STRING_ENCODING
2782 | RequiredOptions::REALLOC,
2783 kind: ShimKind::ErrorContextDebugMessage {
2784 for_module,
2785 encoding: *encoding,
2786 },
2787 sig: WasmSignature {
2788 params: vec![WasmType::I32; 2],
2789 results: vec![],
2790 indirect_params: false,
2791 retptr: false,
2792 },
2793 });
2794 }
2795
2796 Import::ThreadNewIndirect => {
2797 let name = self.shims.len().to_string();
2798 self.push(Shim {
2799 name,
2800 debug_name: "thread.new-indirect".to_string(),
2801 options: RequiredOptions::empty(),
2802 kind: ShimKind::ThreadNewIndirect {
2803 for_module,
2804 func_ty: FuncType::new([ValType::I32], vec![]),
2806 },
2807 sig: WasmSignature {
2808 params: vec![WasmType::I32; 2],
2809 results: vec![WasmType::I32],
2810 indirect_params: false,
2811 retptr: false,
2812 },
2813 });
2814 }
2815
2816 Import::AdapterExport { adapter, func, ty } => {
2819 let name = self.shims.len().to_string();
2820 log::debug!("shim {name} is adapter `{module}::{field}`");
2821 self.push(Shim {
2822 name,
2823 debug_name: format!("adapt-{module}-{field}"),
2824 options: RequiredOptions::MEMORY,
2828 kind: ShimKind::Adapter { adapter, func },
2829 sig: WasmSignature {
2830 params: ty.params().iter().map(to_wasm_type).collect(),
2831 results: ty.results().iter().map(to_wasm_type).collect(),
2832 indirect_params: false,
2833 retptr: false,
2834 },
2835 });
2836
2837 fn to_wasm_type(ty: &wasmparser::ValType) -> WasmType {
2838 match ty {
2839 wasmparser::ValType::I32 => WasmType::I32,
2840 wasmparser::ValType::I64 => WasmType::I64,
2841 wasmparser::ValType::F32 => WasmType::F32,
2842 wasmparser::ValType::F64 => WasmType::F64,
2843 _ => unreachable!(),
2844 }
2845 }
2846 }
2847
2848 Import::InterfaceFunc(key, _, name, abi) => {
2852 self.append_indirect_wit_func(
2853 world,
2854 for_module,
2855 module,
2856 field,
2857 key,
2858 name,
2859 Some(resolve.name_world_key(key)),
2860 *abi,
2861 )?;
2862 }
2863 Import::WorldFunc(key, name, abi) => {
2864 self.append_indirect_wit_func(
2865 world, for_module, module, field, key, name, None, *abi,
2866 )?;
2867 }
2868 }
2869 }
2870
2871 for (export_name, export) in module_exports.iter() {
2877 let id = match export {
2878 Export::ResourceDtor(id) => id,
2879 _ => continue,
2880 };
2881 let resource = resolve.types[*id].name.as_ref().unwrap();
2882 let name = self.shims.len().to_string();
2883 self.push(Shim {
2884 name,
2885 debug_name: format!("dtor-{resource}"),
2886 options: RequiredOptions::empty(),
2887 kind: ShimKind::ResourceDtor {
2888 module: for_module,
2889 export: export_name,
2890 },
2891 sig: WasmSignature {
2892 params: vec![WasmType::I32],
2893 results: Vec::new(),
2894 indirect_params: false,
2895 retptr: false,
2896 },
2897 });
2898 }
2899
2900 Ok(())
2901 }
2902
2903 fn append_indirect_payload_push(
2906 &mut self,
2907 resolve: &Resolve,
2908 for_module: CustomModule<'a>,
2909 module: &str,
2910 async_: bool,
2911 info: &'a PayloadInfo,
2912 kind: PayloadFuncKind,
2913 params: Vec<WasmType>,
2914 results: Vec<WasmType>,
2915 ) {
2916 let debug_name = format!("{module}-{}", info.name);
2917 let name = self.shims.len().to_string();
2918
2919 let payload = info.payload(resolve);
2920 let (wit_param, wit_result) = match kind {
2921 PayloadFuncKind::StreamRead | PayloadFuncKind::FutureRead => (None, payload),
2922 PayloadFuncKind::StreamWrite | PayloadFuncKind::FutureWrite => (payload, None),
2923 };
2924 self.push(Shim {
2925 name,
2926 debug_name,
2927 options: RequiredOptions::MEMORY
2928 | RequiredOptions::for_import(
2929 resolve,
2930 &Function {
2931 name: String::new(),
2932 kind: FunctionKind::Freestanding,
2933 params: match wit_param {
2934 Some(ty) => vec![Param {
2935 name: "a".to_string(),
2936 ty,
2937 span: Default::default(),
2938 }],
2939 None => Vec::new(),
2940 },
2941 result: wit_result,
2942 docs: Default::default(),
2943 stability: Stability::Unknown,
2944 span: Default::default(),
2945 },
2946 if async_ {
2947 AbiVariant::GuestImportAsync
2948 } else {
2949 AbiVariant::GuestImport
2950 },
2951 ),
2952 kind: ShimKind::PayloadFunc {
2953 for_module,
2954 info,
2955 kind,
2956 },
2957 sig: WasmSignature {
2958 params,
2959 results,
2960 indirect_params: false,
2961 retptr: false,
2962 },
2963 });
2964 }
2965
2966 fn append_indirect_wit_func(
2969 &mut self,
2970 world: &'a ComponentWorld<'a>,
2971 for_module: CustomModule<'a>,
2972 module: &str,
2973 field: &str,
2974 key: &WorldKey,
2975 name: &String,
2976 interface_key: Option<String>,
2977 abi: AbiVariant,
2978 ) -> Result<()> {
2979 let resolve = &world.encoder.metadata.resolve;
2980 let metadata = world.module_metadata_for(for_module);
2981 let interface = &world.import_map[&interface_key];
2982 let (index, _, lowering) = interface.lowerings.get_full(&(name.clone(), abi)).unwrap();
2983 let shim_name = self.shims.len().to_string();
2984 match lowering {
2985 Lowering::Direct | Lowering::ResourceDrop(_) => {}
2986
2987 Lowering::Indirect { sig, options } => {
2988 log::debug!(
2989 "shim {shim_name} is import `{module}::{field}` lowering {index} `{name}`",
2990 );
2991 let encoding = metadata
2992 .import_encodings
2993 .get(resolve, key, name)
2994 .ok_or_else(|| {
2995 anyhow::anyhow!(
2996 "missing component metadata for import of \
2997 `{module}::{field}`"
2998 )
2999 })?;
3000 self.push(Shim {
3001 name: shim_name,
3002 debug_name: format!("indirect-{module}-{field}"),
3003 options: *options,
3004 kind: ShimKind::IndirectLowering {
3005 interface: interface_key,
3006 index,
3007 realloc: for_module,
3008 encoding,
3009 },
3010 sig: sig.clone(),
3011 });
3012 }
3013 }
3014
3015 Ok(())
3016 }
3017
3018 fn push(&mut self, shim: Shim<'a>) {
3019 if !self.shims.contains_key(&shim.kind) {
3023 self.shims.insert(shim.kind.clone(), shim);
3024 }
3025 }
3026}
3027
3028fn task_return_options_and_type(
3029 resolve: &Resolve,
3030 ty: Option<Type>,
3031) -> (RequiredOptions, WasmSignature) {
3032 let func_tmp = Function {
3033 name: String::new(),
3034 kind: FunctionKind::Freestanding,
3035 params: match ty {
3036 Some(ty) => vec![Param {
3037 name: "a".to_string(),
3038 ty,
3039 span: Default::default(),
3040 }],
3041 None => Vec::new(),
3042 },
3043 result: None,
3044 docs: Default::default(),
3045 stability: Stability::Unknown,
3046 span: Default::default(),
3047 };
3048 let abi = AbiVariant::GuestImport;
3049 let options = RequiredOptions::for_import(resolve, &func_tmp, abi);
3050 let sig = resolve.wasm_signature(abi, &func_tmp);
3051 (options, sig)
3052}
3053
3054#[derive(Clone, Debug)]
3056pub struct Item {
3057 pub alias: String,
3058 pub kind: ExportKind,
3059 pub which: MainOrAdapter,
3060 pub name: String,
3061}
3062
3063#[derive(Debug, PartialEq, Clone)]
3065pub enum MainOrAdapter {
3066 Main,
3067 Adapter(String),
3068}
3069
3070impl MainOrAdapter {
3071 fn to_custom_module(&self) -> CustomModule<'_> {
3072 match self {
3073 MainOrAdapter::Main => CustomModule::Main,
3074 MainOrAdapter::Adapter(s) => CustomModule::Adapter(s),
3075 }
3076 }
3077}
3078
3079#[derive(Clone)]
3081pub enum Instance {
3082 MainOrAdapter(MainOrAdapter),
3084
3085 Items(Vec<Item>),
3087}
3088
3089#[derive(Clone)]
3092pub struct LibraryInfo {
3093 pub instantiate_after_shims: bool,
3095
3096 pub arguments: Vec<(String, Instance)>,
3098}
3099
3100pub(super) struct Adapter {
3102 wasm: Vec<u8>,
3104
3105 metadata: ModuleMetadata,
3107
3108 required_exports: IndexSet<WorldKey>,
3111
3112 library_info: Option<LibraryInfo>,
3117}
3118
3119#[derive(Default)]
3121pub struct ComponentEncoder {
3122 module: Vec<u8>,
3123 module_import_map: Option<ModuleImportMap>,
3124 pub(super) metadata: Bindgen,
3125 validate: bool,
3126 pub(super) main_module_exports: IndexSet<WorldKey>,
3127 pub(super) adapters: IndexMap<String, Adapter>,
3128 import_name_map: HashMap<String, String>,
3129 realloc_via_memory_grow: bool,
3130 merge_imports_based_on_semver: Option<bool>,
3131 pub(super) reject_legacy_names: bool,
3132 debug_names: bool,
3133}
3134
3135impl ComponentEncoder {
3136 pub fn module(mut self, module: &[u8]) -> Result<Self> {
3142 let (wasm, metadata) = self.decode(module.as_ref())?;
3143 let (wasm, module_import_map) = ModuleImportMap::new(wasm)?;
3144 let exports = self
3145 .merge_metadata(metadata)
3146 .context("failed merge WIT metadata for module with previous metadata")?;
3147 self.main_module_exports.extend(exports);
3148 self.module = if let Some(producers) = &self.metadata.producers {
3149 producers.add_to_wasm(&wasm)?
3150 } else {
3151 wasm.to_vec()
3152 };
3153 self.module_import_map = module_import_map;
3154 Ok(self)
3155 }
3156
3157 fn decode<'a>(&self, wasm: &'a [u8]) -> Result<(Cow<'a, [u8]>, Bindgen)> {
3158 let (bytes, metadata) = metadata::decode(wasm)?;
3159 match bytes {
3160 Some(wasm) => Ok((Cow::Owned(wasm), metadata)),
3161 None => Ok((Cow::Borrowed(wasm), metadata)),
3162 }
3163 }
3164
3165 fn merge_metadata(&mut self, metadata: Bindgen) -> Result<IndexSet<WorldKey>> {
3166 self.metadata.merge(metadata)
3167 }
3168
3169 pub fn validate(mut self, validate: bool) -> Self {
3171 self.validate = validate;
3172 self
3173 }
3174
3175 pub fn debug_names(mut self, debug_names: bool) -> Self {
3177 self.debug_names = debug_names;
3178 self
3179 }
3180
3181 pub fn merge_imports_based_on_semver(mut self, merge: bool) -> Self {
3189 self.merge_imports_based_on_semver = Some(merge);
3190 self
3191 }
3192
3193 pub fn reject_legacy_names(mut self, reject: bool) -> Self {
3202 self.reject_legacy_names = reject;
3203 self
3204 }
3205
3206 pub fn adapter(self, name: &str, bytes: &[u8]) -> Result<Self> {
3224 self.library_or_adapter(name, bytes, None)
3225 }
3226
3227 pub fn library(self, name: &str, bytes: &[u8], library_info: LibraryInfo) -> Result<Self> {
3240 self.library_or_adapter(name, bytes, Some(library_info))
3241 }
3242
3243 fn library_or_adapter(
3244 mut self,
3245 name: &str,
3246 bytes: &[u8],
3247 library_info: Option<LibraryInfo>,
3248 ) -> Result<Self> {
3249 let (wasm, mut metadata) = self.decode(bytes)?;
3250 let adapter_metadata = mem::take(&mut metadata.metadata);
3258 let exports = self.merge_metadata(metadata).with_context(|| {
3259 format!("failed to merge WIT packages of adapter `{name}` into main packages")
3260 })?;
3261 if let Some(library_info) = &library_info {
3262 for (_, instance) in &library_info.arguments {
3264 let resolve = |which: &_| match which {
3265 MainOrAdapter::Main => Ok(()),
3266 MainOrAdapter::Adapter(name) => {
3267 if self.adapters.contains_key(name.as_str()) {
3268 Ok(())
3269 } else {
3270 Err(anyhow!("instance refers to unknown adapter `{name}`"))
3271 }
3272 }
3273 };
3274
3275 match instance {
3276 Instance::MainOrAdapter(which) => resolve(which)?,
3277 Instance::Items(items) => {
3278 for item in items {
3279 resolve(&item.which)?;
3280 }
3281 }
3282 }
3283 }
3284 }
3285 self.adapters.insert(
3286 name.to_string(),
3287 Adapter {
3288 wasm: wasm.to_vec(),
3289 metadata: adapter_metadata,
3290 required_exports: exports,
3291 library_info,
3292 },
3293 );
3294 Ok(self)
3295 }
3296
3297 pub fn realloc_via_memory_grow(mut self, value: bool) -> Self {
3302 self.realloc_via_memory_grow = value;
3303 self
3304 }
3305
3306 pub fn import_name_map(mut self, map: HashMap<String, String>) -> Self {
3317 self.import_name_map = map;
3318 self
3319 }
3320
3321 pub fn encode(&mut self) -> Result<Vec<u8>> {
3323 if self.module.is_empty() {
3324 bail!("a module is required when encoding a component");
3325 }
3326
3327 if self.merge_imports_based_on_semver.unwrap_or(true) {
3328 self.metadata
3329 .resolve
3330 .merge_world_imports_based_on_semver(self.metadata.world)?;
3331 }
3332
3333 let world = ComponentWorld::new(self).context("failed to decode world from module")?;
3334 let mut state = EncodingState {
3335 component: ComponentBuilder::default(),
3336 module_index: None,
3337 instance_index: None,
3338 memory_index: None,
3339 shim_instance_index: None,
3340 fixups_module_index: None,
3341 adapter_modules: IndexMap::new(),
3342 adapter_instances: IndexMap::new(),
3343 import_type_encoding_maps: Default::default(),
3344 export_type_encoding_maps: Default::default(),
3345 imported_instances: Default::default(),
3346 imported_funcs: Default::default(),
3347 exported_instances: Default::default(),
3348 aliased_core_items: Default::default(),
3349 info: &world,
3350 export_task_initialization_wrappers: HashMap::new(),
3351 };
3352 state.encode_imports(&self.import_name_map)?;
3353 state.encode_core_modules();
3354 state.encode_core_instantiation()?;
3355 state.encode_exports(CustomModule::Main)?;
3356 for name in self.adapters.keys() {
3357 state.encode_exports(CustomModule::Adapter(name))?;
3358 }
3359 state.component.append_names();
3360 state
3361 .component
3362 .raw_custom_section(&crate::base_producers().raw_custom_section());
3363 let bytes = state.component.finish();
3364
3365 if self.validate {
3366 Validator::new_with_features(WasmFeatures::all())
3367 .validate_all(&bytes)
3368 .context("failed to validate component output")?;
3369 }
3370
3371 Ok(bytes)
3372 }
3373}
3374
3375impl ComponentWorld<'_> {
3376 fn imports_for(&self, module: CustomModule) -> &ImportMap {
3378 match module {
3379 CustomModule::Main => &self.info.imports,
3380 CustomModule::Adapter(name) => &self.adapters[name].info.imports,
3381 }
3382 }
3383
3384 fn exports_for(&self, module: CustomModule) -> &ExportMap {
3386 match module {
3387 CustomModule::Main => &self.info.exports,
3388 CustomModule::Adapter(name) => &self.adapters[name].info.exports,
3389 }
3390 }
3391
3392 fn module_metadata_for(&self, module: CustomModule) -> &ModuleMetadata {
3394 match module {
3395 CustomModule::Main => &self.encoder.metadata.metadata,
3396 CustomModule::Adapter(name) => &self.encoder.adapters[name].metadata,
3397 }
3398 }
3399}
3400
3401#[cfg(all(test, feature = "dummy-module"))]
3402mod test {
3403 use super::*;
3404 use crate::{dummy_module, embed_component_metadata};
3405 use wit_parser::ManglingAndAbi;
3406
3407 #[test]
3408 fn it_renames_imports() {
3409 let mut resolve = Resolve::new();
3410 let pkg = resolve
3411 .push_str(
3412 "test.wit",
3413 r#"
3414package test:wit;
3415
3416interface i {
3417 f: func();
3418}
3419
3420world test {
3421 import i;
3422 import foo: interface {
3423 f: func();
3424 }
3425}
3426"#,
3427 )
3428 .unwrap();
3429 let world = resolve.select_world(&[pkg], None).unwrap();
3430
3431 let mut module = dummy_module(&resolve, world, ManglingAndAbi::Standard32);
3432
3433 embed_component_metadata(&mut module, &resolve, world, StringEncoding::UTF8).unwrap();
3434
3435 let encoded = ComponentEncoder::default()
3436 .import_name_map(HashMap::from([
3437 (
3438 "foo".to_string(),
3439 "unlocked-dep=<foo:bar/foo@{>=1.0.0 <1.1.0}>".to_string(),
3440 ),
3441 (
3442 "test:wit/i".to_string(),
3443 "locked-dep=<foo:bar/i@1.2.3>".to_string(),
3444 ),
3445 ]))
3446 .module(&module)
3447 .unwrap()
3448 .validate(true)
3449 .encode()
3450 .unwrap();
3451
3452 let wat = wasmprinter::print_bytes(encoded).unwrap();
3453 assert!(wat.contains("unlocked-dep=<foo:bar/foo@{>=1.0.0 <1.1.0}>"));
3454 assert!(wat.contains("locked-dep=<foo:bar/i@1.2.3>"));
3455 }
3456}