1use crate::StringEncoding;
75use crate::metadata::{self, Bindgen, ModuleMetadata};
76use crate::validation::{Export, ExportMap, Import, ImportInstance, ImportMap, PayloadInfo};
77use anyhow::{Context, Result, anyhow, bail};
78use indexmap::{IndexMap, IndexSet};
79use std::borrow::Cow;
80use std::collections::HashMap;
81use std::hash::Hash;
82use std::mem;
83use wasm_encoder::*;
84use wasmparser::{Validator, WasmFeatures};
85use wit_parser::{
86 Function, FunctionKind, InterfaceId, LiveTypes, Resolve, Stability, Type, TypeDefKind, TypeId,
87 TypeOwner, WorldItem, WorldKey,
88 abi::{AbiVariant, WasmSignature, WasmType},
89};
90
91const INDIRECT_TABLE_NAME: &str = "$imports";
92
93mod wit;
94pub use wit::{encode, encode_world};
95
96mod types;
97use types::{InstanceTypeEncoder, RootTypeEncoder, TypeEncodingMaps, ValtypeEncoder};
98mod world;
99use world::{ComponentWorld, ImportedInterface, Lowering};
100
101mod dedupe;
102pub(crate) use dedupe::ModuleImportMap;
103use wasm_metadata::AddMetadataField;
104
105fn to_val_type(ty: &WasmType) -> ValType {
106 match ty {
107 WasmType::I32 => ValType::I32,
108 WasmType::I64 => ValType::I64,
109 WasmType::F32 => ValType::F32,
110 WasmType::F64 => ValType::F64,
111 WasmType::Pointer => ValType::I32,
112 WasmType::PointerOrI64 => ValType::I64,
113 WasmType::Length => ValType::I32,
114 }
115}
116
117bitflags::bitflags! {
118 #[derive(Copy, Clone, Debug)]
121 pub struct RequiredOptions: u8 {
122 const MEMORY = 1 << 0;
125 const REALLOC = 1 << 1;
128 const STRING_ENCODING = 1 << 2;
131 const ASYNC = 1 << 3;
132 }
133}
134
135impl RequiredOptions {
136 fn for_import(resolve: &Resolve, func: &Function, abi: AbiVariant) -> RequiredOptions {
137 let sig = resolve.wasm_signature(abi, func);
138 let mut ret = RequiredOptions::empty();
139 ret.add_lift(TypeContents::for_types(
141 resolve,
142 func.params.iter().map(|(_, t)| t),
143 ));
144 ret.add_lower(TypeContents::for_types(resolve, &func.result));
145
146 if sig.retptr || sig.indirect_params {
149 ret |= RequiredOptions::MEMORY;
150 }
151 if abi == AbiVariant::GuestImportAsync {
152 ret |= RequiredOptions::ASYNC;
153 }
154 ret
155 }
156
157 fn for_export(resolve: &Resolve, func: &Function, abi: AbiVariant) -> RequiredOptions {
158 let sig = resolve.wasm_signature(abi, func);
159 let mut ret = RequiredOptions::empty();
160 ret.add_lower(TypeContents::for_types(
162 resolve,
163 func.params.iter().map(|(_, t)| t),
164 ));
165 ret.add_lift(TypeContents::for_types(resolve, &func.result));
166
167 if sig.retptr || sig.indirect_params {
171 ret |= RequiredOptions::MEMORY;
172 if sig.indirect_params {
173 ret |= RequiredOptions::REALLOC;
174 }
175 }
176 if let AbiVariant::GuestExportAsync | AbiVariant::GuestExportAsyncStackful = abi {
177 ret |= RequiredOptions::ASYNC;
178 }
179 ret
180 }
181
182 fn add_lower(&mut self, types: TypeContents) {
183 if types.contains(TypeContents::LIST) {
187 *self |= RequiredOptions::MEMORY | RequiredOptions::REALLOC;
188 }
189 if types.contains(TypeContents::STRING) {
190 *self |= RequiredOptions::MEMORY
191 | RequiredOptions::STRING_ENCODING
192 | RequiredOptions::REALLOC;
193 }
194 }
195
196 fn add_lift(&mut self, types: TypeContents) {
197 if types.contains(TypeContents::LIST) {
201 *self |= RequiredOptions::MEMORY;
202 }
203 if types.contains(TypeContents::STRING) {
204 *self |= RequiredOptions::MEMORY | RequiredOptions::STRING_ENCODING;
205 }
206 }
207
208 fn into_iter(
209 self,
210 encoding: StringEncoding,
211 memory_index: Option<u32>,
212 realloc_index: Option<u32>,
213 ) -> Result<impl ExactSizeIterator<Item = CanonicalOption>> {
214 #[derive(Default)]
215 struct Iter {
216 options: [Option<CanonicalOption>; 5],
217 current: usize,
218 count: usize,
219 }
220
221 impl Iter {
222 fn push(&mut self, option: CanonicalOption) {
223 assert!(self.count < self.options.len());
224 self.options[self.count] = Some(option);
225 self.count += 1;
226 }
227 }
228
229 impl Iterator for Iter {
230 type Item = CanonicalOption;
231
232 fn next(&mut self) -> Option<Self::Item> {
233 if self.current == self.count {
234 return None;
235 }
236 let option = self.options[self.current];
237 self.current += 1;
238 option
239 }
240
241 fn size_hint(&self) -> (usize, Option<usize>) {
242 (self.count - self.current, Some(self.count - self.current))
243 }
244 }
245
246 impl ExactSizeIterator for Iter {}
247
248 let mut iter = Iter::default();
249
250 if self.contains(RequiredOptions::MEMORY) {
251 iter.push(CanonicalOption::Memory(memory_index.ok_or_else(|| {
252 anyhow!("module does not export a memory named `memory`")
253 })?));
254 }
255
256 if self.contains(RequiredOptions::REALLOC) {
257 iter.push(CanonicalOption::Realloc(realloc_index.ok_or_else(
258 || anyhow!("module does not export a function named `cabi_realloc`"),
259 )?));
260 }
261
262 if self.contains(RequiredOptions::STRING_ENCODING) {
263 iter.push(encoding.into());
264 }
265
266 if self.contains(RequiredOptions::ASYNC) {
267 iter.push(CanonicalOption::Async);
268 }
269
270 Ok(iter)
271 }
272}
273
274bitflags::bitflags! {
275 struct TypeContents: u8 {
278 const STRING = 1 << 0;
279 const LIST = 1 << 1;
280 }
281}
282
283impl TypeContents {
284 fn for_types<'a>(resolve: &Resolve, types: impl IntoIterator<Item = &'a Type>) -> Self {
285 let mut cur = TypeContents::empty();
286 for ty in types {
287 cur |= Self::for_type(resolve, ty);
288 }
289 cur
290 }
291
292 fn for_optional_types<'a>(
293 resolve: &Resolve,
294 types: impl Iterator<Item = Option<&'a Type>>,
295 ) -> Self {
296 Self::for_types(resolve, types.flatten())
297 }
298
299 fn for_optional_type(resolve: &Resolve, ty: Option<&Type>) -> Self {
300 match ty {
301 Some(ty) => Self::for_type(resolve, ty),
302 None => Self::empty(),
303 }
304 }
305
306 fn for_type(resolve: &Resolve, ty: &Type) -> Self {
307 match ty {
308 Type::Id(id) => match &resolve.types[*id].kind {
309 TypeDefKind::Handle(h) => match h {
310 wit_parser::Handle::Own(_) => Self::empty(),
311 wit_parser::Handle::Borrow(_) => Self::empty(),
312 },
313 TypeDefKind::Resource => Self::empty(),
314 TypeDefKind::Record(r) => Self::for_types(resolve, r.fields.iter().map(|f| &f.ty)),
315 TypeDefKind::Tuple(t) => Self::for_types(resolve, t.types.iter()),
316 TypeDefKind::Flags(_) => Self::empty(),
317 TypeDefKind::Option(t) => Self::for_type(resolve, t),
318 TypeDefKind::Result(r) => {
319 Self::for_optional_type(resolve, r.ok.as_ref())
320 | Self::for_optional_type(resolve, r.err.as_ref())
321 }
322 TypeDefKind::Variant(v) => {
323 Self::for_optional_types(resolve, v.cases.iter().map(|c| c.ty.as_ref()))
324 }
325 TypeDefKind::Enum(_) => Self::empty(),
326 TypeDefKind::List(t) => Self::for_type(resolve, t) | Self::LIST,
327 TypeDefKind::FixedSizeList(t, _elements) => Self::for_type(resolve, t),
328 TypeDefKind::Type(t) => Self::for_type(resolve, t),
329 TypeDefKind::Future(_) => Self::empty(),
330 TypeDefKind::Stream(_) => Self::empty(),
331 TypeDefKind::Unknown => unreachable!(),
332 },
333 Type::String => Self::STRING,
334 _ => Self::empty(),
335 }
336 }
337}
338
339pub struct EncodingState<'a> {
341 component: ComponentBuilder,
343 module_index: Option<u32>,
347 instance_index: Option<u32>,
351 memory_index: Option<u32>,
355 shim_instance_index: Option<u32>,
359 fixups_module_index: Option<u32>,
363
364 adapter_modules: IndexMap<&'a str, u32>,
367 adapter_instances: IndexMap<&'a str, u32>,
369
370 imported_instances: IndexMap<InterfaceId, u32>,
372 imported_funcs: IndexMap<String, u32>,
373 exported_instances: IndexMap<InterfaceId, u32>,
374
375 import_type_encoding_maps: TypeEncodingMaps<'a>,
380 export_type_encoding_maps: TypeEncodingMaps<'a>,
381
382 aliased_core_items: HashMap<(u32, String), u32>,
388
389 info: &'a ComponentWorld<'a>,
391}
392
393impl<'a> EncodingState<'a> {
394 fn encode_core_modules(&mut self) {
395 assert!(self.module_index.is_none());
396 let idx = self
397 .component
398 .core_module_raw(Some("main"), &self.info.encoder.module);
399 self.module_index = Some(idx);
400
401 for (name, adapter) in self.info.adapters.iter() {
402 let debug_name = if adapter.library_info.is_some() {
403 name.to_string()
404 } else {
405 format!("wit-component:adapter:{name}")
406 };
407 let idx = if self.info.encoder.debug_names {
408 let mut add_meta = wasm_metadata::AddMetadata::default();
409 add_meta.name = AddMetadataField::Set(debug_name.clone());
410 let wasm = add_meta
411 .to_wasm(&adapter.wasm)
412 .expect("core wasm can get name added");
413 self.component.core_module_raw(Some(&debug_name), &wasm)
414 } else {
415 self.component
416 .core_module_raw(Some(&debug_name), &adapter.wasm)
417 };
418 let prev = self.adapter_modules.insert(name, idx);
419 assert!(prev.is_none());
420 }
421 }
422
423 fn root_import_type_encoder(
424 &mut self,
425 interface: Option<InterfaceId>,
426 ) -> RootTypeEncoder<'_, 'a> {
427 RootTypeEncoder {
428 state: self,
429 interface,
430 import_types: true,
431 }
432 }
433
434 fn root_export_type_encoder(
435 &mut self,
436 interface: Option<InterfaceId>,
437 ) -> RootTypeEncoder<'_, 'a> {
438 RootTypeEncoder {
439 state: self,
440 interface,
441 import_types: false,
442 }
443 }
444
445 fn instance_type_encoder(&mut self, interface: InterfaceId) -> InstanceTypeEncoder<'_, 'a> {
446 InstanceTypeEncoder {
447 state: self,
448 interface,
449 type_encoding_maps: Default::default(),
450 ty: Default::default(),
451 }
452 }
453
454 fn encode_imports(&mut self, name_map: &HashMap<String, String>) -> Result<()> {
455 let mut has_funcs = false;
456 for (name, info) in self.info.import_map.iter() {
457 match name {
458 Some(name) => {
459 self.encode_interface_import(name_map.get(name).unwrap_or(name), info)?
460 }
461 None => has_funcs = true,
462 }
463 }
464
465 let resolve = &self.info.encoder.metadata.resolve;
466 let world = &resolve.worlds[self.info.encoder.metadata.world];
467
468 for (_name, item) in world.imports.iter() {
471 if let WorldItem::Type(ty) = item {
472 self.root_import_type_encoder(None)
473 .encode_valtype(resolve, &Type::Id(*ty))?;
474 }
475 }
476
477 if has_funcs {
478 let info = &self.info.import_map[&None];
479 self.encode_root_import_funcs(info)?;
480 }
481 Ok(())
482 }
483
484 fn encode_interface_import(&mut self, name: &str, info: &ImportedInterface) -> Result<()> {
485 let resolve = &self.info.encoder.metadata.resolve;
486 let interface_id = info.interface.as_ref().unwrap();
487 let interface_id = *interface_id;
488 let interface = &resolve.interfaces[interface_id];
489 log::trace!("encoding imports for `{name}` as {interface_id:?}");
490 let mut encoder = self.instance_type_encoder(interface_id);
491
492 if let Some(live) = encoder.state.info.live_type_imports.get(&interface_id) {
494 for ty in live {
495 log::trace!(
496 "encoding extra type {ty:?} name={:?}",
497 resolve.types[*ty].name
498 );
499 encoder.encode_valtype(resolve, &Type::Id(*ty))?;
500 }
501 }
502
503 for (_, func) in interface.functions.iter() {
506 if !(info
507 .lowerings
508 .contains_key(&(func.name.clone(), AbiVariant::GuestImport))
509 || info
510 .lowerings
511 .contains_key(&(func.name.clone(), AbiVariant::GuestImportAsync)))
512 {
513 continue;
514 }
515 log::trace!("encoding function type for `{}`", func.name);
516 let idx = encoder.encode_func_type(resolve, func)?;
517
518 encoder.ty.export(&func.name, ComponentTypeRef::Func(idx));
519 }
520
521 let ty = encoder.ty;
522 if ty.is_empty() {
525 return Ok(());
526 }
527 let instance_type_idx = self
528 .component
529 .type_instance(Some(&format!("ty-{name}")), &ty);
530 let instance_idx = self
531 .component
532 .import(name, ComponentTypeRef::Instance(instance_type_idx));
533 let prev = self.imported_instances.insert(interface_id, instance_idx);
534 assert!(prev.is_none());
535 Ok(())
536 }
537
538 fn encode_root_import_funcs(&mut self, info: &ImportedInterface) -> Result<()> {
539 let resolve = &self.info.encoder.metadata.resolve;
540 let world = self.info.encoder.metadata.world;
541 for (name, item) in resolve.worlds[world].imports.iter() {
542 let func = match item {
543 WorldItem::Function(f) => f,
544 WorldItem::Interface { .. } | WorldItem::Type(_) => continue,
545 };
546 let name = resolve.name_world_key(name);
547 if !(info
548 .lowerings
549 .contains_key(&(name.clone(), AbiVariant::GuestImport))
550 || info
551 .lowerings
552 .contains_key(&(name.clone(), AbiVariant::GuestImportAsync)))
553 {
554 continue;
555 }
556 log::trace!("encoding function type for `{}`", func.name);
557 let idx = self
558 .root_import_type_encoder(None)
559 .encode_func_type(resolve, func)?;
560 let func_idx = self.component.import(&name, ComponentTypeRef::Func(idx));
561 let prev = self.imported_funcs.insert(name, func_idx);
562 assert!(prev.is_none());
563 }
564 Ok(())
565 }
566
567 fn alias_imported_type(&mut self, interface: InterfaceId, id: TypeId) -> u32 {
568 let ty = &self.info.encoder.metadata.resolve.types[id];
569 let name = ty.name.as_ref().expect("type must have a name");
570 let instance = self.imported_instances[&interface];
571 self.component
572 .alias_export(instance, name, ComponentExportKind::Type)
573 }
574
575 fn alias_exported_type(&mut self, interface: InterfaceId, id: TypeId) -> u32 {
576 let ty = &self.info.encoder.metadata.resolve.types[id];
577 let name = ty.name.as_ref().expect("type must have a name");
578 let instance = self.exported_instances[&interface];
579 self.component
580 .alias_export(instance, name, ComponentExportKind::Type)
581 }
582
583 fn encode_core_instantiation(&mut self) -> Result<()> {
584 let shims = self.encode_shim_instantiation()?;
586
587 self.declare_types_for_imported_intrinsics(&shims)?;
591
592 self.instantiate_main_module(&shims)?;
596
597 let (before, after) = self
600 .info
601 .adapters
602 .iter()
603 .partition::<Vec<_>, _>(|(_, adapter)| {
604 !matches!(
605 adapter.library_info,
606 Some(LibraryInfo {
607 instantiate_after_shims: true,
608 ..
609 })
610 )
611 });
612
613 for (name, _adapter) in before {
614 self.instantiate_adapter_module(&shims, name)?;
615 }
616
617 self.encode_indirect_lowerings(&shims)?;
620
621 for (name, _adapter) in after {
622 self.instantiate_adapter_module(&shims, name)?;
623 }
624
625 self.encode_initialize_with_start()?;
626
627 Ok(())
628 }
629
630 fn lookup_resource_index(&mut self, id: TypeId) -> u32 {
631 let resolve = &self.info.encoder.metadata.resolve;
632 let ty = &resolve.types[id];
633 match ty.owner {
634 TypeOwner::World(_) => self.import_type_encoding_maps.id_to_index[&id],
638 TypeOwner::Interface(i) => {
639 let instance = self.imported_instances[&i];
640 let name = ty.name.as_ref().expect("resources must be named");
641 self.component
642 .alias_export(instance, name, ComponentExportKind::Type)
643 }
644 TypeOwner::None => panic!("resources must have an owner"),
645 }
646 }
647
648 fn encode_exports(&mut self, module: CustomModule) -> Result<()> {
649 let resolve = &self.info.encoder.metadata.resolve;
650 let exports = match module {
651 CustomModule::Main => &self.info.encoder.main_module_exports,
652 CustomModule::Adapter(name) => &self.info.encoder.adapters[name].required_exports,
653 };
654
655 if exports.is_empty() {
656 return Ok(());
657 }
658
659 let mut interface_func_core_names = IndexMap::new();
660 let mut world_func_core_names = IndexMap::new();
661 for (core_name, export) in self.info.exports_for(module).iter() {
662 match export {
663 Export::WorldFunc(_, name, _) => {
664 let prev = world_func_core_names.insert(name, core_name);
665 assert!(prev.is_none());
666 }
667 Export::InterfaceFunc(_, id, name, _) => {
668 let prev = interface_func_core_names
669 .entry(id)
670 .or_insert(IndexMap::new())
671 .insert(name.as_str(), core_name);
672 assert!(prev.is_none());
673 }
674 Export::WorldFuncCallback(..)
675 | Export::InterfaceFuncCallback(..)
676 | Export::WorldFuncPostReturn(..)
677 | Export::InterfaceFuncPostReturn(..)
678 | Export::ResourceDtor(..)
679 | Export::Memory
680 | Export::GeneralPurposeRealloc
681 | Export::GeneralPurposeExportRealloc
682 | Export::GeneralPurposeImportRealloc
683 | Export::Initialize
684 | Export::ReallocForAdapter
685 | Export::IndirectFunctionTable => continue,
686 }
687 }
688
689 let world = &resolve.worlds[self.info.encoder.metadata.world];
690
691 for export_name in exports {
692 let export_string = resolve.name_world_key(export_name);
693 match &world.exports[export_name] {
694 WorldItem::Function(func) => {
695 let ty = self
696 .root_import_type_encoder(None)
697 .encode_func_type(resolve, func)?;
698 let core_name = world_func_core_names[&func.name];
699 let idx = self.encode_lift(module, &core_name, export_name, func, ty)?;
700 self.component
701 .export(&export_string, ComponentExportKind::Func, idx, None);
702 }
703 WorldItem::Interface { id, .. } => {
704 let core_names = interface_func_core_names.get(id);
705 self.encode_interface_export(
706 &export_string,
707 module,
708 export_name,
709 *id,
710 core_names,
711 )?;
712 }
713 WorldItem::Type(_) => unreachable!(),
714 }
715 }
716
717 Ok(())
718 }
719
720 fn encode_interface_export(
721 &mut self,
722 export_name: &str,
723 module: CustomModule<'_>,
724 key: &WorldKey,
725 export: InterfaceId,
726 interface_func_core_names: Option<&IndexMap<&str, &str>>,
727 ) -> Result<()> {
728 log::trace!("encode interface export `{export_name}`");
729 let resolve = &self.info.encoder.metadata.resolve;
730
731 let mut imports = Vec::new();
738 let mut root = self.root_export_type_encoder(Some(export));
739 for (_, func) in &resolve.interfaces[export].functions {
740 let core_name = interface_func_core_names.unwrap()[func.name.as_str()];
741 let ty = root.encode_func_type(resolve, func)?;
742 let func_index = root.state.encode_lift(module, &core_name, key, func, ty)?;
743 imports.push((
744 import_func_name(func),
745 ComponentExportKind::Func,
746 func_index,
747 ));
748 }
749
750 let mut nested = NestedComponentTypeEncoder {
754 component: ComponentBuilder::default(),
755 type_encoding_maps: Default::default(),
756 export_types: false,
757 interface: export,
758 state: self,
759 imports: IndexMap::new(),
760 };
761
762 let mut types_to_import = LiveTypes::default();
772 types_to_import.add_interface(resolve, export);
773 let exports_used = &nested.state.info.exports_used[&export];
774 for ty in types_to_import.iter() {
775 if let TypeOwner::Interface(owner) = resolve.types[ty].owner {
776 if owner == export {
777 continue;
780 }
781
782 let mut encoder = if exports_used.contains(&owner) {
785 nested.state.root_export_type_encoder(Some(export))
786 } else {
787 nested.state.root_import_type_encoder(Some(export))
788 };
789 encoder.encode_valtype(resolve, &Type::Id(ty))?;
790
791 nested.interface = owner;
795 nested.encode_valtype(resolve, &Type::Id(ty))?;
796 }
797 }
798 nested.interface = export;
799
800 let imported_type_maps = nested.type_encoding_maps.clone();
804
805 let mut resources = HashMap::new();
811 for (_name, ty) in resolve.interfaces[export].types.iter() {
812 if !matches!(resolve.types[*ty].kind, TypeDefKind::Resource) {
813 continue;
814 }
815 let idx = match nested.encode_valtype(resolve, &Type::Id(*ty))? {
816 ComponentValType::Type(idx) => idx,
817 _ => unreachable!(),
818 };
819 resources.insert(*ty, idx);
820 }
821
822 for (_, func) in resolve.interfaces[export].functions.iter() {
826 let ty = nested.encode_func_type(resolve, func)?;
827 nested
828 .component
829 .import(&import_func_name(func), ComponentTypeRef::Func(ty));
830 }
831
832 let reverse_map = nested
839 .type_encoding_maps
840 .id_to_index
841 .drain()
842 .map(|p| (p.1, p.0))
843 .collect::<HashMap<_, _>>();
844 nested.type_encoding_maps.def_to_index.clear();
845 for (name, idx) in nested.imports.drain(..) {
846 let id = reverse_map[&idx];
847 let owner = match resolve.types[id].owner {
848 TypeOwner::Interface(id) => id,
849 _ => unreachable!(),
850 };
851 let idx = if owner == export || exports_used.contains(&owner) {
852 log::trace!("consulting exports for {id:?}");
853 nested.state.export_type_encoding_maps.id_to_index[&id]
854 } else {
855 log::trace!("consulting imports for {id:?}");
856 nested.state.import_type_encoding_maps.id_to_index[&id]
857 };
858 imports.push((name, ComponentExportKind::Type, idx))
859 }
860
861 nested.type_encoding_maps = imported_type_maps;
866
867 nested.export_types = true;
874 nested.type_encoding_maps.func_type_map.clear();
875
876 for (_, id) in resolve.interfaces[export].types.iter() {
882 let ty = &resolve.types[*id];
883 match ty.kind {
884 TypeDefKind::Resource => {
885 let idx = nested.component.export(
886 ty.name.as_ref().expect("resources must be named"),
887 ComponentExportKind::Type,
888 resources[id],
889 None,
890 );
891 nested.type_encoding_maps.id_to_index.insert(*id, idx);
892 }
893 _ => {
894 nested.encode_valtype(resolve, &Type::Id(*id))?;
895 }
896 }
897 }
898
899 for (i, (_, func)) in resolve.interfaces[export].functions.iter().enumerate() {
900 let ty = nested.encode_func_type(resolve, func)?;
901 nested.component.export(
902 &func.name,
903 ComponentExportKind::Func,
904 i as u32,
905 Some(ComponentTypeRef::Func(ty)),
906 );
907 }
908
909 let component = nested.component;
913 let component_index = self
914 .component
915 .component(Some(&format!("{export_name}-shim-component")), component);
916 let instance_index = self.component.instantiate(
917 Some(&format!("{export_name}-shim-instance")),
918 component_index,
919 imports,
920 );
921 let idx = self.component.export(
922 export_name,
923 ComponentExportKind::Instance,
924 instance_index,
925 None,
926 );
927 let prev = self.exported_instances.insert(export, idx);
928 assert!(prev.is_none());
929
930 for (_name, id) in resolve.interfaces[export].types.iter() {
938 self.export_type_encoding_maps.id_to_index.remove(id);
939 self.export_type_encoding_maps
940 .def_to_index
941 .remove(&resolve.types[*id].kind);
942 }
943
944 return Ok(());
945
946 struct NestedComponentTypeEncoder<'state, 'a> {
947 component: ComponentBuilder,
948 type_encoding_maps: TypeEncodingMaps<'a>,
949 export_types: bool,
950 interface: InterfaceId,
951 state: &'state mut EncodingState<'a>,
952 imports: IndexMap<String, u32>,
953 }
954
955 impl<'a> ValtypeEncoder<'a> for NestedComponentTypeEncoder<'_, 'a> {
956 fn defined_type(&mut self) -> (u32, ComponentDefinedTypeEncoder<'_>) {
957 self.component.type_defined(None)
958 }
959 fn define_function_type(&mut self) -> (u32, ComponentFuncTypeEncoder<'_>) {
960 self.component.type_function(None)
961 }
962 fn export_type(&mut self, idx: u32, name: &'a str) -> Option<u32> {
963 if self.export_types {
964 Some(
965 self.component
966 .export(name, ComponentExportKind::Type, idx, None),
967 )
968 } else {
969 let name = self.unique_import_name(name);
970 let ret = self
971 .component
972 .import(&name, ComponentTypeRef::Type(TypeBounds::Eq(idx)));
973 self.imports.insert(name, ret);
974 Some(ret)
975 }
976 }
977 fn export_resource(&mut self, name: &'a str) -> u32 {
978 if self.export_types {
979 panic!("resources should already be exported")
980 } else {
981 let name = self.unique_import_name(name);
982 let ret = self
983 .component
984 .import(&name, ComponentTypeRef::Type(TypeBounds::SubResource));
985 self.imports.insert(name, ret);
986 ret
987 }
988 }
989 fn import_type(&mut self, _: InterfaceId, _id: TypeId) -> u32 {
990 unreachable!()
991 }
992 fn type_encoding_maps(&mut self) -> &mut TypeEncodingMaps<'a> {
993 &mut self.type_encoding_maps
994 }
995 fn interface(&self) -> Option<InterfaceId> {
996 Some(self.interface)
997 }
998 }
999
1000 impl NestedComponentTypeEncoder<'_, '_> {
1001 fn unique_import_name(&mut self, name: &str) -> String {
1002 let mut name = format!("import-type-{name}");
1003 let mut n = 0;
1004 while self.imports.contains_key(&name) {
1005 name = format!("{name}{n}");
1006 n += 1;
1007 }
1008 name
1009 }
1010 }
1011
1012 fn import_func_name(f: &Function) -> String {
1013 match f.kind {
1014 FunctionKind::Freestanding | FunctionKind::AsyncFreestanding => {
1015 format!("import-func-{}", f.item_name())
1016 }
1017
1018 FunctionKind::Method(_)
1026 | FunctionKind::AsyncMethod(_)
1027 | FunctionKind::Static(_)
1028 | FunctionKind::AsyncStatic(_)
1029 | FunctionKind::Constructor(_) => {
1030 format!(
1031 "import-{}",
1032 f.name.replace('[', "").replace([']', '.', ' '], "-")
1033 )
1034 }
1035 }
1036 }
1037 }
1038
1039 fn encode_lift(
1040 &mut self,
1041 module: CustomModule<'_>,
1042 core_name: &str,
1043 key: &WorldKey,
1044 func: &Function,
1045 ty: u32,
1046 ) -> Result<u32> {
1047 let resolve = &self.info.encoder.metadata.resolve;
1048 let metadata = self.info.module_metadata_for(module);
1049 let instance_index = self.instance_for(module);
1050 let core_func_index =
1051 self.core_alias_export(Some(core_name), instance_index, core_name, ExportKind::Func);
1052 let exports = self.info.exports_for(module);
1053
1054 let options = RequiredOptions::for_export(
1055 resolve,
1056 func,
1057 exports
1058 .abi(key, func)
1059 .ok_or_else(|| anyhow!("no ABI found for {}", func.name))?,
1060 );
1061
1062 let encoding = metadata
1063 .export_encodings
1064 .get(resolve, key, &func.name)
1065 .unwrap();
1066 let exports = self.info.exports_for(module);
1067 let realloc_index = exports
1068 .export_realloc_for(key, &func.name)
1069 .map(|name| self.core_alias_export(Some(name), instance_index, name, ExportKind::Func));
1070 let mut options = options
1071 .into_iter(encoding, self.memory_index, realloc_index)?
1072 .collect::<Vec<_>>();
1073
1074 if let Some(post_return) = exports.post_return(key, func) {
1075 let post_return = self.core_alias_export(
1076 Some(post_return),
1077 instance_index,
1078 post_return,
1079 ExportKind::Func,
1080 );
1081 options.push(CanonicalOption::PostReturn(post_return));
1082 }
1083 if let Some(callback) = exports.callback(key, func) {
1084 let callback =
1085 self.core_alias_export(Some(callback), instance_index, callback, ExportKind::Func);
1086 options.push(CanonicalOption::Callback(callback));
1087 }
1088 let func_index = self
1089 .component
1090 .lift_func(Some(&func.name), core_func_index, ty, options);
1091 Ok(func_index)
1092 }
1093
1094 fn encode_shim_instantiation(&mut self) -> Result<Shims<'a>> {
1095 let mut ret = Shims::default();
1096
1097 ret.append_indirect(self.info, CustomModule::Main)
1098 .context("failed to register indirect shims for main module")?;
1099
1100 for (adapter_name, _adapter) in self.info.adapters.iter() {
1104 ret.append_indirect(self.info, CustomModule::Adapter(adapter_name))
1105 .with_context(|| {
1106 format!("failed to register indirect shims for adapter {adapter_name}")
1107 })?;
1108 }
1109
1110 if ret.shims.is_empty() {
1111 return Ok(ret);
1112 }
1113
1114 assert!(self.shim_instance_index.is_none());
1115 assert!(self.fixups_module_index.is_none());
1116
1117 let mut types = TypeSection::new();
1126 let mut tables = TableSection::new();
1127 let mut functions = FunctionSection::new();
1128 let mut exports = ExportSection::new();
1129 let mut code = CodeSection::new();
1130 let mut sigs = IndexMap::new();
1131 let mut imports_section = ImportSection::new();
1132 let mut elements = ElementSection::new();
1133 let mut func_indexes = Vec::new();
1134 let mut func_names = NameMap::new();
1135
1136 for (i, shim) in ret.shims.values().enumerate() {
1137 let i = i as u32;
1138 let type_index = *sigs.entry(&shim.sig).or_insert_with(|| {
1139 let index = types.len();
1140 types.ty().function(
1141 shim.sig.params.iter().map(to_val_type),
1142 shim.sig.results.iter().map(to_val_type),
1143 );
1144 index
1145 });
1146
1147 functions.function(type_index);
1148 Self::encode_shim_function(type_index, i, &mut code, shim.sig.params.len() as u32);
1149 exports.export(&shim.name, ExportKind::Func, i);
1150
1151 imports_section.import("", &shim.name, EntityType::Function(type_index));
1152 func_indexes.push(i);
1153 func_names.append(i, &shim.debug_name);
1154 }
1155 let mut names = NameSection::new();
1156 names.module("wit-component:shim");
1157 names.functions(&func_names);
1158
1159 let table_type = TableType {
1160 element_type: RefType::FUNCREF,
1161 minimum: ret.shims.len() as u64,
1162 maximum: Some(ret.shims.len() as u64),
1163 table64: false,
1164 shared: false,
1165 };
1166
1167 tables.table(table_type);
1168
1169 exports.export(INDIRECT_TABLE_NAME, ExportKind::Table, 0);
1170 imports_section.import("", INDIRECT_TABLE_NAME, table_type);
1171
1172 elements.active(
1173 None,
1174 &ConstExpr::i32_const(0),
1175 Elements::Functions(func_indexes.into()),
1176 );
1177
1178 let mut shim = Module::new();
1179 shim.section(&types);
1180 shim.section(&functions);
1181 shim.section(&tables);
1182 shim.section(&exports);
1183 shim.section(&code);
1184 shim.section(&RawCustomSection(
1185 &crate::base_producers().raw_custom_section(),
1186 ));
1187 if self.info.encoder.debug_names {
1188 shim.section(&names);
1189 }
1190
1191 let mut fixups = Module::default();
1192 fixups.section(&types);
1193 fixups.section(&imports_section);
1194 fixups.section(&elements);
1195 fixups.section(&RawCustomSection(
1196 &crate::base_producers().raw_custom_section(),
1197 ));
1198
1199 if self.info.encoder.debug_names {
1200 let mut names = NameSection::new();
1201 names.module("wit-component:fixups");
1202 fixups.section(&names);
1203 }
1204
1205 let shim_module_index = self
1206 .component
1207 .core_module(Some("wit-component-shim-module"), &shim);
1208 let fixup_index = self
1209 .component
1210 .core_module(Some("wit-component-fixup"), &fixups);
1211 self.fixups_module_index = Some(fixup_index);
1212 let shim_instance = self.component.core_instantiate(
1213 Some("wit-component-shim-instance"),
1214 shim_module_index,
1215 [],
1216 );
1217 self.shim_instance_index = Some(shim_instance);
1218
1219 return Ok(ret);
1220 }
1221
1222 fn encode_shim_function(
1223 type_index: u32,
1224 func_index: u32,
1225 code: &mut CodeSection,
1226 param_count: u32,
1227 ) {
1228 let mut func = wasm_encoder::Function::new(std::iter::empty());
1229 for i in 0..param_count {
1230 func.instructions().local_get(i);
1231 }
1232 func.instructions().i32_const(func_index as i32);
1233 func.instructions().call_indirect(0, type_index);
1234 func.instructions().end();
1235 code.function(&func);
1236 }
1237
1238 fn encode_indirect_lowerings(&mut self, shims: &Shims<'_>) -> Result<()> {
1239 if shims.shims.is_empty() {
1240 return Ok(());
1241 }
1242
1243 let shim_instance_index = self
1244 .shim_instance_index
1245 .expect("must have an instantiated shim");
1246
1247 let table_index = self.core_alias_export(
1248 Some("shim table"),
1249 shim_instance_index,
1250 INDIRECT_TABLE_NAME,
1251 ExportKind::Table,
1252 );
1253
1254 let resolve = &self.info.encoder.metadata.resolve;
1255
1256 let mut exports = Vec::new();
1257 exports.push((INDIRECT_TABLE_NAME, ExportKind::Table, table_index));
1258
1259 for shim in shims.shims.values() {
1260 let core_func_index = match &shim.kind {
1261 ShimKind::IndirectLowering {
1268 interface,
1269 index,
1270 realloc,
1271 encoding,
1272 } => {
1273 let interface = &self.info.import_map[interface];
1274 let ((name, _), _) = interface.lowerings.get_index(*index).unwrap();
1275 let func_index = match &interface.interface {
1276 Some(interface_id) => {
1277 let instance_index = self.imported_instances[interface_id];
1278 self.component.alias_export(
1279 instance_index,
1280 name,
1281 ComponentExportKind::Func,
1282 )
1283 }
1284 None => self.imported_funcs[name],
1285 };
1286
1287 let realloc = self
1288 .info
1289 .exports_for(*realloc)
1290 .import_realloc_for(interface.interface, name)
1291 .map(|name| {
1292 let instance = self.instance_for(*realloc);
1293 self.core_alias_export(
1294 Some("realloc"),
1295 instance,
1296 name,
1297 ExportKind::Func,
1298 )
1299 });
1300
1301 self.component.lower_func(
1302 Some(&shim.debug_name),
1303 func_index,
1304 shim.options
1305 .into_iter(*encoding, self.memory_index, realloc)?,
1306 )
1307 }
1308
1309 ShimKind::Adapter { adapter, func } => self.core_alias_export(
1314 Some(func),
1315 self.adapter_instances[adapter],
1316 func,
1317 ExportKind::Func,
1318 ),
1319
1320 ShimKind::ResourceDtor { module, export } => self.core_alias_export(
1325 Some(export),
1326 self.instance_for(*module),
1327 export,
1328 ExportKind::Func,
1329 ),
1330
1331 ShimKind::PayloadFunc {
1332 for_module,
1333 info,
1334 kind,
1335 } => {
1336 let metadata = self.info.module_metadata_for(*for_module);
1337 let exports = self.info.exports_for(*for_module);
1338 let instance_index = self.instance_for(*for_module);
1339 let (encoding, realloc) = if info.imported {
1340 (
1341 metadata
1342 .import_encodings
1343 .get(resolve, &info.key, &info.function),
1344 exports.import_realloc_for(info.interface, &info.function),
1345 )
1346 } else {
1347 (
1348 metadata
1349 .export_encodings
1350 .get(resolve, &info.key, &info.function),
1351 exports.export_realloc_for(&info.key, &info.function),
1352 )
1353 };
1354 let encoding = encoding.unwrap_or(StringEncoding::UTF8);
1355 let realloc_index = realloc.map(|name| {
1356 self.core_alias_export(
1357 Some("realloc"),
1358 instance_index,
1359 name,
1360 ExportKind::Func,
1361 )
1362 });
1363 let type_index = self.payload_type_index(info)?;
1364 let options =
1365 shim.options
1366 .into_iter(encoding, self.memory_index, realloc_index)?;
1367
1368 match kind {
1369 PayloadFuncKind::FutureWrite => {
1370 self.component.future_write(type_index, options)
1371 }
1372 PayloadFuncKind::FutureRead => {
1373 self.component.future_read(type_index, options)
1374 }
1375 PayloadFuncKind::StreamWrite => {
1376 self.component.stream_write(type_index, options)
1377 }
1378 PayloadFuncKind::StreamRead => {
1379 self.component.stream_read(type_index, options)
1380 }
1381 }
1382 }
1383
1384 ShimKind::WaitableSetWait { cancellable } => self
1385 .component
1386 .waitable_set_wait(*cancellable, self.memory_index.unwrap()),
1387 ShimKind::WaitableSetPoll { cancellable } => self
1388 .component
1389 .waitable_set_poll(*cancellable, self.memory_index.unwrap()),
1390 ShimKind::ErrorContextNew { encoding } => self.component.error_context_new(
1391 shim.options.into_iter(*encoding, self.memory_index, None)?,
1392 ),
1393 ShimKind::ErrorContextDebugMessage {
1394 for_module,
1395 encoding,
1396 } => {
1397 let instance_index = self.instance_for(*for_module);
1398 let realloc = self.info.exports_for(*for_module).import_realloc_fallback();
1399 let realloc_index = realloc.map(|r| {
1400 self.core_alias_export(Some("realloc"), instance_index, r, ExportKind::Func)
1401 });
1402
1403 self.component
1404 .error_context_debug_message(shim.options.into_iter(
1405 *encoding,
1406 self.memory_index,
1407 realloc_index,
1408 )?)
1409 }
1410 ShimKind::TaskReturn {
1411 interface,
1412 func,
1413 result,
1414 encoding,
1415 for_module,
1416 } => {
1417 let mut encoder = if interface.is_none() {
1420 self.root_import_type_encoder(*interface)
1421 } else {
1422 self.root_export_type_encoder(*interface)
1423 };
1424 let result = match result {
1425 Some(ty) => Some(encoder.encode_valtype(resolve, ty)?),
1426 None => None,
1427 };
1428
1429 let exports = self.info.exports_for(*for_module);
1430 let realloc = exports.import_realloc_for(*interface, func);
1431
1432 let instance_index = self.instance_for(*for_module);
1433 let realloc_index = realloc.map(|r| {
1434 self.core_alias_export(Some("realloc"), instance_index, r, ExportKind::Func)
1435 });
1436 let options =
1437 shim.options
1438 .into_iter(*encoding, self.memory_index, realloc_index)?;
1439 self.component.task_return(result, options)
1440 }
1441 ShimKind::ThreadNewIndirect {
1442 for_module,
1443 func_ty,
1444 } => {
1445 let (func_ty_idx, f) = self.component.core_type(Some("thread-start"));
1447 f.core().func_type(func_ty);
1448
1449 let exports = self.info.exports_for(*for_module);
1452 let instance_index = self.instance_for(*for_module);
1453 let table_idx = exports.indirect_function_table().map(|table| {
1454 self.core_alias_export(
1455 Some("indirect-function-table"),
1456 instance_index,
1457 table,
1458 ExportKind::Table,
1459 )
1460 }).ok_or_else(|| {
1461 anyhow!(
1462 "table __indirect_function_table must be an exported funcref table for thread.new_indirect"
1463 )
1464 })?;
1465
1466 self.component.thread_new_indirect(func_ty_idx, table_idx)
1467 }
1468 };
1469
1470 exports.push((shim.name.as_str(), ExportKind::Func, core_func_index));
1471 }
1472
1473 let instance_index = self
1474 .component
1475 .core_instantiate_exports(Some("fixup-args"), exports);
1476 self.component.core_instantiate(
1477 Some("fixup"),
1478 self.fixups_module_index.expect("must have fixup module"),
1479 [("", ModuleArg::Instance(instance_index))],
1480 );
1481 Ok(())
1482 }
1483
1484 fn payload_type_index(&mut self, info: &PayloadInfo) -> Result<u32> {
1492 let resolve = &self.info.encoder.metadata.resolve;
1493 let ComponentValType::Type(type_index) = if info.imported || info.interface.is_none() {
1509 self.root_import_type_encoder(None)
1510 } else {
1511 self.root_export_type_encoder(info.interface)
1512 }
1513 .encode_valtype(resolve, &Type::Id(info.ty))?
1514 else {
1515 unreachable!()
1516 };
1517 Ok(type_index)
1518 }
1519
1520 fn declare_types_for_imported_intrinsics(&mut self, shims: &Shims<'_>) -> Result<()> {
1527 let resolve = &self.info.encoder.metadata.resolve;
1528 let world = &resolve.worlds[self.info.encoder.metadata.world];
1529
1530 let main_module_keys = self.info.encoder.main_module_exports.iter();
1533 let main_module_keys = main_module_keys.map(|key| (CustomModule::Main, key));
1534 let adapter_keys = self.info.encoder.adapters.iter().flat_map(|(name, info)| {
1535 info.required_exports
1536 .iter()
1537 .map(move |key| (CustomModule::Adapter(name), key))
1538 });
1539 for (for_module, key) in main_module_keys.chain(adapter_keys) {
1540 let id = match &world.exports[key] {
1541 WorldItem::Interface { id, .. } => *id,
1542 WorldItem::Type { .. } => unreachable!(),
1543 WorldItem::Function(_) => continue,
1544 };
1545
1546 for ty in resolve.interfaces[id].types.values() {
1547 let def = &resolve.types[*ty];
1548 match &def.kind {
1549 TypeDefKind::Resource => {
1553 let exports = self.info.exports_for(for_module);
1556 let dtor = exports.resource_dtor(*ty).map(|name| {
1557 let shim = &shims.shims[&ShimKind::ResourceDtor {
1558 module: for_module,
1559 export: name,
1560 }];
1561 let index = self.shim_instance_index.unwrap();
1562 self.core_alias_export(
1563 Some(&shim.debug_name),
1564 index,
1565 &shim.name,
1566 ExportKind::Func,
1567 )
1568 });
1569
1570 let resource_idx = self.component.type_resource(
1574 Some(def.name.as_ref().unwrap()),
1575 ValType::I32,
1576 dtor,
1577 );
1578 let prev = self
1579 .export_type_encoding_maps
1580 .id_to_index
1581 .insert(*ty, resource_idx);
1582 assert!(prev.is_none());
1583 }
1584 _other => {
1585 self.root_export_type_encoder(Some(id))
1586 .encode_valtype(resolve, &Type::Id(*ty))?;
1587 }
1588 }
1589 }
1590 }
1591 Ok(())
1592 }
1593
1594 fn instantiate_main_module(&mut self, shims: &Shims<'_>) -> Result<()> {
1597 assert!(self.instance_index.is_none());
1598
1599 let instance_index = self.instantiate_core_module(shims, CustomModule::Main)?;
1600
1601 if let Some(memory) = self.info.info.exports.memory() {
1602 self.memory_index = Some(self.core_alias_export(
1603 Some("memory"),
1604 instance_index,
1605 memory,
1606 ExportKind::Memory,
1607 ));
1608 }
1609
1610 self.instance_index = Some(instance_index);
1611 Ok(())
1612 }
1613
1614 fn instantiate_adapter_module(&mut self, shims: &Shims<'_>, name: &'a str) -> Result<()> {
1617 let instance = self.instantiate_core_module(shims, CustomModule::Adapter(name))?;
1618 self.adapter_instances.insert(name, instance);
1619 Ok(())
1620 }
1621
1622 fn instantiate_core_module(
1629 &mut self,
1630 shims: &Shims,
1631 for_module: CustomModule<'_>,
1632 ) -> Result<u32> {
1633 let module = self.module_for(for_module);
1634
1635 let mut args = Vec::new();
1636 for (core_wasm_name, instance) in self.info.imports_for(for_module).modules() {
1637 match instance {
1638 ImportInstance::Names(names) => {
1644 let mut exports = Vec::new();
1645 for (name, import) in names {
1646 log::trace!(
1647 "attempting to materialize import of `{core_wasm_name}::{name}` for {for_module:?}"
1648 );
1649 let (kind, index) = self
1650 .materialize_import(&shims, for_module, import)
1651 .with_context(|| {
1652 format!("failed to satisfy import `{core_wasm_name}::{name}`")
1653 })?;
1654 exports.push((name.as_str(), kind, index));
1655 }
1656 let index = self
1657 .component
1658 .core_instantiate_exports(Some(core_wasm_name), exports);
1659 args.push((core_wasm_name.as_str(), ModuleArg::Instance(index)));
1660 }
1661
1662 ImportInstance::Whole(which) => {
1665 let instance = self.instance_for(which.to_custom_module());
1666 args.push((core_wasm_name.as_str(), ModuleArg::Instance(instance)));
1667 }
1668 }
1669 }
1670
1671 Ok(self
1673 .component
1674 .core_instantiate(Some(for_module.debug_name()), module, args))
1675 }
1676
1677 fn materialize_import(
1684 &mut self,
1685 shims: &Shims<'_>,
1686 for_module: CustomModule<'_>,
1687 import: &'a Import,
1688 ) -> Result<(ExportKind, u32)> {
1689 let resolve = &self.info.encoder.metadata.resolve;
1690 match import {
1691 Import::AdapterExport {
1694 adapter,
1695 func,
1696 ty: _,
1697 } => {
1698 assert!(self.info.encoder.adapters.contains_key(adapter));
1699 Ok(self.materialize_shim_import(shims, &ShimKind::Adapter { adapter, func }))
1700 }
1701
1702 Import::MainModuleMemory => {
1705 let index = self
1706 .memory_index
1707 .ok_or_else(|| anyhow!("main module cannot import memory"))?;
1708 Ok((ExportKind::Memory, index))
1709 }
1710
1711 Import::MainModuleExport { name, kind } => {
1713 let instance = self.instance_index.unwrap();
1714 let index = self.core_alias_export(Some(name), instance, name, *kind);
1715 Ok((*kind, index))
1716 }
1717
1718 Import::Item(item) => {
1722 let instance = self.instance_for(item.which.to_custom_module());
1723 let index =
1724 self.core_alias_export(Some(&item.name), instance, &item.name, item.kind);
1725 Ok((item.kind, index))
1726 }
1727
1728 Import::ExportedResourceDrop(_key, id) => {
1734 let index = self
1735 .component
1736 .resource_drop(self.export_type_encoding_maps.id_to_index[id]);
1737 Ok((ExportKind::Func, index))
1738 }
1739 Import::ExportedResourceRep(_key, id) => {
1740 let index = self
1741 .component
1742 .resource_rep(self.export_type_encoding_maps.id_to_index[id]);
1743 Ok((ExportKind::Func, index))
1744 }
1745 Import::ExportedResourceNew(_key, id) => {
1746 let index = self
1747 .component
1748 .resource_new(self.export_type_encoding_maps.id_to_index[id]);
1749 Ok((ExportKind::Func, index))
1750 }
1751
1752 Import::ImportedResourceDrop(key, iface, id) => {
1757 let ty = &resolve.types[*id];
1758 let name = ty.name.as_ref().unwrap();
1759 self.materialize_wit_import(
1760 shims,
1761 for_module,
1762 iface.map(|_| resolve.name_world_key(key)),
1763 &format!("{name}_drop"),
1764 key,
1765 AbiVariant::GuestImport,
1766 )
1767 }
1768 Import::ExportedTaskReturn(key, interface, func, result) => {
1769 let (options, _sig) = task_return_options_and_type(resolve, *result);
1770 if options.is_empty() {
1771 let mut encoder = if interface.is_none() {
1777 self.root_import_type_encoder(*interface)
1778 } else {
1779 self.root_export_type_encoder(*interface)
1780 };
1781
1782 let result = match result {
1783 Some(ty) => Some(encoder.encode_valtype(resolve, ty)?),
1784 None => None,
1785 };
1786 let index = self.component.task_return(result, []);
1787 Ok((ExportKind::Func, index))
1788 } else {
1789 let metadata = &self.info.module_metadata_for(for_module);
1790 let encoding = metadata.export_encodings.get(resolve, key, func).unwrap();
1791 Ok(self.materialize_shim_import(
1792 shims,
1793 &ShimKind::TaskReturn {
1794 for_module,
1795 interface: *interface,
1796 func,
1797 result: *result,
1798 encoding,
1799 },
1800 ))
1801 }
1802 }
1803 Import::BackpressureSet => {
1804 let index = self.component.backpressure_set();
1805 Ok((ExportKind::Func, index))
1806 }
1807 Import::BackpressureInc => {
1808 let index = self.component.backpressure_inc();
1809 Ok((ExportKind::Func, index))
1810 }
1811 Import::BackpressureDec => {
1812 let index = self.component.backpressure_dec();
1813 Ok((ExportKind::Func, index))
1814 }
1815 Import::WaitableSetWait { cancellable } => Ok(self.materialize_shim_import(
1816 shims,
1817 &ShimKind::WaitableSetWait {
1818 cancellable: *cancellable,
1819 },
1820 )),
1821 Import::WaitableSetPoll { cancellable } => Ok(self.materialize_shim_import(
1822 shims,
1823 &ShimKind::WaitableSetPoll {
1824 cancellable: *cancellable,
1825 },
1826 )),
1827 Import::ThreadYield { cancellable } => {
1828 let index = self.component.thread_yield(*cancellable);
1829 Ok((ExportKind::Func, index))
1830 }
1831 Import::SubtaskDrop => {
1832 let index = self.component.subtask_drop();
1833 Ok((ExportKind::Func, index))
1834 }
1835 Import::SubtaskCancel { async_ } => {
1836 let index = self.component.subtask_cancel(*async_);
1837 Ok((ExportKind::Func, index))
1838 }
1839 Import::StreamNew(info) => {
1840 let ty = self.payload_type_index(info)?;
1841 let index = self.component.stream_new(ty);
1842 Ok((ExportKind::Func, index))
1843 }
1844 Import::StreamRead { info, .. } => Ok(self.materialize_payload_import(
1845 shims,
1846 for_module,
1847 info,
1848 PayloadFuncKind::StreamRead,
1849 )),
1850 Import::StreamWrite { info, .. } => Ok(self.materialize_payload_import(
1851 shims,
1852 for_module,
1853 info,
1854 PayloadFuncKind::StreamWrite,
1855 )),
1856 Import::StreamCancelRead { info, async_ } => {
1857 let ty = self.payload_type_index(info)?;
1858 let index = self.component.stream_cancel_read(ty, *async_);
1859 Ok((ExportKind::Func, index))
1860 }
1861 Import::StreamCancelWrite { info, async_ } => {
1862 let ty = self.payload_type_index(info)?;
1863 let index = self.component.stream_cancel_write(ty, *async_);
1864 Ok((ExportKind::Func, index))
1865 }
1866 Import::StreamDropReadable(info) => {
1867 let type_index = self.payload_type_index(info)?;
1868 let index = self.component.stream_drop_readable(type_index);
1869 Ok((ExportKind::Func, index))
1870 }
1871 Import::StreamDropWritable(info) => {
1872 let type_index = self.payload_type_index(info)?;
1873 let index = self.component.stream_drop_writable(type_index);
1874 Ok((ExportKind::Func, index))
1875 }
1876 Import::FutureNew(info) => {
1877 let ty = self.payload_type_index(info)?;
1878 let index = self.component.future_new(ty);
1879 Ok((ExportKind::Func, index))
1880 }
1881 Import::FutureRead { info, .. } => Ok(self.materialize_payload_import(
1882 shims,
1883 for_module,
1884 info,
1885 PayloadFuncKind::FutureRead,
1886 )),
1887 Import::FutureWrite { info, .. } => Ok(self.materialize_payload_import(
1888 shims,
1889 for_module,
1890 info,
1891 PayloadFuncKind::FutureWrite,
1892 )),
1893 Import::FutureCancelRead { info, async_ } => {
1894 let ty = self.payload_type_index(info)?;
1895 let index = self.component.future_cancel_read(ty, *async_);
1896 Ok((ExportKind::Func, index))
1897 }
1898 Import::FutureCancelWrite { info, async_ } => {
1899 let ty = self.payload_type_index(info)?;
1900 let index = self.component.future_cancel_write(ty, *async_);
1901 Ok((ExportKind::Func, index))
1902 }
1903 Import::FutureDropReadable(info) => {
1904 let type_index = self.payload_type_index(info)?;
1905 let index = self.component.future_drop_readable(type_index);
1906 Ok((ExportKind::Func, index))
1907 }
1908 Import::FutureDropWritable(info) => {
1909 let type_index = self.payload_type_index(info)?;
1910 let index = self.component.future_drop_writable(type_index);
1911 Ok((ExportKind::Func, index))
1912 }
1913 Import::ErrorContextNew { encoding } => Ok(self.materialize_shim_import(
1914 shims,
1915 &ShimKind::ErrorContextNew {
1916 encoding: *encoding,
1917 },
1918 )),
1919 Import::ErrorContextDebugMessage { encoding } => Ok(self.materialize_shim_import(
1920 shims,
1921 &ShimKind::ErrorContextDebugMessage {
1922 for_module,
1923 encoding: *encoding,
1924 },
1925 )),
1926 Import::ErrorContextDrop => {
1927 let index = self.component.error_context_drop();
1928 Ok((ExportKind::Func, index))
1929 }
1930 Import::WorldFunc(key, name, abi) => {
1931 self.materialize_wit_import(shims, for_module, None, name, key, *abi)
1932 }
1933 Import::InterfaceFunc(key, _, name, abi) => self.materialize_wit_import(
1934 shims,
1935 for_module,
1936 Some(resolve.name_world_key(key)),
1937 name,
1938 key,
1939 *abi,
1940 ),
1941
1942 Import::WaitableSetNew => {
1943 let index = self.component.waitable_set_new();
1944 Ok((ExportKind::Func, index))
1945 }
1946 Import::WaitableSetDrop => {
1947 let index = self.component.waitable_set_drop();
1948 Ok((ExportKind::Func, index))
1949 }
1950 Import::WaitableJoin => {
1951 let index = self.component.waitable_join();
1952 Ok((ExportKind::Func, index))
1953 }
1954 Import::ContextGet(n) => {
1955 let index = self.component.context_get(*n);
1956 Ok((ExportKind::Func, index))
1957 }
1958 Import::ContextSet(n) => {
1959 let index = self.component.context_set(*n);
1960 Ok((ExportKind::Func, index))
1961 }
1962 Import::ExportedTaskCancel => {
1963 let index = self.component.task_cancel();
1964 Ok((ExportKind::Func, index))
1965 }
1966 Import::ThreadIndex => {
1967 let index = self.component.thread_index();
1968 Ok((ExportKind::Func, index))
1969 }
1970 Import::ThreadNewIndirect => Ok(self.materialize_shim_import(
1971 shims,
1972 &ShimKind::ThreadNewIndirect {
1973 for_module,
1974 func_ty: FuncType::new([ValType::I32], []),
1976 },
1977 )),
1978 Import::ThreadSwitchTo { cancellable } => {
1979 let index = self.component.thread_switch_to(*cancellable);
1980 Ok((ExportKind::Func, index))
1981 }
1982 Import::ThreadSuspend { cancellable } => {
1983 let index = self.component.thread_suspend(*cancellable);
1984 Ok((ExportKind::Func, index))
1985 }
1986 Import::ThreadResumeLater => {
1987 let index = self.component.thread_resume_later();
1988 Ok((ExportKind::Func, index))
1989 }
1990 Import::ThreadYieldTo { cancellable } => {
1991 let index = self.component.thread_yield_to(*cancellable);
1992 Ok((ExportKind::Func, index))
1993 }
1994 }
1995 }
1996
1997 fn materialize_shim_import(&mut self, shims: &Shims<'_>, kind: &ShimKind) -> (ExportKind, u32) {
2000 let index = self.core_alias_export(
2001 Some(&shims.shims[kind].debug_name),
2002 self.shim_instance_index
2003 .expect("shim should be instantiated"),
2004 &shims.shims[kind].name,
2005 ExportKind::Func,
2006 );
2007 (ExportKind::Func, index)
2008 }
2009
2010 fn materialize_payload_import(
2013 &mut self,
2014 shims: &Shims<'_>,
2015 for_module: CustomModule<'_>,
2016 info: &PayloadInfo,
2017 kind: PayloadFuncKind,
2018 ) -> (ExportKind, u32) {
2019 self.materialize_shim_import(
2020 shims,
2021 &ShimKind::PayloadFunc {
2022 for_module,
2023 info,
2024 kind,
2025 },
2026 )
2027 }
2028
2029 fn materialize_wit_import(
2032 &mut self,
2033 shims: &Shims<'_>,
2034 for_module: CustomModule<'_>,
2035 interface_key: Option<String>,
2036 name: &String,
2037 key: &WorldKey,
2038 abi: AbiVariant,
2039 ) -> Result<(ExportKind, u32)> {
2040 let resolve = &self.info.encoder.metadata.resolve;
2041 let import = &self.info.import_map[&interface_key];
2042 let (index, _, lowering) = import.lowerings.get_full(&(name.clone(), abi)).unwrap();
2043 let metadata = self.info.module_metadata_for(for_module);
2044
2045 let index = match lowering {
2046 Lowering::Direct => {
2049 let func_index = match &import.interface {
2050 Some(interface) => {
2051 let instance_index = self.imported_instances[interface];
2052 self.component
2053 .alias_export(instance_index, name, ComponentExportKind::Func)
2054 }
2055 None => self.imported_funcs[name],
2056 };
2057 self.component.lower_func(
2058 Some(name),
2059 func_index,
2060 if let AbiVariant::GuestImportAsync = abi {
2061 vec![CanonicalOption::Async]
2062 } else {
2063 Vec::new()
2064 },
2065 )
2066 }
2067
2068 Lowering::Indirect { .. } => {
2072 let encoding = metadata.import_encodings.get(resolve, key, name).unwrap();
2073 return Ok(self.materialize_shim_import(
2074 shims,
2075 &ShimKind::IndirectLowering {
2076 interface: interface_key,
2077 index,
2078 realloc: for_module,
2079 encoding,
2080 },
2081 ));
2082 }
2083
2084 Lowering::ResourceDrop(id) => {
2087 let resource_idx = self.lookup_resource_index(*id);
2088 self.component.resource_drop(resource_idx)
2089 }
2090 };
2091 Ok((ExportKind::Func, index))
2092 }
2093
2094 fn encode_initialize_with_start(&mut self) -> Result<()> {
2113 let initialize = match self.info.info.exports.initialize() {
2114 Some(name) => name,
2115 None => return Ok(()),
2118 };
2119 let initialize_index = self.core_alias_export(
2120 Some("start"),
2121 self.instance_index.unwrap(),
2122 initialize,
2123 ExportKind::Func,
2124 );
2125 let mut shim = Module::default();
2126 let mut section = TypeSection::new();
2127 section.ty().function([], []);
2128 shim.section(§ion);
2129 let mut section = ImportSection::new();
2130 section.import("", "", EntityType::Function(0));
2131 shim.section(§ion);
2132 shim.section(&StartSection { function_index: 0 });
2133
2134 let shim_module_index = self.component.core_module(Some("start-shim-module"), &shim);
2139 let shim_args_instance_index = self.component.core_instantiate_exports(
2140 Some("start-shim-args"),
2141 [("", ExportKind::Func, initialize_index)],
2142 );
2143 self.component.core_instantiate(
2144 Some("start-shim-instance"),
2145 shim_module_index,
2146 [("", ModuleArg::Instance(shim_args_instance_index))],
2147 );
2148 Ok(())
2149 }
2150
2151 fn instance_for(&self, module: CustomModule) -> u32 {
2154 match module {
2155 CustomModule::Main => self.instance_index.expect("instantiated by now"),
2156 CustomModule::Adapter(name) => self.adapter_instances[name],
2157 }
2158 }
2159
2160 fn module_for(&self, module: CustomModule) -> u32 {
2163 match module {
2164 CustomModule::Main => self.module_index.unwrap(),
2165 CustomModule::Adapter(name) => self.adapter_modules[name],
2166 }
2167 }
2168
2169 fn core_alias_export(
2172 &mut self,
2173 debug_name: Option<&str>,
2174 instance: u32,
2175 name: &str,
2176 kind: ExportKind,
2177 ) -> u32 {
2178 *self
2179 .aliased_core_items
2180 .entry((instance, name.to_string()))
2181 .or_insert_with(|| {
2182 self.component
2183 .core_alias_export(debug_name, instance, name, kind)
2184 })
2185 }
2186}
2187
2188#[derive(Default)]
2206struct Shims<'a> {
2207 shims: IndexMap<ShimKind<'a>, Shim<'a>>,
2209}
2210
2211struct Shim<'a> {
2212 options: RequiredOptions,
2215
2216 name: String,
2220
2221 debug_name: String,
2224
2225 kind: ShimKind<'a>,
2227
2228 sig: WasmSignature,
2230}
2231
2232#[derive(Debug, Clone, Hash, Eq, PartialEq)]
2235enum PayloadFuncKind {
2236 FutureWrite,
2237 FutureRead,
2238 StreamWrite,
2239 StreamRead,
2240}
2241
2242#[derive(Debug, Clone, Hash, Eq, PartialEq)]
2243enum ShimKind<'a> {
2244 IndirectLowering {
2248 interface: Option<String>,
2250 index: usize,
2252 realloc: CustomModule<'a>,
2254 encoding: StringEncoding,
2256 },
2257 Adapter {
2260 adapter: &'a str,
2262 func: &'a str,
2264 },
2265 ResourceDtor {
2268 module: CustomModule<'a>,
2270 export: &'a str,
2272 },
2273 PayloadFunc {
2277 for_module: CustomModule<'a>,
2280 info: &'a PayloadInfo,
2285 kind: PayloadFuncKind,
2287 },
2288 WaitableSetWait { cancellable: bool },
2292 WaitableSetPoll { cancellable: bool },
2296 TaskReturn {
2298 interface: Option<InterfaceId>,
2301 func: &'a str,
2304 result: Option<Type>,
2306 for_module: CustomModule<'a>,
2308 encoding: StringEncoding,
2310 },
2311 ErrorContextNew {
2315 encoding: StringEncoding,
2317 },
2318 ErrorContextDebugMessage {
2322 for_module: CustomModule<'a>,
2324 encoding: StringEncoding,
2326 },
2327 ThreadNewIndirect {
2330 for_module: CustomModule<'a>,
2332 func_ty: FuncType,
2334 },
2335}
2336
2337#[derive(Debug, Copy, Clone, Hash, Eq, PartialEq)]
2347enum CustomModule<'a> {
2348 Main,
2351 Adapter(&'a str),
2354}
2355
2356impl<'a> CustomModule<'a> {
2357 fn debug_name(&self) -> &'a str {
2358 match self {
2359 CustomModule::Main => "main",
2360 CustomModule::Adapter(s) => s,
2361 }
2362 }
2363}
2364
2365impl<'a> Shims<'a> {
2366 fn append_indirect(
2371 &mut self,
2372 world: &'a ComponentWorld<'a>,
2373 for_module: CustomModule<'a>,
2374 ) -> Result<()> {
2375 let module_imports = world.imports_for(for_module);
2376 let module_exports = world.exports_for(for_module);
2377 let resolve = &world.encoder.metadata.resolve;
2378
2379 for (module, field, import) in module_imports.imports() {
2380 match import {
2381 Import::ImportedResourceDrop(..)
2384 | Import::MainModuleMemory
2385 | Import::MainModuleExport { .. }
2386 | Import::Item(_)
2387 | Import::ExportedResourceDrop(..)
2388 | Import::ExportedResourceRep(..)
2389 | Import::ExportedResourceNew(..)
2390 | Import::ExportedTaskCancel
2391 | Import::ErrorContextDrop
2392 | Import::BackpressureSet
2393 | Import::BackpressureInc
2394 | Import::BackpressureDec
2395 | Import::ThreadYield { .. }
2396 | Import::SubtaskDrop
2397 | Import::SubtaskCancel { .. }
2398 | Import::FutureNew(..)
2399 | Import::StreamNew(..)
2400 | Import::FutureCancelRead { .. }
2401 | Import::FutureCancelWrite { .. }
2402 | Import::FutureDropWritable { .. }
2403 | Import::FutureDropReadable { .. }
2404 | Import::StreamCancelRead { .. }
2405 | Import::StreamCancelWrite { .. }
2406 | Import::StreamDropWritable { .. }
2407 | Import::StreamDropReadable { .. }
2408 | Import::WaitableSetNew
2409 | Import::WaitableSetDrop
2410 | Import::WaitableJoin
2411 | Import::ContextGet(_)
2412 | Import::ContextSet(_)
2413 | Import::ThreadIndex
2414 | Import::ThreadSwitchTo { .. }
2415 | Import::ThreadSuspend { .. }
2416 | Import::ThreadResumeLater
2417 | Import::ThreadYieldTo { .. } => {}
2418
2419 Import::ExportedTaskReturn(key, interface, func, ty) => {
2423 let (options, sig) = task_return_options_and_type(resolve, *ty);
2424 if options.is_empty() {
2425 continue;
2426 }
2427 let name = self.shims.len().to_string();
2428 let encoding = world
2429 .module_metadata_for(for_module)
2430 .export_encodings
2431 .get(resolve, key, func)
2432 .ok_or_else(|| {
2433 anyhow::anyhow!(
2434 "missing component metadata for export of \
2435 `{module}::{field}`"
2436 )
2437 })?;
2438 self.push(Shim {
2439 name,
2440 debug_name: format!("task-return-{func}"),
2441 options,
2442 kind: ShimKind::TaskReturn {
2443 interface: *interface,
2444 func,
2445 result: *ty,
2446 for_module,
2447 encoding,
2448 },
2449 sig,
2450 });
2451 }
2452
2453 Import::FutureWrite { async_, info } => {
2454 self.append_indirect_payload_push(
2455 resolve,
2456 for_module,
2457 module,
2458 *async_,
2459 info,
2460 PayloadFuncKind::FutureWrite,
2461 vec![WasmType::I32; 2],
2462 vec![WasmType::I32],
2463 );
2464 }
2465 Import::FutureRead { async_, info } => {
2466 self.append_indirect_payload_push(
2467 resolve,
2468 for_module,
2469 module,
2470 *async_,
2471 info,
2472 PayloadFuncKind::FutureRead,
2473 vec![WasmType::I32; 2],
2474 vec![WasmType::I32],
2475 );
2476 }
2477 Import::StreamWrite { async_, info } => {
2478 self.append_indirect_payload_push(
2479 resolve,
2480 for_module,
2481 module,
2482 *async_,
2483 info,
2484 PayloadFuncKind::StreamWrite,
2485 vec![WasmType::I32; 3],
2486 vec![WasmType::I32],
2487 );
2488 }
2489 Import::StreamRead { async_, info } => {
2490 self.append_indirect_payload_push(
2491 resolve,
2492 for_module,
2493 module,
2494 *async_,
2495 info,
2496 PayloadFuncKind::StreamRead,
2497 vec![WasmType::I32; 3],
2498 vec![WasmType::I32],
2499 );
2500 }
2501
2502 Import::WaitableSetWait { cancellable } => {
2503 let name = self.shims.len().to_string();
2504 self.push(Shim {
2505 name,
2506 debug_name: "waitable-set.wait".to_string(),
2507 options: RequiredOptions::empty(),
2508 kind: ShimKind::WaitableSetWait {
2509 cancellable: *cancellable,
2510 },
2511 sig: WasmSignature {
2512 params: vec![WasmType::I32; 2],
2513 results: vec![WasmType::I32],
2514 indirect_params: false,
2515 retptr: false,
2516 },
2517 });
2518 }
2519
2520 Import::WaitableSetPoll { cancellable } => {
2521 let name = self.shims.len().to_string();
2522 self.push(Shim {
2523 name,
2524 debug_name: "waitable-set.poll".to_string(),
2525 options: RequiredOptions::empty(),
2526 kind: ShimKind::WaitableSetPoll {
2527 cancellable: *cancellable,
2528 },
2529 sig: WasmSignature {
2530 params: vec![WasmType::I32; 2],
2531 results: vec![WasmType::I32],
2532 indirect_params: false,
2533 retptr: false,
2534 },
2535 });
2536 }
2537
2538 Import::ErrorContextNew { encoding } => {
2539 let name = self.shims.len().to_string();
2540 self.push(Shim {
2541 name,
2542 debug_name: "error-new".to_string(),
2543 options: RequiredOptions::MEMORY | RequiredOptions::STRING_ENCODING,
2544 kind: ShimKind::ErrorContextNew {
2545 encoding: *encoding,
2546 },
2547 sig: WasmSignature {
2548 params: vec![WasmType::I32; 2],
2549 results: vec![WasmType::I32],
2550 indirect_params: false,
2551 retptr: false,
2552 },
2553 });
2554 }
2555
2556 Import::ErrorContextDebugMessage { encoding } => {
2557 let name = self.shims.len().to_string();
2558 self.push(Shim {
2559 name,
2560 debug_name: "error-debug-message".to_string(),
2561 options: RequiredOptions::MEMORY
2562 | RequiredOptions::STRING_ENCODING
2563 | RequiredOptions::REALLOC,
2564 kind: ShimKind::ErrorContextDebugMessage {
2565 for_module,
2566 encoding: *encoding,
2567 },
2568 sig: WasmSignature {
2569 params: vec![WasmType::I32; 2],
2570 results: vec![],
2571 indirect_params: false,
2572 retptr: false,
2573 },
2574 });
2575 }
2576
2577 Import::ThreadNewIndirect => {
2578 let name = self.shims.len().to_string();
2579 self.push(Shim {
2580 name,
2581 debug_name: "thread.new_indirect".to_string(),
2582 options: RequiredOptions::empty(),
2583 kind: ShimKind::ThreadNewIndirect {
2584 for_module,
2585 func_ty: FuncType::new([ValType::I32], vec![]),
2587 },
2588 sig: WasmSignature {
2589 params: vec![WasmType::I32; 2],
2590 results: vec![WasmType::I32],
2591 indirect_params: false,
2592 retptr: false,
2593 },
2594 });
2595 }
2596
2597 Import::AdapterExport { adapter, func, ty } => {
2600 let name = self.shims.len().to_string();
2601 log::debug!("shim {name} is adapter `{module}::{field}`");
2602 self.push(Shim {
2603 name,
2604 debug_name: format!("adapt-{module}-{field}"),
2605 options: RequiredOptions::MEMORY,
2609 kind: ShimKind::Adapter { adapter, func },
2610 sig: WasmSignature {
2611 params: ty.params().iter().map(to_wasm_type).collect(),
2612 results: ty.results().iter().map(to_wasm_type).collect(),
2613 indirect_params: false,
2614 retptr: false,
2615 },
2616 });
2617
2618 fn to_wasm_type(ty: &wasmparser::ValType) -> WasmType {
2619 match ty {
2620 wasmparser::ValType::I32 => WasmType::I32,
2621 wasmparser::ValType::I64 => WasmType::I64,
2622 wasmparser::ValType::F32 => WasmType::F32,
2623 wasmparser::ValType::F64 => WasmType::F64,
2624 _ => unreachable!(),
2625 }
2626 }
2627 }
2628
2629 Import::InterfaceFunc(key, _, name, abi) => {
2633 self.append_indirect_wit_func(
2634 world,
2635 for_module,
2636 module,
2637 field,
2638 key,
2639 name,
2640 Some(resolve.name_world_key(key)),
2641 *abi,
2642 )?;
2643 }
2644 Import::WorldFunc(key, name, abi) => {
2645 self.append_indirect_wit_func(
2646 world, for_module, module, field, key, name, None, *abi,
2647 )?;
2648 }
2649 }
2650 }
2651
2652 for (export_name, export) in module_exports.iter() {
2658 let id = match export {
2659 Export::ResourceDtor(id) => id,
2660 _ => continue,
2661 };
2662 let resource = resolve.types[*id].name.as_ref().unwrap();
2663 let name = self.shims.len().to_string();
2664 self.push(Shim {
2665 name,
2666 debug_name: format!("dtor-{resource}"),
2667 options: RequiredOptions::empty(),
2668 kind: ShimKind::ResourceDtor {
2669 module: for_module,
2670 export: export_name,
2671 },
2672 sig: WasmSignature {
2673 params: vec![WasmType::I32],
2674 results: Vec::new(),
2675 indirect_params: false,
2676 retptr: false,
2677 },
2678 });
2679 }
2680
2681 Ok(())
2682 }
2683
2684 fn append_indirect_payload_push(
2687 &mut self,
2688 resolve: &Resolve,
2689 for_module: CustomModule<'a>,
2690 module: &str,
2691 async_: bool,
2692 info: &'a PayloadInfo,
2693 kind: PayloadFuncKind,
2694 params: Vec<WasmType>,
2695 results: Vec<WasmType>,
2696 ) {
2697 let debug_name = format!("{module}-{}", info.name);
2698 let name = self.shims.len().to_string();
2699
2700 let payload = info.payload(resolve);
2701 let (wit_param, wit_result) = match kind {
2702 PayloadFuncKind::StreamRead | PayloadFuncKind::FutureRead => (None, payload),
2703 PayloadFuncKind::StreamWrite | PayloadFuncKind::FutureWrite => (payload, None),
2704 };
2705 self.push(Shim {
2706 name,
2707 debug_name,
2708 options: RequiredOptions::MEMORY
2709 | RequiredOptions::for_import(
2710 resolve,
2711 &Function {
2712 name: String::new(),
2713 kind: FunctionKind::Freestanding,
2714 params: match wit_param {
2715 Some(ty) => vec![("a".to_string(), ty)],
2716 None => Vec::new(),
2717 },
2718 result: wit_result,
2719 docs: Default::default(),
2720 stability: Stability::Unknown,
2721 },
2722 if async_ {
2723 AbiVariant::GuestImportAsync
2724 } else {
2725 AbiVariant::GuestImport
2726 },
2727 ),
2728 kind: ShimKind::PayloadFunc {
2729 for_module,
2730 info,
2731 kind,
2732 },
2733 sig: WasmSignature {
2734 params,
2735 results,
2736 indirect_params: false,
2737 retptr: false,
2738 },
2739 });
2740 }
2741
2742 fn append_indirect_wit_func(
2745 &mut self,
2746 world: &'a ComponentWorld<'a>,
2747 for_module: CustomModule<'a>,
2748 module: &str,
2749 field: &str,
2750 key: &WorldKey,
2751 name: &String,
2752 interface_key: Option<String>,
2753 abi: AbiVariant,
2754 ) -> Result<()> {
2755 let resolve = &world.encoder.metadata.resolve;
2756 let metadata = world.module_metadata_for(for_module);
2757 let interface = &world.import_map[&interface_key];
2758 let (index, _, lowering) = interface.lowerings.get_full(&(name.clone(), abi)).unwrap();
2759 let shim_name = self.shims.len().to_string();
2760 match lowering {
2761 Lowering::Direct | Lowering::ResourceDrop(_) => {}
2762
2763 Lowering::Indirect { sig, options } => {
2764 log::debug!(
2765 "shim {shim_name} is import `{module}::{field}` lowering {index} `{name}`",
2766 );
2767 let encoding = metadata
2768 .import_encodings
2769 .get(resolve, key, name)
2770 .ok_or_else(|| {
2771 anyhow::anyhow!(
2772 "missing component metadata for import of \
2773 `{module}::{field}`"
2774 )
2775 })?;
2776 self.push(Shim {
2777 name: shim_name,
2778 debug_name: format!("indirect-{module}-{field}"),
2779 options: *options,
2780 kind: ShimKind::IndirectLowering {
2781 interface: interface_key,
2782 index,
2783 realloc: for_module,
2784 encoding,
2785 },
2786 sig: sig.clone(),
2787 });
2788 }
2789 }
2790
2791 Ok(())
2792 }
2793
2794 fn push(&mut self, shim: Shim<'a>) {
2795 if !self.shims.contains_key(&shim.kind) {
2799 self.shims.insert(shim.kind.clone(), shim);
2800 }
2801 }
2802}
2803
2804fn task_return_options_and_type(
2805 resolve: &Resolve,
2806 ty: Option<Type>,
2807) -> (RequiredOptions, WasmSignature) {
2808 let func_tmp = Function {
2809 name: String::new(),
2810 kind: FunctionKind::Freestanding,
2811 params: match ty {
2812 Some(ty) => vec![("a".to_string(), ty)],
2813 None => Vec::new(),
2814 },
2815 result: None,
2816 docs: Default::default(),
2817 stability: Stability::Unknown,
2818 };
2819 let abi = AbiVariant::GuestImport;
2820 let options = RequiredOptions::for_import(resolve, &func_tmp, abi);
2821 let sig = resolve.wasm_signature(abi, &func_tmp);
2822 (options, sig)
2823}
2824
2825#[derive(Clone, Debug)]
2827pub struct Item {
2828 pub alias: String,
2829 pub kind: ExportKind,
2830 pub which: MainOrAdapter,
2831 pub name: String,
2832}
2833
2834#[derive(Debug, PartialEq, Clone)]
2836pub enum MainOrAdapter {
2837 Main,
2838 Adapter(String),
2839}
2840
2841impl MainOrAdapter {
2842 fn to_custom_module(&self) -> CustomModule<'_> {
2843 match self {
2844 MainOrAdapter::Main => CustomModule::Main,
2845 MainOrAdapter::Adapter(s) => CustomModule::Adapter(s),
2846 }
2847 }
2848}
2849
2850#[derive(Clone)]
2852pub enum Instance {
2853 MainOrAdapter(MainOrAdapter),
2855
2856 Items(Vec<Item>),
2858}
2859
2860#[derive(Clone)]
2863pub struct LibraryInfo {
2864 pub instantiate_after_shims: bool,
2866
2867 pub arguments: Vec<(String, Instance)>,
2869}
2870
2871pub(super) struct Adapter {
2873 wasm: Vec<u8>,
2875
2876 metadata: ModuleMetadata,
2878
2879 required_exports: IndexSet<WorldKey>,
2882
2883 library_info: Option<LibraryInfo>,
2888}
2889
2890#[derive(Default)]
2892pub struct ComponentEncoder {
2893 module: Vec<u8>,
2894 module_import_map: Option<ModuleImportMap>,
2895 pub(super) metadata: Bindgen,
2896 validate: bool,
2897 pub(super) main_module_exports: IndexSet<WorldKey>,
2898 pub(super) adapters: IndexMap<String, Adapter>,
2899 import_name_map: HashMap<String, String>,
2900 realloc_via_memory_grow: bool,
2901 merge_imports_based_on_semver: Option<bool>,
2902 pub(super) reject_legacy_names: bool,
2903 debug_names: bool,
2904}
2905
2906impl ComponentEncoder {
2907 pub fn module(mut self, module: &[u8]) -> Result<Self> {
2913 let (wasm, metadata) = self.decode(module.as_ref())?;
2914 let (wasm, module_import_map) = ModuleImportMap::new(wasm)?;
2915 let exports = self
2916 .merge_metadata(metadata)
2917 .context("failed merge WIT metadata for module with previous metadata")?;
2918 self.main_module_exports.extend(exports);
2919 self.module = if let Some(producers) = &self.metadata.producers {
2920 producers.add_to_wasm(&wasm)?
2921 } else {
2922 wasm.to_vec()
2923 };
2924 self.module_import_map = module_import_map;
2925 Ok(self)
2926 }
2927
2928 fn decode<'a>(&self, wasm: &'a [u8]) -> Result<(Cow<'a, [u8]>, Bindgen)> {
2929 let (bytes, metadata) = metadata::decode(wasm)?;
2930 match bytes {
2931 Some(wasm) => Ok((Cow::Owned(wasm), metadata)),
2932 None => Ok((Cow::Borrowed(wasm), metadata)),
2933 }
2934 }
2935
2936 fn merge_metadata(&mut self, metadata: Bindgen) -> Result<IndexSet<WorldKey>> {
2937 self.metadata.merge(metadata)
2938 }
2939
2940 pub fn validate(mut self, validate: bool) -> Self {
2942 self.validate = validate;
2943 self
2944 }
2945
2946 pub fn debug_names(mut self, debug_names: bool) -> Self {
2948 self.debug_names = debug_names;
2949 self
2950 }
2951
2952 pub fn merge_imports_based_on_semver(mut self, merge: bool) -> Self {
2960 self.merge_imports_based_on_semver = Some(merge);
2961 self
2962 }
2963
2964 pub fn reject_legacy_names(mut self, reject: bool) -> Self {
2973 self.reject_legacy_names = reject;
2974 self
2975 }
2976
2977 pub fn adapter(self, name: &str, bytes: &[u8]) -> Result<Self> {
2995 self.library_or_adapter(name, bytes, None)
2996 }
2997
2998 pub fn library(self, name: &str, bytes: &[u8], library_info: LibraryInfo) -> Result<Self> {
3011 self.library_or_adapter(name, bytes, Some(library_info))
3012 }
3013
3014 fn library_or_adapter(
3015 mut self,
3016 name: &str,
3017 bytes: &[u8],
3018 library_info: Option<LibraryInfo>,
3019 ) -> Result<Self> {
3020 let (wasm, mut metadata) = self.decode(bytes)?;
3021 let adapter_metadata = mem::take(&mut metadata.metadata);
3029 let exports = self.merge_metadata(metadata).with_context(|| {
3030 format!("failed to merge WIT packages of adapter `{name}` into main packages")
3031 })?;
3032 if let Some(library_info) = &library_info {
3033 for (_, instance) in &library_info.arguments {
3035 let resolve = |which: &_| match which {
3036 MainOrAdapter::Main => Ok(()),
3037 MainOrAdapter::Adapter(name) => {
3038 if self.adapters.contains_key(name.as_str()) {
3039 Ok(())
3040 } else {
3041 Err(anyhow!("instance refers to unknown adapter `{name}`"))
3042 }
3043 }
3044 };
3045
3046 match instance {
3047 Instance::MainOrAdapter(which) => resolve(which)?,
3048 Instance::Items(items) => {
3049 for item in items {
3050 resolve(&item.which)?;
3051 }
3052 }
3053 }
3054 }
3055 }
3056 self.adapters.insert(
3057 name.to_string(),
3058 Adapter {
3059 wasm: wasm.to_vec(),
3060 metadata: adapter_metadata,
3061 required_exports: exports,
3062 library_info,
3063 },
3064 );
3065 Ok(self)
3066 }
3067
3068 pub fn realloc_via_memory_grow(mut self, value: bool) -> Self {
3073 self.realloc_via_memory_grow = value;
3074 self
3075 }
3076
3077 pub fn import_name_map(mut self, map: HashMap<String, String>) -> Self {
3088 self.import_name_map = map;
3089 self
3090 }
3091
3092 pub fn encode(&mut self) -> Result<Vec<u8>> {
3094 if self.module.is_empty() {
3095 bail!("a module is required when encoding a component");
3096 }
3097
3098 if self.merge_imports_based_on_semver.unwrap_or(true) {
3099 self.metadata
3100 .resolve
3101 .merge_world_imports_based_on_semver(self.metadata.world)?;
3102 }
3103
3104 let world = ComponentWorld::new(self).context("failed to decode world from module")?;
3105 let mut state = EncodingState {
3106 component: ComponentBuilder::default(),
3107 module_index: None,
3108 instance_index: None,
3109 memory_index: None,
3110 shim_instance_index: None,
3111 fixups_module_index: None,
3112 adapter_modules: IndexMap::new(),
3113 adapter_instances: IndexMap::new(),
3114 import_type_encoding_maps: Default::default(),
3115 export_type_encoding_maps: Default::default(),
3116 imported_instances: Default::default(),
3117 imported_funcs: Default::default(),
3118 exported_instances: Default::default(),
3119 aliased_core_items: Default::default(),
3120 info: &world,
3121 };
3122 state.encode_imports(&self.import_name_map)?;
3123 state.encode_core_modules();
3124 state.encode_core_instantiation()?;
3125 state.encode_exports(CustomModule::Main)?;
3126 for name in self.adapters.keys() {
3127 state.encode_exports(CustomModule::Adapter(name))?;
3128 }
3129 state.component.append_names();
3130 state
3131 .component
3132 .raw_custom_section(&crate::base_producers().raw_custom_section());
3133 let bytes = state.component.finish();
3134
3135 if self.validate {
3136 Validator::new_with_features(WasmFeatures::all())
3137 .validate_all(&bytes)
3138 .context("failed to validate component output")?;
3139 }
3140
3141 Ok(bytes)
3142 }
3143}
3144
3145impl ComponentWorld<'_> {
3146 fn imports_for(&self, module: CustomModule) -> &ImportMap {
3148 match module {
3149 CustomModule::Main => &self.info.imports,
3150 CustomModule::Adapter(name) => &self.adapters[name].info.imports,
3151 }
3152 }
3153
3154 fn exports_for(&self, module: CustomModule) -> &ExportMap {
3156 match module {
3157 CustomModule::Main => &self.info.exports,
3158 CustomModule::Adapter(name) => &self.adapters[name].info.exports,
3159 }
3160 }
3161
3162 fn module_metadata_for(&self, module: CustomModule) -> &ModuleMetadata {
3164 match module {
3165 CustomModule::Main => &self.encoder.metadata.metadata,
3166 CustomModule::Adapter(name) => &self.encoder.adapters[name].metadata,
3167 }
3168 }
3169}
3170
3171#[cfg(all(test, feature = "dummy-module"))]
3172mod test {
3173 use super::*;
3174 use crate::{dummy_module, embed_component_metadata};
3175 use wit_parser::ManglingAndAbi;
3176
3177 #[test]
3178 fn it_renames_imports() {
3179 let mut resolve = Resolve::new();
3180 let pkg = resolve
3181 .push_str(
3182 "test.wit",
3183 r#"
3184package test:wit;
3185
3186interface i {
3187 f: func();
3188}
3189
3190world test {
3191 import i;
3192 import foo: interface {
3193 f: func();
3194 }
3195}
3196"#,
3197 )
3198 .unwrap();
3199 let world = resolve.select_world(&[pkg], None).unwrap();
3200
3201 let mut module = dummy_module(&resolve, world, ManglingAndAbi::Standard32);
3202
3203 embed_component_metadata(&mut module, &resolve, world, StringEncoding::UTF8).unwrap();
3204
3205 let encoded = ComponentEncoder::default()
3206 .import_name_map(HashMap::from([
3207 (
3208 "foo".to_string(),
3209 "unlocked-dep=<foo:bar/foo@{>=1.0.0 <1.1.0}>".to_string(),
3210 ),
3211 (
3212 "test:wit/i".to_string(),
3213 "locked-dep=<foo:bar/i@1.2.3>".to_string(),
3214 ),
3215 ]))
3216 .module(&module)
3217 .unwrap()
3218 .validate(true)
3219 .encode()
3220 .unwrap();
3221
3222 let wat = wasmprinter::print_bytes(encoded).unwrap();
3223 assert!(wat.contains("unlocked-dep=<foo:bar/foo@{>=1.0.0 <1.1.0}>"));
3224 assert!(wat.contains("locked-dep=<foo:bar/i@1.2.3>"));
3225 }
3226}