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.component.core_module_raw(&self.info.encoder.module);
397 self.module_index = Some(idx);
398
399 for (name, adapter) in self.info.adapters.iter() {
400 let mut add_meta = wasm_metadata::AddMetadata::default();
401 add_meta.name = AddMetadataField::Set(if adapter.library_info.is_some() {
402 name.to_string()
403 } else {
404 format!("wit-component:adapter:{name}")
405 });
406 let wasm = add_meta
407 .to_wasm(&adapter.wasm)
408 .expect("core wasm can get name added");
409 let idx = self.component.core_module_raw(&wasm);
410 let prev = self.adapter_modules.insert(name, idx);
411 assert!(prev.is_none());
412 }
413 }
414
415 fn root_import_type_encoder(
416 &mut self,
417 interface: Option<InterfaceId>,
418 ) -> RootTypeEncoder<'_, 'a> {
419 RootTypeEncoder {
420 state: self,
421 interface,
422 import_types: true,
423 }
424 }
425
426 fn root_export_type_encoder(
427 &mut self,
428 interface: Option<InterfaceId>,
429 ) -> RootTypeEncoder<'_, 'a> {
430 RootTypeEncoder {
431 state: self,
432 interface,
433 import_types: false,
434 }
435 }
436
437 fn instance_type_encoder(&mut self, interface: InterfaceId) -> InstanceTypeEncoder<'_, 'a> {
438 InstanceTypeEncoder {
439 state: self,
440 interface,
441 type_encoding_maps: Default::default(),
442 ty: Default::default(),
443 }
444 }
445
446 fn encode_imports(&mut self, name_map: &HashMap<String, String>) -> Result<()> {
447 let mut has_funcs = false;
448 for (name, info) in self.info.import_map.iter() {
449 match name {
450 Some(name) => {
451 self.encode_interface_import(name_map.get(name).unwrap_or(name), info)?
452 }
453 None => has_funcs = true,
454 }
455 }
456
457 let resolve = &self.info.encoder.metadata.resolve;
458 let world = &resolve.worlds[self.info.encoder.metadata.world];
459
460 for (_name, item) in world.imports.iter() {
463 if let WorldItem::Type(ty) = item {
464 self.root_import_type_encoder(None)
465 .encode_valtype(resolve, &Type::Id(*ty))?;
466 }
467 }
468
469 if has_funcs {
470 let info = &self.info.import_map[&None];
471 self.encode_root_import_funcs(info)?;
472 }
473 Ok(())
474 }
475
476 fn encode_interface_import(&mut self, name: &str, info: &ImportedInterface) -> Result<()> {
477 let resolve = &self.info.encoder.metadata.resolve;
478 let interface_id = info.interface.as_ref().unwrap();
479 let interface_id = *interface_id;
480 let interface = &resolve.interfaces[interface_id];
481 log::trace!("encoding imports for `{name}` as {interface_id:?}");
482 let mut encoder = self.instance_type_encoder(interface_id);
483
484 if let Some(live) = encoder.state.info.live_type_imports.get(&interface_id) {
486 for ty in live {
487 log::trace!(
488 "encoding extra type {ty:?} name={:?}",
489 resolve.types[*ty].name
490 );
491 encoder.encode_valtype(resolve, &Type::Id(*ty))?;
492 }
493 }
494
495 for (_, func) in interface.functions.iter() {
498 if !(info
499 .lowerings
500 .contains_key(&(func.name.clone(), AbiVariant::GuestImport))
501 || info
502 .lowerings
503 .contains_key(&(func.name.clone(), AbiVariant::GuestImportAsync)))
504 {
505 continue;
506 }
507 log::trace!("encoding function type for `{}`", func.name);
508 let idx = encoder.encode_func_type(resolve, func)?;
509
510 encoder.ty.export(&func.name, ComponentTypeRef::Func(idx));
511 }
512
513 let ty = encoder.ty;
514 if ty.is_empty() {
517 return Ok(());
518 }
519 let instance_type_idx = self.component.type_instance(&ty);
520 let instance_idx = self
521 .component
522 .import(name, ComponentTypeRef::Instance(instance_type_idx));
523 let prev = self.imported_instances.insert(interface_id, instance_idx);
524 assert!(prev.is_none());
525 Ok(())
526 }
527
528 fn encode_root_import_funcs(&mut self, info: &ImportedInterface) -> Result<()> {
529 let resolve = &self.info.encoder.metadata.resolve;
530 let world = self.info.encoder.metadata.world;
531 for (name, item) in resolve.worlds[world].imports.iter() {
532 let func = match item {
533 WorldItem::Function(f) => f,
534 WorldItem::Interface { .. } | WorldItem::Type(_) => continue,
535 };
536 let name = resolve.name_world_key(name);
537 if !(info
538 .lowerings
539 .contains_key(&(name.clone(), AbiVariant::GuestImport))
540 || info
541 .lowerings
542 .contains_key(&(name.clone(), AbiVariant::GuestImportAsync)))
543 {
544 continue;
545 }
546 log::trace!("encoding function type for `{}`", func.name);
547 let idx = self
548 .root_import_type_encoder(None)
549 .encode_func_type(resolve, func)?;
550 let func_idx = self.component.import(&name, ComponentTypeRef::Func(idx));
551 let prev = self.imported_funcs.insert(name, func_idx);
552 assert!(prev.is_none());
553 }
554 Ok(())
555 }
556
557 fn alias_imported_type(&mut self, interface: InterfaceId, id: TypeId) -> u32 {
558 let ty = &self.info.encoder.metadata.resolve.types[id];
559 let name = ty.name.as_ref().expect("type must have a name");
560 let instance = self.imported_instances[&interface];
561 self.component
562 .alias_export(instance, name, ComponentExportKind::Type)
563 }
564
565 fn alias_exported_type(&mut self, interface: InterfaceId, id: TypeId) -> u32 {
566 let ty = &self.info.encoder.metadata.resolve.types[id];
567 let name = ty.name.as_ref().expect("type must have a name");
568 let instance = self.exported_instances[&interface];
569 self.component
570 .alias_export(instance, name, ComponentExportKind::Type)
571 }
572
573 fn encode_core_instantiation(&mut self) -> Result<()> {
574 let shims = self.encode_shim_instantiation()?;
576
577 self.declare_types_for_imported_intrinsics(&shims)?;
581
582 self.instantiate_main_module(&shims)?;
586
587 let (before, after) = self
590 .info
591 .adapters
592 .iter()
593 .partition::<Vec<_>, _>(|(_, adapter)| {
594 !matches!(
595 adapter.library_info,
596 Some(LibraryInfo {
597 instantiate_after_shims: true,
598 ..
599 })
600 )
601 });
602
603 for (name, _adapter) in before {
604 self.instantiate_adapter_module(&shims, name)?;
605 }
606
607 self.encode_indirect_lowerings(&shims)?;
610
611 for (name, _adapter) in after {
612 self.instantiate_adapter_module(&shims, name)?;
613 }
614
615 self.encode_initialize_with_start()?;
616
617 Ok(())
618 }
619
620 fn lookup_resource_index(&mut self, id: TypeId) -> u32 {
621 let resolve = &self.info.encoder.metadata.resolve;
622 let ty = &resolve.types[id];
623 match ty.owner {
624 TypeOwner::World(_) => self.import_type_encoding_maps.id_to_index[&id],
628 TypeOwner::Interface(i) => {
629 let instance = self.imported_instances[&i];
630 let name = ty.name.as_ref().expect("resources must be named");
631 self.component
632 .alias_export(instance, name, ComponentExportKind::Type)
633 }
634 TypeOwner::None => panic!("resources must have an owner"),
635 }
636 }
637
638 fn encode_exports(&mut self, module: CustomModule) -> Result<()> {
639 let resolve = &self.info.encoder.metadata.resolve;
640 let exports = match module {
641 CustomModule::Main => &self.info.encoder.main_module_exports,
642 CustomModule::Adapter(name) => &self.info.encoder.adapters[name].required_exports,
643 };
644
645 if exports.is_empty() {
646 return Ok(());
647 }
648
649 let mut interface_func_core_names = IndexMap::new();
650 let mut world_func_core_names = IndexMap::new();
651 for (core_name, export) in self.info.exports_for(module).iter() {
652 match export {
653 Export::WorldFunc(_, name, _) => {
654 let prev = world_func_core_names.insert(name, core_name);
655 assert!(prev.is_none());
656 }
657 Export::InterfaceFunc(_, id, name, _) => {
658 let prev = interface_func_core_names
659 .entry(id)
660 .or_insert(IndexMap::new())
661 .insert(name.as_str(), core_name);
662 assert!(prev.is_none());
663 }
664 Export::WorldFuncCallback(..)
665 | Export::InterfaceFuncCallback(..)
666 | Export::WorldFuncPostReturn(..)
667 | Export::InterfaceFuncPostReturn(..)
668 | Export::ResourceDtor(..)
669 | Export::Memory
670 | Export::GeneralPurposeRealloc
671 | Export::GeneralPurposeExportRealloc
672 | Export::GeneralPurposeImportRealloc
673 | Export::Initialize
674 | Export::ReallocForAdapter
675 | Export::IndirectFunctionTable => continue,
676 }
677 }
678
679 let world = &resolve.worlds[self.info.encoder.metadata.world];
680
681 for export_name in exports {
682 let export_string = resolve.name_world_key(export_name);
683 match &world.exports[export_name] {
684 WorldItem::Function(func) => {
685 let ty = self
686 .root_import_type_encoder(None)
687 .encode_func_type(resolve, func)?;
688 let core_name = world_func_core_names[&func.name];
689 let idx = self.encode_lift(module, &core_name, export_name, func, ty)?;
690 self.component
691 .export(&export_string, ComponentExportKind::Func, idx, None);
692 }
693 WorldItem::Interface { id, .. } => {
694 let core_names = interface_func_core_names.get(id);
695 self.encode_interface_export(
696 &export_string,
697 module,
698 export_name,
699 *id,
700 core_names,
701 )?;
702 }
703 WorldItem::Type(_) => unreachable!(),
704 }
705 }
706
707 Ok(())
708 }
709
710 fn encode_interface_export(
711 &mut self,
712 export_name: &str,
713 module: CustomModule<'_>,
714 key: &WorldKey,
715 export: InterfaceId,
716 interface_func_core_names: Option<&IndexMap<&str, &str>>,
717 ) -> Result<()> {
718 log::trace!("encode interface export `{export_name}`");
719 let resolve = &self.info.encoder.metadata.resolve;
720
721 let mut imports = Vec::new();
728 let mut root = self.root_export_type_encoder(Some(export));
729 for (_, func) in &resolve.interfaces[export].functions {
730 let core_name = interface_func_core_names.unwrap()[func.name.as_str()];
731 let ty = root.encode_func_type(resolve, func)?;
732 let func_index = root.state.encode_lift(module, &core_name, key, func, ty)?;
733 imports.push((
734 import_func_name(func),
735 ComponentExportKind::Func,
736 func_index,
737 ));
738 }
739
740 let mut nested = NestedComponentTypeEncoder {
744 component: ComponentBuilder::default(),
745 type_encoding_maps: Default::default(),
746 export_types: false,
747 interface: export,
748 state: self,
749 imports: IndexMap::new(),
750 };
751
752 let mut types_to_import = LiveTypes::default();
762 types_to_import.add_interface(resolve, export);
763 let exports_used = &nested.state.info.exports_used[&export];
764 for ty in types_to_import.iter() {
765 if let TypeOwner::Interface(owner) = resolve.types[ty].owner {
766 if owner == export {
767 continue;
770 }
771
772 let mut encoder = if exports_used.contains(&owner) {
775 nested.state.root_export_type_encoder(Some(export))
776 } else {
777 nested.state.root_import_type_encoder(Some(export))
778 };
779 encoder.encode_valtype(resolve, &Type::Id(ty))?;
780
781 nested.interface = owner;
785 nested.encode_valtype(resolve, &Type::Id(ty))?;
786 }
787 }
788 nested.interface = export;
789
790 let imported_type_maps = nested.type_encoding_maps.clone();
794
795 let mut resources = HashMap::new();
801 for (_name, ty) in resolve.interfaces[export].types.iter() {
802 if !matches!(resolve.types[*ty].kind, TypeDefKind::Resource) {
803 continue;
804 }
805 let idx = match nested.encode_valtype(resolve, &Type::Id(*ty))? {
806 ComponentValType::Type(idx) => idx,
807 _ => unreachable!(),
808 };
809 resources.insert(*ty, idx);
810 }
811
812 for (_, func) in resolve.interfaces[export].functions.iter() {
816 let ty = nested.encode_func_type(resolve, func)?;
817 nested
818 .component
819 .import(&import_func_name(func), ComponentTypeRef::Func(ty));
820 }
821
822 let reverse_map = nested
829 .type_encoding_maps
830 .id_to_index
831 .drain()
832 .map(|p| (p.1, p.0))
833 .collect::<HashMap<_, _>>();
834 nested.type_encoding_maps.def_to_index.clear();
835 for (name, idx) in nested.imports.drain(..) {
836 let id = reverse_map[&idx];
837 let owner = match resolve.types[id].owner {
838 TypeOwner::Interface(id) => id,
839 _ => unreachable!(),
840 };
841 let idx = if owner == export || exports_used.contains(&owner) {
842 log::trace!("consulting exports for {id:?}");
843 nested.state.export_type_encoding_maps.id_to_index[&id]
844 } else {
845 log::trace!("consulting imports for {id:?}");
846 nested.state.import_type_encoding_maps.id_to_index[&id]
847 };
848 imports.push((name, ComponentExportKind::Type, idx))
849 }
850
851 nested.type_encoding_maps = imported_type_maps;
856
857 nested.export_types = true;
864 nested.type_encoding_maps.func_type_map.clear();
865
866 for (_, id) in resolve.interfaces[export].types.iter() {
872 let ty = &resolve.types[*id];
873 match ty.kind {
874 TypeDefKind::Resource => {
875 let idx = nested.component.export(
876 ty.name.as_ref().expect("resources must be named"),
877 ComponentExportKind::Type,
878 resources[id],
879 None,
880 );
881 nested.type_encoding_maps.id_to_index.insert(*id, idx);
882 }
883 _ => {
884 nested.encode_valtype(resolve, &Type::Id(*id))?;
885 }
886 }
887 }
888
889 for (i, (_, func)) in resolve.interfaces[export].functions.iter().enumerate() {
890 let ty = nested.encode_func_type(resolve, func)?;
891 nested.component.export(
892 &func.name,
893 ComponentExportKind::Func,
894 i as u32,
895 Some(ComponentTypeRef::Func(ty)),
896 );
897 }
898
899 let component = nested.component;
903 let component_index = self.component.component(component);
904 let instance_index = self.component.instantiate(component_index, imports);
905 let idx = self.component.export(
906 export_name,
907 ComponentExportKind::Instance,
908 instance_index,
909 None,
910 );
911 let prev = self.exported_instances.insert(export, idx);
912 assert!(prev.is_none());
913
914 for (_name, id) in resolve.interfaces[export].types.iter() {
922 self.export_type_encoding_maps.id_to_index.remove(id);
923 self.export_type_encoding_maps
924 .def_to_index
925 .remove(&resolve.types[*id].kind);
926 }
927
928 return Ok(());
929
930 struct NestedComponentTypeEncoder<'state, 'a> {
931 component: ComponentBuilder,
932 type_encoding_maps: TypeEncodingMaps<'a>,
933 export_types: bool,
934 interface: InterfaceId,
935 state: &'state mut EncodingState<'a>,
936 imports: IndexMap<String, u32>,
937 }
938
939 impl<'a> ValtypeEncoder<'a> for NestedComponentTypeEncoder<'_, 'a> {
940 fn defined_type(&mut self) -> (u32, ComponentDefinedTypeEncoder<'_>) {
941 self.component.type_defined()
942 }
943 fn define_function_type(&mut self) -> (u32, ComponentFuncTypeEncoder<'_>) {
944 self.component.type_function()
945 }
946 fn export_type(&mut self, idx: u32, name: &'a str) -> Option<u32> {
947 if self.export_types {
948 Some(
949 self.component
950 .export(name, ComponentExportKind::Type, idx, None),
951 )
952 } else {
953 let name = self.unique_import_name(name);
954 let ret = self
955 .component
956 .import(&name, ComponentTypeRef::Type(TypeBounds::Eq(idx)));
957 self.imports.insert(name, ret);
958 Some(ret)
959 }
960 }
961 fn export_resource(&mut self, name: &'a str) -> u32 {
962 if self.export_types {
963 panic!("resources should already be exported")
964 } else {
965 let name = self.unique_import_name(name);
966 let ret = self
967 .component
968 .import(&name, ComponentTypeRef::Type(TypeBounds::SubResource));
969 self.imports.insert(name, ret);
970 ret
971 }
972 }
973 fn import_type(&mut self, _: InterfaceId, _id: TypeId) -> u32 {
974 unreachable!()
975 }
976 fn type_encoding_maps(&mut self) -> &mut TypeEncodingMaps<'a> {
977 &mut self.type_encoding_maps
978 }
979 fn interface(&self) -> Option<InterfaceId> {
980 Some(self.interface)
981 }
982 }
983
984 impl NestedComponentTypeEncoder<'_, '_> {
985 fn unique_import_name(&mut self, name: &str) -> String {
986 let mut name = format!("import-type-{name}");
987 let mut n = 0;
988 while self.imports.contains_key(&name) {
989 name = format!("{name}{n}");
990 n += 1;
991 }
992 name
993 }
994 }
995
996 fn import_func_name(f: &Function) -> String {
997 match f.kind {
998 FunctionKind::Freestanding | FunctionKind::AsyncFreestanding => {
999 format!("import-func-{}", f.item_name())
1000 }
1001
1002 FunctionKind::Method(_)
1010 | FunctionKind::AsyncMethod(_)
1011 | FunctionKind::Static(_)
1012 | FunctionKind::AsyncStatic(_)
1013 | FunctionKind::Constructor(_) => {
1014 format!(
1015 "import-{}",
1016 f.name.replace('[', "").replace([']', '.', ' '], "-")
1017 )
1018 }
1019 }
1020 }
1021 }
1022
1023 fn encode_lift(
1024 &mut self,
1025 module: CustomModule<'_>,
1026 core_name: &str,
1027 key: &WorldKey,
1028 func: &Function,
1029 ty: u32,
1030 ) -> Result<u32> {
1031 let resolve = &self.info.encoder.metadata.resolve;
1032 let metadata = self.info.module_metadata_for(module);
1033 let instance_index = self.instance_for(module);
1034 let core_func_index = self.core_alias_export(instance_index, core_name, ExportKind::Func);
1035 let exports = self.info.exports_for(module);
1036
1037 let options = RequiredOptions::for_export(
1038 resolve,
1039 func,
1040 exports
1041 .abi(key, func)
1042 .ok_or_else(|| anyhow!("no ABI found for {}", func.name))?,
1043 );
1044
1045 let encoding = metadata
1046 .export_encodings
1047 .get(resolve, key, &func.name)
1048 .unwrap();
1049 let exports = self.info.exports_for(module);
1050 let realloc_index = exports
1051 .export_realloc_for(key, &func.name)
1052 .map(|name| self.core_alias_export(instance_index, name, ExportKind::Func));
1053 let mut options = options
1054 .into_iter(encoding, self.memory_index, realloc_index)?
1055 .collect::<Vec<_>>();
1056
1057 if let Some(post_return) = exports.post_return(key, func) {
1058 let post_return = self.core_alias_export(instance_index, post_return, ExportKind::Func);
1059 options.push(CanonicalOption::PostReturn(post_return));
1060 }
1061 if let Some(callback) = exports.callback(key, func) {
1062 let callback = self.core_alias_export(instance_index, callback, ExportKind::Func);
1063 options.push(CanonicalOption::Callback(callback));
1064 }
1065 let func_index = self.component.lift_func(core_func_index, ty, options);
1066 Ok(func_index)
1067 }
1068
1069 fn encode_shim_instantiation(&mut self) -> Result<Shims<'a>> {
1070 let mut ret = Shims::default();
1071
1072 ret.append_indirect(self.info, CustomModule::Main)
1073 .context("failed to register indirect shims for main module")?;
1074
1075 for (adapter_name, _adapter) in self.info.adapters.iter() {
1079 ret.append_indirect(self.info, CustomModule::Adapter(adapter_name))
1080 .with_context(|| {
1081 format!("failed to register indirect shims for adapter {adapter_name}")
1082 })?;
1083 }
1084
1085 if ret.shims.is_empty() {
1086 return Ok(ret);
1087 }
1088
1089 assert!(self.shim_instance_index.is_none());
1090 assert!(self.fixups_module_index.is_none());
1091
1092 let mut types = TypeSection::new();
1101 let mut tables = TableSection::new();
1102 let mut functions = FunctionSection::new();
1103 let mut exports = ExportSection::new();
1104 let mut code = CodeSection::new();
1105 let mut sigs = IndexMap::new();
1106 let mut imports_section = ImportSection::new();
1107 let mut elements = ElementSection::new();
1108 let mut func_indexes = Vec::new();
1109 let mut func_names = NameMap::new();
1110
1111 for (i, shim) in ret.shims.values().enumerate() {
1112 let i = i as u32;
1113 let type_index = *sigs.entry(&shim.sig).or_insert_with(|| {
1114 let index = types.len();
1115 types.ty().function(
1116 shim.sig.params.iter().map(to_val_type),
1117 shim.sig.results.iter().map(to_val_type),
1118 );
1119 index
1120 });
1121
1122 functions.function(type_index);
1123 Self::encode_shim_function(type_index, i, &mut code, shim.sig.params.len() as u32);
1124 exports.export(&shim.name, ExportKind::Func, i);
1125
1126 imports_section.import("", &shim.name, EntityType::Function(type_index));
1127 func_indexes.push(i);
1128 func_names.append(i, &shim.debug_name);
1129 }
1130 let mut names = NameSection::new();
1131 names.module("wit-component:shim");
1132 names.functions(&func_names);
1133
1134 let table_type = TableType {
1135 element_type: RefType::FUNCREF,
1136 minimum: ret.shims.len() as u64,
1137 maximum: Some(ret.shims.len() as u64),
1138 table64: false,
1139 shared: false,
1140 };
1141
1142 tables.table(table_type);
1143
1144 exports.export(INDIRECT_TABLE_NAME, ExportKind::Table, 0);
1145 imports_section.import("", INDIRECT_TABLE_NAME, table_type);
1146
1147 elements.active(
1148 None,
1149 &ConstExpr::i32_const(0),
1150 Elements::Functions(func_indexes.into()),
1151 );
1152
1153 let mut shim = Module::new();
1154 shim.section(&types);
1155 shim.section(&functions);
1156 shim.section(&tables);
1157 shim.section(&exports);
1158 shim.section(&code);
1159 shim.section(&RawCustomSection(
1160 &crate::base_producers().raw_custom_section(),
1161 ));
1162 shim.section(&names);
1163
1164 let mut fixups = Module::default();
1165 fixups.section(&types);
1166 fixups.section(&imports_section);
1167 fixups.section(&elements);
1168 fixups.section(&RawCustomSection(
1169 &crate::base_producers().raw_custom_section(),
1170 ));
1171
1172 let mut names = NameSection::new();
1173 names.module("wit-component:fixups");
1174 fixups.section(&names);
1175
1176 let shim_module_index = self.component.core_module(&shim);
1177 self.fixups_module_index = Some(self.component.core_module(&fixups));
1178 self.shim_instance_index = Some(self.component.core_instantiate(shim_module_index, []));
1179
1180 return Ok(ret);
1181 }
1182
1183 fn encode_shim_function(
1184 type_index: u32,
1185 func_index: u32,
1186 code: &mut CodeSection,
1187 param_count: u32,
1188 ) {
1189 let mut func = wasm_encoder::Function::new(std::iter::empty());
1190 for i in 0..param_count {
1191 func.instructions().local_get(i);
1192 }
1193 func.instructions().i32_const(func_index as i32);
1194 func.instructions().call_indirect(0, type_index);
1195 func.instructions().end();
1196 code.function(&func);
1197 }
1198
1199 fn encode_indirect_lowerings(&mut self, shims: &Shims<'_>) -> Result<()> {
1200 if shims.shims.is_empty() {
1201 return Ok(());
1202 }
1203
1204 let shim_instance_index = self
1205 .shim_instance_index
1206 .expect("must have an instantiated shim");
1207
1208 let table_index =
1209 self.core_alias_export(shim_instance_index, INDIRECT_TABLE_NAME, ExportKind::Table);
1210
1211 let resolve = &self.info.encoder.metadata.resolve;
1212
1213 let mut exports = Vec::new();
1214 exports.push((INDIRECT_TABLE_NAME, ExportKind::Table, table_index));
1215
1216 for shim in shims.shims.values() {
1217 let core_func_index = match &shim.kind {
1218 ShimKind::IndirectLowering {
1225 interface,
1226 index,
1227 realloc,
1228 encoding,
1229 } => {
1230 let interface = &self.info.import_map[interface];
1231 let ((name, _), _) = interface.lowerings.get_index(*index).unwrap();
1232 let func_index = match &interface.interface {
1233 Some(interface_id) => {
1234 let instance_index = self.imported_instances[interface_id];
1235 self.component.alias_export(
1236 instance_index,
1237 name,
1238 ComponentExportKind::Func,
1239 )
1240 }
1241 None => self.imported_funcs[name],
1242 };
1243
1244 let realloc = self
1245 .info
1246 .exports_for(*realloc)
1247 .import_realloc_for(interface.interface, name)
1248 .map(|name| {
1249 let instance = self.instance_for(*realloc);
1250 self.core_alias_export(instance, name, ExportKind::Func)
1251 });
1252
1253 self.component.lower_func(
1254 func_index,
1255 shim.options
1256 .into_iter(*encoding, self.memory_index, realloc)?,
1257 )
1258 }
1259
1260 ShimKind::Adapter { adapter, func } => {
1265 self.core_alias_export(self.adapter_instances[adapter], func, ExportKind::Func)
1266 }
1267
1268 ShimKind::ResourceDtor { module, export } => {
1273 self.core_alias_export(self.instance_for(*module), export, ExportKind::Func)
1274 }
1275
1276 ShimKind::PayloadFunc {
1277 for_module,
1278 info,
1279 kind,
1280 } => {
1281 let metadata = self.info.module_metadata_for(*for_module);
1282 let exports = self.info.exports_for(*for_module);
1283 let instance_index = self.instance_for(*for_module);
1284 let (encoding, realloc) = if info.imported {
1285 (
1286 metadata
1287 .import_encodings
1288 .get(resolve, &info.key, &info.function),
1289 exports.import_realloc_for(info.interface, &info.function),
1290 )
1291 } else {
1292 (
1293 metadata
1294 .export_encodings
1295 .get(resolve, &info.key, &info.function),
1296 exports.export_realloc_for(&info.key, &info.function),
1297 )
1298 };
1299 let encoding = encoding.unwrap_or(StringEncoding::UTF8);
1300 let realloc_index = realloc
1301 .map(|name| self.core_alias_export(instance_index, name, ExportKind::Func));
1302 let type_index = self.payload_type_index(info)?;
1303 let options =
1304 shim.options
1305 .into_iter(encoding, self.memory_index, realloc_index)?;
1306
1307 match kind {
1308 PayloadFuncKind::FutureWrite => {
1309 self.component.future_write(type_index, options)
1310 }
1311 PayloadFuncKind::FutureRead => {
1312 self.component.future_read(type_index, options)
1313 }
1314 PayloadFuncKind::StreamWrite => {
1315 self.component.stream_write(type_index, options)
1316 }
1317 PayloadFuncKind::StreamRead => {
1318 self.component.stream_read(type_index, options)
1319 }
1320 }
1321 }
1322
1323 ShimKind::WaitableSetWait { cancellable } => self
1324 .component
1325 .waitable_set_wait(*cancellable, self.memory_index.unwrap()),
1326 ShimKind::WaitableSetPoll { cancellable } => self
1327 .component
1328 .waitable_set_poll(*cancellable, self.memory_index.unwrap()),
1329 ShimKind::ErrorContextNew { encoding } => self.component.error_context_new(
1330 shim.options.into_iter(*encoding, self.memory_index, None)?,
1331 ),
1332 ShimKind::ErrorContextDebugMessage {
1333 for_module,
1334 encoding,
1335 } => {
1336 let instance_index = self.instance_for(*for_module);
1337 let realloc = self.info.exports_for(*for_module).import_realloc_fallback();
1338 let realloc_index = realloc
1339 .map(|r| self.core_alias_export(instance_index, r, ExportKind::Func));
1340
1341 self.component
1342 .error_context_debug_message(shim.options.into_iter(
1343 *encoding,
1344 self.memory_index,
1345 realloc_index,
1346 )?)
1347 }
1348 ShimKind::TaskReturn {
1349 interface,
1350 func,
1351 result,
1352 encoding,
1353 for_module,
1354 } => {
1355 let mut encoder = if interface.is_none() {
1358 self.root_import_type_encoder(*interface)
1359 } else {
1360 self.root_export_type_encoder(*interface)
1361 };
1362 let result = match result {
1363 Some(ty) => Some(encoder.encode_valtype(resolve, ty)?),
1364 None => None,
1365 };
1366
1367 let exports = self.info.exports_for(*for_module);
1368 let realloc = exports.import_realloc_for(*interface, func);
1369
1370 let instance_index = self.instance_for(*for_module);
1371 let realloc_index = realloc
1372 .map(|r| self.core_alias_export(instance_index, r, ExportKind::Func));
1373 let options =
1374 shim.options
1375 .into_iter(*encoding, self.memory_index, realloc_index)?;
1376 self.component.task_return(result, options)
1377 }
1378 ShimKind::ThreadNewIndirect {
1379 for_module,
1380 func_ty,
1381 } => {
1382 let (func_ty_idx, f) = self.component.core_type();
1384 f.core().func_type(func_ty);
1385
1386 let exports = self.info.exports_for(*for_module);
1389 let instance_index = self.instance_for(*for_module);
1390 let table_idx = exports.indirect_function_table().map(|table| {
1391 self.core_alias_export(instance_index, table, ExportKind::Table)
1392 }).ok_or_else(|| {
1393 anyhow!(
1394 "table __indirect_function_table must be an exported funcref table for thread.new_indirect"
1395 )
1396 })?;
1397
1398 self.component.thread_new_indirect(func_ty_idx, table_idx)
1399 }
1400 };
1401
1402 exports.push((shim.name.as_str(), ExportKind::Func, core_func_index));
1403 }
1404
1405 let instance_index = self.component.core_instantiate_exports(exports);
1406 self.component.core_instantiate(
1407 self.fixups_module_index.expect("must have fixup module"),
1408 [("", ModuleArg::Instance(instance_index))],
1409 );
1410 Ok(())
1411 }
1412
1413 fn payload_type_index(&mut self, info: &PayloadInfo) -> Result<u32> {
1421 let resolve = &self.info.encoder.metadata.resolve;
1422 let ComponentValType::Type(type_index) = if info.imported || info.interface.is_none() {
1438 self.root_import_type_encoder(None)
1439 } else {
1440 self.root_export_type_encoder(info.interface)
1441 }
1442 .encode_valtype(resolve, &Type::Id(info.ty))?
1443 else {
1444 unreachable!()
1445 };
1446 Ok(type_index)
1447 }
1448
1449 fn declare_types_for_imported_intrinsics(&mut self, shims: &Shims<'_>) -> Result<()> {
1456 let resolve = &self.info.encoder.metadata.resolve;
1457 let world = &resolve.worlds[self.info.encoder.metadata.world];
1458
1459 let main_module_keys = self.info.encoder.main_module_exports.iter();
1462 let main_module_keys = main_module_keys.map(|key| (CustomModule::Main, key));
1463 let adapter_keys = self.info.encoder.adapters.iter().flat_map(|(name, info)| {
1464 info.required_exports
1465 .iter()
1466 .map(move |key| (CustomModule::Adapter(name), key))
1467 });
1468 for (for_module, key) in main_module_keys.chain(adapter_keys) {
1469 let id = match &world.exports[key] {
1470 WorldItem::Interface { id, .. } => *id,
1471 WorldItem::Type { .. } => unreachable!(),
1472 WorldItem::Function(_) => continue,
1473 };
1474
1475 for ty in resolve.interfaces[id].types.values() {
1476 match &resolve.types[*ty].kind {
1477 TypeDefKind::Resource => {
1481 let exports = self.info.exports_for(for_module);
1484 let dtor = exports.resource_dtor(*ty).map(|name| {
1485 let name = &shims.shims[&ShimKind::ResourceDtor {
1486 module: for_module,
1487 export: name,
1488 }]
1489 .name;
1490 let shim = self.shim_instance_index.unwrap();
1491 self.core_alias_export(shim, name, ExportKind::Func)
1492 });
1493
1494 let resource_idx = self.component.type_resource(ValType::I32, dtor);
1498 let prev = self
1499 .export_type_encoding_maps
1500 .id_to_index
1501 .insert(*ty, resource_idx);
1502 assert!(prev.is_none());
1503 }
1504 _other => {
1505 self.root_export_type_encoder(Some(id))
1506 .encode_valtype(resolve, &Type::Id(*ty))?;
1507 }
1508 }
1509 }
1510 }
1511 Ok(())
1512 }
1513
1514 fn instantiate_main_module(&mut self, shims: &Shims<'_>) -> Result<()> {
1517 assert!(self.instance_index.is_none());
1518
1519 let instance_index = self.instantiate_core_module(shims, CustomModule::Main)?;
1520
1521 if let Some(memory) = self.info.info.exports.memory() {
1522 self.memory_index =
1523 Some(self.core_alias_export(instance_index, memory, ExportKind::Memory));
1524 }
1525
1526 self.instance_index = Some(instance_index);
1527 Ok(())
1528 }
1529
1530 fn instantiate_adapter_module(&mut self, shims: &Shims<'_>, name: &'a str) -> Result<()> {
1533 let instance = self.instantiate_core_module(shims, CustomModule::Adapter(name))?;
1534 self.adapter_instances.insert(name, instance);
1535 Ok(())
1536 }
1537
1538 fn instantiate_core_module(
1545 &mut self,
1546 shims: &Shims,
1547 for_module: CustomModule<'_>,
1548 ) -> Result<u32> {
1549 let module = self.module_for(for_module);
1550
1551 let mut args = Vec::new();
1552 for (core_wasm_name, instance) in self.info.imports_for(for_module).modules() {
1553 match instance {
1554 ImportInstance::Names(names) => {
1560 let mut exports = Vec::new();
1561 for (name, import) in names {
1562 log::trace!(
1563 "attempting to materialize import of `{core_wasm_name}::{name}` for {for_module:?}"
1564 );
1565 let (kind, index) = self
1566 .materialize_import(&shims, for_module, import)
1567 .with_context(|| {
1568 format!("failed to satisfy import `{core_wasm_name}::{name}`")
1569 })?;
1570 exports.push((name.as_str(), kind, index));
1571 }
1572 let index = self.component.core_instantiate_exports(exports);
1573 args.push((core_wasm_name.as_str(), ModuleArg::Instance(index)));
1574 }
1575
1576 ImportInstance::Whole(which) => {
1579 let instance = self.instance_for(which.to_custom_module());
1580 args.push((core_wasm_name.as_str(), ModuleArg::Instance(instance)));
1581 }
1582 }
1583 }
1584
1585 Ok(self.component.core_instantiate(module, args))
1587 }
1588
1589 fn materialize_import(
1596 &mut self,
1597 shims: &Shims<'_>,
1598 for_module: CustomModule<'_>,
1599 import: &'a Import,
1600 ) -> Result<(ExportKind, u32)> {
1601 let resolve = &self.info.encoder.metadata.resolve;
1602 match import {
1603 Import::AdapterExport {
1606 adapter,
1607 func,
1608 ty: _,
1609 } => {
1610 assert!(self.info.encoder.adapters.contains_key(adapter));
1611 Ok(self.materialize_shim_import(shims, &ShimKind::Adapter { adapter, func }))
1612 }
1613
1614 Import::MainModuleMemory => {
1617 let index = self
1618 .memory_index
1619 .ok_or_else(|| anyhow!("main module cannot import memory"))?;
1620 Ok((ExportKind::Memory, index))
1621 }
1622
1623 Import::MainModuleExport { name, kind } => {
1625 let instance = self.instance_index.unwrap();
1626 let index = self.core_alias_export(instance, name, *kind);
1627 Ok((*kind, index))
1628 }
1629
1630 Import::Item(item) => {
1634 let instance = self.instance_for(item.which.to_custom_module());
1635 let index = self.core_alias_export(instance, &item.name, item.kind);
1636 Ok((item.kind, index))
1637 }
1638
1639 Import::ExportedResourceDrop(_key, id) => {
1645 let index = self
1646 .component
1647 .resource_drop(self.export_type_encoding_maps.id_to_index[id]);
1648 Ok((ExportKind::Func, index))
1649 }
1650 Import::ExportedResourceRep(_key, id) => {
1651 let index = self
1652 .component
1653 .resource_rep(self.export_type_encoding_maps.id_to_index[id]);
1654 Ok((ExportKind::Func, index))
1655 }
1656 Import::ExportedResourceNew(_key, id) => {
1657 let index = self
1658 .component
1659 .resource_new(self.export_type_encoding_maps.id_to_index[id]);
1660 Ok((ExportKind::Func, index))
1661 }
1662
1663 Import::ImportedResourceDrop(key, iface, id) => {
1668 let ty = &resolve.types[*id];
1669 let name = ty.name.as_ref().unwrap();
1670 self.materialize_wit_import(
1671 shims,
1672 for_module,
1673 iface.map(|_| resolve.name_world_key(key)),
1674 &format!("{name}_drop"),
1675 key,
1676 AbiVariant::GuestImport,
1677 )
1678 }
1679 Import::ExportedTaskReturn(key, interface, func, result) => {
1680 let (options, _sig) = task_return_options_and_type(resolve, *result);
1681 if options.is_empty() {
1682 let mut encoder = if interface.is_none() {
1688 self.root_import_type_encoder(*interface)
1689 } else {
1690 self.root_export_type_encoder(*interface)
1691 };
1692
1693 let result = match result {
1694 Some(ty) => Some(encoder.encode_valtype(resolve, ty)?),
1695 None => None,
1696 };
1697 let index = self.component.task_return(result, []);
1698 Ok((ExportKind::Func, index))
1699 } else {
1700 let metadata = &self.info.encoder.metadata.metadata;
1701 let encoding = metadata.export_encodings.get(resolve, key, func).unwrap();
1702 Ok(self.materialize_shim_import(
1703 shims,
1704 &ShimKind::TaskReturn {
1705 for_module,
1706 interface: *interface,
1707 func,
1708 result: *result,
1709 encoding,
1710 },
1711 ))
1712 }
1713 }
1714 Import::BackpressureSet => {
1715 let index = self.component.backpressure_set();
1716 Ok((ExportKind::Func, index))
1717 }
1718 Import::BackpressureInc => {
1719 let index = self.component.backpressure_inc();
1720 Ok((ExportKind::Func, index))
1721 }
1722 Import::BackpressureDec => {
1723 let index = self.component.backpressure_dec();
1724 Ok((ExportKind::Func, index))
1725 }
1726 Import::WaitableSetWait { cancellable } => Ok(self.materialize_shim_import(
1727 shims,
1728 &ShimKind::WaitableSetWait {
1729 cancellable: *cancellable,
1730 },
1731 )),
1732 Import::WaitableSetPoll { cancellable } => Ok(self.materialize_shim_import(
1733 shims,
1734 &ShimKind::WaitableSetPoll {
1735 cancellable: *cancellable,
1736 },
1737 )),
1738 Import::ThreadYield { cancellable } => {
1739 let index = self.component.thread_yield(*cancellable);
1740 Ok((ExportKind::Func, index))
1741 }
1742 Import::SubtaskDrop => {
1743 let index = self.component.subtask_drop();
1744 Ok((ExportKind::Func, index))
1745 }
1746 Import::SubtaskCancel { async_ } => {
1747 let index = self.component.subtask_cancel(*async_);
1748 Ok((ExportKind::Func, index))
1749 }
1750 Import::StreamNew(info) => {
1751 let ty = self.payload_type_index(info)?;
1752 let index = self.component.stream_new(ty);
1753 Ok((ExportKind::Func, index))
1754 }
1755 Import::StreamRead { info, .. } => Ok(self.materialize_payload_import(
1756 shims,
1757 for_module,
1758 info,
1759 PayloadFuncKind::StreamRead,
1760 )),
1761 Import::StreamWrite { info, .. } => Ok(self.materialize_payload_import(
1762 shims,
1763 for_module,
1764 info,
1765 PayloadFuncKind::StreamWrite,
1766 )),
1767 Import::StreamCancelRead { info, async_ } => {
1768 let ty = self.payload_type_index(info)?;
1769 let index = self.component.stream_cancel_read(ty, *async_);
1770 Ok((ExportKind::Func, index))
1771 }
1772 Import::StreamCancelWrite { info, async_ } => {
1773 let ty = self.payload_type_index(info)?;
1774 let index = self.component.stream_cancel_write(ty, *async_);
1775 Ok((ExportKind::Func, index))
1776 }
1777 Import::StreamDropReadable(info) => {
1778 let type_index = self.payload_type_index(info)?;
1779 let index = self.component.stream_drop_readable(type_index);
1780 Ok((ExportKind::Func, index))
1781 }
1782 Import::StreamDropWritable(info) => {
1783 let type_index = self.payload_type_index(info)?;
1784 let index = self.component.stream_drop_writable(type_index);
1785 Ok((ExportKind::Func, index))
1786 }
1787 Import::FutureNew(info) => {
1788 let ty = self.payload_type_index(info)?;
1789 let index = self.component.future_new(ty);
1790 Ok((ExportKind::Func, index))
1791 }
1792 Import::FutureRead { info, .. } => Ok(self.materialize_payload_import(
1793 shims,
1794 for_module,
1795 info,
1796 PayloadFuncKind::FutureRead,
1797 )),
1798 Import::FutureWrite { info, .. } => Ok(self.materialize_payload_import(
1799 shims,
1800 for_module,
1801 info,
1802 PayloadFuncKind::FutureWrite,
1803 )),
1804 Import::FutureCancelRead { info, async_ } => {
1805 let ty = self.payload_type_index(info)?;
1806 let index = self.component.future_cancel_read(ty, *async_);
1807 Ok((ExportKind::Func, index))
1808 }
1809 Import::FutureCancelWrite { info, async_ } => {
1810 let ty = self.payload_type_index(info)?;
1811 let index = self.component.future_cancel_write(ty, *async_);
1812 Ok((ExportKind::Func, index))
1813 }
1814 Import::FutureDropReadable(info) => {
1815 let type_index = self.payload_type_index(info)?;
1816 let index = self.component.future_drop_readable(type_index);
1817 Ok((ExportKind::Func, index))
1818 }
1819 Import::FutureDropWritable(info) => {
1820 let type_index = self.payload_type_index(info)?;
1821 let index = self.component.future_drop_writable(type_index);
1822 Ok((ExportKind::Func, index))
1823 }
1824 Import::ErrorContextNew { encoding } => Ok(self.materialize_shim_import(
1825 shims,
1826 &ShimKind::ErrorContextNew {
1827 encoding: *encoding,
1828 },
1829 )),
1830 Import::ErrorContextDebugMessage { encoding } => Ok(self.materialize_shim_import(
1831 shims,
1832 &ShimKind::ErrorContextDebugMessage {
1833 for_module,
1834 encoding: *encoding,
1835 },
1836 )),
1837 Import::ErrorContextDrop => {
1838 let index = self.component.error_context_drop();
1839 Ok((ExportKind::Func, index))
1840 }
1841 Import::WorldFunc(key, name, abi) => {
1842 self.materialize_wit_import(shims, for_module, None, name, key, *abi)
1843 }
1844 Import::InterfaceFunc(key, _, name, abi) => self.materialize_wit_import(
1845 shims,
1846 for_module,
1847 Some(resolve.name_world_key(key)),
1848 name,
1849 key,
1850 *abi,
1851 ),
1852
1853 Import::WaitableSetNew => {
1854 let index = self.component.waitable_set_new();
1855 Ok((ExportKind::Func, index))
1856 }
1857 Import::WaitableSetDrop => {
1858 let index = self.component.waitable_set_drop();
1859 Ok((ExportKind::Func, index))
1860 }
1861 Import::WaitableJoin => {
1862 let index = self.component.waitable_join();
1863 Ok((ExportKind::Func, index))
1864 }
1865 Import::ContextGet(n) => {
1866 let index = self.component.context_get(*n);
1867 Ok((ExportKind::Func, index))
1868 }
1869 Import::ContextSet(n) => {
1870 let index = self.component.context_set(*n);
1871 Ok((ExportKind::Func, index))
1872 }
1873 Import::ExportedTaskCancel => {
1874 let index = self.component.task_cancel();
1875 Ok((ExportKind::Func, index))
1876 }
1877 Import::ThreadIndex => {
1878 let index = self.component.thread_index();
1879 Ok((ExportKind::Func, index))
1880 }
1881 Import::ThreadNewIndirect => Ok(self.materialize_shim_import(
1882 shims,
1883 &ShimKind::ThreadNewIndirect {
1884 for_module,
1885 func_ty: FuncType::new([ValType::I32], []),
1887 },
1888 )),
1889 Import::ThreadSwitchTo { cancellable } => {
1890 let index = self.component.thread_switch_to(*cancellable);
1891 Ok((ExportKind::Func, index))
1892 }
1893 Import::ThreadSuspend { cancellable } => {
1894 let index = self.component.thread_suspend(*cancellable);
1895 Ok((ExportKind::Func, index))
1896 }
1897 Import::ThreadResumeLater => {
1898 let index = self.component.thread_resume_later();
1899 Ok((ExportKind::Func, index))
1900 }
1901 Import::ThreadYieldTo { cancellable } => {
1902 let index = self.component.thread_yield_to(*cancellable);
1903 Ok((ExportKind::Func, index))
1904 }
1905 }
1906 }
1907
1908 fn materialize_shim_import(&mut self, shims: &Shims<'_>, kind: &ShimKind) -> (ExportKind, u32) {
1911 let index = self.core_alias_export(
1912 self.shim_instance_index
1913 .expect("shim should be instantiated"),
1914 &shims.shims[kind].name,
1915 ExportKind::Func,
1916 );
1917 (ExportKind::Func, index)
1918 }
1919
1920 fn materialize_payload_import(
1923 &mut self,
1924 shims: &Shims<'_>,
1925 for_module: CustomModule<'_>,
1926 info: &PayloadInfo,
1927 kind: PayloadFuncKind,
1928 ) -> (ExportKind, u32) {
1929 self.materialize_shim_import(
1930 shims,
1931 &ShimKind::PayloadFunc {
1932 for_module,
1933 info,
1934 kind,
1935 },
1936 )
1937 }
1938
1939 fn materialize_wit_import(
1942 &mut self,
1943 shims: &Shims<'_>,
1944 for_module: CustomModule<'_>,
1945 interface_key: Option<String>,
1946 name: &String,
1947 key: &WorldKey,
1948 abi: AbiVariant,
1949 ) -> Result<(ExportKind, u32)> {
1950 let resolve = &self.info.encoder.metadata.resolve;
1951 let import = &self.info.import_map[&interface_key];
1952 let (index, _, lowering) = import.lowerings.get_full(&(name.clone(), abi)).unwrap();
1953 let metadata = self.info.module_metadata_for(for_module);
1954
1955 let index = match lowering {
1956 Lowering::Direct => {
1959 let func_index = match &import.interface {
1960 Some(interface) => {
1961 let instance_index = self.imported_instances[interface];
1962 self.component
1963 .alias_export(instance_index, name, ComponentExportKind::Func)
1964 }
1965 None => self.imported_funcs[name],
1966 };
1967 self.component.lower_func(
1968 func_index,
1969 if let AbiVariant::GuestImportAsync = abi {
1970 vec![CanonicalOption::Async]
1971 } else {
1972 Vec::new()
1973 },
1974 )
1975 }
1976
1977 Lowering::Indirect { .. } => {
1981 let encoding = metadata.import_encodings.get(resolve, key, name).unwrap();
1982 return Ok(self.materialize_shim_import(
1983 shims,
1984 &ShimKind::IndirectLowering {
1985 interface: interface_key,
1986 index,
1987 realloc: for_module,
1988 encoding,
1989 },
1990 ));
1991 }
1992
1993 Lowering::ResourceDrop(id) => {
1996 let resource_idx = self.lookup_resource_index(*id);
1997 self.component.resource_drop(resource_idx)
1998 }
1999 };
2000 Ok((ExportKind::Func, index))
2001 }
2002
2003 fn encode_initialize_with_start(&mut self) -> Result<()> {
2022 let initialize = match self.info.info.exports.initialize() {
2023 Some(name) => name,
2024 None => return Ok(()),
2027 };
2028 let initialize_index =
2029 self.core_alias_export(self.instance_index.unwrap(), initialize, ExportKind::Func);
2030 let mut shim = Module::default();
2031 let mut section = TypeSection::new();
2032 section.ty().function([], []);
2033 shim.section(§ion);
2034 let mut section = ImportSection::new();
2035 section.import("", "", EntityType::Function(0));
2036 shim.section(§ion);
2037 shim.section(&StartSection { function_index: 0 });
2038
2039 let shim_module_index = self.component.core_module(&shim);
2044 let shim_args_instance_index =
2045 self.component
2046 .core_instantiate_exports([("", ExportKind::Func, initialize_index)]);
2047 self.component.core_instantiate(
2048 shim_module_index,
2049 [("", ModuleArg::Instance(shim_args_instance_index))],
2050 );
2051 Ok(())
2052 }
2053
2054 fn instance_for(&self, module: CustomModule) -> u32 {
2057 match module {
2058 CustomModule::Main => self.instance_index.expect("instantiated by now"),
2059 CustomModule::Adapter(name) => self.adapter_instances[name],
2060 }
2061 }
2062
2063 fn module_for(&self, module: CustomModule) -> u32 {
2066 match module {
2067 CustomModule::Main => self.module_index.unwrap(),
2068 CustomModule::Adapter(name) => self.adapter_modules[name],
2069 }
2070 }
2071
2072 fn core_alias_export(&mut self, instance: u32, name: &str, kind: ExportKind) -> u32 {
2075 *self
2076 .aliased_core_items
2077 .entry((instance, name.to_string()))
2078 .or_insert_with(|| self.component.core_alias_export(instance, name, kind))
2079 }
2080}
2081
2082#[derive(Default)]
2100struct Shims<'a> {
2101 shims: IndexMap<ShimKind<'a>, Shim<'a>>,
2103}
2104
2105struct Shim<'a> {
2106 options: RequiredOptions,
2109
2110 name: String,
2114
2115 debug_name: String,
2118
2119 kind: ShimKind<'a>,
2121
2122 sig: WasmSignature,
2124}
2125
2126#[derive(Debug, Clone, Hash, Eq, PartialEq)]
2129enum PayloadFuncKind {
2130 FutureWrite,
2131 FutureRead,
2132 StreamWrite,
2133 StreamRead,
2134}
2135
2136#[derive(Debug, Clone, Hash, Eq, PartialEq)]
2137enum ShimKind<'a> {
2138 IndirectLowering {
2142 interface: Option<String>,
2144 index: usize,
2146 realloc: CustomModule<'a>,
2148 encoding: StringEncoding,
2150 },
2151 Adapter {
2154 adapter: &'a str,
2156 func: &'a str,
2158 },
2159 ResourceDtor {
2162 module: CustomModule<'a>,
2164 export: &'a str,
2166 },
2167 PayloadFunc {
2171 for_module: CustomModule<'a>,
2174 info: &'a PayloadInfo,
2179 kind: PayloadFuncKind,
2181 },
2182 WaitableSetWait { cancellable: bool },
2186 WaitableSetPoll { cancellable: bool },
2190 TaskReturn {
2192 interface: Option<InterfaceId>,
2195 func: &'a str,
2198 result: Option<Type>,
2200 for_module: CustomModule<'a>,
2202 encoding: StringEncoding,
2204 },
2205 ErrorContextNew {
2209 encoding: StringEncoding,
2211 },
2212 ErrorContextDebugMessage {
2216 for_module: CustomModule<'a>,
2218 encoding: StringEncoding,
2220 },
2221 ThreadNewIndirect {
2224 for_module: CustomModule<'a>,
2226 func_ty: FuncType,
2228 },
2229}
2230
2231#[derive(Debug, Copy, Clone, Hash, Eq, PartialEq)]
2241enum CustomModule<'a> {
2242 Main,
2245 Adapter(&'a str),
2248}
2249
2250impl<'a> Shims<'a> {
2251 fn append_indirect(
2256 &mut self,
2257 world: &'a ComponentWorld<'a>,
2258 for_module: CustomModule<'a>,
2259 ) -> Result<()> {
2260 let module_imports = world.imports_for(for_module);
2261 let module_exports = world.exports_for(for_module);
2262 let resolve = &world.encoder.metadata.resolve;
2263
2264 for (module, field, import) in module_imports.imports() {
2265 match import {
2266 Import::ImportedResourceDrop(..)
2269 | Import::MainModuleMemory
2270 | Import::MainModuleExport { .. }
2271 | Import::Item(_)
2272 | Import::ExportedResourceDrop(..)
2273 | Import::ExportedResourceRep(..)
2274 | Import::ExportedResourceNew(..)
2275 | Import::ExportedTaskCancel
2276 | Import::ErrorContextDrop
2277 | Import::BackpressureSet
2278 | Import::BackpressureInc
2279 | Import::BackpressureDec
2280 | Import::ThreadYield { .. }
2281 | Import::SubtaskDrop
2282 | Import::SubtaskCancel { .. }
2283 | Import::FutureNew(..)
2284 | Import::StreamNew(..)
2285 | Import::FutureCancelRead { .. }
2286 | Import::FutureCancelWrite { .. }
2287 | Import::FutureDropWritable { .. }
2288 | Import::FutureDropReadable { .. }
2289 | Import::StreamCancelRead { .. }
2290 | Import::StreamCancelWrite { .. }
2291 | Import::StreamDropWritable { .. }
2292 | Import::StreamDropReadable { .. }
2293 | Import::WaitableSetNew
2294 | Import::WaitableSetDrop
2295 | Import::WaitableJoin
2296 | Import::ContextGet(_)
2297 | Import::ContextSet(_)
2298 | Import::ThreadIndex
2299 | Import::ThreadSwitchTo { .. }
2300 | Import::ThreadSuspend { .. }
2301 | Import::ThreadResumeLater
2302 | Import::ThreadYieldTo { .. } => {}
2303
2304 Import::ExportedTaskReturn(key, interface, func, ty) => {
2308 let (options, sig) = task_return_options_and_type(resolve, *ty);
2309 if options.is_empty() {
2310 continue;
2311 }
2312 let name = self.shims.len().to_string();
2313 let encoding = world
2314 .module_metadata_for(for_module)
2315 .export_encodings
2316 .get(resolve, key, func)
2317 .ok_or_else(|| {
2318 anyhow::anyhow!(
2319 "missing component metadata for export of \
2320 `{module}::{field}`"
2321 )
2322 })?;
2323 self.push(Shim {
2324 name,
2325 debug_name: format!("task-return-{func}"),
2326 options,
2327 kind: ShimKind::TaskReturn {
2328 interface: *interface,
2329 func,
2330 result: *ty,
2331 for_module,
2332 encoding,
2333 },
2334 sig,
2335 });
2336 }
2337
2338 Import::FutureWrite { async_, info } => {
2339 self.append_indirect_payload_push(
2340 resolve,
2341 for_module,
2342 module,
2343 *async_,
2344 info,
2345 PayloadFuncKind::FutureWrite,
2346 vec![WasmType::I32; 2],
2347 vec![WasmType::I32],
2348 );
2349 }
2350 Import::FutureRead { async_, info } => {
2351 self.append_indirect_payload_push(
2352 resolve,
2353 for_module,
2354 module,
2355 *async_,
2356 info,
2357 PayloadFuncKind::FutureRead,
2358 vec![WasmType::I32; 2],
2359 vec![WasmType::I32],
2360 );
2361 }
2362 Import::StreamWrite { async_, info } => {
2363 self.append_indirect_payload_push(
2364 resolve,
2365 for_module,
2366 module,
2367 *async_,
2368 info,
2369 PayloadFuncKind::StreamWrite,
2370 vec![WasmType::I32; 3],
2371 vec![WasmType::I32],
2372 );
2373 }
2374 Import::StreamRead { async_, info } => {
2375 self.append_indirect_payload_push(
2376 resolve,
2377 for_module,
2378 module,
2379 *async_,
2380 info,
2381 PayloadFuncKind::StreamRead,
2382 vec![WasmType::I32; 3],
2383 vec![WasmType::I32],
2384 );
2385 }
2386
2387 Import::WaitableSetWait { cancellable } => {
2388 let name = self.shims.len().to_string();
2389 self.push(Shim {
2390 name,
2391 debug_name: "waitable-set.wait".to_string(),
2392 options: RequiredOptions::empty(),
2393 kind: ShimKind::WaitableSetWait {
2394 cancellable: *cancellable,
2395 },
2396 sig: WasmSignature {
2397 params: vec![WasmType::I32; 2],
2398 results: vec![WasmType::I32],
2399 indirect_params: false,
2400 retptr: false,
2401 },
2402 });
2403 }
2404
2405 Import::WaitableSetPoll { cancellable } => {
2406 let name = self.shims.len().to_string();
2407 self.push(Shim {
2408 name,
2409 debug_name: "waitable-set.poll".to_string(),
2410 options: RequiredOptions::empty(),
2411 kind: ShimKind::WaitableSetPoll {
2412 cancellable: *cancellable,
2413 },
2414 sig: WasmSignature {
2415 params: vec![WasmType::I32; 2],
2416 results: vec![WasmType::I32],
2417 indirect_params: false,
2418 retptr: false,
2419 },
2420 });
2421 }
2422
2423 Import::ErrorContextNew { encoding } => {
2424 let name = self.shims.len().to_string();
2425 self.push(Shim {
2426 name,
2427 debug_name: "error-new".to_string(),
2428 options: RequiredOptions::MEMORY | RequiredOptions::STRING_ENCODING,
2429 kind: ShimKind::ErrorContextNew {
2430 encoding: *encoding,
2431 },
2432 sig: WasmSignature {
2433 params: vec![WasmType::I32; 2],
2434 results: vec![WasmType::I32],
2435 indirect_params: false,
2436 retptr: false,
2437 },
2438 });
2439 }
2440
2441 Import::ErrorContextDebugMessage { encoding } => {
2442 let name = self.shims.len().to_string();
2443 self.push(Shim {
2444 name,
2445 debug_name: "error-debug-message".to_string(),
2446 options: RequiredOptions::MEMORY
2447 | RequiredOptions::STRING_ENCODING
2448 | RequiredOptions::REALLOC,
2449 kind: ShimKind::ErrorContextDebugMessage {
2450 for_module,
2451 encoding: *encoding,
2452 },
2453 sig: WasmSignature {
2454 params: vec![WasmType::I32; 2],
2455 results: vec![],
2456 indirect_params: false,
2457 retptr: false,
2458 },
2459 });
2460 }
2461
2462 Import::ThreadNewIndirect => {
2463 let name = self.shims.len().to_string();
2464 self.push(Shim {
2465 name,
2466 debug_name: "thread.new_indirect".to_string(),
2467 options: RequiredOptions::empty(),
2468 kind: ShimKind::ThreadNewIndirect {
2469 for_module,
2470 func_ty: FuncType::new([ValType::I32], vec![]),
2472 },
2473 sig: WasmSignature {
2474 params: vec![WasmType::I32; 2],
2475 results: vec![WasmType::I32],
2476 indirect_params: false,
2477 retptr: false,
2478 },
2479 });
2480 }
2481
2482 Import::AdapterExport { adapter, func, ty } => {
2485 let name = self.shims.len().to_string();
2486 log::debug!("shim {name} is adapter `{module}::{field}`");
2487 self.push(Shim {
2488 name,
2489 debug_name: format!("adapt-{module}-{field}"),
2490 options: RequiredOptions::MEMORY,
2494 kind: ShimKind::Adapter { adapter, func },
2495 sig: WasmSignature {
2496 params: ty.params().iter().map(to_wasm_type).collect(),
2497 results: ty.results().iter().map(to_wasm_type).collect(),
2498 indirect_params: false,
2499 retptr: false,
2500 },
2501 });
2502
2503 fn to_wasm_type(ty: &wasmparser::ValType) -> WasmType {
2504 match ty {
2505 wasmparser::ValType::I32 => WasmType::I32,
2506 wasmparser::ValType::I64 => WasmType::I64,
2507 wasmparser::ValType::F32 => WasmType::F32,
2508 wasmparser::ValType::F64 => WasmType::F64,
2509 _ => unreachable!(),
2510 }
2511 }
2512 }
2513
2514 Import::InterfaceFunc(key, _, name, abi) => {
2518 self.append_indirect_wit_func(
2519 world,
2520 for_module,
2521 module,
2522 field,
2523 key,
2524 name,
2525 Some(resolve.name_world_key(key)),
2526 *abi,
2527 )?;
2528 }
2529 Import::WorldFunc(key, name, abi) => {
2530 self.append_indirect_wit_func(
2531 world, for_module, module, field, key, name, None, *abi,
2532 )?;
2533 }
2534 }
2535 }
2536
2537 for (export_name, export) in module_exports.iter() {
2543 let id = match export {
2544 Export::ResourceDtor(id) => id,
2545 _ => continue,
2546 };
2547 let resource = resolve.types[*id].name.as_ref().unwrap();
2548 let name = self.shims.len().to_string();
2549 self.push(Shim {
2550 name,
2551 debug_name: format!("dtor-{resource}"),
2552 options: RequiredOptions::empty(),
2553 kind: ShimKind::ResourceDtor {
2554 module: for_module,
2555 export: export_name,
2556 },
2557 sig: WasmSignature {
2558 params: vec![WasmType::I32],
2559 results: Vec::new(),
2560 indirect_params: false,
2561 retptr: false,
2562 },
2563 });
2564 }
2565
2566 Ok(())
2567 }
2568
2569 fn append_indirect_payload_push(
2572 &mut self,
2573 resolve: &Resolve,
2574 for_module: CustomModule<'a>,
2575 module: &str,
2576 async_: bool,
2577 info: &'a PayloadInfo,
2578 kind: PayloadFuncKind,
2579 params: Vec<WasmType>,
2580 results: Vec<WasmType>,
2581 ) {
2582 let debug_name = format!("{module}-{}", info.name);
2583 let name = self.shims.len().to_string();
2584
2585 let payload = info.payload(resolve);
2586 let (wit_param, wit_result) = match kind {
2587 PayloadFuncKind::StreamRead | PayloadFuncKind::FutureRead => (None, payload),
2588 PayloadFuncKind::StreamWrite | PayloadFuncKind::FutureWrite => (payload, None),
2589 };
2590 self.push(Shim {
2591 name,
2592 debug_name,
2593 options: RequiredOptions::MEMORY
2594 | RequiredOptions::for_import(
2595 resolve,
2596 &Function {
2597 name: String::new(),
2598 kind: FunctionKind::Freestanding,
2599 params: match wit_param {
2600 Some(ty) => vec![("a".to_string(), ty)],
2601 None => Vec::new(),
2602 },
2603 result: wit_result,
2604 docs: Default::default(),
2605 stability: Stability::Unknown,
2606 },
2607 if async_ {
2608 AbiVariant::GuestImportAsync
2609 } else {
2610 AbiVariant::GuestImport
2611 },
2612 ),
2613 kind: ShimKind::PayloadFunc {
2614 for_module,
2615 info,
2616 kind,
2617 },
2618 sig: WasmSignature {
2619 params,
2620 results,
2621 indirect_params: false,
2622 retptr: false,
2623 },
2624 });
2625 }
2626
2627 fn append_indirect_wit_func(
2630 &mut self,
2631 world: &'a ComponentWorld<'a>,
2632 for_module: CustomModule<'a>,
2633 module: &str,
2634 field: &str,
2635 key: &WorldKey,
2636 name: &String,
2637 interface_key: Option<String>,
2638 abi: AbiVariant,
2639 ) -> Result<()> {
2640 let resolve = &world.encoder.metadata.resolve;
2641 let metadata = world.module_metadata_for(for_module);
2642 let interface = &world.import_map[&interface_key];
2643 let (index, _, lowering) = interface.lowerings.get_full(&(name.clone(), abi)).unwrap();
2644 let shim_name = self.shims.len().to_string();
2645 match lowering {
2646 Lowering::Direct | Lowering::ResourceDrop(_) => {}
2647
2648 Lowering::Indirect { sig, options } => {
2649 log::debug!(
2650 "shim {shim_name} is import `{module}::{field}` lowering {index} `{name}`",
2651 );
2652 let encoding = metadata
2653 .import_encodings
2654 .get(resolve, key, name)
2655 .ok_or_else(|| {
2656 anyhow::anyhow!(
2657 "missing component metadata for import of \
2658 `{module}::{field}`"
2659 )
2660 })?;
2661 self.push(Shim {
2662 name: shim_name,
2663 debug_name: format!("indirect-{module}-{field}"),
2664 options: *options,
2665 kind: ShimKind::IndirectLowering {
2666 interface: interface_key,
2667 index,
2668 realloc: for_module,
2669 encoding,
2670 },
2671 sig: sig.clone(),
2672 });
2673 }
2674 }
2675
2676 Ok(())
2677 }
2678
2679 fn push(&mut self, shim: Shim<'a>) {
2680 if !self.shims.contains_key(&shim.kind) {
2684 self.shims.insert(shim.kind.clone(), shim);
2685 }
2686 }
2687}
2688
2689fn task_return_options_and_type(
2690 resolve: &Resolve,
2691 ty: Option<Type>,
2692) -> (RequiredOptions, WasmSignature) {
2693 let func_tmp = Function {
2694 name: String::new(),
2695 kind: FunctionKind::Freestanding,
2696 params: match ty {
2697 Some(ty) => vec![("a".to_string(), ty)],
2698 None => Vec::new(),
2699 },
2700 result: None,
2701 docs: Default::default(),
2702 stability: Stability::Unknown,
2703 };
2704 let abi = AbiVariant::GuestImport;
2705 let options = RequiredOptions::for_import(resolve, &func_tmp, abi);
2706 let sig = resolve.wasm_signature(abi, &func_tmp);
2707 (options, sig)
2708}
2709
2710#[derive(Clone, Debug)]
2712pub struct Item {
2713 pub alias: String,
2714 pub kind: ExportKind,
2715 pub which: MainOrAdapter,
2716 pub name: String,
2717}
2718
2719#[derive(Debug, PartialEq, Clone)]
2721pub enum MainOrAdapter {
2722 Main,
2723 Adapter(String),
2724}
2725
2726impl MainOrAdapter {
2727 fn to_custom_module(&self) -> CustomModule<'_> {
2728 match self {
2729 MainOrAdapter::Main => CustomModule::Main,
2730 MainOrAdapter::Adapter(s) => CustomModule::Adapter(s),
2731 }
2732 }
2733}
2734
2735#[derive(Clone)]
2737pub enum Instance {
2738 MainOrAdapter(MainOrAdapter),
2740
2741 Items(Vec<Item>),
2743}
2744
2745#[derive(Clone)]
2748pub struct LibraryInfo {
2749 pub instantiate_after_shims: bool,
2751
2752 pub arguments: Vec<(String, Instance)>,
2754}
2755
2756pub(super) struct Adapter {
2758 wasm: Vec<u8>,
2760
2761 metadata: ModuleMetadata,
2763
2764 required_exports: IndexSet<WorldKey>,
2767
2768 library_info: Option<LibraryInfo>,
2773}
2774
2775#[derive(Default)]
2777pub struct ComponentEncoder {
2778 module: Vec<u8>,
2779 module_import_map: Option<ModuleImportMap>,
2780 pub(super) metadata: Bindgen,
2781 validate: bool,
2782 pub(super) main_module_exports: IndexSet<WorldKey>,
2783 pub(super) adapters: IndexMap<String, Adapter>,
2784 import_name_map: HashMap<String, String>,
2785 realloc_via_memory_grow: bool,
2786 merge_imports_based_on_semver: Option<bool>,
2787 pub(super) reject_legacy_names: bool,
2788}
2789
2790impl ComponentEncoder {
2791 pub fn module(mut self, module: &[u8]) -> Result<Self> {
2797 let (wasm, metadata) = self.decode(module.as_ref())?;
2798 let (wasm, module_import_map) = ModuleImportMap::new(wasm)?;
2799 let exports = self
2800 .merge_metadata(metadata)
2801 .context("failed merge WIT metadata for module with previous metadata")?;
2802 self.main_module_exports.extend(exports);
2803 self.module = if let Some(producers) = &self.metadata.producers {
2804 producers.add_to_wasm(&wasm)?
2805 } else {
2806 wasm.to_vec()
2807 };
2808 self.module_import_map = module_import_map;
2809 Ok(self)
2810 }
2811
2812 fn decode<'a>(&self, wasm: &'a [u8]) -> Result<(Cow<'a, [u8]>, Bindgen)> {
2813 let (bytes, metadata) = metadata::decode(wasm)?;
2814 match bytes {
2815 Some(wasm) => Ok((Cow::Owned(wasm), metadata)),
2816 None => Ok((Cow::Borrowed(wasm), metadata)),
2817 }
2818 }
2819
2820 fn merge_metadata(&mut self, metadata: Bindgen) -> Result<IndexSet<WorldKey>> {
2821 self.metadata.merge(metadata)
2822 }
2823
2824 pub fn validate(mut self, validate: bool) -> Self {
2826 self.validate = validate;
2827 self
2828 }
2829
2830 pub fn merge_imports_based_on_semver(mut self, merge: bool) -> Self {
2838 self.merge_imports_based_on_semver = Some(merge);
2839 self
2840 }
2841
2842 pub fn reject_legacy_names(mut self, reject: bool) -> Self {
2851 self.reject_legacy_names = reject;
2852 self
2853 }
2854
2855 pub fn adapter(self, name: &str, bytes: &[u8]) -> Result<Self> {
2873 self.library_or_adapter(name, bytes, None)
2874 }
2875
2876 pub fn library(self, name: &str, bytes: &[u8], library_info: LibraryInfo) -> Result<Self> {
2889 self.library_or_adapter(name, bytes, Some(library_info))
2890 }
2891
2892 fn library_or_adapter(
2893 mut self,
2894 name: &str,
2895 bytes: &[u8],
2896 library_info: Option<LibraryInfo>,
2897 ) -> Result<Self> {
2898 let (wasm, mut metadata) = self.decode(bytes)?;
2899 let adapter_metadata = mem::take(&mut metadata.metadata);
2907 let exports = self.merge_metadata(metadata).with_context(|| {
2908 format!("failed to merge WIT packages of adapter `{name}` into main packages")
2909 })?;
2910 if let Some(library_info) = &library_info {
2911 for (_, instance) in &library_info.arguments {
2913 let resolve = |which: &_| match which {
2914 MainOrAdapter::Main => Ok(()),
2915 MainOrAdapter::Adapter(name) => {
2916 if self.adapters.contains_key(name.as_str()) {
2917 Ok(())
2918 } else {
2919 Err(anyhow!("instance refers to unknown adapter `{name}`"))
2920 }
2921 }
2922 };
2923
2924 match instance {
2925 Instance::MainOrAdapter(which) => resolve(which)?,
2926 Instance::Items(items) => {
2927 for item in items {
2928 resolve(&item.which)?;
2929 }
2930 }
2931 }
2932 }
2933 }
2934 self.adapters.insert(
2935 name.to_string(),
2936 Adapter {
2937 wasm: wasm.to_vec(),
2938 metadata: adapter_metadata,
2939 required_exports: exports,
2940 library_info,
2941 },
2942 );
2943 Ok(self)
2944 }
2945
2946 pub fn realloc_via_memory_grow(mut self, value: bool) -> Self {
2951 self.realloc_via_memory_grow = value;
2952 self
2953 }
2954
2955 pub fn import_name_map(mut self, map: HashMap<String, String>) -> Self {
2966 self.import_name_map = map;
2967 self
2968 }
2969
2970 pub fn encode(&mut self) -> Result<Vec<u8>> {
2972 if self.module.is_empty() {
2973 bail!("a module is required when encoding a component");
2974 }
2975
2976 if self.merge_imports_based_on_semver.unwrap_or(true) {
2977 self.metadata
2978 .resolve
2979 .merge_world_imports_based_on_semver(self.metadata.world)?;
2980 }
2981
2982 let world = ComponentWorld::new(self).context("failed to decode world from module")?;
2983 let mut state = EncodingState {
2984 component: ComponentBuilder::default(),
2985 module_index: None,
2986 instance_index: None,
2987 memory_index: None,
2988 shim_instance_index: None,
2989 fixups_module_index: None,
2990 adapter_modules: IndexMap::new(),
2991 adapter_instances: IndexMap::new(),
2992 import_type_encoding_maps: Default::default(),
2993 export_type_encoding_maps: Default::default(),
2994 imported_instances: Default::default(),
2995 imported_funcs: Default::default(),
2996 exported_instances: Default::default(),
2997 aliased_core_items: Default::default(),
2998 info: &world,
2999 };
3000 state.encode_imports(&self.import_name_map)?;
3001 state.encode_core_modules();
3002 state.encode_core_instantiation()?;
3003 state.encode_exports(CustomModule::Main)?;
3004 for name in self.adapters.keys() {
3005 state.encode_exports(CustomModule::Adapter(name))?;
3006 }
3007 state
3008 .component
3009 .raw_custom_section(&crate::base_producers().raw_custom_section());
3010 let bytes = state.component.finish();
3011
3012 if self.validate {
3013 Validator::new_with_features(WasmFeatures::all())
3014 .validate_all(&bytes)
3015 .context("failed to validate component output")?;
3016 }
3017
3018 Ok(bytes)
3019 }
3020}
3021
3022impl ComponentWorld<'_> {
3023 fn imports_for(&self, module: CustomModule) -> &ImportMap {
3025 match module {
3026 CustomModule::Main => &self.info.imports,
3027 CustomModule::Adapter(name) => &self.adapters[name].info.imports,
3028 }
3029 }
3030
3031 fn exports_for(&self, module: CustomModule) -> &ExportMap {
3033 match module {
3034 CustomModule::Main => &self.info.exports,
3035 CustomModule::Adapter(name) => &self.adapters[name].info.exports,
3036 }
3037 }
3038
3039 fn module_metadata_for(&self, module: CustomModule) -> &ModuleMetadata {
3041 match module {
3042 CustomModule::Main => &self.encoder.metadata.metadata,
3043 CustomModule::Adapter(name) => &self.encoder.adapters[name].metadata,
3044 }
3045 }
3046}
3047
3048#[cfg(all(test, feature = "dummy-module"))]
3049mod test {
3050 use super::*;
3051 use crate::{dummy_module, embed_component_metadata};
3052 use wit_parser::ManglingAndAbi;
3053
3054 #[test]
3055 fn it_renames_imports() {
3056 let mut resolve = Resolve::new();
3057 let pkg = resolve
3058 .push_str(
3059 "test.wit",
3060 r#"
3061package test:wit;
3062
3063interface i {
3064 f: func();
3065}
3066
3067world test {
3068 import i;
3069 import foo: interface {
3070 f: func();
3071 }
3072}
3073"#,
3074 )
3075 .unwrap();
3076 let world = resolve.select_world(&[pkg], None).unwrap();
3077
3078 let mut module = dummy_module(&resolve, world, ManglingAndAbi::Standard32);
3079
3080 embed_component_metadata(&mut module, &resolve, world, StringEncoding::UTF8).unwrap();
3081
3082 let encoded = ComponentEncoder::default()
3083 .import_name_map(HashMap::from([
3084 (
3085 "foo".to_string(),
3086 "unlocked-dep=<foo:bar/foo@{>=1.0.0 <1.1.0}>".to_string(),
3087 ),
3088 (
3089 "test:wit/i".to_string(),
3090 "locked-dep=<foo:bar/i@1.2.3>".to_string(),
3091 ),
3092 ]))
3093 .module(&module)
3094 .unwrap()
3095 .validate(true)
3096 .encode()
3097 .unwrap();
3098
3099 let wat = wasmprinter::print_bytes(encoded).unwrap();
3100 assert!(wat.contains("unlocked-dep=<foo:bar/foo@{>=1.0.0 <1.1.0}>"));
3101 assert!(wat.contains("locked-dep=<foo:bar/i@1.2.3>"));
3102 }
3103}