1use crate::metadata::{self, Bindgen, ModuleMetadata};
75use crate::validation::{Export, ExportMap, Import, ImportInstance, ImportMap, PayloadInfo};
76use crate::StringEncoding;
77use anyhow::{anyhow, bail, Context, Result};
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 abi::{AbiVariant, WasmSignature, WasmType},
87 Function, FunctionKind, InterfaceId, LiveTypes, Resolve, Stability, Type, TypeDefKind, TypeId,
88 TypeOwner, WorldItem, WorldKey,
89};
90
91const INDIRECT_TABLE_NAME: &str = "$imports";
92
93mod wit;
94pub use wit::{encode, encode_world};
95
96mod types;
97use types::{InstanceTypeEncoder, RootTypeEncoder, ValtypeEncoder};
98mod world;
99use world::{ComponentWorld, ImportedInterface, Lowering};
100
101fn to_val_type(ty: &WasmType) -> ValType {
102 match ty {
103 WasmType::I32 => ValType::I32,
104 WasmType::I64 => ValType::I64,
105 WasmType::F32 => ValType::F32,
106 WasmType::F64 => ValType::F64,
107 WasmType::Pointer => ValType::I32,
108 WasmType::PointerOrI64 => ValType::I64,
109 WasmType::Length => ValType::I32,
110 }
111}
112
113bitflags::bitflags! {
114 #[derive(Copy, Clone, Debug)]
117 pub struct RequiredOptions: u8 {
118 const MEMORY = 1 << 0;
121 const REALLOC = 1 << 1;
124 const STRING_ENCODING = 1 << 2;
127 const ASYNC = 1 << 3;
128 }
129}
130
131impl RequiredOptions {
132 fn for_import(resolve: &Resolve, func: &Function, abi: AbiVariant) -> RequiredOptions {
133 let sig = resolve.wasm_signature(abi, func);
134 let mut ret = RequiredOptions::empty();
135 ret.add_lift(TypeContents::for_types(
137 resolve,
138 func.params.iter().map(|(_, t)| t),
139 ));
140 ret.add_lower(TypeContents::for_types(resolve, &func.result));
141
142 if sig.retptr || sig.indirect_params {
145 ret |= RequiredOptions::MEMORY;
146 }
147 if abi == AbiVariant::GuestImportAsync {
148 ret |= RequiredOptions::ASYNC;
149 }
150 ret
151 }
152
153 fn for_export(resolve: &Resolve, func: &Function, abi: AbiVariant) -> RequiredOptions {
154 let sig = resolve.wasm_signature(abi, func);
155 let mut ret = RequiredOptions::empty();
156 ret.add_lower(TypeContents::for_types(
158 resolve,
159 func.params.iter().map(|(_, t)| t),
160 ));
161 ret.add_lift(TypeContents::for_types(resolve, &func.result));
162
163 if sig.retptr || sig.indirect_params {
167 ret |= RequiredOptions::MEMORY;
168 if sig.indirect_params {
169 ret |= RequiredOptions::REALLOC;
170 }
171 }
172 if let AbiVariant::GuestExportAsync | AbiVariant::GuestExportAsyncStackful = abi {
173 ret |= RequiredOptions::ASYNC;
174 }
175 ret
176 }
177
178 fn add_lower(&mut self, types: TypeContents) {
179 if types.contains(TypeContents::LIST) {
183 *self |= RequiredOptions::MEMORY | RequiredOptions::REALLOC;
184 }
185 if types.contains(TypeContents::STRING) {
186 *self |= RequiredOptions::MEMORY
187 | RequiredOptions::STRING_ENCODING
188 | RequiredOptions::REALLOC;
189 }
190 }
191
192 fn add_lift(&mut self, types: TypeContents) {
193 if types.contains(TypeContents::LIST) {
197 *self |= RequiredOptions::MEMORY;
198 }
199 if types.contains(TypeContents::STRING) {
200 *self |= RequiredOptions::MEMORY | RequiredOptions::STRING_ENCODING;
201 }
202 }
203
204 fn into_iter(
205 self,
206 encoding: StringEncoding,
207 memory_index: Option<u32>,
208 realloc_index: Option<u32>,
209 ) -> Result<impl ExactSizeIterator<Item = CanonicalOption>> {
210 #[derive(Default)]
211 struct Iter {
212 options: [Option<CanonicalOption>; 5],
213 current: usize,
214 count: usize,
215 }
216
217 impl Iter {
218 fn push(&mut self, option: CanonicalOption) {
219 assert!(self.count < self.options.len());
220 self.options[self.count] = Some(option);
221 self.count += 1;
222 }
223 }
224
225 impl Iterator for Iter {
226 type Item = CanonicalOption;
227
228 fn next(&mut self) -> Option<Self::Item> {
229 if self.current == self.count {
230 return None;
231 }
232 let option = self.options[self.current];
233 self.current += 1;
234 option
235 }
236
237 fn size_hint(&self) -> (usize, Option<usize>) {
238 (self.count - self.current, Some(self.count - self.current))
239 }
240 }
241
242 impl ExactSizeIterator for Iter {}
243
244 let mut iter = Iter::default();
245
246 if self.contains(RequiredOptions::MEMORY) {
247 iter.push(CanonicalOption::Memory(memory_index.ok_or_else(|| {
248 anyhow!("module does not export a memory named `memory`")
249 })?));
250 }
251
252 if self.contains(RequiredOptions::REALLOC) {
253 iter.push(CanonicalOption::Realloc(realloc_index.ok_or_else(
254 || anyhow!("module does not export a function named `cabi_realloc`"),
255 )?));
256 }
257
258 if self.contains(RequiredOptions::STRING_ENCODING) {
259 iter.push(encoding.into());
260 }
261
262 if self.contains(RequiredOptions::ASYNC) {
263 iter.push(CanonicalOption::Async);
264 }
265
266 Ok(iter)
267 }
268}
269
270bitflags::bitflags! {
271 struct TypeContents: u8 {
274 const STRING = 1 << 0;
275 const LIST = 1 << 1;
276 }
277}
278
279impl TypeContents {
280 fn for_types<'a>(resolve: &Resolve, types: impl IntoIterator<Item = &'a Type>) -> Self {
281 let mut cur = TypeContents::empty();
282 for ty in types {
283 cur |= Self::for_type(resolve, ty);
284 }
285 cur
286 }
287
288 fn for_optional_types<'a>(
289 resolve: &Resolve,
290 types: impl Iterator<Item = Option<&'a Type>>,
291 ) -> Self {
292 Self::for_types(resolve, types.flatten())
293 }
294
295 fn for_optional_type(resolve: &Resolve, ty: Option<&Type>) -> Self {
296 match ty {
297 Some(ty) => Self::for_type(resolve, ty),
298 None => Self::empty(),
299 }
300 }
301
302 fn for_type(resolve: &Resolve, ty: &Type) -> Self {
303 match ty {
304 Type::Id(id) => match &resolve.types[*id].kind {
305 TypeDefKind::Handle(h) => match h {
306 wit_parser::Handle::Own(_) => Self::empty(),
307 wit_parser::Handle::Borrow(_) => Self::empty(),
308 },
309 TypeDefKind::Resource => Self::empty(),
310 TypeDefKind::Record(r) => Self::for_types(resolve, r.fields.iter().map(|f| &f.ty)),
311 TypeDefKind::Tuple(t) => Self::for_types(resolve, t.types.iter()),
312 TypeDefKind::Flags(_) => Self::empty(),
313 TypeDefKind::Option(t) => Self::for_type(resolve, t),
314 TypeDefKind::Result(r) => {
315 Self::for_optional_type(resolve, r.ok.as_ref())
316 | Self::for_optional_type(resolve, r.err.as_ref())
317 }
318 TypeDefKind::Variant(v) => {
319 Self::for_optional_types(resolve, v.cases.iter().map(|c| c.ty.as_ref()))
320 }
321 TypeDefKind::Enum(_) => Self::empty(),
322 TypeDefKind::List(t) => Self::for_type(resolve, t) | Self::LIST,
323 TypeDefKind::FixedSizeList(t, _elements) => Self::for_type(resolve, t),
324 TypeDefKind::Type(t) => Self::for_type(resolve, t),
325 TypeDefKind::Future(_) => Self::empty(),
326 TypeDefKind::Stream(_) => Self::empty(),
327 TypeDefKind::Unknown => unreachable!(),
328 },
329 Type::String => Self::STRING,
330 _ => Self::empty(),
331 }
332 }
333}
334
335pub struct EncodingState<'a> {
337 component: ComponentBuilder,
339 module_index: Option<u32>,
343 instance_index: Option<u32>,
347 memory_index: Option<u32>,
351 shim_instance_index: Option<u32>,
355 fixups_module_index: Option<u32>,
359
360 adapter_modules: IndexMap<&'a str, u32>,
363 adapter_instances: IndexMap<&'a str, u32>,
365
366 imported_instances: IndexMap<InterfaceId, u32>,
368 imported_funcs: IndexMap<String, u32>,
369 exported_instances: IndexMap<InterfaceId, u32>,
370
371 import_type_map: HashMap<TypeId, u32>,
376 import_func_type_map: HashMap<types::FunctionKey<'a>, u32>,
377 export_type_map: HashMap<TypeId, u32>,
378 export_func_type_map: HashMap<types::FunctionKey<'a>, u32>,
379
380 aliased_core_items: HashMap<(u32, String), u32>,
386
387 info: &'a ComponentWorld<'a>,
389}
390
391impl<'a> EncodingState<'a> {
392 fn encode_core_modules(&mut self) {
393 assert!(self.module_index.is_none());
394 let idx = self.component.core_module_raw(&self.info.encoder.module);
395 self.module_index = Some(idx);
396
397 for (name, adapter) in self.info.adapters.iter() {
398 let mut add_meta = wasm_metadata::AddMetadata::default();
399 add_meta.name = Some(if adapter.library_info.is_some() {
400 name.to_string()
401 } else {
402 format!("wit-component:adapter:{name}")
403 });
404 let wasm = add_meta
405 .to_wasm(&adapter.wasm)
406 .expect("core wasm can get name added");
407 let idx = self.component.core_module_raw(&wasm);
408 let prev = self.adapter_modules.insert(name, idx);
409 assert!(prev.is_none());
410 }
411 }
412
413 fn root_import_type_encoder(
414 &mut self,
415 interface: Option<InterfaceId>,
416 ) -> RootTypeEncoder<'_, 'a> {
417 RootTypeEncoder {
418 state: self,
419 interface,
420 import_types: true,
421 }
422 }
423
424 fn root_export_type_encoder(
425 &mut self,
426 interface: Option<InterfaceId>,
427 ) -> RootTypeEncoder<'_, 'a> {
428 RootTypeEncoder {
429 state: self,
430 interface,
431 import_types: false,
432 }
433 }
434
435 fn instance_type_encoder(&mut self, interface: InterfaceId) -> InstanceTypeEncoder<'_, 'a> {
436 InstanceTypeEncoder {
437 state: self,
438 interface,
439 type_map: Default::default(),
440 func_type_map: Default::default(),
441 ty: Default::default(),
442 }
443 }
444
445 fn encode_imports(&mut self, name_map: &HashMap<String, String>) -> Result<()> {
446 let mut has_funcs = false;
447 for (name, info) in self.info.import_map.iter() {
448 match name {
449 Some(name) => {
450 self.encode_interface_import(name_map.get(name).unwrap_or(name), info)?
451 }
452 None => has_funcs = true,
453 }
454 }
455
456 let resolve = &self.info.encoder.metadata.resolve;
457 let world = &resolve.worlds[self.info.encoder.metadata.world];
458
459 for (_name, item) in world.imports.iter() {
462 if let WorldItem::Type(ty) = item {
463 self.root_import_type_encoder(None)
464 .encode_valtype(resolve, &Type::Id(*ty))?;
465 }
466 }
467
468 if has_funcs {
469 let info = &self.info.import_map[&None];
470 self.encode_root_import_funcs(info)?;
471 }
472 Ok(())
473 }
474
475 fn encode_interface_import(&mut self, name: &str, info: &ImportedInterface) -> Result<()> {
476 let resolve = &self.info.encoder.metadata.resolve;
477 let interface_id = info.interface.as_ref().unwrap();
478 let interface_id = *interface_id;
479 let interface = &resolve.interfaces[interface_id];
480 log::trace!("encoding imports for `{name}` as {:?}", interface_id);
481 let mut encoder = self.instance_type_encoder(interface_id);
482
483 if let Some(live) = encoder.state.info.live_type_imports.get(&interface_id) {
485 for ty in live {
486 log::trace!(
487 "encoding extra type {ty:?} name={:?}",
488 resolve.types[*ty].name
489 );
490 encoder.encode_valtype(resolve, &Type::Id(*ty))?;
491 }
492 }
493
494 for (_, func) in interface.functions.iter() {
497 if !(info
498 .lowerings
499 .contains_key(&(func.name.clone(), AbiVariant::GuestImport))
500 || info
501 .lowerings
502 .contains_key(&(func.name.clone(), AbiVariant::GuestImportAsync)))
503 {
504 continue;
505 }
506 log::trace!("encoding function type for `{}`", func.name);
507 let idx = encoder.encode_func_type(resolve, func)?;
508
509 encoder.ty.export(&func.name, ComponentTypeRef::Func(idx));
510 }
511
512 let ty = encoder.ty;
513 if ty.is_empty() {
516 return Ok(());
517 }
518 let instance_type_idx = self.component.type_instance(&ty);
519 let instance_idx = self
520 .component
521 .import(name, ComponentTypeRef::Instance(instance_type_idx));
522 let prev = self.imported_instances.insert(interface_id, instance_idx);
523 assert!(prev.is_none());
524 Ok(())
525 }
526
527 fn encode_root_import_funcs(&mut self, info: &ImportedInterface) -> Result<()> {
528 let resolve = &self.info.encoder.metadata.resolve;
529 let world = self.info.encoder.metadata.world;
530 for (name, item) in resolve.worlds[world].imports.iter() {
531 let func = match item {
532 WorldItem::Function(f) => f,
533 WorldItem::Interface { .. } | WorldItem::Type(_) => continue,
534 };
535 let name = resolve.name_world_key(name);
536 if !(info
537 .lowerings
538 .contains_key(&(name.clone(), AbiVariant::GuestImport))
539 || info
540 .lowerings
541 .contains_key(&(name.clone(), AbiVariant::GuestImportAsync)))
542 {
543 continue;
544 }
545 log::trace!("encoding function type for `{}`", func.name);
546 let idx = self
547 .root_import_type_encoder(None)
548 .encode_func_type(resolve, func)?;
549 let func_idx = self.component.import(&name, ComponentTypeRef::Func(idx));
550 let prev = self.imported_funcs.insert(name, func_idx);
551 assert!(prev.is_none());
552 }
553 Ok(())
554 }
555
556 fn alias_imported_type(&mut self, interface: InterfaceId, id: TypeId) -> u32 {
557 let ty = &self.info.encoder.metadata.resolve.types[id];
558 let name = ty.name.as_ref().expect("type must have a name");
559 let instance = self.imported_instances[&interface];
560 self.component
561 .alias_export(instance, name, ComponentExportKind::Type)
562 }
563
564 fn alias_exported_type(&mut self, interface: InterfaceId, id: TypeId) -> u32 {
565 let ty = &self.info.encoder.metadata.resolve.types[id];
566 let name = ty.name.as_ref().expect("type must have a name");
567 let instance = self.exported_instances[&interface];
568 self.component
569 .alias_export(instance, name, ComponentExportKind::Type)
570 }
571
572 fn encode_core_instantiation(&mut self) -> Result<()> {
573 let shims = self.encode_shim_instantiation()?;
575
576 self.declare_types_for_imported_intrinsics(&shims)?;
580
581 self.instantiate_main_module(&shims)?;
585
586 let (before, after) = self
589 .info
590 .adapters
591 .iter()
592 .partition::<Vec<_>, _>(|(_, adapter)| {
593 !matches!(
594 adapter.library_info,
595 Some(LibraryInfo {
596 instantiate_after_shims: true,
597 ..
598 })
599 )
600 });
601
602 for (name, _adapter) in before {
603 self.instantiate_adapter_module(&shims, name)?;
604 }
605
606 self.encode_indirect_lowerings(&shims)?;
609
610 for (name, _adapter) in after {
611 self.instantiate_adapter_module(&shims, name)?;
612 }
613
614 self.encode_initialize_with_start()?;
615
616 Ok(())
617 }
618
619 fn lookup_resource_index(&mut self, id: TypeId) -> u32 {
620 let resolve = &self.info.encoder.metadata.resolve;
621 let ty = &resolve.types[id];
622 match ty.owner {
623 TypeOwner::World(_) => self.import_type_map[&id],
627 TypeOwner::Interface(i) => {
628 let instance = self.imported_instances[&i];
629 let name = ty.name.as_ref().expect("resources must be named");
630 self.component
631 .alias_export(instance, name, ComponentExportKind::Type)
632 }
633 TypeOwner::None => panic!("resources must have an owner"),
634 }
635 }
636
637 fn encode_exports(&mut self, module: CustomModule) -> Result<()> {
638 let resolve = &self.info.encoder.metadata.resolve;
639 let exports = match module {
640 CustomModule::Main => &self.info.encoder.main_module_exports,
641 CustomModule::Adapter(name) => &self.info.encoder.adapters[name].required_exports,
642 };
643
644 if exports.is_empty() {
645 return Ok(());
646 }
647
648 let mut interface_func_core_names = IndexMap::new();
649 let mut world_func_core_names = IndexMap::new();
650 for (core_name, export) in self.info.exports_for(module).iter() {
651 match export {
652 Export::WorldFunc(_, name, _) => {
653 let prev = world_func_core_names.insert(name, core_name);
654 assert!(prev.is_none());
655 }
656 Export::InterfaceFunc(_, id, name, _) => {
657 let prev = interface_func_core_names
658 .entry(id)
659 .or_insert(IndexMap::new())
660 .insert(name.as_str(), core_name);
661 assert!(prev.is_none());
662 }
663 Export::WorldFuncCallback(..)
664 | Export::InterfaceFuncCallback(..)
665 | Export::WorldFuncPostReturn(..)
666 | Export::InterfaceFuncPostReturn(..)
667 | Export::ResourceDtor(..)
668 | Export::Memory
669 | Export::GeneralPurposeRealloc
670 | Export::GeneralPurposeExportRealloc
671 | Export::GeneralPurposeImportRealloc
672 | Export::Initialize
673 | Export::ReallocForAdapter => continue,
674 }
675 }
676
677 let world = &resolve.worlds[self.info.encoder.metadata.world];
678
679 for export_name in exports {
680 let export_string = resolve.name_world_key(export_name);
681 match &world.exports[export_name] {
682 WorldItem::Function(func) => {
683 let ty = self
684 .root_import_type_encoder(None)
685 .encode_func_type(resolve, func)?;
686 let core_name = world_func_core_names[&func.name];
687 let idx = self.encode_lift(module, &core_name, export_name, func, ty)?;
688 self.component
689 .export(&export_string, ComponentExportKind::Func, idx, None);
690 }
691 WorldItem::Interface { id, .. } => {
692 let core_names = interface_func_core_names.get(id);
693 self.encode_interface_export(
694 &export_string,
695 module,
696 export_name,
697 *id,
698 core_names,
699 )?;
700 }
701 WorldItem::Type(_) => unreachable!(),
702 }
703 }
704
705 Ok(())
706 }
707
708 fn encode_interface_export(
709 &mut self,
710 export_name: &str,
711 module: CustomModule<'_>,
712 key: &WorldKey,
713 export: InterfaceId,
714 interface_func_core_names: Option<&IndexMap<&str, &str>>,
715 ) -> Result<()> {
716 log::trace!("encode interface export `{export_name}`");
717 let resolve = &self.info.encoder.metadata.resolve;
718
719 let mut imports = Vec::new();
726 let mut root = self.root_export_type_encoder(Some(export));
727 for (_, func) in &resolve.interfaces[export].functions {
728 let core_name = interface_func_core_names.unwrap()[func.name.as_str()];
729 let ty = root.encode_func_type(resolve, func)?;
730 let func_index = root.state.encode_lift(module, &core_name, key, func, ty)?;
731 imports.push((
732 import_func_name(func),
733 ComponentExportKind::Func,
734 func_index,
735 ));
736 }
737
738 let mut nested = NestedComponentTypeEncoder {
742 component: ComponentBuilder::default(),
743 type_map: Default::default(),
744 func_type_map: Default::default(),
745 export_types: false,
746 interface: export,
747 state: self,
748 imports: IndexMap::new(),
749 };
750
751 let mut types_to_import = LiveTypes::default();
761 types_to_import.add_interface(resolve, export);
762 let exports_used = &nested.state.info.exports_used[&export];
763 for ty in types_to_import.iter() {
764 if let TypeOwner::Interface(owner) = resolve.types[ty].owner {
765 if owner == export {
766 continue;
769 }
770
771 let mut encoder = if exports_used.contains(&owner) {
774 nested.state.root_export_type_encoder(Some(export))
775 } else {
776 nested.state.root_import_type_encoder(Some(export))
777 };
778 encoder.encode_valtype(resolve, &Type::Id(ty))?;
779
780 nested.interface = owner;
784 nested.encode_valtype(resolve, &Type::Id(ty))?;
785 }
786 }
787 nested.interface = export;
788
789 let imported_types = nested.type_map.clone();
793
794 let mut resources = HashMap::new();
800 for (_name, ty) in resolve.interfaces[export].types.iter() {
801 if !matches!(resolve.types[*ty].kind, TypeDefKind::Resource) {
802 continue;
803 }
804 let idx = match nested.encode_valtype(resolve, &Type::Id(*ty))? {
805 ComponentValType::Type(idx) => idx,
806 _ => unreachable!(),
807 };
808 resources.insert(*ty, idx);
809 }
810
811 for (_, func) in resolve.interfaces[export].functions.iter() {
815 let ty = nested.encode_func_type(resolve, func)?;
816 nested
817 .component
818 .import(&import_func_name(func), ComponentTypeRef::Func(ty));
819 }
820
821 let reverse_map = nested
828 .type_map
829 .drain()
830 .map(|p| (p.1, p.0))
831 .collect::<HashMap<_, _>>();
832 for (name, idx) in nested.imports.drain(..) {
833 let id = reverse_map[&idx];
834 let owner = match resolve.types[id].owner {
835 TypeOwner::Interface(id) => id,
836 _ => unreachable!(),
837 };
838 let idx = if owner == export || exports_used.contains(&owner) {
839 log::trace!("consulting exports for {id:?}");
840 nested.state.export_type_map[&id]
841 } else {
842 log::trace!("consulting imports for {id:?}");
843 nested.state.import_type_map[&id]
844 };
845 imports.push((name, ComponentExportKind::Type, idx))
846 }
847
848 nested.type_map = imported_types;
853
854 nested.export_types = true;
861 nested.func_type_map.clear();
862
863 for (_, id) in resolve.interfaces[export].types.iter() {
869 let ty = &resolve.types[*id];
870 match ty.kind {
871 TypeDefKind::Resource => {
872 let idx = nested.component.export(
873 ty.name.as_ref().expect("resources must be named"),
874 ComponentExportKind::Type,
875 resources[id],
876 None,
877 );
878 nested.type_map.insert(*id, idx);
879 }
880 _ => {
881 nested.encode_valtype(resolve, &Type::Id(*id))?;
882 }
883 }
884 }
885
886 for (i, (_, func)) in resolve.interfaces[export].functions.iter().enumerate() {
887 let ty = nested.encode_func_type(resolve, func)?;
888 nested.component.export(
889 &func.name,
890 ComponentExportKind::Func,
891 i as u32,
892 Some(ComponentTypeRef::Func(ty)),
893 );
894 }
895
896 let component = nested.component;
900 let component_index = self.component.component(component);
901 let instance_index = self.component.instantiate(component_index, imports);
902 let idx = self.component.export(
903 export_name,
904 ComponentExportKind::Instance,
905 instance_index,
906 None,
907 );
908 let prev = self.exported_instances.insert(export, idx);
909 assert!(prev.is_none());
910
911 for (_name, id) in resolve.interfaces[export].types.iter() {
919 self.export_type_map.remove(id);
920 }
921
922 return Ok(());
923
924 struct NestedComponentTypeEncoder<'state, 'a> {
925 component: ComponentBuilder,
926 type_map: HashMap<TypeId, u32>,
927 func_type_map: HashMap<types::FunctionKey<'a>, u32>,
928 export_types: bool,
929 interface: InterfaceId,
930 state: &'state mut EncodingState<'a>,
931 imports: IndexMap<String, u32>,
932 }
933
934 impl<'a> ValtypeEncoder<'a> for NestedComponentTypeEncoder<'_, 'a> {
935 fn defined_type(&mut self) -> (u32, ComponentDefinedTypeEncoder<'_>) {
936 self.component.type_defined()
937 }
938 fn define_function_type(&mut self) -> (u32, ComponentFuncTypeEncoder<'_>) {
939 self.component.type_function()
940 }
941 fn export_type(&mut self, idx: u32, name: &'a str) -> Option<u32> {
942 if self.export_types {
943 Some(
944 self.component
945 .export(name, ComponentExportKind::Type, idx, None),
946 )
947 } else {
948 let name = self.unique_import_name(name);
949 let ret = self
950 .component
951 .import(&name, ComponentTypeRef::Type(TypeBounds::Eq(idx)));
952 self.imports.insert(name, ret);
953 Some(ret)
954 }
955 }
956 fn export_resource(&mut self, name: &'a str) -> u32 {
957 if self.export_types {
958 panic!("resources should already be exported")
959 } else {
960 let name = self.unique_import_name(name);
961 let ret = self
962 .component
963 .import(&name, ComponentTypeRef::Type(TypeBounds::SubResource));
964 self.imports.insert(name, ret);
965 ret
966 }
967 }
968 fn import_type(&mut self, _: InterfaceId, _id: TypeId) -> u32 {
969 unreachable!()
970 }
971 fn type_map(&mut self) -> &mut HashMap<TypeId, u32> {
972 &mut self.type_map
973 }
974 fn func_type_map(&mut self) -> &mut HashMap<types::FunctionKey<'a>, u32> {
975 &mut self.func_type_map
976 }
977 fn interface(&self) -> Option<InterfaceId> {
978 Some(self.interface)
979 }
980 }
981
982 impl NestedComponentTypeEncoder<'_, '_> {
983 fn unique_import_name(&mut self, name: &str) -> String {
984 let mut name = format!("import-type-{name}");
985 let mut n = 0;
986 while self.imports.contains_key(&name) {
987 name = format!("{name}{n}");
988 n += 1;
989 }
990 name
991 }
992 }
993
994 fn import_func_name(f: &Function) -> String {
995 match f.kind {
996 FunctionKind::Freestanding | FunctionKind::AsyncFreestanding => {
997 format!("import-func-{}", f.item_name())
998 }
999
1000 FunctionKind::Method(_)
1008 | FunctionKind::AsyncMethod(_)
1009 | FunctionKind::Static(_)
1010 | FunctionKind::AsyncStatic(_)
1011 | FunctionKind::Constructor(_) => {
1012 format!(
1013 "import-{}",
1014 f.name.replace('[', "").replace([']', '.', ' '], "-")
1015 )
1016 }
1017 }
1018 }
1019 }
1020
1021 fn encode_lift(
1022 &mut self,
1023 module: CustomModule<'_>,
1024 core_name: &str,
1025 key: &WorldKey,
1026 func: &Function,
1027 ty: u32,
1028 ) -> Result<u32> {
1029 let resolve = &self.info.encoder.metadata.resolve;
1030 let metadata = self.info.module_metadata_for(module);
1031 let instance_index = self.instance_for(module);
1032 let core_func_index = self.core_alias_export(instance_index, core_name, ExportKind::Func);
1033 let exports = self.info.exports_for(module);
1034
1035 let options = RequiredOptions::for_export(
1036 resolve,
1037 func,
1038 exports
1039 .abi(key, func)
1040 .ok_or_else(|| anyhow!("no ABI found for {}", func.name))?,
1041 );
1042
1043 let encoding = metadata
1044 .export_encodings
1045 .get(resolve, key, &func.name)
1046 .unwrap();
1047 let exports = self.info.exports_for(module);
1048 let realloc_index = exports
1049 .export_realloc_for(key, &func.name)
1050 .map(|name| self.core_alias_export(instance_index, name, ExportKind::Func));
1051 let mut options = options
1052 .into_iter(encoding, self.memory_index, realloc_index)?
1053 .collect::<Vec<_>>();
1054
1055 if let Some(post_return) = exports.post_return(key, func) {
1056 let post_return = self.core_alias_export(instance_index, post_return, ExportKind::Func);
1057 options.push(CanonicalOption::PostReturn(post_return));
1058 }
1059 if let Some(callback) = exports.callback(key, func) {
1060 let callback = self.core_alias_export(instance_index, callback, ExportKind::Func);
1061 options.push(CanonicalOption::Callback(callback));
1062 }
1063 let func_index = self.component.lift_func(core_func_index, ty, options);
1064 Ok(func_index)
1065 }
1066
1067 fn encode_shim_instantiation(&mut self) -> Result<Shims<'a>> {
1068 let mut ret = Shims::default();
1069
1070 ret.append_indirect(self.info, CustomModule::Main)
1071 .context("failed to register indirect shims for main module")?;
1072
1073 for (adapter_name, _adapter) in self.info.adapters.iter() {
1077 ret.append_indirect(self.info, CustomModule::Adapter(adapter_name))
1078 .with_context(|| {
1079 format!("failed to register indirect shims for adapter {adapter_name}")
1080 })?;
1081 }
1082
1083 if ret.shims.is_empty() {
1084 return Ok(ret);
1085 }
1086
1087 assert!(self.shim_instance_index.is_none());
1088 assert!(self.fixups_module_index.is_none());
1089
1090 let mut types = TypeSection::new();
1099 let mut tables = TableSection::new();
1100 let mut functions = FunctionSection::new();
1101 let mut exports = ExportSection::new();
1102 let mut code = CodeSection::new();
1103 let mut sigs = IndexMap::new();
1104 let mut imports_section = ImportSection::new();
1105 let mut elements = ElementSection::new();
1106 let mut func_indexes = Vec::new();
1107 let mut func_names = NameMap::new();
1108
1109 for (i, shim) in ret.shims.values().enumerate() {
1110 let i = i as u32;
1111 let type_index = *sigs.entry(&shim.sig).or_insert_with(|| {
1112 let index = types.len();
1113 types.ty().function(
1114 shim.sig.params.iter().map(to_val_type),
1115 shim.sig.results.iter().map(to_val_type),
1116 );
1117 index
1118 });
1119
1120 functions.function(type_index);
1121 Self::encode_shim_function(type_index, i, &mut code, shim.sig.params.len() as u32);
1122 exports.export(&shim.name, ExportKind::Func, i);
1123
1124 imports_section.import("", &shim.name, EntityType::Function(type_index));
1125 func_indexes.push(i);
1126 func_names.append(i, &shim.debug_name);
1127 }
1128 let mut names = NameSection::new();
1129 names.module("wit-component:shim");
1130 names.functions(&func_names);
1131
1132 let table_type = TableType {
1133 element_type: RefType::FUNCREF,
1134 minimum: ret.shims.len() as u64,
1135 maximum: Some(ret.shims.len() as u64),
1136 table64: false,
1137 shared: false,
1138 };
1139
1140 tables.table(table_type);
1141
1142 exports.export(INDIRECT_TABLE_NAME, ExportKind::Table, 0);
1143 imports_section.import("", INDIRECT_TABLE_NAME, table_type);
1144
1145 elements.active(
1146 None,
1147 &ConstExpr::i32_const(0),
1148 Elements::Functions(func_indexes.into()),
1149 );
1150
1151 let mut shim = Module::new();
1152 shim.section(&types);
1153 shim.section(&functions);
1154 shim.section(&tables);
1155 shim.section(&exports);
1156 shim.section(&code);
1157 shim.section(&RawCustomSection(
1158 &crate::base_producers().raw_custom_section(),
1159 ));
1160 shim.section(&names);
1161
1162 let mut fixups = Module::default();
1163 fixups.section(&types);
1164 fixups.section(&imports_section);
1165 fixups.section(&elements);
1166 fixups.section(&RawCustomSection(
1167 &crate::base_producers().raw_custom_section(),
1168 ));
1169
1170 let mut names = NameSection::new();
1171 names.module("wit-component:fixups");
1172 fixups.section(&names);
1173
1174 let shim_module_index = self.component.core_module(&shim);
1175 self.fixups_module_index = Some(self.component.core_module(&fixups));
1176 self.shim_instance_index = Some(self.component.core_instantiate(shim_module_index, []));
1177
1178 return Ok(ret);
1179 }
1180
1181 fn encode_shim_function(
1182 type_index: u32,
1183 func_index: u32,
1184 code: &mut CodeSection,
1185 param_count: u32,
1186 ) {
1187 let mut func = wasm_encoder::Function::new(std::iter::empty());
1188 for i in 0..param_count {
1189 func.instructions().local_get(i);
1190 }
1191 func.instructions().i32_const(func_index as i32);
1192 func.instructions().call_indirect(0, type_index);
1193 func.instructions().end();
1194 code.function(&func);
1195 }
1196
1197 fn encode_indirect_lowerings(&mut self, shims: &Shims<'_>) -> Result<()> {
1198 if shims.shims.is_empty() {
1199 return Ok(());
1200 }
1201
1202 let shim_instance_index = self
1203 .shim_instance_index
1204 .expect("must have an instantiated shim");
1205
1206 let table_index =
1207 self.core_alias_export(shim_instance_index, INDIRECT_TABLE_NAME, ExportKind::Table);
1208
1209 let resolve = &self.info.encoder.metadata.resolve;
1210
1211 let mut exports = Vec::new();
1212 exports.push((INDIRECT_TABLE_NAME, ExportKind::Table, table_index));
1213
1214 for shim in shims.shims.values() {
1215 let core_func_index = match &shim.kind {
1216 ShimKind::IndirectLowering {
1223 interface,
1224 index,
1225 realloc,
1226 encoding,
1227 } => {
1228 let interface = &self.info.import_map[interface];
1229 let ((name, _), _) = interface.lowerings.get_index(*index).unwrap();
1230 let func_index = match &interface.interface {
1231 Some(interface_id) => {
1232 let instance_index = self.imported_instances[interface_id];
1233 self.component.alias_export(
1234 instance_index,
1235 name,
1236 ComponentExportKind::Func,
1237 )
1238 }
1239 None => self.imported_funcs[name],
1240 };
1241
1242 let realloc = self
1243 .info
1244 .exports_for(*realloc)
1245 .import_realloc_for(interface.interface, name)
1246 .map(|name| {
1247 let instance = self.instance_for(*realloc);
1248 self.core_alias_export(instance, name, ExportKind::Func)
1249 });
1250
1251 self.component.lower_func(
1252 func_index,
1253 shim.options
1254 .into_iter(*encoding, self.memory_index, realloc)?,
1255 )
1256 }
1257
1258 ShimKind::Adapter { adapter, func } => {
1263 self.core_alias_export(self.adapter_instances[adapter], func, ExportKind::Func)
1264 }
1265
1266 ShimKind::ResourceDtor { module, export } => {
1271 self.core_alias_export(self.instance_for(*module), export, ExportKind::Func)
1272 }
1273
1274 ShimKind::PayloadFunc {
1275 for_module,
1276 info,
1277 kind,
1278 } => {
1279 let metadata = self.info.module_metadata_for(*for_module);
1280 let exports = self.info.exports_for(*for_module);
1281 let instance_index = self.instance_for(*for_module);
1282 let (encoding, realloc) = if info.imported {
1283 (
1284 metadata
1285 .import_encodings
1286 .get(resolve, &info.key, &info.function),
1287 exports.import_realloc_for(info.interface, &info.function),
1288 )
1289 } else {
1290 (
1291 metadata
1292 .export_encodings
1293 .get(resolve, &info.key, &info.function),
1294 exports.export_realloc_for(&info.key, &info.function),
1295 )
1296 };
1297 let encoding = encoding.unwrap_or(StringEncoding::UTF8);
1298 let realloc_index = realloc
1299 .map(|name| self.core_alias_export(instance_index, name, ExportKind::Func));
1300 let type_index = self.payload_type_index(info)?;
1301 let options =
1302 shim.options
1303 .into_iter(encoding, self.memory_index, realloc_index)?;
1304
1305 match kind {
1306 PayloadFuncKind::FutureWrite => {
1307 self.component.future_write(type_index, options)
1308 }
1309 PayloadFuncKind::FutureRead => {
1310 self.component.future_read(type_index, options)
1311 }
1312 PayloadFuncKind::StreamWrite => {
1313 self.component.stream_write(type_index, options)
1314 }
1315 PayloadFuncKind::StreamRead => {
1316 self.component.stream_read(type_index, options)
1317 }
1318 }
1319 }
1320
1321 ShimKind::WaitableSetWait { async_ } => self
1322 .component
1323 .waitable_set_wait(*async_, self.memory_index.unwrap()),
1324 ShimKind::WaitableSetPoll { async_ } => self
1325 .component
1326 .waitable_set_poll(*async_, self.memory_index.unwrap()),
1327 ShimKind::ErrorContextNew { encoding } => self.component.error_context_new(
1328 shim.options.into_iter(*encoding, self.memory_index, None)?,
1329 ),
1330 ShimKind::ErrorContextDebugMessage {
1331 for_module,
1332 encoding,
1333 } => {
1334 let instance_index = self.instance_for(*for_module);
1335 let realloc = self.info.exports_for(*for_module).import_realloc_fallback();
1336 let realloc_index = realloc
1337 .map(|r| self.core_alias_export(instance_index, r, ExportKind::Func));
1338
1339 self.component
1340 .error_context_debug_message(shim.options.into_iter(
1341 *encoding,
1342 self.memory_index,
1343 realloc_index,
1344 )?)
1345 }
1346 ShimKind::TaskReturn {
1347 interface,
1348 func,
1349 result,
1350 encoding,
1351 for_module,
1352 } => {
1353 let mut encoder = if interface.is_none() {
1356 self.root_import_type_encoder(*interface)
1357 } else {
1358 self.root_export_type_encoder(*interface)
1359 };
1360 let result = match result {
1361 Some(ty) => Some(encoder.encode_valtype(resolve, ty)?),
1362 None => None,
1363 };
1364
1365 let exports = self.info.exports_for(*for_module);
1366 let realloc = exports.import_realloc_for(*interface, func);
1367
1368 let instance_index = self.instance_for(*for_module);
1369 let realloc_index = realloc
1370 .map(|r| self.core_alias_export(instance_index, r, ExportKind::Func));
1371 let options =
1372 shim.options
1373 .into_iter(*encoding, self.memory_index, realloc_index)?;
1374 self.component.task_return(result, options)
1375 }
1376 };
1377
1378 exports.push((shim.name.as_str(), ExportKind::Func, core_func_index));
1379 }
1380
1381 let instance_index = self.component.core_instantiate_exports(exports);
1382 self.component.core_instantiate(
1383 self.fixups_module_index.expect("must have fixup module"),
1384 [("", ModuleArg::Instance(instance_index))],
1385 );
1386 Ok(())
1387 }
1388
1389 fn payload_type_index(&mut self, info: &PayloadInfo) -> Result<u32> {
1397 let resolve = &self.info.encoder.metadata.resolve;
1398 let ComponentValType::Type(type_index) = if info.imported || info.interface.is_none() {
1414 self.root_import_type_encoder(None)
1415 } else {
1416 self.root_export_type_encoder(info.interface)
1417 }
1418 .encode_valtype(resolve, &Type::Id(info.ty))?
1419 else {
1420 unreachable!()
1421 };
1422 Ok(type_index)
1423 }
1424
1425 fn declare_types_for_imported_intrinsics(&mut self, shims: &Shims<'_>) -> Result<()> {
1432 let resolve = &self.info.encoder.metadata.resolve;
1433 let world = &resolve.worlds[self.info.encoder.metadata.world];
1434
1435 let main_module_keys = self.info.encoder.main_module_exports.iter();
1438 let main_module_keys = main_module_keys.map(|key| (CustomModule::Main, key));
1439 let adapter_keys = self.info.encoder.adapters.iter().flat_map(|(name, info)| {
1440 info.required_exports
1441 .iter()
1442 .map(move |key| (CustomModule::Adapter(name), key))
1443 });
1444 for (for_module, key) in main_module_keys.chain(adapter_keys) {
1445 let id = match &world.exports[key] {
1446 WorldItem::Interface { id, .. } => *id,
1447 WorldItem::Type { .. } => unreachable!(),
1448 WorldItem::Function(_) => continue,
1449 };
1450
1451 for ty in resolve.interfaces[id].types.values() {
1452 match &resolve.types[*ty].kind {
1453 TypeDefKind::Resource => {
1457 let exports = self.info.exports_for(for_module);
1460 let dtor = exports.resource_dtor(*ty).map(|name| {
1461 let name = &shims.shims[&ShimKind::ResourceDtor {
1462 module: for_module,
1463 export: name,
1464 }]
1465 .name;
1466 let shim = self.shim_instance_index.unwrap();
1467 self.core_alias_export(shim, name, ExportKind::Func)
1468 });
1469
1470 let resource_idx = self.component.type_resource(ValType::I32, dtor);
1474 let prev = self.export_type_map.insert(*ty, resource_idx);
1475 assert!(prev.is_none());
1476 }
1477 _other => {
1478 self.root_export_type_encoder(Some(id))
1479 .encode_valtype(resolve, &Type::Id(*ty))?;
1480 }
1481 }
1482 }
1483 }
1484 Ok(())
1485 }
1486
1487 fn instantiate_main_module(&mut self, shims: &Shims<'_>) -> Result<()> {
1490 assert!(self.instance_index.is_none());
1491
1492 let instance_index = self.instantiate_core_module(shims, CustomModule::Main)?;
1493
1494 if let Some(memory) = self.info.info.exports.memory() {
1495 self.memory_index =
1496 Some(self.core_alias_export(instance_index, memory, ExportKind::Memory));
1497 }
1498
1499 self.instance_index = Some(instance_index);
1500 Ok(())
1501 }
1502
1503 fn instantiate_adapter_module(&mut self, shims: &Shims<'_>, name: &'a str) -> Result<()> {
1506 let instance = self.instantiate_core_module(shims, CustomModule::Adapter(name))?;
1507 self.adapter_instances.insert(name, instance);
1508 Ok(())
1509 }
1510
1511 fn instantiate_core_module(
1518 &mut self,
1519 shims: &Shims,
1520 for_module: CustomModule<'_>,
1521 ) -> Result<u32> {
1522 let module = self.module_for(for_module);
1523
1524 let mut args = Vec::new();
1525 for (core_wasm_name, instance) in self.info.imports_for(for_module).modules() {
1526 match instance {
1527 ImportInstance::Names(names) => {
1533 let mut exports = Vec::new();
1534 for (name, import) in names {
1535 let (kind, index) = self
1536 .materialize_import(&shims, for_module, core_wasm_name, name, import)
1537 .with_context(|| {
1538 format!("failed to satisfy import `{core_wasm_name}::{name}`")
1539 })?;
1540 exports.push((name.as_str(), kind, index));
1541 }
1542 let index = self.component.core_instantiate_exports(exports);
1543 args.push((core_wasm_name.as_str(), ModuleArg::Instance(index)));
1544 }
1545
1546 ImportInstance::Whole(which) => {
1549 let instance = self.instance_for(which.to_custom_module());
1550 args.push((core_wasm_name.as_str(), ModuleArg::Instance(instance)));
1551 }
1552 }
1553 }
1554
1555 Ok(self.component.core_instantiate(module, args))
1557 }
1558
1559 fn materialize_import(
1566 &mut self,
1567 shims: &Shims<'_>,
1568 for_module: CustomModule<'_>,
1569 module: &str,
1570 field: &str,
1571 import: &'a Import,
1572 ) -> Result<(ExportKind, u32)> {
1573 log::trace!("attempting to materialize import of `{module}::{field}` for {for_module:?}");
1574 let resolve = &self.info.encoder.metadata.resolve;
1575 match import {
1576 Import::AdapterExport(_) => {
1579 assert!(self.info.encoder.adapters.contains_key(module));
1580 Ok(self.materialize_shim_import(
1581 shims,
1582 &ShimKind::Adapter {
1583 adapter: module,
1584 func: field,
1585 },
1586 ))
1587 }
1588
1589 Import::MainModuleMemory => {
1592 let index = self
1593 .memory_index
1594 .ok_or_else(|| anyhow!("main module cannot import memory"))?;
1595 Ok((ExportKind::Memory, index))
1596 }
1597
1598 Import::MainModuleExport { name, kind } => {
1600 let instance = self.instance_index.unwrap();
1601 let index = self.core_alias_export(instance, name, *kind);
1602 Ok((*kind, index))
1603 }
1604
1605 Import::Item(item) => {
1609 let instance = self.instance_for(item.which.to_custom_module());
1610 let index = self.core_alias_export(instance, &item.name, item.kind);
1611 Ok((item.kind, index))
1612 }
1613
1614 Import::ExportedResourceDrop(_key, id) => {
1620 let index = self.component.resource_drop(self.export_type_map[id]);
1621 Ok((ExportKind::Func, index))
1622 }
1623 Import::ExportedResourceRep(_key, id) => {
1624 let index = self.component.resource_rep(self.export_type_map[id]);
1625 Ok((ExportKind::Func, index))
1626 }
1627 Import::ExportedResourceNew(_key, id) => {
1628 let index = self.component.resource_new(self.export_type_map[id]);
1629 Ok((ExportKind::Func, index))
1630 }
1631
1632 Import::ImportedResourceDrop(key, iface, id) => {
1637 let ty = &resolve.types[*id];
1638 let name = ty.name.as_ref().unwrap();
1639 self.materialize_wit_import(
1640 shims,
1641 for_module,
1642 iface.map(|_| resolve.name_world_key(key)),
1643 &format!("{name}_drop"),
1644 key,
1645 AbiVariant::GuestImport,
1646 )
1647 }
1648 Import::ExportedTaskReturn(key, interface, func, result) => {
1649 let (options, _sig) = task_return_options_and_type(resolve, *result);
1650 if options.is_empty() {
1651 let mut encoder = if interface.is_none() {
1657 self.root_import_type_encoder(*interface)
1658 } else {
1659 self.root_export_type_encoder(*interface)
1660 };
1661
1662 let result = match result {
1663 Some(ty) => Some(encoder.encode_valtype(resolve, ty)?),
1664 None => None,
1665 };
1666 let index = self.component.task_return(result, []);
1667 Ok((ExportKind::Func, index))
1668 } else {
1669 let metadata = &self.info.encoder.metadata.metadata;
1670 let encoding = metadata.export_encodings.get(resolve, key, func).unwrap();
1671 Ok(self.materialize_shim_import(
1672 shims,
1673 &ShimKind::TaskReturn {
1674 for_module,
1675 interface: *interface,
1676 func,
1677 result: *result,
1678 encoding,
1679 },
1680 ))
1681 }
1682 }
1683 Import::BackpressureSet => {
1684 let index = self.component.backpressure_set();
1685 Ok((ExportKind::Func, index))
1686 }
1687 Import::WaitableSetWait { async_ } => {
1688 Ok(self
1689 .materialize_shim_import(shims, &ShimKind::WaitableSetWait { async_: *async_ }))
1690 }
1691 Import::WaitableSetPoll { async_ } => {
1692 Ok(self
1693 .materialize_shim_import(shims, &ShimKind::WaitableSetPoll { async_: *async_ }))
1694 }
1695 Import::Yield { async_ } => {
1696 let index = self.component.yield_(*async_);
1697 Ok((ExportKind::Func, index))
1698 }
1699 Import::SubtaskDrop => {
1700 let index = self.component.subtask_drop();
1701 Ok((ExportKind::Func, index))
1702 }
1703 Import::SubtaskCancel { async_ } => {
1704 let index = self.component.subtask_cancel(*async_);
1705 Ok((ExportKind::Func, index))
1706 }
1707 Import::StreamNew(info) => {
1708 let ty = self.payload_type_index(info)?;
1709 let index = self.component.stream_new(ty);
1710 Ok((ExportKind::Func, index))
1711 }
1712 Import::StreamRead { info, .. } => Ok(self.materialize_payload_import(
1713 shims,
1714 for_module,
1715 info,
1716 PayloadFuncKind::StreamRead,
1717 )),
1718 Import::StreamWrite { info, .. } => Ok(self.materialize_payload_import(
1719 shims,
1720 for_module,
1721 info,
1722 PayloadFuncKind::StreamWrite,
1723 )),
1724 Import::StreamCancelRead { info, async_ } => {
1725 let ty = self.payload_type_index(info)?;
1726 let index = self.component.stream_cancel_read(ty, *async_);
1727 Ok((ExportKind::Func, index))
1728 }
1729 Import::StreamCancelWrite { info, async_ } => {
1730 let ty = self.payload_type_index(info)?;
1731 let index = self.component.stream_cancel_write(ty, *async_);
1732 Ok((ExportKind::Func, index))
1733 }
1734 Import::StreamCloseReadable(info) => {
1735 let type_index = self.payload_type_index(info)?;
1736 let index = self.component.stream_close_readable(type_index);
1737 Ok((ExportKind::Func, index))
1738 }
1739 Import::StreamCloseWritable(info) => {
1740 let type_index = self.payload_type_index(info)?;
1741 let index = self.component.stream_close_writable(type_index);
1742 Ok((ExportKind::Func, index))
1743 }
1744 Import::FutureNew(info) => {
1745 let ty = self.payload_type_index(info)?;
1746 let index = self.component.future_new(ty);
1747 Ok((ExportKind::Func, index))
1748 }
1749 Import::FutureRead { info, .. } => Ok(self.materialize_payload_import(
1750 shims,
1751 for_module,
1752 info,
1753 PayloadFuncKind::FutureRead,
1754 )),
1755 Import::FutureWrite { info, .. } => Ok(self.materialize_payload_import(
1756 shims,
1757 for_module,
1758 info,
1759 PayloadFuncKind::FutureWrite,
1760 )),
1761 Import::FutureCancelRead { info, async_ } => {
1762 let ty = self.payload_type_index(info)?;
1763 let index = self.component.future_cancel_read(ty, *async_);
1764 Ok((ExportKind::Func, index))
1765 }
1766 Import::FutureCancelWrite { info, async_ } => {
1767 let ty = self.payload_type_index(info)?;
1768 let index = self.component.future_cancel_write(ty, *async_);
1769 Ok((ExportKind::Func, index))
1770 }
1771 Import::FutureCloseReadable(info) => {
1772 let type_index = self.payload_type_index(info)?;
1773 let index = self.component.future_close_readable(type_index);
1774 Ok((ExportKind::Func, index))
1775 }
1776 Import::FutureCloseWritable(info) => {
1777 let type_index = self.payload_type_index(info)?;
1778 let index = self.component.future_close_writable(type_index);
1779 Ok((ExportKind::Func, index))
1780 }
1781 Import::ErrorContextNew { encoding } => Ok(self.materialize_shim_import(
1782 shims,
1783 &ShimKind::ErrorContextNew {
1784 encoding: *encoding,
1785 },
1786 )),
1787 Import::ErrorContextDebugMessage { encoding } => Ok(self.materialize_shim_import(
1788 shims,
1789 &ShimKind::ErrorContextDebugMessage {
1790 for_module,
1791 encoding: *encoding,
1792 },
1793 )),
1794 Import::ErrorContextDrop => {
1795 let index = self.component.error_context_drop();
1796 Ok((ExportKind::Func, index))
1797 }
1798 Import::WorldFunc(key, name, abi) => {
1799 self.materialize_wit_import(shims, for_module, None, name, key, *abi)
1800 }
1801 Import::InterfaceFunc(key, _, name, abi) => self.materialize_wit_import(
1802 shims,
1803 for_module,
1804 Some(resolve.name_world_key(key)),
1805 name,
1806 key,
1807 *abi,
1808 ),
1809
1810 Import::WaitableSetNew => {
1811 let index = self.component.waitable_set_new();
1812 Ok((ExportKind::Func, index))
1813 }
1814 Import::WaitableSetDrop => {
1815 let index = self.component.waitable_set_drop();
1816 Ok((ExportKind::Func, index))
1817 }
1818 Import::WaitableJoin => {
1819 let index = self.component.waitable_join();
1820 Ok((ExportKind::Func, index))
1821 }
1822 Import::ContextGet(n) => {
1823 let index = self.component.context_get(*n);
1824 Ok((ExportKind::Func, index))
1825 }
1826 Import::ContextSet(n) => {
1827 let index = self.component.context_set(*n);
1828 Ok((ExportKind::Func, index))
1829 }
1830 Import::ExportedTaskCancel => {
1831 let index = self.component.task_cancel();
1832 Ok((ExportKind::Func, index))
1833 }
1834 }
1835 }
1836
1837 fn materialize_shim_import(&mut self, shims: &Shims<'_>, kind: &ShimKind) -> (ExportKind, u32) {
1840 let index = self.core_alias_export(
1841 self.shim_instance_index
1842 .expect("shim should be instantiated"),
1843 &shims.shims[kind].name,
1844 ExportKind::Func,
1845 );
1846 (ExportKind::Func, index)
1847 }
1848
1849 fn materialize_payload_import(
1852 &mut self,
1853 shims: &Shims<'_>,
1854 for_module: CustomModule<'_>,
1855 info: &PayloadInfo,
1856 kind: PayloadFuncKind,
1857 ) -> (ExportKind, u32) {
1858 self.materialize_shim_import(
1859 shims,
1860 &ShimKind::PayloadFunc {
1861 for_module,
1862 info,
1863 kind,
1864 },
1865 )
1866 }
1867
1868 fn materialize_wit_import(
1871 &mut self,
1872 shims: &Shims<'_>,
1873 for_module: CustomModule<'_>,
1874 interface_key: Option<String>,
1875 name: &String,
1876 key: &WorldKey,
1877 abi: AbiVariant,
1878 ) -> Result<(ExportKind, u32)> {
1879 let resolve = &self.info.encoder.metadata.resolve;
1880 let import = &self.info.import_map[&interface_key];
1881 let (index, _, lowering) = import.lowerings.get_full(&(name.clone(), abi)).unwrap();
1882 let metadata = self.info.module_metadata_for(for_module);
1883
1884 let index = match lowering {
1885 Lowering::Direct => {
1888 let func_index = match &import.interface {
1889 Some(interface) => {
1890 let instance_index = self.imported_instances[interface];
1891 self.component
1892 .alias_export(instance_index, name, ComponentExportKind::Func)
1893 }
1894 None => self.imported_funcs[name],
1895 };
1896 self.component.lower_func(
1897 func_index,
1898 if let AbiVariant::GuestImportAsync = abi {
1899 vec![CanonicalOption::Async]
1900 } else {
1901 Vec::new()
1902 },
1903 )
1904 }
1905
1906 Lowering::Indirect { .. } => {
1910 let encoding = metadata.import_encodings.get(resolve, key, name).unwrap();
1911 return Ok(self.materialize_shim_import(
1912 shims,
1913 &ShimKind::IndirectLowering {
1914 interface: interface_key,
1915 index,
1916 realloc: for_module,
1917 encoding,
1918 },
1919 ));
1920 }
1921
1922 Lowering::ResourceDrop(id) => {
1925 let resource_idx = self.lookup_resource_index(*id);
1926 self.component.resource_drop(resource_idx)
1927 }
1928 };
1929 Ok((ExportKind::Func, index))
1930 }
1931
1932 fn encode_initialize_with_start(&mut self) -> Result<()> {
1951 let initialize = match self.info.info.exports.initialize() {
1952 Some(name) => name,
1953 None => return Ok(()),
1956 };
1957 let initialize_index =
1958 self.core_alias_export(self.instance_index.unwrap(), initialize, ExportKind::Func);
1959 let mut shim = Module::default();
1960 let mut section = TypeSection::new();
1961 section.ty().function([], []);
1962 shim.section(§ion);
1963 let mut section = ImportSection::new();
1964 section.import("", "", EntityType::Function(0));
1965 shim.section(§ion);
1966 shim.section(&StartSection { function_index: 0 });
1967
1968 let shim_module_index = self.component.core_module(&shim);
1973 let shim_args_instance_index =
1974 self.component
1975 .core_instantiate_exports([("", ExportKind::Func, initialize_index)]);
1976 self.component.core_instantiate(
1977 shim_module_index,
1978 [("", ModuleArg::Instance(shim_args_instance_index))],
1979 );
1980 Ok(())
1981 }
1982
1983 fn instance_for(&self, module: CustomModule) -> u32 {
1986 match module {
1987 CustomModule::Main => self.instance_index.expect("instantiated by now"),
1988 CustomModule::Adapter(name) => self.adapter_instances[name],
1989 }
1990 }
1991
1992 fn module_for(&self, module: CustomModule) -> u32 {
1995 match module {
1996 CustomModule::Main => self.module_index.unwrap(),
1997 CustomModule::Adapter(name) => self.adapter_modules[name],
1998 }
1999 }
2000
2001 fn core_alias_export(&mut self, instance: u32, name: &str, kind: ExportKind) -> u32 {
2004 *self
2005 .aliased_core_items
2006 .entry((instance, name.to_string()))
2007 .or_insert_with(|| self.component.core_alias_export(instance, name, kind))
2008 }
2009}
2010
2011#[derive(Default)]
2029struct Shims<'a> {
2030 shims: IndexMap<ShimKind<'a>, Shim<'a>>,
2032}
2033
2034struct Shim<'a> {
2035 options: RequiredOptions,
2038
2039 name: String,
2043
2044 debug_name: String,
2047
2048 kind: ShimKind<'a>,
2050
2051 sig: WasmSignature,
2053}
2054
2055#[derive(Debug, Clone, Hash, Eq, PartialEq)]
2058enum PayloadFuncKind {
2059 FutureWrite,
2060 FutureRead,
2061 StreamWrite,
2062 StreamRead,
2063}
2064
2065#[derive(Debug, Clone, Hash, Eq, PartialEq)]
2066enum ShimKind<'a> {
2067 IndirectLowering {
2071 interface: Option<String>,
2073 index: usize,
2075 realloc: CustomModule<'a>,
2077 encoding: StringEncoding,
2079 },
2080 Adapter {
2083 adapter: &'a str,
2085 func: &'a str,
2087 },
2088 ResourceDtor {
2091 module: CustomModule<'a>,
2093 export: &'a str,
2095 },
2096 PayloadFunc {
2100 for_module: CustomModule<'a>,
2103 info: &'a PayloadInfo,
2108 kind: PayloadFuncKind,
2110 },
2111 WaitableSetWait { async_: bool },
2115 WaitableSetPoll { async_: bool },
2119 TaskReturn {
2121 interface: Option<InterfaceId>,
2124 func: &'a str,
2127 result: Option<Type>,
2129 for_module: CustomModule<'a>,
2131 encoding: StringEncoding,
2133 },
2134 ErrorContextNew {
2138 encoding: StringEncoding,
2140 },
2141 ErrorContextDebugMessage {
2145 for_module: CustomModule<'a>,
2147 encoding: StringEncoding,
2149 },
2150}
2151
2152#[derive(Debug, Copy, Clone, Hash, Eq, PartialEq)]
2162enum CustomModule<'a> {
2163 Main,
2166 Adapter(&'a str),
2169}
2170
2171impl<'a> Shims<'a> {
2172 fn append_indirect(
2177 &mut self,
2178 world: &'a ComponentWorld<'a>,
2179 for_module: CustomModule<'a>,
2180 ) -> Result<()> {
2181 let module_imports = world.imports_for(for_module);
2182 let module_exports = world.exports_for(for_module);
2183 let resolve = &world.encoder.metadata.resolve;
2184
2185 for (module, field, import) in module_imports.imports() {
2186 match import {
2187 Import::ImportedResourceDrop(..)
2190 | Import::MainModuleMemory
2191 | Import::MainModuleExport { .. }
2192 | Import::Item(_)
2193 | Import::ExportedResourceDrop(..)
2194 | Import::ExportedResourceRep(..)
2195 | Import::ExportedResourceNew(..)
2196 | Import::ExportedTaskCancel
2197 | Import::ErrorContextDrop
2198 | Import::BackpressureSet
2199 | Import::Yield { .. }
2200 | Import::SubtaskDrop
2201 | Import::SubtaskCancel { .. }
2202 | Import::FutureNew(..)
2203 | Import::StreamNew(..)
2204 | Import::FutureCancelRead { .. }
2205 | Import::FutureCancelWrite { .. }
2206 | Import::FutureCloseWritable { .. }
2207 | Import::FutureCloseReadable { .. }
2208 | Import::StreamCancelRead { .. }
2209 | Import::StreamCancelWrite { .. }
2210 | Import::StreamCloseWritable { .. }
2211 | Import::StreamCloseReadable { .. }
2212 | Import::WaitableSetNew
2213 | Import::WaitableSetDrop
2214 | Import::WaitableJoin
2215 | Import::ContextGet(_)
2216 | Import::ContextSet(_) => {}
2217
2218 Import::ExportedTaskReturn(key, interface, func, ty) => {
2222 let (options, sig) = task_return_options_and_type(resolve, *ty);
2223 if options.is_empty() {
2224 continue;
2225 }
2226 let name = self.shims.len().to_string();
2227 let encoding = world
2228 .module_metadata_for(for_module)
2229 .export_encodings
2230 .get(resolve, key, func)
2231 .ok_or_else(|| {
2232 anyhow::anyhow!(
2233 "missing component metadata for export of \
2234 `{module}::{field}`"
2235 )
2236 })?;
2237 self.push(Shim {
2238 name,
2239 debug_name: format!("task-return-{func}"),
2240 options,
2241 kind: ShimKind::TaskReturn {
2242 interface: *interface,
2243 func,
2244 result: *ty,
2245 for_module,
2246 encoding,
2247 },
2248 sig,
2249 });
2250 }
2251
2252 Import::FutureWrite { async_, info } => {
2253 self.append_indirect_payload_push(
2254 resolve,
2255 for_module,
2256 module,
2257 *async_,
2258 info,
2259 PayloadFuncKind::FutureWrite,
2260 vec![WasmType::I32; 2],
2261 vec![WasmType::I32],
2262 );
2263 }
2264 Import::FutureRead { async_, info } => {
2265 self.append_indirect_payload_push(
2266 resolve,
2267 for_module,
2268 module,
2269 *async_,
2270 info,
2271 PayloadFuncKind::FutureRead,
2272 vec![WasmType::I32; 2],
2273 vec![WasmType::I32],
2274 );
2275 }
2276 Import::StreamWrite { async_, info } => {
2277 self.append_indirect_payload_push(
2278 resolve,
2279 for_module,
2280 module,
2281 *async_,
2282 info,
2283 PayloadFuncKind::StreamWrite,
2284 vec![WasmType::I32; 3],
2285 vec![WasmType::I32],
2286 );
2287 }
2288 Import::StreamRead { async_, info } => {
2289 self.append_indirect_payload_push(
2290 resolve,
2291 for_module,
2292 module,
2293 *async_,
2294 info,
2295 PayloadFuncKind::StreamRead,
2296 vec![WasmType::I32; 3],
2297 vec![WasmType::I32],
2298 );
2299 }
2300
2301 Import::WaitableSetWait { async_ } => {
2302 let name = self.shims.len().to_string();
2303 self.push(Shim {
2304 name,
2305 debug_name: "waitable-set.wait".to_string(),
2306 options: RequiredOptions::empty(),
2307 kind: ShimKind::WaitableSetWait { async_: *async_ },
2308 sig: WasmSignature {
2309 params: vec![WasmType::I32; 2],
2310 results: vec![WasmType::I32],
2311 indirect_params: false,
2312 retptr: false,
2313 },
2314 });
2315 }
2316
2317 Import::WaitableSetPoll { async_ } => {
2318 let name = self.shims.len().to_string();
2319 self.push(Shim {
2320 name,
2321 debug_name: "waitable-set.poll".to_string(),
2322 options: RequiredOptions::empty(),
2323 kind: ShimKind::WaitableSetPoll { async_: *async_ },
2324 sig: WasmSignature {
2325 params: vec![WasmType::I32; 2],
2326 results: vec![WasmType::I32],
2327 indirect_params: false,
2328 retptr: false,
2329 },
2330 });
2331 }
2332
2333 Import::ErrorContextNew { encoding } => {
2334 let name = self.shims.len().to_string();
2335 self.push(Shim {
2336 name,
2337 debug_name: "error-new".to_string(),
2338 options: RequiredOptions::MEMORY | RequiredOptions::STRING_ENCODING,
2339 kind: ShimKind::ErrorContextNew {
2340 encoding: *encoding,
2341 },
2342 sig: WasmSignature {
2343 params: vec![WasmType::I32; 2],
2344 results: vec![WasmType::I32],
2345 indirect_params: false,
2346 retptr: false,
2347 },
2348 });
2349 }
2350
2351 Import::ErrorContextDebugMessage { encoding } => {
2352 let name = self.shims.len().to_string();
2353 self.push(Shim {
2354 name,
2355 debug_name: "error-debug-message".to_string(),
2356 options: RequiredOptions::MEMORY
2357 | RequiredOptions::STRING_ENCODING
2358 | RequiredOptions::REALLOC,
2359 kind: ShimKind::ErrorContextDebugMessage {
2360 for_module,
2361 encoding: *encoding,
2362 },
2363 sig: WasmSignature {
2364 params: vec![WasmType::I32; 2],
2365 results: vec![],
2366 indirect_params: false,
2367 retptr: false,
2368 },
2369 });
2370 }
2371
2372 Import::AdapterExport(ty) => {
2375 let name = self.shims.len().to_string();
2376 log::debug!("shim {name} is adapter `{module}::{field}`");
2377 self.push(Shim {
2378 name,
2379 debug_name: format!("adapt-{module}-{field}"),
2380 options: RequiredOptions::MEMORY,
2384 kind: ShimKind::Adapter {
2385 adapter: module,
2386 func: field,
2387 },
2388 sig: WasmSignature {
2389 params: ty.params().iter().map(to_wasm_type).collect(),
2390 results: ty.results().iter().map(to_wasm_type).collect(),
2391 indirect_params: false,
2392 retptr: false,
2393 },
2394 });
2395
2396 fn to_wasm_type(ty: &wasmparser::ValType) -> WasmType {
2397 match ty {
2398 wasmparser::ValType::I32 => WasmType::I32,
2399 wasmparser::ValType::I64 => WasmType::I64,
2400 wasmparser::ValType::F32 => WasmType::F32,
2401 wasmparser::ValType::F64 => WasmType::F64,
2402 _ => unreachable!(),
2403 }
2404 }
2405 }
2406
2407 Import::InterfaceFunc(key, _, name, abi) => {
2411 self.append_indirect_wit_func(
2412 world,
2413 for_module,
2414 module,
2415 field,
2416 key,
2417 name,
2418 Some(resolve.name_world_key(key)),
2419 *abi,
2420 )?;
2421 }
2422 Import::WorldFunc(key, name, abi) => {
2423 self.append_indirect_wit_func(
2424 world, for_module, module, field, key, name, None, *abi,
2425 )?;
2426 }
2427 }
2428 }
2429
2430 for (export_name, export) in module_exports.iter() {
2436 let id = match export {
2437 Export::ResourceDtor(id) => id,
2438 _ => continue,
2439 };
2440 let resource = resolve.types[*id].name.as_ref().unwrap();
2441 let name = self.shims.len().to_string();
2442 self.push(Shim {
2443 name,
2444 debug_name: format!("dtor-{resource}"),
2445 options: RequiredOptions::empty(),
2446 kind: ShimKind::ResourceDtor {
2447 module: for_module,
2448 export: export_name,
2449 },
2450 sig: WasmSignature {
2451 params: vec![WasmType::I32],
2452 results: Vec::new(),
2453 indirect_params: false,
2454 retptr: false,
2455 },
2456 });
2457 }
2458
2459 Ok(())
2460 }
2461
2462 fn append_indirect_payload_push(
2465 &mut self,
2466 resolve: &Resolve,
2467 for_module: CustomModule<'a>,
2468 module: &str,
2469 async_: bool,
2470 info: &'a PayloadInfo,
2471 kind: PayloadFuncKind,
2472 params: Vec<WasmType>,
2473 results: Vec<WasmType>,
2474 ) {
2475 let debug_name = format!("{module}-{}", info.name);
2476 let name = self.shims.len().to_string();
2477
2478 let payload = info.payload(resolve);
2479 let (wit_param, wit_result) = match kind {
2480 PayloadFuncKind::StreamRead | PayloadFuncKind::FutureRead => (None, payload),
2481 PayloadFuncKind::StreamWrite | PayloadFuncKind::FutureWrite => (payload, None),
2482 };
2483 self.push(Shim {
2484 name,
2485 debug_name,
2486 options: RequiredOptions::MEMORY
2487 | RequiredOptions::for_import(
2488 resolve,
2489 &Function {
2490 name: String::new(),
2491 kind: FunctionKind::Freestanding,
2492 params: match wit_param {
2493 Some(ty) => vec![("a".to_string(), ty)],
2494 None => Vec::new(),
2495 },
2496 result: wit_result,
2497 docs: Default::default(),
2498 stability: Stability::Unknown,
2499 },
2500 if async_ {
2501 AbiVariant::GuestImportAsync
2502 } else {
2503 AbiVariant::GuestImport
2504 },
2505 ),
2506 kind: ShimKind::PayloadFunc {
2507 for_module,
2508 info,
2509 kind,
2510 },
2511 sig: WasmSignature {
2512 params,
2513 results,
2514 indirect_params: false,
2515 retptr: false,
2516 },
2517 });
2518 }
2519
2520 fn append_indirect_wit_func(
2523 &mut self,
2524 world: &'a ComponentWorld<'a>,
2525 for_module: CustomModule<'a>,
2526 module: &str,
2527 field: &str,
2528 key: &WorldKey,
2529 name: &String,
2530 interface_key: Option<String>,
2531 abi: AbiVariant,
2532 ) -> Result<()> {
2533 let resolve = &world.encoder.metadata.resolve;
2534 let metadata = world.module_metadata_for(for_module);
2535 let interface = &world.import_map[&interface_key];
2536 let (index, _, lowering) = interface.lowerings.get_full(&(name.clone(), abi)).unwrap();
2537 let shim_name = self.shims.len().to_string();
2538 match lowering {
2539 Lowering::Direct | Lowering::ResourceDrop(_) => {}
2540
2541 Lowering::Indirect { sig, options } => {
2542 log::debug!(
2543 "shim {shim_name} is import `{module}::{field}` lowering {index} `{name}`",
2544 );
2545 let encoding = metadata
2546 .import_encodings
2547 .get(resolve, key, name)
2548 .ok_or_else(|| {
2549 anyhow::anyhow!(
2550 "missing component metadata for import of \
2551 `{module}::{field}`"
2552 )
2553 })?;
2554 self.push(Shim {
2555 name: shim_name,
2556 debug_name: format!("indirect-{module}-{field}"),
2557 options: *options,
2558 kind: ShimKind::IndirectLowering {
2559 interface: interface_key,
2560 index,
2561 realloc: for_module,
2562 encoding,
2563 },
2564 sig: sig.clone(),
2565 });
2566 }
2567 }
2568
2569 Ok(())
2570 }
2571
2572 fn push(&mut self, shim: Shim<'a>) {
2573 if !self.shims.contains_key(&shim.kind) {
2577 self.shims.insert(shim.kind.clone(), shim);
2578 }
2579 }
2580}
2581
2582fn task_return_options_and_type(
2583 resolve: &Resolve,
2584 ty: Option<Type>,
2585) -> (RequiredOptions, WasmSignature) {
2586 let func_tmp = Function {
2587 name: String::new(),
2588 kind: FunctionKind::Freestanding,
2589 params: match ty {
2590 Some(ty) => vec![("a".to_string(), ty)],
2591 None => Vec::new(),
2592 },
2593 result: None,
2594 docs: Default::default(),
2595 stability: Stability::Unknown,
2596 };
2597 let abi = AbiVariant::GuestImport;
2598 let options = RequiredOptions::for_import(resolve, &func_tmp, abi);
2599 let sig = resolve.wasm_signature(abi, &func_tmp);
2600 (options, sig)
2601}
2602
2603#[derive(Clone, Debug)]
2605pub struct Item {
2606 pub alias: String,
2607 pub kind: ExportKind,
2608 pub which: MainOrAdapter,
2609 pub name: String,
2610}
2611
2612#[derive(Debug, PartialEq, Clone)]
2614pub enum MainOrAdapter {
2615 Main,
2616 Adapter(String),
2617}
2618
2619impl MainOrAdapter {
2620 fn to_custom_module(&self) -> CustomModule<'_> {
2621 match self {
2622 MainOrAdapter::Main => CustomModule::Main,
2623 MainOrAdapter::Adapter(s) => CustomModule::Adapter(s),
2624 }
2625 }
2626}
2627
2628#[derive(Clone)]
2630pub enum Instance {
2631 MainOrAdapter(MainOrAdapter),
2633
2634 Items(Vec<Item>),
2636}
2637
2638#[derive(Clone)]
2641pub struct LibraryInfo {
2642 pub instantiate_after_shims: bool,
2644
2645 pub arguments: Vec<(String, Instance)>,
2647}
2648
2649pub(super) struct Adapter {
2651 wasm: Vec<u8>,
2653
2654 metadata: ModuleMetadata,
2656
2657 required_exports: IndexSet<WorldKey>,
2660
2661 library_info: Option<LibraryInfo>,
2666}
2667
2668#[derive(Default)]
2670pub struct ComponentEncoder {
2671 module: Vec<u8>,
2672 pub(super) metadata: Bindgen,
2673 validate: bool,
2674 pub(super) main_module_exports: IndexSet<WorldKey>,
2675 pub(super) adapters: IndexMap<String, Adapter>,
2676 import_name_map: HashMap<String, String>,
2677 realloc_via_memory_grow: bool,
2678 merge_imports_based_on_semver: Option<bool>,
2679 pub(super) reject_legacy_names: bool,
2680}
2681
2682impl ComponentEncoder {
2683 pub fn module(mut self, module: &[u8]) -> Result<Self> {
2689 let (wasm, metadata) = self.decode(module)?;
2690 let exports = self
2691 .merge_metadata(metadata)
2692 .context("failed merge WIT metadata for module with previous metadata")?;
2693 self.main_module_exports.extend(exports);
2694 self.module = if let Some(producers) = &self.metadata.producers {
2695 producers.add_to_wasm(&wasm)?
2696 } else {
2697 wasm.to_vec()
2698 };
2699 Ok(self)
2700 }
2701
2702 fn decode<'a>(&self, wasm: &'a [u8]) -> Result<(Cow<'a, [u8]>, Bindgen)> {
2703 let (bytes, metadata) = metadata::decode(wasm)?;
2704 match bytes {
2705 Some(wasm) => Ok((Cow::Owned(wasm), metadata)),
2706 None => Ok((Cow::Borrowed(wasm), metadata)),
2707 }
2708 }
2709
2710 fn merge_metadata(&mut self, metadata: Bindgen) -> Result<IndexSet<WorldKey>> {
2711 self.metadata.merge(metadata)
2712 }
2713
2714 pub fn validate(mut self, validate: bool) -> Self {
2716 self.validate = validate;
2717 self
2718 }
2719
2720 pub fn merge_imports_based_on_semver(mut self, merge: bool) -> Self {
2728 self.merge_imports_based_on_semver = Some(merge);
2729 self
2730 }
2731
2732 pub fn reject_legacy_names(mut self, reject: bool) -> Self {
2741 self.reject_legacy_names = reject;
2742 self
2743 }
2744
2745 pub fn adapter(self, name: &str, bytes: &[u8]) -> Result<Self> {
2763 self.library_or_adapter(name, bytes, None)
2764 }
2765
2766 pub fn library(self, name: &str, bytes: &[u8], library_info: LibraryInfo) -> Result<Self> {
2779 self.library_or_adapter(name, bytes, Some(library_info))
2780 }
2781
2782 fn library_or_adapter(
2783 mut self,
2784 name: &str,
2785 bytes: &[u8],
2786 library_info: Option<LibraryInfo>,
2787 ) -> Result<Self> {
2788 let (wasm, mut metadata) = self.decode(bytes)?;
2789 let adapter_metadata = mem::take(&mut metadata.metadata);
2797 let exports = self.merge_metadata(metadata).with_context(|| {
2798 format!("failed to merge WIT packages of adapter `{name}` into main packages")
2799 })?;
2800 if let Some(library_info) = &library_info {
2801 for (_, instance) in &library_info.arguments {
2803 let resolve = |which: &_| match which {
2804 MainOrAdapter::Main => Ok(()),
2805 MainOrAdapter::Adapter(name) => {
2806 if self.adapters.contains_key(name.as_str()) {
2807 Ok(())
2808 } else {
2809 Err(anyhow!("instance refers to unknown adapter `{name}`"))
2810 }
2811 }
2812 };
2813
2814 match instance {
2815 Instance::MainOrAdapter(which) => resolve(which)?,
2816 Instance::Items(items) => {
2817 for item in items {
2818 resolve(&item.which)?;
2819 }
2820 }
2821 }
2822 }
2823 }
2824 self.adapters.insert(
2825 name.to_string(),
2826 Adapter {
2827 wasm: wasm.to_vec(),
2828 metadata: adapter_metadata,
2829 required_exports: exports,
2830 library_info,
2831 },
2832 );
2833 Ok(self)
2834 }
2835
2836 pub fn realloc_via_memory_grow(mut self, value: bool) -> Self {
2841 self.realloc_via_memory_grow = value;
2842 self
2843 }
2844
2845 pub fn import_name_map(mut self, map: HashMap<String, String>) -> Self {
2856 self.import_name_map = map;
2857 self
2858 }
2859
2860 pub fn encode(&mut self) -> Result<Vec<u8>> {
2862 if self.module.is_empty() {
2863 bail!("a module is required when encoding a component");
2864 }
2865
2866 if self.merge_imports_based_on_semver.unwrap_or(true) {
2867 self.metadata
2868 .resolve
2869 .merge_world_imports_based_on_semver(self.metadata.world)?;
2870 }
2871
2872 let world = ComponentWorld::new(self).context("failed to decode world from module")?;
2873 let mut state = EncodingState {
2874 component: ComponentBuilder::default(),
2875 module_index: None,
2876 instance_index: None,
2877 memory_index: None,
2878 shim_instance_index: None,
2879 fixups_module_index: None,
2880 adapter_modules: IndexMap::new(),
2881 adapter_instances: IndexMap::new(),
2882 import_type_map: HashMap::new(),
2883 import_func_type_map: HashMap::new(),
2884 export_type_map: HashMap::new(),
2885 export_func_type_map: HashMap::new(),
2886 imported_instances: Default::default(),
2887 imported_funcs: Default::default(),
2888 exported_instances: Default::default(),
2889 aliased_core_items: Default::default(),
2890 info: &world,
2891 };
2892 state.encode_imports(&self.import_name_map)?;
2893 state.encode_core_modules();
2894 state.encode_core_instantiation()?;
2895 state.encode_exports(CustomModule::Main)?;
2896 for name in self.adapters.keys() {
2897 state.encode_exports(CustomModule::Adapter(name))?;
2898 }
2899 state
2900 .component
2901 .raw_custom_section(&crate::base_producers().raw_custom_section());
2902 let bytes = state.component.finish();
2903
2904 if self.validate {
2905 Validator::new_with_features(WasmFeatures::all())
2906 .validate_all(&bytes)
2907 .context("failed to validate component output")?;
2908 }
2909
2910 Ok(bytes)
2911 }
2912}
2913
2914impl ComponentWorld<'_> {
2915 fn imports_for(&self, module: CustomModule) -> &ImportMap {
2917 match module {
2918 CustomModule::Main => &self.info.imports,
2919 CustomModule::Adapter(name) => &self.adapters[name].info.imports,
2920 }
2921 }
2922
2923 fn exports_for(&self, module: CustomModule) -> &ExportMap {
2925 match module {
2926 CustomModule::Main => &self.info.exports,
2927 CustomModule::Adapter(name) => &self.adapters[name].info.exports,
2928 }
2929 }
2930
2931 fn module_metadata_for(&self, module: CustomModule) -> &ModuleMetadata {
2933 match module {
2934 CustomModule::Main => &self.encoder.metadata.metadata,
2935 CustomModule::Adapter(name) => &self.encoder.adapters[name].metadata,
2936 }
2937 }
2938}
2939
2940#[cfg(all(test, feature = "dummy-module"))]
2941mod test {
2942 use super::*;
2943 use crate::{dummy_module, embed_component_metadata};
2944 use wit_parser::ManglingAndAbi;
2945
2946 #[test]
2947 fn it_renames_imports() {
2948 let mut resolve = Resolve::new();
2949 let pkg = resolve
2950 .push_str(
2951 "test.wit",
2952 r#"
2953package test:wit;
2954
2955interface i {
2956 f: func();
2957}
2958
2959world test {
2960 import i;
2961 import foo: interface {
2962 f: func();
2963 }
2964}
2965"#,
2966 )
2967 .unwrap();
2968 let world = resolve.select_world(pkg, None).unwrap();
2969
2970 let mut module = dummy_module(&resolve, world, ManglingAndAbi::Standard32);
2971
2972 embed_component_metadata(&mut module, &resolve, world, StringEncoding::UTF8).unwrap();
2973
2974 let encoded = ComponentEncoder::default()
2975 .import_name_map(HashMap::from([
2976 (
2977 "foo".to_string(),
2978 "unlocked-dep=<foo:bar/foo@{>=1.0.0 <1.1.0}>".to_string(),
2979 ),
2980 (
2981 "test:wit/i".to_string(),
2982 "locked-dep=<foo:bar/i@1.2.3>".to_string(),
2983 ),
2984 ]))
2985 .module(&module)
2986 .unwrap()
2987 .validate(true)
2988 .encode()
2989 .unwrap();
2990
2991 let wat = wasmprinter::print_bytes(encoded).unwrap();
2992 assert!(wat.contains("unlocked-dep=<foo:bar/foo@{>=1.0.0 <1.1.0}>"));
2993 assert!(wat.contains("locked-dep=<foo:bar/i@1.2.3>"));
2994 }
2995}