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, Resolve, Stability, Type, TypeDefKind, TypeId,
89 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
119bitflags::bitflags! {
120 #[derive(Copy, Clone, Debug)]
123 pub struct RequiredOptions: u8 {
124 const MEMORY = 1 << 0;
127 const REALLOC = 1 << 1;
130 const STRING_ENCODING = 1 << 2;
133 const ASYNC = 1 << 3;
134 }
135}
136
137impl RequiredOptions {
138 fn for_import(resolve: &Resolve, func: &Function, abi: AbiVariant) -> RequiredOptions {
139 let sig = resolve.wasm_signature(abi, func);
140 let mut ret = RequiredOptions::empty();
141 ret.add_lift(TypeContents::for_types(
143 resolve,
144 func.params.iter().map(|(_, t)| t),
145 ));
146 ret.add_lower(TypeContents::for_types(resolve, &func.result));
147
148 if sig.retptr || sig.indirect_params {
151 ret |= RequiredOptions::MEMORY;
152 }
153 if abi == AbiVariant::GuestImportAsync {
154 ret |= RequiredOptions::ASYNC;
155 }
156 ret
157 }
158
159 fn for_export(resolve: &Resolve, func: &Function, abi: AbiVariant) -> RequiredOptions {
160 let sig = resolve.wasm_signature(abi, func);
161 let mut ret = RequiredOptions::empty();
162 ret.add_lower(TypeContents::for_types(
164 resolve,
165 func.params.iter().map(|(_, t)| t),
166 ));
167 ret.add_lift(TypeContents::for_types(resolve, &func.result));
168
169 if sig.retptr || sig.indirect_params {
173 ret |= RequiredOptions::MEMORY;
174 if sig.indirect_params {
175 ret |= RequiredOptions::REALLOC;
176 }
177 }
178 if let AbiVariant::GuestExportAsync | AbiVariant::GuestExportAsyncStackful = abi {
179 ret |= RequiredOptions::ASYNC;
180 ret |= task_return_options_and_type(resolve, func.result).0;
181 }
182 ret
183 }
184
185 fn add_lower(&mut self, types: TypeContents) {
186 if types.contains(TypeContents::NEEDS_MEMORY) {
190 *self |= RequiredOptions::MEMORY | RequiredOptions::REALLOC;
191 }
192 if types.contains(TypeContents::STRING) {
193 *self |= RequiredOptions::MEMORY
194 | RequiredOptions::STRING_ENCODING
195 | RequiredOptions::REALLOC;
196 }
197 }
198
199 fn add_lift(&mut self, types: TypeContents) {
200 if types.contains(TypeContents::NEEDS_MEMORY) {
204 *self |= RequiredOptions::MEMORY;
205 }
206 if types.contains(TypeContents::STRING) {
207 *self |= RequiredOptions::MEMORY | RequiredOptions::STRING_ENCODING;
208 }
209 }
210
211 fn into_iter(
212 self,
213 encoding: StringEncoding,
214 memory_index: Option<u32>,
215 realloc_index: Option<u32>,
216 ) -> Result<impl ExactSizeIterator<Item = CanonicalOption>> {
217 #[derive(Default)]
218 struct Iter {
219 options: [Option<CanonicalOption>; 5],
220 current: usize,
221 count: usize,
222 }
223
224 impl Iter {
225 fn push(&mut self, option: CanonicalOption) {
226 assert!(self.count < self.options.len());
227 self.options[self.count] = Some(option);
228 self.count += 1;
229 }
230 }
231
232 impl Iterator for Iter {
233 type Item = CanonicalOption;
234
235 fn next(&mut self) -> Option<Self::Item> {
236 if self.current == self.count {
237 return None;
238 }
239 let option = self.options[self.current];
240 self.current += 1;
241 option
242 }
243
244 fn size_hint(&self) -> (usize, Option<usize>) {
245 (self.count - self.current, Some(self.count - self.current))
246 }
247 }
248
249 impl ExactSizeIterator for Iter {}
250
251 let mut iter = Iter::default();
252
253 if self.contains(RequiredOptions::MEMORY) {
254 iter.push(CanonicalOption::Memory(memory_index.ok_or_else(|| {
255 anyhow!("module does not export a memory named `memory`")
256 })?));
257 }
258
259 if self.contains(RequiredOptions::REALLOC) {
260 iter.push(CanonicalOption::Realloc(realloc_index.ok_or_else(
261 || anyhow!("module does not export a function named `cabi_realloc`"),
262 )?));
263 }
264
265 if self.contains(RequiredOptions::STRING_ENCODING) {
266 iter.push(encoding.into());
267 }
268
269 if self.contains(RequiredOptions::ASYNC) {
270 iter.push(CanonicalOption::Async);
271 }
272
273 Ok(iter)
274 }
275}
276
277bitflags::bitflags! {
278 struct TypeContents: u8 {
281 const STRING = 1 << 0;
282 const NEEDS_MEMORY = 1 << 1;
283 }
284}
285
286impl TypeContents {
287 fn for_types<'a>(resolve: &Resolve, types: impl IntoIterator<Item = &'a Type>) -> Self {
288 let mut cur = TypeContents::empty();
289 for ty in types {
290 cur |= Self::for_type(resolve, ty);
291 }
292 cur
293 }
294
295 fn for_optional_types<'a>(
296 resolve: &Resolve,
297 types: impl Iterator<Item = Option<&'a Type>>,
298 ) -> Self {
299 Self::for_types(resolve, types.flatten())
300 }
301
302 fn for_optional_type(resolve: &Resolve, ty: Option<&Type>) -> Self {
303 match ty {
304 Some(ty) => Self::for_type(resolve, ty),
305 None => Self::empty(),
306 }
307 }
308
309 fn for_type(resolve: &Resolve, ty: &Type) -> Self {
310 match ty {
311 Type::Id(id) => match &resolve.types[*id].kind {
312 TypeDefKind::Handle(h) => match h {
313 wit_parser::Handle::Own(_) => Self::empty(),
314 wit_parser::Handle::Borrow(_) => Self::empty(),
315 },
316 TypeDefKind::Resource => Self::empty(),
317 TypeDefKind::Record(r) => Self::for_types(resolve, r.fields.iter().map(|f| &f.ty)),
318 TypeDefKind::Tuple(t) => Self::for_types(resolve, t.types.iter()),
319 TypeDefKind::Flags(_) => Self::empty(),
320 TypeDefKind::Option(t) => Self::for_type(resolve, t),
321 TypeDefKind::Result(r) => {
322 Self::for_optional_type(resolve, r.ok.as_ref())
323 | Self::for_optional_type(resolve, r.err.as_ref())
324 }
325 TypeDefKind::Variant(v) => {
326 Self::for_optional_types(resolve, v.cases.iter().map(|c| c.ty.as_ref()))
327 }
328 TypeDefKind::Enum(_) => Self::empty(),
329 TypeDefKind::List(t) => Self::for_type(resolve, t) | Self::NEEDS_MEMORY,
330 TypeDefKind::Map(k, v) => {
331 Self::for_type(resolve, k) | Self::for_type(resolve, v) | Self::NEEDS_MEMORY
332 }
333 TypeDefKind::FixedSizeList(t, _elements) => Self::for_type(resolve, t),
334 TypeDefKind::Type(t) => Self::for_type(resolve, t),
335 TypeDefKind::Future(_) => Self::empty(),
336 TypeDefKind::Stream(_) => Self::empty(),
337 TypeDefKind::Unknown => unreachable!(),
338 },
339 Type::String => Self::STRING,
340 _ => Self::empty(),
341 }
342 }
343}
344
345pub struct EncodingState<'a> {
347 component: ComponentBuilder,
349 module_index: Option<u32>,
353 instance_index: Option<u32>,
357 memory_index: Option<u32>,
361 shim_instance_index: Option<u32>,
365 fixups_module_index: Option<u32>,
369
370 adapter_modules: IndexMap<&'a str, u32>,
373 adapter_instances: IndexMap<&'a str, u32>,
375
376 imported_instances: IndexMap<InterfaceId, u32>,
378 imported_funcs: IndexMap<String, u32>,
379 exported_instances: IndexMap<InterfaceId, u32>,
380
381 import_type_encoding_maps: TypeEncodingMaps<'a>,
386 export_type_encoding_maps: TypeEncodingMaps<'a>,
387
388 aliased_core_items: HashMap<(u32, String), u32>,
394
395 info: &'a ComponentWorld<'a>,
397}
398
399impl<'a> EncodingState<'a> {
400 fn encode_core_modules(&mut self) {
401 assert!(self.module_index.is_none());
402 let idx = self
403 .component
404 .core_module_raw(Some("main"), &self.info.encoder.module);
405 self.module_index = Some(idx);
406
407 for (name, adapter) in self.info.adapters.iter() {
408 let debug_name = if adapter.library_info.is_some() {
409 name.to_string()
410 } else {
411 format!("wit-component:adapter:{name}")
412 };
413 let idx = if self.info.encoder.debug_names {
414 let mut add_meta = wasm_metadata::AddMetadata::default();
415 add_meta.name = AddMetadataField::Set(debug_name.clone());
416 let wasm = add_meta
417 .to_wasm(&adapter.wasm)
418 .expect("core wasm can get name added");
419 self.component.core_module_raw(Some(&debug_name), &wasm)
420 } else {
421 self.component
422 .core_module_raw(Some(&debug_name), &adapter.wasm)
423 };
424 let prev = self.adapter_modules.insert(name, idx);
425 assert!(prev.is_none());
426 }
427 }
428
429 fn root_import_type_encoder(
430 &mut self,
431 interface: Option<InterfaceId>,
432 ) -> RootTypeEncoder<'_, 'a> {
433 RootTypeEncoder {
434 state: self,
435 interface,
436 import_types: true,
437 }
438 }
439
440 fn root_export_type_encoder(
441 &mut self,
442 interface: Option<InterfaceId>,
443 ) -> RootTypeEncoder<'_, 'a> {
444 RootTypeEncoder {
445 state: self,
446 interface,
447 import_types: false,
448 }
449 }
450
451 fn instance_type_encoder(&mut self, interface: InterfaceId) -> InstanceTypeEncoder<'_, 'a> {
452 InstanceTypeEncoder {
453 state: self,
454 interface,
455 type_encoding_maps: Default::default(),
456 ty: Default::default(),
457 }
458 }
459
460 fn encode_imports(&mut self, name_map: &HashMap<String, String>) -> Result<()> {
461 let mut has_funcs = false;
462 for (name, info) in self.info.import_map.iter() {
463 match name {
464 Some(name) => {
465 self.encode_interface_import(name_map.get(name).unwrap_or(name), info)?
466 }
467 None => has_funcs = true,
468 }
469 }
470
471 let resolve = &self.info.encoder.metadata.resolve;
472 let world = &resolve.worlds[self.info.encoder.metadata.world];
473
474 for (_name, item) in world.imports.iter() {
477 if let WorldItem::Type(ty) = item {
478 self.root_import_type_encoder(None)
479 .encode_valtype(resolve, &Type::Id(*ty))?;
480 }
481 }
482
483 if has_funcs {
484 let info = &self.info.import_map[&None];
485 self.encode_root_import_funcs(info)?;
486 }
487 Ok(())
488 }
489
490 fn encode_interface_import(&mut self, name: &str, info: &ImportedInterface) -> Result<()> {
491 let resolve = &self.info.encoder.metadata.resolve;
492 let interface_id = info.interface.as_ref().unwrap();
493 let interface_id = *interface_id;
494 let interface = &resolve.interfaces[interface_id];
495 log::trace!("encoding imports for `{name}` as {interface_id:?}");
496 let mut encoder = self.instance_type_encoder(interface_id);
497
498 if let Some(live) = encoder.state.info.live_type_imports.get(&interface_id) {
500 for ty in live {
501 log::trace!(
502 "encoding extra type {ty:?} name={:?}",
503 resolve.types[*ty].name
504 );
505 encoder.encode_valtype(resolve, &Type::Id(*ty))?;
506 }
507 }
508
509 for (_, func) in interface.functions.iter() {
512 if !(info
513 .lowerings
514 .contains_key(&(func.name.clone(), AbiVariant::GuestImport))
515 || info
516 .lowerings
517 .contains_key(&(func.name.clone(), AbiVariant::GuestImportAsync)))
518 {
519 continue;
520 }
521 log::trace!("encoding function type for `{}`", func.name);
522 let idx = encoder.encode_func_type(resolve, func)?;
523
524 encoder.ty.export(&func.name, ComponentTypeRef::Func(idx));
525 }
526
527 let ty = encoder.ty;
528 if ty.is_empty() {
531 return Ok(());
532 }
533 let instance_type_idx = self
534 .component
535 .type_instance(Some(&format!("ty-{name}")), &ty);
536 let instance_idx = self
537 .component
538 .import(name, ComponentTypeRef::Instance(instance_type_idx));
539 let prev = self.imported_instances.insert(interface_id, instance_idx);
540 assert!(prev.is_none());
541 Ok(())
542 }
543
544 fn encode_root_import_funcs(&mut self, info: &ImportedInterface) -> Result<()> {
545 let resolve = &self.info.encoder.metadata.resolve;
546 let world = self.info.encoder.metadata.world;
547 for (name, item) in resolve.worlds[world].imports.iter() {
548 let func = match item {
549 WorldItem::Function(f) => f,
550 WorldItem::Interface { .. } | WorldItem::Type(_) => continue,
551 };
552 let name = resolve.name_world_key(name);
553 if !(info
554 .lowerings
555 .contains_key(&(name.clone(), AbiVariant::GuestImport))
556 || info
557 .lowerings
558 .contains_key(&(name.clone(), AbiVariant::GuestImportAsync)))
559 {
560 continue;
561 }
562 log::trace!("encoding function type for `{}`", func.name);
563 let idx = self
564 .root_import_type_encoder(None)
565 .encode_func_type(resolve, func)?;
566 let func_idx = self.component.import(&name, ComponentTypeRef::Func(idx));
567 let prev = self.imported_funcs.insert(name, func_idx);
568 assert!(prev.is_none());
569 }
570 Ok(())
571 }
572
573 fn alias_imported_type(&mut self, interface: InterfaceId, id: TypeId) -> u32 {
574 let ty = &self.info.encoder.metadata.resolve.types[id];
575 let name = ty.name.as_ref().expect("type must have a name");
576 let instance = self.imported_instances[&interface];
577 self.component
578 .alias_export(instance, name, ComponentExportKind::Type)
579 }
580
581 fn alias_exported_type(&mut self, interface: InterfaceId, id: TypeId) -> u32 {
582 let ty = &self.info.encoder.metadata.resolve.types[id];
583 let name = ty.name.as_ref().expect("type must have a name");
584 let instance = self.exported_instances[&interface];
585 self.component
586 .alias_export(instance, name, ComponentExportKind::Type)
587 }
588
589 fn encode_core_instantiation(&mut self) -> Result<()> {
590 let shims = self.encode_shim_instantiation()?;
592
593 self.declare_types_for_imported_intrinsics(&shims)?;
597
598 self.instantiate_main_module(&shims)?;
602
603 let (before, after) = self
606 .info
607 .adapters
608 .iter()
609 .partition::<Vec<_>, _>(|(_, adapter)| {
610 !matches!(
611 adapter.library_info,
612 Some(LibraryInfo {
613 instantiate_after_shims: true,
614 ..
615 })
616 )
617 });
618
619 for (name, _adapter) in before {
620 self.instantiate_adapter_module(&shims, name)?;
621 }
622
623 self.encode_indirect_lowerings(&shims)?;
626
627 for (name, _adapter) in after {
628 self.instantiate_adapter_module(&shims, name)?;
629 }
630
631 self.encode_initialize_with_start()?;
632
633 Ok(())
634 }
635
636 fn lookup_resource_index(&mut self, id: TypeId) -> u32 {
637 let resolve = &self.info.encoder.metadata.resolve;
638 let ty = &resolve.types[id];
639 match ty.owner {
640 TypeOwner::World(_) => self.import_type_encoding_maps.id_to_index[&id],
644 TypeOwner::Interface(i) => {
645 let instance = self.imported_instances[&i];
646 let name = ty.name.as_ref().expect("resources must be named");
647 self.component
648 .alias_export(instance, name, ComponentExportKind::Type)
649 }
650 TypeOwner::None => panic!("resources must have an owner"),
651 }
652 }
653
654 fn encode_exports(&mut self, module: CustomModule) -> Result<()> {
655 let resolve = &self.info.encoder.metadata.resolve;
656 let exports = match module {
657 CustomModule::Main => &self.info.encoder.main_module_exports,
658 CustomModule::Adapter(name) => &self.info.encoder.adapters[name].required_exports,
659 };
660
661 if exports.is_empty() {
662 return Ok(());
663 }
664
665 let mut interface_func_core_names = IndexMap::new();
666 let mut world_func_core_names = IndexMap::new();
667 for (core_name, export) in self.info.exports_for(module).iter() {
668 match export {
669 Export::WorldFunc(_, name, _) => {
670 let prev = world_func_core_names.insert(name, core_name);
671 assert!(prev.is_none());
672 }
673 Export::InterfaceFunc(_, id, name, _) => {
674 let prev = interface_func_core_names
675 .entry(id)
676 .or_insert(IndexMap::new())
677 .insert(name.as_str(), core_name);
678 assert!(prev.is_none());
679 }
680 Export::WorldFuncCallback(..)
681 | Export::InterfaceFuncCallback(..)
682 | Export::WorldFuncPostReturn(..)
683 | Export::InterfaceFuncPostReturn(..)
684 | Export::ResourceDtor(..)
685 | Export::Memory
686 | Export::GeneralPurposeRealloc
687 | Export::GeneralPurposeExportRealloc
688 | Export::GeneralPurposeImportRealloc
689 | Export::Initialize
690 | Export::ReallocForAdapter
691 | Export::IndirectFunctionTable => continue,
692 }
693 }
694
695 let world = &resolve.worlds[self.info.encoder.metadata.world];
696
697 for export_name in exports {
698 let export_string = resolve.name_world_key(export_name);
699 match &world.exports[export_name] {
700 WorldItem::Function(func) => {
701 let ty = self
702 .root_import_type_encoder(None)
703 .encode_func_type(resolve, func)?;
704 let core_name = world_func_core_names[&func.name];
705 let idx = self.encode_lift(module, &core_name, export_name, func, ty)?;
706 self.component
707 .export(&export_string, ComponentExportKind::Func, idx, None);
708 }
709 WorldItem::Interface { id, .. } => {
710 let core_names = interface_func_core_names.get(id);
711 self.encode_interface_export(
712 &export_string,
713 module,
714 export_name,
715 *id,
716 core_names,
717 )?;
718 }
719 WorldItem::Type(_) => unreachable!(),
720 }
721 }
722
723 Ok(())
724 }
725
726 fn encode_interface_export(
727 &mut self,
728 export_name: &str,
729 module: CustomModule<'_>,
730 key: &WorldKey,
731 export: InterfaceId,
732 interface_func_core_names: Option<&IndexMap<&str, &str>>,
733 ) -> Result<()> {
734 log::trace!("encode interface export `{export_name}`");
735 let resolve = &self.info.encoder.metadata.resolve;
736
737 let mut imports = Vec::new();
744 let mut root = self.root_export_type_encoder(Some(export));
745 for (_, func) in &resolve.interfaces[export].functions {
746 let core_name = interface_func_core_names.unwrap()[func.name.as_str()];
747 let ty = root.encode_func_type(resolve, func)?;
748 let func_index = root.state.encode_lift(module, &core_name, key, func, ty)?;
749 imports.push((
750 import_func_name(func),
751 ComponentExportKind::Func,
752 func_index,
753 ));
754 }
755
756 let mut nested = NestedComponentTypeEncoder {
760 component: ComponentBuilder::default(),
761 type_encoding_maps: Default::default(),
762 export_types: false,
763 interface: export,
764 state: self,
765 imports: IndexMap::new(),
766 };
767
768 let mut types_to_import = LiveTypes::default();
778 types_to_import.add_interface(resolve, export);
779 let exports_used = &nested.state.info.exports_used[&export];
780 for ty in types_to_import.iter() {
781 if let TypeOwner::Interface(owner) = resolve.types[ty].owner {
782 if owner == export {
783 continue;
786 }
787
788 let mut encoder = if exports_used.contains(&owner) {
791 nested.state.root_export_type_encoder(Some(export))
792 } else {
793 nested.state.root_import_type_encoder(Some(export))
794 };
795 encoder.encode_valtype(resolve, &Type::Id(ty))?;
796
797 nested.interface = owner;
801 nested.encode_valtype(resolve, &Type::Id(ty))?;
802 }
803 }
804 nested.interface = export;
805
806 let imported_type_maps = nested.type_encoding_maps.clone();
810
811 let mut resources = HashMap::new();
817 for (_name, ty) in resolve.interfaces[export].types.iter() {
818 if !matches!(resolve.types[*ty].kind, TypeDefKind::Resource) {
819 continue;
820 }
821 let idx = match nested.encode_valtype(resolve, &Type::Id(*ty))? {
822 ComponentValType::Type(idx) => idx,
823 _ => unreachable!(),
824 };
825 resources.insert(*ty, idx);
826 }
827
828 for (_, func) in resolve.interfaces[export].functions.iter() {
832 let ty = nested.encode_func_type(resolve, func)?;
833 nested
834 .component
835 .import(&import_func_name(func), ComponentTypeRef::Func(ty));
836 }
837
838 let reverse_map = nested
845 .type_encoding_maps
846 .id_to_index
847 .drain()
848 .map(|p| (p.1, p.0))
849 .collect::<HashMap<_, _>>();
850 nested.type_encoding_maps.def_to_index.clear();
851 for (name, idx) in nested.imports.drain(..) {
852 let id = reverse_map[&idx];
853 let owner = match resolve.types[id].owner {
854 TypeOwner::Interface(id) => id,
855 _ => unreachable!(),
856 };
857 let idx = if owner == export || exports_used.contains(&owner) {
858 log::trace!("consulting exports for {id:?}");
859 nested.state.export_type_encoding_maps.id_to_index[&id]
860 } else {
861 log::trace!("consulting imports for {id:?}");
862 nested.state.import_type_encoding_maps.id_to_index[&id]
863 };
864 imports.push((name, ComponentExportKind::Type, idx))
865 }
866
867 nested.type_encoding_maps = imported_type_maps;
872
873 nested.export_types = true;
880 nested.type_encoding_maps.func_type_map.clear();
881
882 for (_, id) in resolve.interfaces[export].types.iter() {
888 let ty = &resolve.types[*id];
889 match ty.kind {
890 TypeDefKind::Resource => {
891 let idx = nested.component.export(
892 ty.name.as_ref().expect("resources must be named"),
893 ComponentExportKind::Type,
894 resources[id],
895 None,
896 );
897 nested.type_encoding_maps.id_to_index.insert(*id, idx);
898 }
899 _ => {
900 nested.encode_valtype(resolve, &Type::Id(*id))?;
901 }
902 }
903 }
904
905 for (i, (_, func)) in resolve.interfaces[export].functions.iter().enumerate() {
906 let ty = nested.encode_func_type(resolve, func)?;
907 nested.component.export(
908 &func.name,
909 ComponentExportKind::Func,
910 i as u32,
911 Some(ComponentTypeRef::Func(ty)),
912 );
913 }
914
915 let component = nested.component;
919 let component_index = self
920 .component
921 .component(Some(&format!("{export_name}-shim-component")), component);
922 let instance_index = self.component.instantiate(
923 Some(&format!("{export_name}-shim-instance")),
924 component_index,
925 imports,
926 );
927 let idx = self.component.export(
928 export_name,
929 ComponentExportKind::Instance,
930 instance_index,
931 None,
932 );
933 let prev = self.exported_instances.insert(export, idx);
934 assert!(prev.is_none());
935
936 for (_name, id) in resolve.interfaces[export].types.iter() {
944 self.export_type_encoding_maps.id_to_index.remove(id);
945 self.export_type_encoding_maps
946 .def_to_index
947 .remove(&resolve.types[*id].kind);
948 }
949
950 return Ok(());
951
952 struct NestedComponentTypeEncoder<'state, 'a> {
953 component: ComponentBuilder,
954 type_encoding_maps: TypeEncodingMaps<'a>,
955 export_types: bool,
956 interface: InterfaceId,
957 state: &'state mut EncodingState<'a>,
958 imports: IndexMap<String, u32>,
959 }
960
961 impl<'a> ValtypeEncoder<'a> for NestedComponentTypeEncoder<'_, 'a> {
962 fn defined_type(&mut self) -> (u32, ComponentDefinedTypeEncoder<'_>) {
963 self.component.type_defined(None)
964 }
965 fn define_function_type(&mut self) -> (u32, ComponentFuncTypeEncoder<'_>) {
966 self.component.type_function(None)
967 }
968 fn export_type(&mut self, idx: u32, name: &'a str) -> Option<u32> {
969 if self.export_types {
970 Some(
971 self.component
972 .export(name, ComponentExportKind::Type, idx, None),
973 )
974 } else {
975 let name = self.unique_import_name(name);
976 let ret = self
977 .component
978 .import(&name, ComponentTypeRef::Type(TypeBounds::Eq(idx)));
979 self.imports.insert(name, ret);
980 Some(ret)
981 }
982 }
983 fn export_resource(&mut self, name: &'a str) -> u32 {
984 if self.export_types {
985 panic!("resources should already be exported")
986 } else {
987 let name = self.unique_import_name(name);
988 let ret = self
989 .component
990 .import(&name, ComponentTypeRef::Type(TypeBounds::SubResource));
991 self.imports.insert(name, ret);
992 ret
993 }
994 }
995 fn import_type(&mut self, _: InterfaceId, _id: TypeId) -> u32 {
996 unreachable!()
997 }
998 fn type_encoding_maps(&mut self) -> &mut TypeEncodingMaps<'a> {
999 &mut self.type_encoding_maps
1000 }
1001 fn interface(&self) -> Option<InterfaceId> {
1002 Some(self.interface)
1003 }
1004 }
1005
1006 impl NestedComponentTypeEncoder<'_, '_> {
1007 fn unique_import_name(&mut self, name: &str) -> String {
1008 let mut name = format!("import-type-{name}");
1009 let mut n = 0;
1010 while self.imports.contains_key(&name) {
1011 name = format!("{name}{n}");
1012 n += 1;
1013 }
1014 name
1015 }
1016 }
1017
1018 fn import_func_name(f: &Function) -> String {
1019 match f.kind {
1020 FunctionKind::Freestanding | FunctionKind::AsyncFreestanding => {
1021 format!("import-func-{}", f.item_name())
1022 }
1023
1024 FunctionKind::Method(_)
1032 | FunctionKind::AsyncMethod(_)
1033 | FunctionKind::Static(_)
1034 | FunctionKind::AsyncStatic(_)
1035 | FunctionKind::Constructor(_) => {
1036 format!(
1037 "import-{}",
1038 f.name.replace('[', "").replace([']', '.', ' '], "-")
1039 )
1040 }
1041 }
1042 }
1043 }
1044
1045 fn encode_lift(
1046 &mut self,
1047 module: CustomModule<'_>,
1048 core_name: &str,
1049 key: &WorldKey,
1050 func: &Function,
1051 ty: u32,
1052 ) -> Result<u32> {
1053 let resolve = &self.info.encoder.metadata.resolve;
1054 let metadata = self.info.module_metadata_for(module);
1055 let instance_index = self.instance_for(module);
1056 let core_func_index =
1057 self.core_alias_export(Some(core_name), instance_index, core_name, ExportKind::Func);
1058 let exports = self.info.exports_for(module);
1059
1060 let options = RequiredOptions::for_export(
1061 resolve,
1062 func,
1063 exports
1064 .abi(key, func)
1065 .ok_or_else(|| anyhow!("no ABI found for {}", func.name))?,
1066 );
1067
1068 let encoding = metadata
1069 .export_encodings
1070 .get(resolve, key, &func.name)
1071 .unwrap();
1072 let exports = self.info.exports_for(module);
1073 let realloc_index = exports
1074 .export_realloc_for(key, &func.name)
1075 .map(|name| self.core_alias_export(Some(name), instance_index, name, ExportKind::Func));
1076 let mut options = options
1077 .into_iter(encoding, self.memory_index, realloc_index)?
1078 .collect::<Vec<_>>();
1079
1080 if let Some(post_return) = exports.post_return(key, func) {
1081 let post_return = self.core_alias_export(
1082 Some(post_return),
1083 instance_index,
1084 post_return,
1085 ExportKind::Func,
1086 );
1087 options.push(CanonicalOption::PostReturn(post_return));
1088 }
1089 if let Some(callback) = exports.callback(key, func) {
1090 let callback =
1091 self.core_alias_export(Some(callback), instance_index, callback, ExportKind::Func);
1092 options.push(CanonicalOption::Callback(callback));
1093 }
1094 let func_index = self
1095 .component
1096 .lift_func(Some(&func.name), core_func_index, ty, options);
1097 Ok(func_index)
1098 }
1099
1100 fn encode_shim_instantiation(&mut self) -> Result<Shims<'a>> {
1101 let mut ret = Shims::default();
1102
1103 ret.append_indirect(self.info, CustomModule::Main)
1104 .context("failed to register indirect shims for main module")?;
1105
1106 for (adapter_name, _adapter) in self.info.adapters.iter() {
1110 ret.append_indirect(self.info, CustomModule::Adapter(adapter_name))
1111 .with_context(|| {
1112 format!("failed to register indirect shims for adapter {adapter_name}")
1113 })?;
1114 }
1115
1116 if ret.shims.is_empty() {
1117 return Ok(ret);
1118 }
1119
1120 assert!(self.shim_instance_index.is_none());
1121 assert!(self.fixups_module_index.is_none());
1122
1123 let mut types = TypeSection::new();
1132 let mut tables = TableSection::new();
1133 let mut functions = FunctionSection::new();
1134 let mut exports = ExportSection::new();
1135 let mut code = CodeSection::new();
1136 let mut sigs = IndexMap::new();
1137 let mut imports_section = ImportSection::new();
1138 let mut elements = ElementSection::new();
1139 let mut func_indexes = Vec::new();
1140 let mut func_names = NameMap::new();
1141
1142 for (i, shim) in ret.shims.values().enumerate() {
1143 let i = i as u32;
1144 let type_index = *sigs.entry(&shim.sig).or_insert_with(|| {
1145 let index = types.len();
1146 types.ty().function(
1147 shim.sig.params.iter().map(to_val_type),
1148 shim.sig.results.iter().map(to_val_type),
1149 );
1150 index
1151 });
1152
1153 functions.function(type_index);
1154 Self::encode_shim_function(type_index, i, &mut code, shim.sig.params.len() as u32);
1155 exports.export(&shim.name, ExportKind::Func, i);
1156
1157 imports_section.import("", &shim.name, EntityType::Function(type_index));
1158 func_indexes.push(i);
1159 func_names.append(i, &shim.debug_name);
1160 }
1161 let mut names = NameSection::new();
1162 names.module("wit-component:shim");
1163 names.functions(&func_names);
1164
1165 let table_type = TableType {
1166 element_type: RefType::FUNCREF,
1167 minimum: ret.shims.len() as u64,
1168 maximum: Some(ret.shims.len() as u64),
1169 table64: false,
1170 shared: false,
1171 };
1172
1173 tables.table(table_type);
1174
1175 exports.export(INDIRECT_TABLE_NAME, ExportKind::Table, 0);
1176 imports_section.import("", INDIRECT_TABLE_NAME, table_type);
1177
1178 elements.active(
1179 None,
1180 &ConstExpr::i32_const(0),
1181 Elements::Functions(func_indexes.into()),
1182 );
1183
1184 let mut shim = Module::new();
1185 shim.section(&types);
1186 shim.section(&functions);
1187 shim.section(&tables);
1188 shim.section(&exports);
1189 shim.section(&code);
1190 shim.section(&RawCustomSection(
1191 &crate::base_producers().raw_custom_section(),
1192 ));
1193 if self.info.encoder.debug_names {
1194 shim.section(&names);
1195 }
1196
1197 let mut fixups = Module::default();
1198 fixups.section(&types);
1199 fixups.section(&imports_section);
1200 fixups.section(&elements);
1201 fixups.section(&RawCustomSection(
1202 &crate::base_producers().raw_custom_section(),
1203 ));
1204
1205 if self.info.encoder.debug_names {
1206 let mut names = NameSection::new();
1207 names.module("wit-component:fixups");
1208 fixups.section(&names);
1209 }
1210
1211 let shim_module_index = self
1212 .component
1213 .core_module(Some("wit-component-shim-module"), &shim);
1214 let fixup_index = self
1215 .component
1216 .core_module(Some("wit-component-fixup"), &fixups);
1217 self.fixups_module_index = Some(fixup_index);
1218 let shim_instance = self.component.core_instantiate(
1219 Some("wit-component-shim-instance"),
1220 shim_module_index,
1221 [],
1222 );
1223 self.shim_instance_index = Some(shim_instance);
1224
1225 return Ok(ret);
1226 }
1227
1228 fn encode_shim_function(
1229 type_index: u32,
1230 func_index: u32,
1231 code: &mut CodeSection,
1232 param_count: u32,
1233 ) {
1234 let mut func = wasm_encoder::Function::new(std::iter::empty());
1235 for i in 0..param_count {
1236 func.instructions().local_get(i);
1237 }
1238 func.instructions().i32_const(func_index as i32);
1239 func.instructions().call_indirect(0, type_index);
1240 func.instructions().end();
1241 code.function(&func);
1242 }
1243
1244 fn encode_indirect_lowerings(&mut self, shims: &Shims<'_>) -> Result<()> {
1245 if shims.shims.is_empty() {
1246 return Ok(());
1247 }
1248
1249 let shim_instance_index = self
1250 .shim_instance_index
1251 .expect("must have an instantiated shim");
1252
1253 let table_index = self.core_alias_export(
1254 Some("shim table"),
1255 shim_instance_index,
1256 INDIRECT_TABLE_NAME,
1257 ExportKind::Table,
1258 );
1259
1260 let resolve = &self.info.encoder.metadata.resolve;
1261
1262 let mut exports = Vec::new();
1263 exports.push((INDIRECT_TABLE_NAME, ExportKind::Table, table_index));
1264
1265 for shim in shims.shims.values() {
1266 let core_func_index = match &shim.kind {
1267 ShimKind::IndirectLowering {
1274 interface,
1275 index,
1276 realloc,
1277 encoding,
1278 } => {
1279 let interface = &self.info.import_map[interface];
1280 let ((name, _), _) = interface.lowerings.get_index(*index).unwrap();
1281 let func_index = match &interface.interface {
1282 Some(interface_id) => {
1283 let instance_index = self.imported_instances[interface_id];
1284 self.component.alias_export(
1285 instance_index,
1286 name,
1287 ComponentExportKind::Func,
1288 )
1289 }
1290 None => self.imported_funcs[name],
1291 };
1292
1293 let realloc = self
1294 .info
1295 .exports_for(*realloc)
1296 .import_realloc_for(interface.interface, name)
1297 .map(|name| {
1298 let instance = self.instance_for(*realloc);
1299 self.core_alias_export(
1300 Some("realloc"),
1301 instance,
1302 name,
1303 ExportKind::Func,
1304 )
1305 });
1306
1307 self.component.lower_func(
1308 Some(&shim.debug_name),
1309 func_index,
1310 shim.options
1311 .into_iter(*encoding, self.memory_index, realloc)?,
1312 )
1313 }
1314
1315 ShimKind::Adapter { adapter, func } => self.core_alias_export(
1320 Some(func),
1321 self.adapter_instances[adapter],
1322 func,
1323 ExportKind::Func,
1324 ),
1325
1326 ShimKind::ResourceDtor { module, export } => self.core_alias_export(
1331 Some(export),
1332 self.instance_for(*module),
1333 export,
1334 ExportKind::Func,
1335 ),
1336
1337 ShimKind::PayloadFunc {
1338 for_module,
1339 info,
1340 kind,
1341 } => {
1342 let metadata = self.info.module_metadata_for(*for_module);
1343 let exports = self.info.exports_for(*for_module);
1344 let instance_index = self.instance_for(*for_module);
1345 let (encoding, realloc) = match &info.ty {
1346 PayloadType::Type { function, .. } => {
1347 if info.imported {
1348 (
1349 metadata.import_encodings.get(resolve, &info.key, function),
1350 exports.import_realloc_for(info.interface, function),
1351 )
1352 } else {
1353 (
1354 metadata.export_encodings.get(resolve, &info.key, function),
1355 exports.export_realloc_for(&info.key, function),
1356 )
1357 }
1358 }
1359 PayloadType::UnitFuture | PayloadType::UnitStream => (None, None),
1360 };
1361 let encoding = encoding.unwrap_or(StringEncoding::UTF8);
1362 let realloc_index = realloc.map(|name| {
1363 self.core_alias_export(
1364 Some("realloc"),
1365 instance_index,
1366 name,
1367 ExportKind::Func,
1368 )
1369 });
1370 let type_index = self.payload_type_index(info)?;
1371 let options =
1372 shim.options
1373 .into_iter(encoding, self.memory_index, realloc_index)?;
1374
1375 match kind {
1376 PayloadFuncKind::FutureWrite => {
1377 self.component.future_write(type_index, options)
1378 }
1379 PayloadFuncKind::FutureRead => {
1380 self.component.future_read(type_index, options)
1381 }
1382 PayloadFuncKind::StreamWrite => {
1383 self.component.stream_write(type_index, options)
1384 }
1385 PayloadFuncKind::StreamRead => {
1386 self.component.stream_read(type_index, options)
1387 }
1388 }
1389 }
1390
1391 ShimKind::WaitableSetWait { cancellable } => self
1392 .component
1393 .waitable_set_wait(*cancellable, self.memory_index.unwrap()),
1394 ShimKind::WaitableSetPoll { cancellable } => self
1395 .component
1396 .waitable_set_poll(*cancellable, self.memory_index.unwrap()),
1397 ShimKind::ErrorContextNew { encoding } => self.component.error_context_new(
1398 shim.options.into_iter(*encoding, self.memory_index, None)?,
1399 ),
1400 ShimKind::ErrorContextDebugMessage {
1401 for_module,
1402 encoding,
1403 } => {
1404 let instance_index = self.instance_for(*for_module);
1405 let realloc = self.info.exports_for(*for_module).import_realloc_fallback();
1406 let realloc_index = realloc.map(|r| {
1407 self.core_alias_export(Some("realloc"), instance_index, r, ExportKind::Func)
1408 });
1409
1410 self.component
1411 .error_context_debug_message(shim.options.into_iter(
1412 *encoding,
1413 self.memory_index,
1414 realloc_index,
1415 )?)
1416 }
1417 ShimKind::TaskReturn {
1418 interface,
1419 func,
1420 result,
1421 encoding,
1422 for_module,
1423 } => {
1424 let mut encoder = if interface.is_none() {
1427 self.root_import_type_encoder(*interface)
1428 } else {
1429 self.root_export_type_encoder(*interface)
1430 };
1431 let result = match result {
1432 Some(ty) => Some(encoder.encode_valtype(resolve, ty)?),
1433 None => None,
1434 };
1435
1436 let exports = self.info.exports_for(*for_module);
1437 let realloc = exports.import_realloc_for(*interface, func);
1438
1439 let instance_index = self.instance_for(*for_module);
1440 let realloc_index = realloc.map(|r| {
1441 self.core_alias_export(Some("realloc"), instance_index, r, ExportKind::Func)
1442 });
1443 let options =
1444 shim.options
1445 .into_iter(*encoding, self.memory_index, realloc_index)?;
1446 self.component.task_return(result, options)
1447 }
1448 ShimKind::ThreadNewIndirect {
1449 for_module,
1450 func_ty,
1451 } => {
1452 let (func_ty_idx, f) = self.component.core_type(Some("thread-start"));
1454 f.core().func_type(func_ty);
1455
1456 let exports = self.info.exports_for(*for_module);
1459 let instance_index = self.instance_for(*for_module);
1460 let table_idx = exports.indirect_function_table().map(|table| {
1461 self.core_alias_export(
1462 Some("indirect-function-table"),
1463 instance_index,
1464 table,
1465 ExportKind::Table,
1466 )
1467 }).ok_or_else(|| {
1468 anyhow!(
1469 "table __indirect_function_table must be an exported funcref table for thread.new-indirect"
1470 )
1471 })?;
1472
1473 self.component.thread_new_indirect(func_ty_idx, table_idx)
1474 }
1475 };
1476
1477 exports.push((shim.name.as_str(), ExportKind::Func, core_func_index));
1478 }
1479
1480 let instance_index = self
1481 .component
1482 .core_instantiate_exports(Some("fixup-args"), exports);
1483 self.component.core_instantiate(
1484 Some("fixup"),
1485 self.fixups_module_index.expect("must have fixup module"),
1486 [("", ModuleArg::Instance(instance_index))],
1487 );
1488 Ok(())
1489 }
1490
1491 fn payload_type_index(&mut self, info: &PayloadInfo) -> Result<u32> {
1499 let resolve = &self.info.encoder.metadata.resolve;
1500 let mut encoder = if info.imported || info.interface.is_none() {
1516 self.root_import_type_encoder(None)
1517 } else {
1518 self.root_export_type_encoder(info.interface)
1519 };
1520 match info.ty {
1521 PayloadType::Type { id, .. } => match encoder.encode_valtype(resolve, &Type::Id(id))? {
1522 ComponentValType::Type(index) => Ok(index),
1523 ComponentValType::Primitive(_) => unreachable!(),
1524 },
1525 PayloadType::UnitFuture => Ok(encoder.encode_unit_future()),
1526 PayloadType::UnitStream => Ok(encoder.encode_unit_stream()),
1527 }
1528 }
1529
1530 fn declare_types_for_imported_intrinsics(&mut self, shims: &Shims<'_>) -> Result<()> {
1537 let resolve = &self.info.encoder.metadata.resolve;
1538 let world = &resolve.worlds[self.info.encoder.metadata.world];
1539
1540 let main_module_keys = self.info.encoder.main_module_exports.iter();
1543 let main_module_keys = main_module_keys.map(|key| (CustomModule::Main, key));
1544 let adapter_keys = self.info.encoder.adapters.iter().flat_map(|(name, info)| {
1545 info.required_exports
1546 .iter()
1547 .map(move |key| (CustomModule::Adapter(name), key))
1548 });
1549 for (for_module, key) in main_module_keys.chain(adapter_keys) {
1550 let id = match &world.exports[key] {
1551 WorldItem::Interface { id, .. } => *id,
1552 WorldItem::Type { .. } => unreachable!(),
1553 WorldItem::Function(_) => continue,
1554 };
1555
1556 for ty in resolve.interfaces[id].types.values() {
1557 let def = &resolve.types[*ty];
1558 match &def.kind {
1559 TypeDefKind::Resource => {
1563 let exports = self.info.exports_for(for_module);
1566 let dtor = exports.resource_dtor(*ty).map(|name| {
1567 let shim = &shims.shims[&ShimKind::ResourceDtor {
1568 module: for_module,
1569 export: name,
1570 }];
1571 let index = self.shim_instance_index.unwrap();
1572 self.core_alias_export(
1573 Some(&shim.debug_name),
1574 index,
1575 &shim.name,
1576 ExportKind::Func,
1577 )
1578 });
1579
1580 let resource_idx = self.component.type_resource(
1584 Some(def.name.as_ref().unwrap()),
1585 ValType::I32,
1586 dtor,
1587 );
1588 let prev = self
1589 .export_type_encoding_maps
1590 .id_to_index
1591 .insert(*ty, resource_idx);
1592 assert!(prev.is_none());
1593 }
1594 _other => {
1595 self.root_export_type_encoder(Some(id))
1596 .encode_valtype(resolve, &Type::Id(*ty))?;
1597 }
1598 }
1599 }
1600 }
1601 Ok(())
1602 }
1603
1604 fn instantiate_main_module(&mut self, shims: &Shims<'_>) -> Result<()> {
1607 assert!(self.instance_index.is_none());
1608
1609 let instance_index = self.instantiate_core_module(shims, CustomModule::Main)?;
1610
1611 if let Some(memory) = self.info.info.exports.memory() {
1612 self.memory_index = Some(self.core_alias_export(
1613 Some("memory"),
1614 instance_index,
1615 memory,
1616 ExportKind::Memory,
1617 ));
1618 }
1619
1620 self.instance_index = Some(instance_index);
1621 Ok(())
1622 }
1623
1624 fn instantiate_adapter_module(&mut self, shims: &Shims<'_>, name: &'a str) -> Result<()> {
1627 let instance = self.instantiate_core_module(shims, CustomModule::Adapter(name))?;
1628 self.adapter_instances.insert(name, instance);
1629 Ok(())
1630 }
1631
1632 fn instantiate_core_module(
1639 &mut self,
1640 shims: &Shims,
1641 for_module: CustomModule<'_>,
1642 ) -> Result<u32> {
1643 let module = self.module_for(for_module);
1644
1645 let mut args = Vec::new();
1646 for (core_wasm_name, instance) in self.info.imports_for(for_module).modules() {
1647 match instance {
1648 ImportInstance::Names(names) => {
1654 let mut exports = Vec::new();
1655 for (name, import) in names {
1656 log::trace!(
1657 "attempting to materialize import of `{core_wasm_name}::{name}` for {for_module:?}"
1658 );
1659 let (kind, index) = self
1660 .materialize_import(&shims, for_module, import)
1661 .with_context(|| {
1662 format!("failed to satisfy import `{core_wasm_name}::{name}`")
1663 })?;
1664 exports.push((name.as_str(), kind, index));
1665 }
1666 let index = self
1667 .component
1668 .core_instantiate_exports(Some(core_wasm_name), exports);
1669 args.push((core_wasm_name.as_str(), ModuleArg::Instance(index)));
1670 }
1671
1672 ImportInstance::Whole(which) => {
1675 let instance = self.instance_for(which.to_custom_module());
1676 args.push((core_wasm_name.as_str(), ModuleArg::Instance(instance)));
1677 }
1678 }
1679 }
1680
1681 Ok(self
1683 .component
1684 .core_instantiate(Some(for_module.debug_name()), module, args))
1685 }
1686
1687 fn materialize_import(
1694 &mut self,
1695 shims: &Shims<'_>,
1696 for_module: CustomModule<'_>,
1697 import: &'a Import,
1698 ) -> Result<(ExportKind, u32)> {
1699 let resolve = &self.info.encoder.metadata.resolve;
1700 match import {
1701 Import::AdapterExport {
1704 adapter,
1705 func,
1706 ty: _,
1707 } => {
1708 assert!(self.info.encoder.adapters.contains_key(adapter));
1709 Ok(self.materialize_shim_import(shims, &ShimKind::Adapter { adapter, func }))
1710 }
1711
1712 Import::MainModuleMemory => {
1715 let index = self
1716 .memory_index
1717 .ok_or_else(|| anyhow!("main module cannot import memory"))?;
1718 Ok((ExportKind::Memory, index))
1719 }
1720
1721 Import::MainModuleExport { name, kind } => {
1723 let instance = self.instance_index.unwrap();
1724 let index = self.core_alias_export(Some(name), instance, name, *kind);
1725 Ok((*kind, index))
1726 }
1727
1728 Import::Item(item) => {
1732 let instance = self.instance_for(item.which.to_custom_module());
1733 let index =
1734 self.core_alias_export(Some(&item.name), instance, &item.name, item.kind);
1735 Ok((item.kind, index))
1736 }
1737
1738 Import::ExportedResourceDrop(_key, id) => {
1744 let index = self
1745 .component
1746 .resource_drop(self.export_type_encoding_maps.id_to_index[id]);
1747 Ok((ExportKind::Func, index))
1748 }
1749 Import::ExportedResourceRep(_key, id) => {
1750 let index = self
1751 .component
1752 .resource_rep(self.export_type_encoding_maps.id_to_index[id]);
1753 Ok((ExportKind::Func, index))
1754 }
1755 Import::ExportedResourceNew(_key, id) => {
1756 let index = self
1757 .component
1758 .resource_new(self.export_type_encoding_maps.id_to_index[id]);
1759 Ok((ExportKind::Func, index))
1760 }
1761
1762 Import::ImportedResourceDrop(key, iface, id) => {
1767 let ty = &resolve.types[*id];
1768 let name = ty.name.as_ref().unwrap();
1769 self.materialize_wit_import(
1770 shims,
1771 for_module,
1772 iface.map(|_| resolve.name_world_key(key)),
1773 &format!("{name}_drop"),
1774 key,
1775 AbiVariant::GuestImport,
1776 )
1777 }
1778 Import::ExportedTaskReturn(key, interface, func, result) => {
1779 let (options, _sig) = task_return_options_and_type(resolve, *result);
1780 if options.is_empty() {
1781 let mut encoder = if interface.is_none() {
1787 self.root_import_type_encoder(*interface)
1788 } else {
1789 self.root_export_type_encoder(*interface)
1790 };
1791
1792 let result = match result {
1793 Some(ty) => Some(encoder.encode_valtype(resolve, ty)?),
1794 None => None,
1795 };
1796 let index = self.component.task_return(result, []);
1797 Ok((ExportKind::Func, index))
1798 } else {
1799 let metadata = &self.info.module_metadata_for(for_module);
1800 let encoding = metadata.export_encodings.get(resolve, key, func).unwrap();
1801 Ok(self.materialize_shim_import(
1802 shims,
1803 &ShimKind::TaskReturn {
1804 for_module,
1805 interface: *interface,
1806 func,
1807 result: *result,
1808 encoding,
1809 },
1810 ))
1811 }
1812 }
1813 Import::BackpressureInc => {
1814 let index = self.component.backpressure_inc();
1815 Ok((ExportKind::Func, index))
1816 }
1817 Import::BackpressureDec => {
1818 let index = self.component.backpressure_dec();
1819 Ok((ExportKind::Func, index))
1820 }
1821 Import::WaitableSetWait { cancellable } => Ok(self.materialize_shim_import(
1822 shims,
1823 &ShimKind::WaitableSetWait {
1824 cancellable: *cancellable,
1825 },
1826 )),
1827 Import::WaitableSetPoll { cancellable } => Ok(self.materialize_shim_import(
1828 shims,
1829 &ShimKind::WaitableSetPoll {
1830 cancellable: *cancellable,
1831 },
1832 )),
1833 Import::ThreadYield { cancellable } => {
1834 let index = self.component.thread_yield(*cancellable);
1835 Ok((ExportKind::Func, index))
1836 }
1837 Import::SubtaskDrop => {
1838 let index = self.component.subtask_drop();
1839 Ok((ExportKind::Func, index))
1840 }
1841 Import::SubtaskCancel { async_ } => {
1842 let index = self.component.subtask_cancel(*async_);
1843 Ok((ExportKind::Func, index))
1844 }
1845 Import::StreamNew(info) => {
1846 let ty = self.payload_type_index(info)?;
1847 let index = self.component.stream_new(ty);
1848 Ok((ExportKind::Func, index))
1849 }
1850 Import::StreamRead { info, .. } => Ok(self.materialize_payload_import(
1851 shims,
1852 for_module,
1853 info,
1854 PayloadFuncKind::StreamRead,
1855 )),
1856 Import::StreamWrite { info, .. } => Ok(self.materialize_payload_import(
1857 shims,
1858 for_module,
1859 info,
1860 PayloadFuncKind::StreamWrite,
1861 )),
1862 Import::StreamCancelRead { info, async_ } => {
1863 let ty = self.payload_type_index(info)?;
1864 let index = self.component.stream_cancel_read(ty, *async_);
1865 Ok((ExportKind::Func, index))
1866 }
1867 Import::StreamCancelWrite { info, async_ } => {
1868 let ty = self.payload_type_index(info)?;
1869 let index = self.component.stream_cancel_write(ty, *async_);
1870 Ok((ExportKind::Func, index))
1871 }
1872 Import::StreamDropReadable(info) => {
1873 let type_index = self.payload_type_index(info)?;
1874 let index = self.component.stream_drop_readable(type_index);
1875 Ok((ExportKind::Func, index))
1876 }
1877 Import::StreamDropWritable(info) => {
1878 let type_index = self.payload_type_index(info)?;
1879 let index = self.component.stream_drop_writable(type_index);
1880 Ok((ExportKind::Func, index))
1881 }
1882 Import::FutureNew(info) => {
1883 let ty = self.payload_type_index(info)?;
1884 let index = self.component.future_new(ty);
1885 Ok((ExportKind::Func, index))
1886 }
1887 Import::FutureRead { info, .. } => Ok(self.materialize_payload_import(
1888 shims,
1889 for_module,
1890 info,
1891 PayloadFuncKind::FutureRead,
1892 )),
1893 Import::FutureWrite { info, .. } => Ok(self.materialize_payload_import(
1894 shims,
1895 for_module,
1896 info,
1897 PayloadFuncKind::FutureWrite,
1898 )),
1899 Import::FutureCancelRead { info, async_ } => {
1900 let ty = self.payload_type_index(info)?;
1901 let index = self.component.future_cancel_read(ty, *async_);
1902 Ok((ExportKind::Func, index))
1903 }
1904 Import::FutureCancelWrite { info, async_ } => {
1905 let ty = self.payload_type_index(info)?;
1906 let index = self.component.future_cancel_write(ty, *async_);
1907 Ok((ExportKind::Func, index))
1908 }
1909 Import::FutureDropReadable(info) => {
1910 let type_index = self.payload_type_index(info)?;
1911 let index = self.component.future_drop_readable(type_index);
1912 Ok((ExportKind::Func, index))
1913 }
1914 Import::FutureDropWritable(info) => {
1915 let type_index = self.payload_type_index(info)?;
1916 let index = self.component.future_drop_writable(type_index);
1917 Ok((ExportKind::Func, index))
1918 }
1919 Import::ErrorContextNew { encoding } => Ok(self.materialize_shim_import(
1920 shims,
1921 &ShimKind::ErrorContextNew {
1922 encoding: *encoding,
1923 },
1924 )),
1925 Import::ErrorContextDebugMessage { encoding } => Ok(self.materialize_shim_import(
1926 shims,
1927 &ShimKind::ErrorContextDebugMessage {
1928 for_module,
1929 encoding: *encoding,
1930 },
1931 )),
1932 Import::ErrorContextDrop => {
1933 let index = self.component.error_context_drop();
1934 Ok((ExportKind::Func, index))
1935 }
1936 Import::WorldFunc(key, name, abi) => {
1937 self.materialize_wit_import(shims, for_module, None, name, key, *abi)
1938 }
1939 Import::InterfaceFunc(key, _, name, abi) => self.materialize_wit_import(
1940 shims,
1941 for_module,
1942 Some(resolve.name_world_key(key)),
1943 name,
1944 key,
1945 *abi,
1946 ),
1947
1948 Import::WaitableSetNew => {
1949 let index = self.component.waitable_set_new();
1950 Ok((ExportKind::Func, index))
1951 }
1952 Import::WaitableSetDrop => {
1953 let index = self.component.waitable_set_drop();
1954 Ok((ExportKind::Func, index))
1955 }
1956 Import::WaitableJoin => {
1957 let index = self.component.waitable_join();
1958 Ok((ExportKind::Func, index))
1959 }
1960 Import::ContextGet(n) => {
1961 let index = self.component.context_get(*n);
1962 Ok((ExportKind::Func, index))
1963 }
1964 Import::ContextSet(n) => {
1965 let index = self.component.context_set(*n);
1966 Ok((ExportKind::Func, index))
1967 }
1968 Import::ExportedTaskCancel => {
1969 let index = self.component.task_cancel();
1970 Ok((ExportKind::Func, index))
1971 }
1972 Import::ThreadIndex => {
1973 let index = self.component.thread_index();
1974 Ok((ExportKind::Func, index))
1975 }
1976 Import::ThreadNewIndirect => Ok(self.materialize_shim_import(
1977 shims,
1978 &ShimKind::ThreadNewIndirect {
1979 for_module,
1980 func_ty: FuncType::new([ValType::I32], []),
1982 },
1983 )),
1984 Import::ThreadSwitchTo { cancellable } => {
1985 let index = self.component.thread_switch_to(*cancellable);
1986 Ok((ExportKind::Func, index))
1987 }
1988 Import::ThreadSuspend { cancellable } => {
1989 let index = self.component.thread_suspend(*cancellable);
1990 Ok((ExportKind::Func, index))
1991 }
1992 Import::ThreadResumeLater => {
1993 let index = self.component.thread_resume_later();
1994 Ok((ExportKind::Func, index))
1995 }
1996 Import::ThreadYieldTo { cancellable } => {
1997 let index = self.component.thread_yield_to(*cancellable);
1998 Ok((ExportKind::Func, index))
1999 }
2000 }
2001 }
2002
2003 fn materialize_shim_import(&mut self, shims: &Shims<'_>, kind: &ShimKind) -> (ExportKind, u32) {
2006 let index = self.core_alias_export(
2007 Some(&shims.shims[kind].debug_name),
2008 self.shim_instance_index
2009 .expect("shim should be instantiated"),
2010 &shims.shims[kind].name,
2011 ExportKind::Func,
2012 );
2013 (ExportKind::Func, index)
2014 }
2015
2016 fn materialize_payload_import(
2019 &mut self,
2020 shims: &Shims<'_>,
2021 for_module: CustomModule<'_>,
2022 info: &PayloadInfo,
2023 kind: PayloadFuncKind,
2024 ) -> (ExportKind, u32) {
2025 self.materialize_shim_import(
2026 shims,
2027 &ShimKind::PayloadFunc {
2028 for_module,
2029 info,
2030 kind,
2031 },
2032 )
2033 }
2034
2035 fn materialize_wit_import(
2038 &mut self,
2039 shims: &Shims<'_>,
2040 for_module: CustomModule<'_>,
2041 interface_key: Option<String>,
2042 name: &String,
2043 key: &WorldKey,
2044 abi: AbiVariant,
2045 ) -> Result<(ExportKind, u32)> {
2046 let resolve = &self.info.encoder.metadata.resolve;
2047 let import = &self.info.import_map[&interface_key];
2048 let (index, _, lowering) = import.lowerings.get_full(&(name.clone(), abi)).unwrap();
2049 let metadata = self.info.module_metadata_for(for_module);
2050
2051 let index = match lowering {
2052 Lowering::Direct => {
2055 let func_index = match &import.interface {
2056 Some(interface) => {
2057 let instance_index = self.imported_instances[interface];
2058 self.component
2059 .alias_export(instance_index, name, ComponentExportKind::Func)
2060 }
2061 None => self.imported_funcs[name],
2062 };
2063 self.component.lower_func(
2064 Some(name),
2065 func_index,
2066 if let AbiVariant::GuestImportAsync = abi {
2067 vec![CanonicalOption::Async]
2068 } else {
2069 Vec::new()
2070 },
2071 )
2072 }
2073
2074 Lowering::Indirect { .. } => {
2078 let encoding = metadata.import_encodings.get(resolve, key, name).unwrap();
2079 return Ok(self.materialize_shim_import(
2080 shims,
2081 &ShimKind::IndirectLowering {
2082 interface: interface_key,
2083 index,
2084 realloc: for_module,
2085 encoding,
2086 },
2087 ));
2088 }
2089
2090 Lowering::ResourceDrop(id) => {
2093 let resource_idx = self.lookup_resource_index(*id);
2094 self.component.resource_drop(resource_idx)
2095 }
2096 };
2097 Ok((ExportKind::Func, index))
2098 }
2099
2100 fn encode_initialize_with_start(&mut self) -> Result<()> {
2119 let initialize = match self.info.info.exports.initialize() {
2120 Some(name) => name,
2121 None => return Ok(()),
2124 };
2125 let initialize_index = self.core_alias_export(
2126 Some("start"),
2127 self.instance_index.unwrap(),
2128 initialize,
2129 ExportKind::Func,
2130 );
2131 let mut shim = Module::default();
2132 let mut section = TypeSection::new();
2133 section.ty().function([], []);
2134 shim.section(§ion);
2135 let mut section = ImportSection::new();
2136 section.import("", "", EntityType::Function(0));
2137 shim.section(§ion);
2138 shim.section(&StartSection { function_index: 0 });
2139
2140 let shim_module_index = self.component.core_module(Some("start-shim-module"), &shim);
2145 let shim_args_instance_index = self.component.core_instantiate_exports(
2146 Some("start-shim-args"),
2147 [("", ExportKind::Func, initialize_index)],
2148 );
2149 self.component.core_instantiate(
2150 Some("start-shim-instance"),
2151 shim_module_index,
2152 [("", ModuleArg::Instance(shim_args_instance_index))],
2153 );
2154 Ok(())
2155 }
2156
2157 fn instance_for(&self, module: CustomModule) -> u32 {
2160 match module {
2161 CustomModule::Main => self.instance_index.expect("instantiated by now"),
2162 CustomModule::Adapter(name) => self.adapter_instances[name],
2163 }
2164 }
2165
2166 fn module_for(&self, module: CustomModule) -> u32 {
2169 match module {
2170 CustomModule::Main => self.module_index.unwrap(),
2171 CustomModule::Adapter(name) => self.adapter_modules[name],
2172 }
2173 }
2174
2175 fn core_alias_export(
2178 &mut self,
2179 debug_name: Option<&str>,
2180 instance: u32,
2181 name: &str,
2182 kind: ExportKind,
2183 ) -> u32 {
2184 *self
2185 .aliased_core_items
2186 .entry((instance, name.to_string()))
2187 .or_insert_with(|| {
2188 self.component
2189 .core_alias_export(debug_name, instance, name, kind)
2190 })
2191 }
2192}
2193
2194#[derive(Default)]
2212struct Shims<'a> {
2213 shims: IndexMap<ShimKind<'a>, Shim<'a>>,
2215}
2216
2217struct Shim<'a> {
2218 options: RequiredOptions,
2221
2222 name: String,
2226
2227 debug_name: String,
2230
2231 kind: ShimKind<'a>,
2233
2234 sig: WasmSignature,
2236}
2237
2238#[derive(Debug, Clone, Hash, Eq, PartialEq)]
2241enum PayloadFuncKind {
2242 FutureWrite,
2243 FutureRead,
2244 StreamWrite,
2245 StreamRead,
2246}
2247
2248#[derive(Debug, Clone, Hash, Eq, PartialEq)]
2249enum ShimKind<'a> {
2250 IndirectLowering {
2254 interface: Option<String>,
2256 index: usize,
2258 realloc: CustomModule<'a>,
2260 encoding: StringEncoding,
2262 },
2263 Adapter {
2266 adapter: &'a str,
2268 func: &'a str,
2270 },
2271 ResourceDtor {
2274 module: CustomModule<'a>,
2276 export: &'a str,
2278 },
2279 PayloadFunc {
2283 for_module: CustomModule<'a>,
2286 info: &'a PayloadInfo,
2291 kind: PayloadFuncKind,
2293 },
2294 WaitableSetWait { cancellable: bool },
2298 WaitableSetPoll { cancellable: bool },
2302 TaskReturn {
2304 interface: Option<InterfaceId>,
2307 func: &'a str,
2310 result: Option<Type>,
2312 for_module: CustomModule<'a>,
2314 encoding: StringEncoding,
2316 },
2317 ErrorContextNew {
2321 encoding: StringEncoding,
2323 },
2324 ErrorContextDebugMessage {
2328 for_module: CustomModule<'a>,
2330 encoding: StringEncoding,
2332 },
2333 ThreadNewIndirect {
2336 for_module: CustomModule<'a>,
2338 func_ty: FuncType,
2340 },
2341}
2342
2343#[derive(Debug, Copy, Clone, Hash, Eq, PartialEq)]
2353enum CustomModule<'a> {
2354 Main,
2357 Adapter(&'a str),
2360}
2361
2362impl<'a> CustomModule<'a> {
2363 fn debug_name(&self) -> &'a str {
2364 match self {
2365 CustomModule::Main => "main",
2366 CustomModule::Adapter(s) => s,
2367 }
2368 }
2369}
2370
2371impl<'a> Shims<'a> {
2372 fn append_indirect(
2377 &mut self,
2378 world: &'a ComponentWorld<'a>,
2379 for_module: CustomModule<'a>,
2380 ) -> Result<()> {
2381 let module_imports = world.imports_for(for_module);
2382 let module_exports = world.exports_for(for_module);
2383 let resolve = &world.encoder.metadata.resolve;
2384
2385 for (module, field, import) in module_imports.imports() {
2386 match import {
2387 Import::ImportedResourceDrop(..)
2390 | Import::MainModuleMemory
2391 | Import::MainModuleExport { .. }
2392 | Import::Item(_)
2393 | Import::ExportedResourceDrop(..)
2394 | Import::ExportedResourceRep(..)
2395 | Import::ExportedResourceNew(..)
2396 | Import::ExportedTaskCancel
2397 | Import::ErrorContextDrop
2398 | Import::BackpressureInc
2399 | Import::BackpressureDec
2400 | Import::ThreadYield { .. }
2401 | Import::SubtaskDrop
2402 | Import::SubtaskCancel { .. }
2403 | Import::FutureNew(..)
2404 | Import::StreamNew(..)
2405 | Import::FutureCancelRead { .. }
2406 | Import::FutureCancelWrite { .. }
2407 | Import::FutureDropWritable { .. }
2408 | Import::FutureDropReadable { .. }
2409 | Import::StreamCancelRead { .. }
2410 | Import::StreamCancelWrite { .. }
2411 | Import::StreamDropWritable { .. }
2412 | Import::StreamDropReadable { .. }
2413 | Import::WaitableSetNew
2414 | Import::WaitableSetDrop
2415 | Import::WaitableJoin
2416 | Import::ContextGet(_)
2417 | Import::ContextSet(_)
2418 | Import::ThreadIndex
2419 | Import::ThreadSwitchTo { .. }
2420 | Import::ThreadSuspend { .. }
2421 | Import::ThreadResumeLater
2422 | Import::ThreadYieldTo { .. } => {}
2423
2424 Import::ExportedTaskReturn(key, interface, func, ty) => {
2428 let (options, sig) = task_return_options_and_type(resolve, *ty);
2429 if options.is_empty() {
2430 continue;
2431 }
2432 let name = self.shims.len().to_string();
2433 let encoding = world
2434 .module_metadata_for(for_module)
2435 .export_encodings
2436 .get(resolve, key, func)
2437 .ok_or_else(|| {
2438 anyhow::anyhow!(
2439 "missing component metadata for export of \
2440 `{module}::{field}`"
2441 )
2442 })?;
2443 self.push(Shim {
2444 name,
2445 debug_name: format!("task-return-{func}"),
2446 options,
2447 kind: ShimKind::TaskReturn {
2448 interface: *interface,
2449 func,
2450 result: *ty,
2451 for_module,
2452 encoding,
2453 },
2454 sig,
2455 });
2456 }
2457
2458 Import::FutureWrite { async_, info } => {
2459 self.append_indirect_payload_push(
2460 resolve,
2461 for_module,
2462 module,
2463 *async_,
2464 info,
2465 PayloadFuncKind::FutureWrite,
2466 vec![WasmType::I32; 2],
2467 vec![WasmType::I32],
2468 );
2469 }
2470 Import::FutureRead { async_, info } => {
2471 self.append_indirect_payload_push(
2472 resolve,
2473 for_module,
2474 module,
2475 *async_,
2476 info,
2477 PayloadFuncKind::FutureRead,
2478 vec![WasmType::I32; 2],
2479 vec![WasmType::I32],
2480 );
2481 }
2482 Import::StreamWrite { async_, info } => {
2483 self.append_indirect_payload_push(
2484 resolve,
2485 for_module,
2486 module,
2487 *async_,
2488 info,
2489 PayloadFuncKind::StreamWrite,
2490 vec![WasmType::I32; 3],
2491 vec![WasmType::I32],
2492 );
2493 }
2494 Import::StreamRead { async_, info } => {
2495 self.append_indirect_payload_push(
2496 resolve,
2497 for_module,
2498 module,
2499 *async_,
2500 info,
2501 PayloadFuncKind::StreamRead,
2502 vec![WasmType::I32; 3],
2503 vec![WasmType::I32],
2504 );
2505 }
2506
2507 Import::WaitableSetWait { cancellable } => {
2508 let name = self.shims.len().to_string();
2509 self.push(Shim {
2510 name,
2511 debug_name: "waitable-set.wait".to_string(),
2512 options: RequiredOptions::empty(),
2513 kind: ShimKind::WaitableSetWait {
2514 cancellable: *cancellable,
2515 },
2516 sig: WasmSignature {
2517 params: vec![WasmType::I32; 2],
2518 results: vec![WasmType::I32],
2519 indirect_params: false,
2520 retptr: false,
2521 },
2522 });
2523 }
2524
2525 Import::WaitableSetPoll { cancellable } => {
2526 let name = self.shims.len().to_string();
2527 self.push(Shim {
2528 name,
2529 debug_name: "waitable-set.poll".to_string(),
2530 options: RequiredOptions::empty(),
2531 kind: ShimKind::WaitableSetPoll {
2532 cancellable: *cancellable,
2533 },
2534 sig: WasmSignature {
2535 params: vec![WasmType::I32; 2],
2536 results: vec![WasmType::I32],
2537 indirect_params: false,
2538 retptr: false,
2539 },
2540 });
2541 }
2542
2543 Import::ErrorContextNew { encoding } => {
2544 let name = self.shims.len().to_string();
2545 self.push(Shim {
2546 name,
2547 debug_name: "error-new".to_string(),
2548 options: RequiredOptions::MEMORY | RequiredOptions::STRING_ENCODING,
2549 kind: ShimKind::ErrorContextNew {
2550 encoding: *encoding,
2551 },
2552 sig: WasmSignature {
2553 params: vec![WasmType::I32; 2],
2554 results: vec![WasmType::I32],
2555 indirect_params: false,
2556 retptr: false,
2557 },
2558 });
2559 }
2560
2561 Import::ErrorContextDebugMessage { encoding } => {
2562 let name = self.shims.len().to_string();
2563 self.push(Shim {
2564 name,
2565 debug_name: "error-debug-message".to_string(),
2566 options: RequiredOptions::MEMORY
2567 | RequiredOptions::STRING_ENCODING
2568 | RequiredOptions::REALLOC,
2569 kind: ShimKind::ErrorContextDebugMessage {
2570 for_module,
2571 encoding: *encoding,
2572 },
2573 sig: WasmSignature {
2574 params: vec![WasmType::I32; 2],
2575 results: vec![],
2576 indirect_params: false,
2577 retptr: false,
2578 },
2579 });
2580 }
2581
2582 Import::ThreadNewIndirect => {
2583 let name = self.shims.len().to_string();
2584 self.push(Shim {
2585 name,
2586 debug_name: "thread.new-indirect".to_string(),
2587 options: RequiredOptions::empty(),
2588 kind: ShimKind::ThreadNewIndirect {
2589 for_module,
2590 func_ty: FuncType::new([ValType::I32], vec![]),
2592 },
2593 sig: WasmSignature {
2594 params: vec![WasmType::I32; 2],
2595 results: vec![WasmType::I32],
2596 indirect_params: false,
2597 retptr: false,
2598 },
2599 });
2600 }
2601
2602 Import::AdapterExport { adapter, func, ty } => {
2605 let name = self.shims.len().to_string();
2606 log::debug!("shim {name} is adapter `{module}::{field}`");
2607 self.push(Shim {
2608 name,
2609 debug_name: format!("adapt-{module}-{field}"),
2610 options: RequiredOptions::MEMORY,
2614 kind: ShimKind::Adapter { adapter, func },
2615 sig: WasmSignature {
2616 params: ty.params().iter().map(to_wasm_type).collect(),
2617 results: ty.results().iter().map(to_wasm_type).collect(),
2618 indirect_params: false,
2619 retptr: false,
2620 },
2621 });
2622
2623 fn to_wasm_type(ty: &wasmparser::ValType) -> WasmType {
2624 match ty {
2625 wasmparser::ValType::I32 => WasmType::I32,
2626 wasmparser::ValType::I64 => WasmType::I64,
2627 wasmparser::ValType::F32 => WasmType::F32,
2628 wasmparser::ValType::F64 => WasmType::F64,
2629 _ => unreachable!(),
2630 }
2631 }
2632 }
2633
2634 Import::InterfaceFunc(key, _, name, abi) => {
2638 self.append_indirect_wit_func(
2639 world,
2640 for_module,
2641 module,
2642 field,
2643 key,
2644 name,
2645 Some(resolve.name_world_key(key)),
2646 *abi,
2647 )?;
2648 }
2649 Import::WorldFunc(key, name, abi) => {
2650 self.append_indirect_wit_func(
2651 world, for_module, module, field, key, name, None, *abi,
2652 )?;
2653 }
2654 }
2655 }
2656
2657 for (export_name, export) in module_exports.iter() {
2663 let id = match export {
2664 Export::ResourceDtor(id) => id,
2665 _ => continue,
2666 };
2667 let resource = resolve.types[*id].name.as_ref().unwrap();
2668 let name = self.shims.len().to_string();
2669 self.push(Shim {
2670 name,
2671 debug_name: format!("dtor-{resource}"),
2672 options: RequiredOptions::empty(),
2673 kind: ShimKind::ResourceDtor {
2674 module: for_module,
2675 export: export_name,
2676 },
2677 sig: WasmSignature {
2678 params: vec![WasmType::I32],
2679 results: Vec::new(),
2680 indirect_params: false,
2681 retptr: false,
2682 },
2683 });
2684 }
2685
2686 Ok(())
2687 }
2688
2689 fn append_indirect_payload_push(
2692 &mut self,
2693 resolve: &Resolve,
2694 for_module: CustomModule<'a>,
2695 module: &str,
2696 async_: bool,
2697 info: &'a PayloadInfo,
2698 kind: PayloadFuncKind,
2699 params: Vec<WasmType>,
2700 results: Vec<WasmType>,
2701 ) {
2702 let debug_name = format!("{module}-{}", info.name);
2703 let name = self.shims.len().to_string();
2704
2705 let payload = info.payload(resolve);
2706 let (wit_param, wit_result) = match kind {
2707 PayloadFuncKind::StreamRead | PayloadFuncKind::FutureRead => (None, payload),
2708 PayloadFuncKind::StreamWrite | PayloadFuncKind::FutureWrite => (payload, None),
2709 };
2710 self.push(Shim {
2711 name,
2712 debug_name,
2713 options: RequiredOptions::MEMORY
2714 | RequiredOptions::for_import(
2715 resolve,
2716 &Function {
2717 name: String::new(),
2718 kind: FunctionKind::Freestanding,
2719 params: match wit_param {
2720 Some(ty) => vec![("a".to_string(), ty)],
2721 None => Vec::new(),
2722 },
2723 result: wit_result,
2724 docs: Default::default(),
2725 stability: Stability::Unknown,
2726 },
2727 if async_ {
2728 AbiVariant::GuestImportAsync
2729 } else {
2730 AbiVariant::GuestImport
2731 },
2732 ),
2733 kind: ShimKind::PayloadFunc {
2734 for_module,
2735 info,
2736 kind,
2737 },
2738 sig: WasmSignature {
2739 params,
2740 results,
2741 indirect_params: false,
2742 retptr: false,
2743 },
2744 });
2745 }
2746
2747 fn append_indirect_wit_func(
2750 &mut self,
2751 world: &'a ComponentWorld<'a>,
2752 for_module: CustomModule<'a>,
2753 module: &str,
2754 field: &str,
2755 key: &WorldKey,
2756 name: &String,
2757 interface_key: Option<String>,
2758 abi: AbiVariant,
2759 ) -> Result<()> {
2760 let resolve = &world.encoder.metadata.resolve;
2761 let metadata = world.module_metadata_for(for_module);
2762 let interface = &world.import_map[&interface_key];
2763 let (index, _, lowering) = interface.lowerings.get_full(&(name.clone(), abi)).unwrap();
2764 let shim_name = self.shims.len().to_string();
2765 match lowering {
2766 Lowering::Direct | Lowering::ResourceDrop(_) => {}
2767
2768 Lowering::Indirect { sig, options } => {
2769 log::debug!(
2770 "shim {shim_name} is import `{module}::{field}` lowering {index} `{name}`",
2771 );
2772 let encoding = metadata
2773 .import_encodings
2774 .get(resolve, key, name)
2775 .ok_or_else(|| {
2776 anyhow::anyhow!(
2777 "missing component metadata for import of \
2778 `{module}::{field}`"
2779 )
2780 })?;
2781 self.push(Shim {
2782 name: shim_name,
2783 debug_name: format!("indirect-{module}-{field}"),
2784 options: *options,
2785 kind: ShimKind::IndirectLowering {
2786 interface: interface_key,
2787 index,
2788 realloc: for_module,
2789 encoding,
2790 },
2791 sig: sig.clone(),
2792 });
2793 }
2794 }
2795
2796 Ok(())
2797 }
2798
2799 fn push(&mut self, shim: Shim<'a>) {
2800 if !self.shims.contains_key(&shim.kind) {
2804 self.shims.insert(shim.kind.clone(), shim);
2805 }
2806 }
2807}
2808
2809fn task_return_options_and_type(
2810 resolve: &Resolve,
2811 ty: Option<Type>,
2812) -> (RequiredOptions, WasmSignature) {
2813 let func_tmp = Function {
2814 name: String::new(),
2815 kind: FunctionKind::Freestanding,
2816 params: match ty {
2817 Some(ty) => vec![("a".to_string(), ty)],
2818 None => Vec::new(),
2819 },
2820 result: None,
2821 docs: Default::default(),
2822 stability: Stability::Unknown,
2823 };
2824 let abi = AbiVariant::GuestImport;
2825 let options = RequiredOptions::for_import(resolve, &func_tmp, abi);
2826 let sig = resolve.wasm_signature(abi, &func_tmp);
2827 (options, sig)
2828}
2829
2830#[derive(Clone, Debug)]
2832pub struct Item {
2833 pub alias: String,
2834 pub kind: ExportKind,
2835 pub which: MainOrAdapter,
2836 pub name: String,
2837}
2838
2839#[derive(Debug, PartialEq, Clone)]
2841pub enum MainOrAdapter {
2842 Main,
2843 Adapter(String),
2844}
2845
2846impl MainOrAdapter {
2847 fn to_custom_module(&self) -> CustomModule<'_> {
2848 match self {
2849 MainOrAdapter::Main => CustomModule::Main,
2850 MainOrAdapter::Adapter(s) => CustomModule::Adapter(s),
2851 }
2852 }
2853}
2854
2855#[derive(Clone)]
2857pub enum Instance {
2858 MainOrAdapter(MainOrAdapter),
2860
2861 Items(Vec<Item>),
2863}
2864
2865#[derive(Clone)]
2868pub struct LibraryInfo {
2869 pub instantiate_after_shims: bool,
2871
2872 pub arguments: Vec<(String, Instance)>,
2874}
2875
2876pub(super) struct Adapter {
2878 wasm: Vec<u8>,
2880
2881 metadata: ModuleMetadata,
2883
2884 required_exports: IndexSet<WorldKey>,
2887
2888 library_info: Option<LibraryInfo>,
2893}
2894
2895#[derive(Default)]
2897pub struct ComponentEncoder {
2898 module: Vec<u8>,
2899 module_import_map: Option<ModuleImportMap>,
2900 pub(super) metadata: Bindgen,
2901 validate: bool,
2902 pub(super) main_module_exports: IndexSet<WorldKey>,
2903 pub(super) adapters: IndexMap<String, Adapter>,
2904 import_name_map: HashMap<String, String>,
2905 realloc_via_memory_grow: bool,
2906 merge_imports_based_on_semver: Option<bool>,
2907 pub(super) reject_legacy_names: bool,
2908 debug_names: bool,
2909}
2910
2911impl ComponentEncoder {
2912 pub fn module(mut self, module: &[u8]) -> Result<Self> {
2918 let (wasm, metadata) = self.decode(module.as_ref())?;
2919 let (wasm, module_import_map) = ModuleImportMap::new(wasm)?;
2920 let exports = self
2921 .merge_metadata(metadata)
2922 .context("failed merge WIT metadata for module with previous metadata")?;
2923 self.main_module_exports.extend(exports);
2924 self.module = if let Some(producers) = &self.metadata.producers {
2925 producers.add_to_wasm(&wasm)?
2926 } else {
2927 wasm.to_vec()
2928 };
2929 self.module_import_map = module_import_map;
2930 Ok(self)
2931 }
2932
2933 fn decode<'a>(&self, wasm: &'a [u8]) -> Result<(Cow<'a, [u8]>, Bindgen)> {
2934 let (bytes, metadata) = metadata::decode(wasm)?;
2935 match bytes {
2936 Some(wasm) => Ok((Cow::Owned(wasm), metadata)),
2937 None => Ok((Cow::Borrowed(wasm), metadata)),
2938 }
2939 }
2940
2941 fn merge_metadata(&mut self, metadata: Bindgen) -> Result<IndexSet<WorldKey>> {
2942 self.metadata.merge(metadata)
2943 }
2944
2945 pub fn validate(mut self, validate: bool) -> Self {
2947 self.validate = validate;
2948 self
2949 }
2950
2951 pub fn debug_names(mut self, debug_names: bool) -> Self {
2953 self.debug_names = debug_names;
2954 self
2955 }
2956
2957 pub fn merge_imports_based_on_semver(mut self, merge: bool) -> Self {
2965 self.merge_imports_based_on_semver = Some(merge);
2966 self
2967 }
2968
2969 pub fn reject_legacy_names(mut self, reject: bool) -> Self {
2978 self.reject_legacy_names = reject;
2979 self
2980 }
2981
2982 pub fn adapter(self, name: &str, bytes: &[u8]) -> Result<Self> {
3000 self.library_or_adapter(name, bytes, None)
3001 }
3002
3003 pub fn library(self, name: &str, bytes: &[u8], library_info: LibraryInfo) -> Result<Self> {
3016 self.library_or_adapter(name, bytes, Some(library_info))
3017 }
3018
3019 fn library_or_adapter(
3020 mut self,
3021 name: &str,
3022 bytes: &[u8],
3023 library_info: Option<LibraryInfo>,
3024 ) -> Result<Self> {
3025 let (wasm, mut metadata) = self.decode(bytes)?;
3026 let adapter_metadata = mem::take(&mut metadata.metadata);
3034 let exports = self.merge_metadata(metadata).with_context(|| {
3035 format!("failed to merge WIT packages of adapter `{name}` into main packages")
3036 })?;
3037 if let Some(library_info) = &library_info {
3038 for (_, instance) in &library_info.arguments {
3040 let resolve = |which: &_| match which {
3041 MainOrAdapter::Main => Ok(()),
3042 MainOrAdapter::Adapter(name) => {
3043 if self.adapters.contains_key(name.as_str()) {
3044 Ok(())
3045 } else {
3046 Err(anyhow!("instance refers to unknown adapter `{name}`"))
3047 }
3048 }
3049 };
3050
3051 match instance {
3052 Instance::MainOrAdapter(which) => resolve(which)?,
3053 Instance::Items(items) => {
3054 for item in items {
3055 resolve(&item.which)?;
3056 }
3057 }
3058 }
3059 }
3060 }
3061 self.adapters.insert(
3062 name.to_string(),
3063 Adapter {
3064 wasm: wasm.to_vec(),
3065 metadata: adapter_metadata,
3066 required_exports: exports,
3067 library_info,
3068 },
3069 );
3070 Ok(self)
3071 }
3072
3073 pub fn realloc_via_memory_grow(mut self, value: bool) -> Self {
3078 self.realloc_via_memory_grow = value;
3079 self
3080 }
3081
3082 pub fn import_name_map(mut self, map: HashMap<String, String>) -> Self {
3093 self.import_name_map = map;
3094 self
3095 }
3096
3097 pub fn encode(&mut self) -> Result<Vec<u8>> {
3099 if self.module.is_empty() {
3100 bail!("a module is required when encoding a component");
3101 }
3102
3103 if self.merge_imports_based_on_semver.unwrap_or(true) {
3104 self.metadata
3105 .resolve
3106 .merge_world_imports_based_on_semver(self.metadata.world)?;
3107 }
3108
3109 let world = ComponentWorld::new(self).context("failed to decode world from module")?;
3110 let mut state = EncodingState {
3111 component: ComponentBuilder::default(),
3112 module_index: None,
3113 instance_index: None,
3114 memory_index: None,
3115 shim_instance_index: None,
3116 fixups_module_index: None,
3117 adapter_modules: IndexMap::new(),
3118 adapter_instances: IndexMap::new(),
3119 import_type_encoding_maps: Default::default(),
3120 export_type_encoding_maps: Default::default(),
3121 imported_instances: Default::default(),
3122 imported_funcs: Default::default(),
3123 exported_instances: Default::default(),
3124 aliased_core_items: Default::default(),
3125 info: &world,
3126 };
3127 state.encode_imports(&self.import_name_map)?;
3128 state.encode_core_modules();
3129 state.encode_core_instantiation()?;
3130 state.encode_exports(CustomModule::Main)?;
3131 for name in self.adapters.keys() {
3132 state.encode_exports(CustomModule::Adapter(name))?;
3133 }
3134 state.component.append_names();
3135 state
3136 .component
3137 .raw_custom_section(&crate::base_producers().raw_custom_section());
3138 let bytes = state.component.finish();
3139
3140 if self.validate {
3141 Validator::new_with_features(WasmFeatures::all())
3142 .validate_all(&bytes)
3143 .context("failed to validate component output")?;
3144 }
3145
3146 Ok(bytes)
3147 }
3148}
3149
3150impl ComponentWorld<'_> {
3151 fn imports_for(&self, module: CustomModule) -> &ImportMap {
3153 match module {
3154 CustomModule::Main => &self.info.imports,
3155 CustomModule::Adapter(name) => &self.adapters[name].info.imports,
3156 }
3157 }
3158
3159 fn exports_for(&self, module: CustomModule) -> &ExportMap {
3161 match module {
3162 CustomModule::Main => &self.info.exports,
3163 CustomModule::Adapter(name) => &self.adapters[name].info.exports,
3164 }
3165 }
3166
3167 fn module_metadata_for(&self, module: CustomModule) -> &ModuleMetadata {
3169 match module {
3170 CustomModule::Main => &self.encoder.metadata.metadata,
3171 CustomModule::Adapter(name) => &self.encoder.adapters[name].metadata,
3172 }
3173 }
3174}
3175
3176#[cfg(all(test, feature = "dummy-module"))]
3177mod test {
3178 use super::*;
3179 use crate::{dummy_module, embed_component_metadata};
3180 use wit_parser::ManglingAndAbi;
3181
3182 #[test]
3183 fn it_renames_imports() {
3184 let mut resolve = Resolve::new();
3185 let pkg = resolve
3186 .push_str(
3187 "test.wit",
3188 r#"
3189package test:wit;
3190
3191interface i {
3192 f: func();
3193}
3194
3195world test {
3196 import i;
3197 import foo: interface {
3198 f: func();
3199 }
3200}
3201"#,
3202 )
3203 .unwrap();
3204 let world = resolve.select_world(&[pkg], None).unwrap();
3205
3206 let mut module = dummy_module(&resolve, world, ManglingAndAbi::Standard32);
3207
3208 embed_component_metadata(&mut module, &resolve, world, StringEncoding::UTF8).unwrap();
3209
3210 let encoded = ComponentEncoder::default()
3211 .import_name_map(HashMap::from([
3212 (
3213 "foo".to_string(),
3214 "unlocked-dep=<foo:bar/foo@{>=1.0.0 <1.1.0}>".to_string(),
3215 ),
3216 (
3217 "test:wit/i".to_string(),
3218 "locked-dep=<foo:bar/i@1.2.3>".to_string(),
3219 ),
3220 ]))
3221 .module(&module)
3222 .unwrap()
3223 .validate(true)
3224 .encode()
3225 .unwrap();
3226
3227 let wat = wasmprinter::print_bytes(encoded).unwrap();
3228 assert!(wat.contains("unlocked-dep=<foo:bar/foo@{>=1.0.0 <1.1.0}>"));
3229 assert!(wat.contains("locked-dep=<foo:bar/i@1.2.3>"));
3230 }
3231}