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