1use crate::encoding::world::WorldAdapter;
75use crate::metadata::{self, Bindgen, ModuleMetadata};
76use crate::validation::{
77 ResourceInfo, ValidatedModule, BARE_FUNC_MODULE_NAME, MAIN_MODULE_IMPORT_NAME,
78 POST_RETURN_PREFIX,
79};
80use crate::StringEncoding;
81use anyhow::{anyhow, bail, Context, Result};
82use indexmap::{IndexMap, IndexSet};
83use std::collections::HashMap;
84use std::hash::Hash;
85use wasm_encoder::*;
86use wasmparser::{Validator, WasmFeatures};
87use wit_parser::{
88 abi::{AbiVariant, WasmSignature, WasmType},
89 Function, FunctionKind, InterfaceId, LiveTypes, Resolve, Type, TypeDefKind, TypeId, TypeOwner,
90 WorldItem, WorldKey,
91};
92
93const INDIRECT_TABLE_NAME: &str = "$imports";
94
95mod wit;
96pub use wit::{encode, encode_world};
97
98mod types;
99use types::{InstanceTypeEncoder, RootTypeEncoder, ValtypeEncoder};
100mod world;
101use world::{ComponentWorld, ImportedInterface, Lowering};
102
103fn to_val_type(ty: &WasmType) -> ValType {
104 match ty {
105 WasmType::I32 => ValType::I32,
106 WasmType::I64 => ValType::I64,
107 WasmType::F32 => ValType::F32,
108 WasmType::F64 => ValType::F64,
109 WasmType::Pointer => ValType::I32,
110 WasmType::PointerOrI64 => ValType::I64,
111 WasmType::Length => ValType::I32,
112 }
113}
114
115bitflags::bitflags! {
116 #[derive(Copy, Clone, Debug)]
119 pub struct RequiredOptions: u8 {
120 const MEMORY = 1 << 0;
123 const REALLOC = 1 << 1;
126 const STRING_ENCODING = 1 << 2;
129 }
130}
131
132impl RequiredOptions {
133 fn for_import(resolve: &Resolve, func: &Function) -> RequiredOptions {
134 let sig = resolve.wasm_signature(AbiVariant::GuestImport, func);
135 let mut ret = RequiredOptions::empty();
136 ret.add_lift(TypeContents::for_types(
138 resolve,
139 func.params.iter().map(|(_, t)| t),
140 ));
141 ret.add_lower(TypeContents::for_types(resolve, func.results.iter_types()));
142
143 if sig.retptr || sig.indirect_params {
146 ret |= RequiredOptions::MEMORY;
147 }
148 ret
149 }
150
151 fn for_export(resolve: &Resolve, func: &Function) -> RequiredOptions {
152 let sig = resolve.wasm_signature(AbiVariant::GuestExport, func);
153 let mut ret = RequiredOptions::empty();
154 ret.add_lower(TypeContents::for_types(
156 resolve,
157 func.params.iter().map(|(_, t)| t),
158 ));
159 ret.add_lift(TypeContents::for_types(resolve, func.results.iter_types()));
160
161 if sig.retptr || sig.indirect_params {
165 ret |= RequiredOptions::MEMORY;
166 if sig.indirect_params {
167 ret |= RequiredOptions::REALLOC;
168 }
169 }
170 ret
171 }
172
173 fn add_lower(&mut self, types: TypeContents) {
174 if types.contains(TypeContents::LIST) {
178 *self |= RequiredOptions::MEMORY | RequiredOptions::REALLOC;
179 }
180 if types.contains(TypeContents::STRING) {
181 *self |= RequiredOptions::MEMORY
182 | RequiredOptions::STRING_ENCODING
183 | RequiredOptions::REALLOC;
184 }
185 }
186
187 fn add_lift(&mut self, types: TypeContents) {
188 if types.contains(TypeContents::LIST) {
192 *self |= RequiredOptions::MEMORY;
193 }
194 if types.contains(TypeContents::STRING) {
195 *self |= RequiredOptions::MEMORY | RequiredOptions::STRING_ENCODING;
196 }
197 }
198
199 fn into_iter(
200 self,
201 encoding: StringEncoding,
202 memory_index: Option<u32>,
203 realloc_index: Option<u32>,
204 ) -> Result<impl ExactSizeIterator<Item = CanonicalOption>> {
205 #[derive(Default)]
206 struct Iter {
207 options: [Option<CanonicalOption>; 3],
208 current: usize,
209 count: usize,
210 }
211
212 impl Iter {
213 fn push(&mut self, option: CanonicalOption) {
214 assert!(self.count < self.options.len());
215 self.options[self.count] = Some(option);
216 self.count += 1;
217 }
218 }
219
220 impl Iterator for Iter {
221 type Item = CanonicalOption;
222
223 fn next(&mut self) -> Option<Self::Item> {
224 if self.current == self.count {
225 return None;
226 }
227 let option = self.options[self.current];
228 self.current += 1;
229 option
230 }
231
232 fn size_hint(&self) -> (usize, Option<usize>) {
233 (self.count - self.current, Some(self.count - self.current))
234 }
235 }
236
237 impl ExactSizeIterator for Iter {}
238
239 let mut iter = Iter::default();
240
241 if self.contains(RequiredOptions::MEMORY) {
242 iter.push(CanonicalOption::Memory(memory_index.ok_or_else(|| {
243 anyhow!("module does not export a memory named `memory`")
244 })?));
245 }
246
247 if self.contains(RequiredOptions::REALLOC) {
248 iter.push(CanonicalOption::Realloc(realloc_index.ok_or_else(
249 || anyhow!("module does not export a function named `cabi_realloc`"),
250 )?));
251 }
252
253 if self.contains(RequiredOptions::STRING_ENCODING) {
254 iter.push(encoding.into());
255 }
256
257 Ok(iter)
258 }
259}
260
261bitflags::bitflags! {
262 struct TypeContents: u8 {
265 const STRING = 1 << 0;
266 const LIST = 1 << 1;
267 }
268}
269
270impl TypeContents {
271 fn for_types<'a>(resolve: &Resolve, types: impl Iterator<Item = &'a Type>) -> Self {
272 let mut cur = TypeContents::empty();
273 for ty in types {
274 cur |= Self::for_type(resolve, ty);
275 }
276 cur
277 }
278
279 fn for_optional_types<'a>(
280 resolve: &Resolve,
281 types: impl Iterator<Item = Option<&'a Type>>,
282 ) -> Self {
283 Self::for_types(resolve, types.flatten())
284 }
285
286 fn for_optional_type(resolve: &Resolve, ty: Option<&Type>) -> Self {
287 match ty {
288 Some(ty) => Self::for_type(resolve, ty),
289 None => Self::empty(),
290 }
291 }
292
293 fn for_type(resolve: &Resolve, ty: &Type) -> Self {
294 match ty {
295 Type::Id(id) => match &resolve.types[*id].kind {
296 TypeDefKind::Handle(h) => match h {
297 wit_parser::Handle::Own(_) => Self::empty(),
298 wit_parser::Handle::Borrow(_) => Self::empty(),
299 },
300 TypeDefKind::Resource => Self::empty(),
301 TypeDefKind::Record(r) => Self::for_types(resolve, r.fields.iter().map(|f| &f.ty)),
302 TypeDefKind::Tuple(t) => Self::for_types(resolve, t.types.iter()),
303 TypeDefKind::Flags(_) => Self::empty(),
304 TypeDefKind::Option(t) => Self::for_type(resolve, t),
305 TypeDefKind::Result(r) => {
306 Self::for_optional_type(resolve, r.ok.as_ref())
307 | Self::for_optional_type(resolve, r.err.as_ref())
308 }
309 TypeDefKind::Variant(v) => {
310 Self::for_optional_types(resolve, v.cases.iter().map(|c| c.ty.as_ref()))
311 }
312 TypeDefKind::Enum(_) => Self::empty(),
313 TypeDefKind::List(t) => Self::for_type(resolve, t) | Self::LIST,
314 TypeDefKind::Type(t) => Self::for_type(resolve, t),
315 TypeDefKind::Future(_) => todo!("encoding for future"),
316 TypeDefKind::Stream(_) => todo!("encoding for stream"),
317 TypeDefKind::Unknown => unreachable!(),
318 },
319 Type::String => Self::STRING,
320 _ => Self::empty(),
321 }
322 }
323}
324
325pub struct EncodingState<'a> {
327 component: ComponentBuilder,
329 module_index: Option<u32>,
333 instance_index: Option<u32>,
337 memory_index: Option<u32>,
341 realloc_index: Option<u32>,
345 shim_instance_index: Option<u32>,
349 fixups_module_index: Option<u32>,
353
354 adapter_modules: IndexMap<&'a str, u32>,
357 adapter_instances: IndexMap<&'a str, u32>,
359 adapter_import_reallocs: IndexMap<&'a str, Option<u32>>,
363 adapter_export_reallocs: IndexMap<&'a str, Option<u32>>,
364
365 imported_instances: IndexMap<InterfaceId, u32>,
367 imported_funcs: IndexMap<String, u32>,
368 exported_instances: IndexMap<InterfaceId, u32>,
369
370 import_type_map: HashMap<TypeId, u32>,
375 import_func_type_map: HashMap<types::FunctionKey<'a>, u32>,
376 export_type_map: HashMap<TypeId, u32>,
377 export_func_type_map: HashMap<types::FunctionKey<'a>, u32>,
378
379 info: &'a ComponentWorld<'a>,
381}
382
383impl<'a> EncodingState<'a> {
384 fn encode_core_modules(&mut self) {
385 assert!(self.module_index.is_none());
386 let idx = self.component.core_module_raw(&self.info.encoder.module);
387 self.module_index = Some(idx);
388
389 for (name, adapter) in self.info.adapters.iter() {
390 let add_meta = wasm_metadata::AddMetadata {
391 name: Some(if adapter.library_info.is_some() {
392 name.to_string()
393 } else {
394 format!("wit-component:adapter:{name}")
395 }),
396 ..Default::default()
397 };
398 let wasm = add_meta
399 .to_wasm(&adapter.wasm)
400 .expect("core wasm can get name added");
401 let idx = self.component.core_module_raw(&wasm);
402 let prev = self.adapter_modules.insert(name, idx);
403 assert!(prev.is_none());
404 }
405 }
406
407 fn root_import_type_encoder(
408 &mut self,
409 interface: Option<InterfaceId>,
410 ) -> RootTypeEncoder<'_, 'a> {
411 RootTypeEncoder {
412 state: self,
413 interface,
414 import_types: true,
415 }
416 }
417
418 fn root_export_type_encoder(
419 &mut self,
420 interface: Option<InterfaceId>,
421 ) -> RootTypeEncoder<'_, 'a> {
422 RootTypeEncoder {
423 state: self,
424 interface,
425 import_types: false,
426 }
427 }
428
429 fn instance_type_encoder(&mut self, interface: InterfaceId) -> InstanceTypeEncoder<'_, 'a> {
430 InstanceTypeEncoder {
431 state: self,
432 interface,
433 type_map: Default::default(),
434 func_type_map: Default::default(),
435 ty: Default::default(),
436 }
437 }
438
439 fn encode_imports(&mut self, name_map: &HashMap<String, String>) -> Result<()> {
440 let mut has_funcs = false;
441 for (name, info) in self.info.import_map.iter() {
442 match name {
443 Some(name) => {
444 self.encode_interface_import(name_map.get(name).unwrap_or(name), info)?
445 }
446 None => has_funcs = true,
447 }
448 }
449
450 let resolve = &self.info.encoder.metadata.resolve;
451 let world = &resolve.worlds[self.info.encoder.metadata.world];
452 for (_name, item) in world.imports.iter() {
453 if let WorldItem::Type(ty) = item {
454 self.root_import_type_encoder(None)
455 .encode_valtype(resolve, &Type::Id(*ty))?;
456 }
457 }
458
459 if has_funcs {
460 let info = &self.info.import_map[&None];
461 self.encode_root_import_funcs(info)?;
462 }
463 Ok(())
464 }
465
466 fn encode_interface_import(&mut self, name: &str, info: &ImportedInterface) -> Result<()> {
467 let resolve = &self.info.encoder.metadata.resolve;
468 let interface_id = info.interface.as_ref().unwrap();
469 let interface_id = *interface_id;
470 let interface = &resolve.interfaces[interface_id];
471 log::trace!("encoding imports for `{name}` as {:?}", interface_id);
472 let mut encoder = self.instance_type_encoder(interface_id);
473
474 if let Some(live) = encoder.state.info.live_type_imports.get(&interface_id) {
476 for ty in live {
477 log::trace!(
478 "encoding extra type {ty:?} name={:?}",
479 resolve.types[*ty].name
480 );
481 encoder.encode_valtype(resolve, &Type::Id(*ty))?;
482 }
483 }
484
485 for (_, func) in interface.functions.iter() {
488 if !info.lowerings.contains_key(&func.name) {
489 continue;
490 }
491 log::trace!("encoding function type for `{}`", func.name);
492 let idx = encoder.encode_func_type(resolve, func)?;
493
494 encoder.ty.export(&func.name, ComponentTypeRef::Func(idx));
495 }
496
497 let ty = encoder.ty;
498 if ty.is_empty() {
501 return Ok(());
502 }
503 let instance_type_idx = self.component.type_instance(&ty);
504 let instance_idx = self
505 .component
506 .import(name, ComponentTypeRef::Instance(instance_type_idx));
507 let prev = self.imported_instances.insert(interface_id, instance_idx);
508 assert!(prev.is_none());
509 Ok(())
510 }
511
512 fn encode_root_import_funcs(&mut self, info: &ImportedInterface) -> Result<()> {
513 let resolve = &self.info.encoder.metadata.resolve;
514 let world = self.info.encoder.metadata.world;
515 for (name, item) in resolve.worlds[world].imports.iter() {
516 let func = match item {
517 WorldItem::Function(f) => f,
518 WorldItem::Interface(_) | WorldItem::Type(_) => continue,
519 };
520 let name = resolve.name_world_key(name);
521 if !info.lowerings.contains_key(&name) {
522 continue;
523 }
524 log::trace!("encoding function type for `{}`", func.name);
525 let idx = self
526 .root_import_type_encoder(None)
527 .encode_func_type(resolve, func)?;
528 let func_idx = self.component.import(&name, ComponentTypeRef::Func(idx));
529 let prev = self.imported_funcs.insert(name, func_idx);
530 assert!(prev.is_none());
531 }
532 Ok(())
533 }
534
535 fn alias_imported_type(&mut self, interface: InterfaceId, id: TypeId) -> u32 {
536 let ty = &self.info.encoder.metadata.resolve.types[id];
537 let name = ty.name.as_ref().expect("type must have a name");
538 let instance = self.imported_instances[&interface];
539 self.component
540 .alias_export(instance, name, ComponentExportKind::Type)
541 }
542
543 fn alias_exported_type(&mut self, interface: InterfaceId, id: TypeId) -> u32 {
544 let ty = &self.info.encoder.metadata.resolve.types[id];
545 let name = ty.name.as_ref().expect("type must have a name");
546 let instance = self.exported_instances[&interface];
547 self.component
548 .alias_export(instance, name, ComponentExportKind::Type)
549 }
550
551 fn encode_core_instantiation(&mut self) -> Result<()> {
552 let info = &self.info.info;
553
554 let shims = self.encode_shim_instantiation()?;
556
557 let mut args = Vec::new();
560 for core_wasm_name in info.required_imports.keys() {
561 let index = self.import_instance_to_lowered_core_instance(
562 CustomModule::Main,
563 core_wasm_name,
564 &shims,
565 info.metadata,
566 );
567 args.push((*core_wasm_name, ModuleArg::Instance(index)));
568 }
569
570 for (adapter, funcs) in info.adapters_required.iter() {
575 let shim_instance = self
576 .shim_instance_index
577 .expect("shim should be instantiated");
578 let mut exports = Vec::new();
579
580 for (func, _ty) in funcs {
581 let index = self.component.core_alias_export(
582 shim_instance,
583 &shims.shim_names[&ShimKind::Adapter { adapter, func }],
584 ExportKind::Func,
585 );
586 exports.push((*func, ExportKind::Func, index));
587 }
588
589 let index = self.component.core_instantiate_exports(exports);
590 args.push((*adapter, ModuleArg::Instance(index)));
591 }
592
593 self.add_resource_funcs(
594 CustomModule::Main,
595 &info.required_resource_funcs,
596 &shims,
597 &mut args,
598 );
599
600 self.instantiate_core_module(args, info);
605
606 let (before, after) = self
609 .info
610 .adapters
611 .iter()
612 .partition::<Vec<_>, _>(|(_, adapter)| {
613 !matches!(
614 adapter.library_info,
615 Some(LibraryInfo {
616 instantiate_after_shims: true,
617 ..
618 })
619 )
620 });
621
622 for (name, adapter) in before {
623 self.instantiate_adapter_module(&shims, name, adapter);
624 }
625
626 self.encode_indirect_lowerings(&shims)?;
629
630 for (name, adapter) in after {
631 self.instantiate_adapter_module(&shims, name, adapter);
632 }
633
634 Ok(())
635 }
636
637 fn import_instance_to_lowered_core_instance(
646 &mut self,
647 for_module: CustomModule<'_>,
648 core_wasm_name: &str,
649 shims: &Shims<'_>,
650 metadata: &ModuleMetadata,
651 ) -> u32 {
652 let interface = if core_wasm_name == BARE_FUNC_MODULE_NAME {
653 None
654 } else {
655 Some(core_wasm_name.to_string())
656 };
657 let import = &self.info.import_map[&interface];
658 let required_imports = match for_module {
659 CustomModule::Main => &self.info.info.required_imports[core_wasm_name],
660 CustomModule::Adapter(name) => {
661 &self.info.adapters[name].info.required_imports[core_wasm_name]
662 }
663 };
664 let mut exports = Vec::with_capacity(import.lowerings.len());
665
666 for (index, (name, lowering)) in import.lowerings.iter().enumerate() {
667 if !required_imports.funcs.contains(name.as_str()) {
668 continue;
669 }
670 let index = match lowering {
671 Lowering::Direct => {
674 let func_index = match &import.interface {
675 Some(interface) => {
676 let instance_index = self.imported_instances[interface];
677 self.component.alias_export(
678 instance_index,
679 name,
680 ComponentExportKind::Func,
681 )
682 }
683 None => self.imported_funcs[name],
684 };
685 self.component.lower_func(func_index, [])
686 }
687
688 Lowering::Indirect { .. } => {
691 let encoding =
692 metadata.import_encodings[&(core_wasm_name.to_string(), name.clone())];
693 self.component.core_alias_export(
694 self.shim_instance_index
695 .expect("shim should be instantiated"),
696 &shims.shim_names[&ShimKind::IndirectLowering {
697 interface: interface.clone(),
698 index,
699 realloc: for_module,
700 encoding,
701 }],
702 ExportKind::Func,
703 )
704 }
705
706 Lowering::ResourceDrop(id) => {
707 let resource_idx = self.lookup_resource_index(*id);
708 self.component.resource_drop(resource_idx)
709 }
710 };
711 exports.push((name.as_str(), ExportKind::Func, index));
712 }
713
714 self.component.core_instantiate_exports(exports)
715 }
716
717 fn lookup_resource_index(&mut self, id: TypeId) -> u32 {
718 let resolve = &self.info.encoder.metadata.resolve;
719 let ty = &resolve.types[id];
720 match ty.owner {
721 TypeOwner::World(_) => self.import_type_map[&id],
725 TypeOwner::Interface(i) => {
726 let instance = self.imported_instances[&i];
727 let name = ty.name.as_ref().expect("resources must be named");
728 self.component
729 .alias_export(instance, name, ComponentExportKind::Type)
730 }
731 TypeOwner::None => panic!("resources must have an owner"),
732 }
733 }
734
735 fn encode_exports(&mut self, module: CustomModule) -> Result<()> {
736 let resolve = &self.info.encoder.metadata.resolve;
737 let exports = match module {
738 CustomModule::Main => &self.info.encoder.main_module_exports,
739 CustomModule::Adapter(name) => &self.info.encoder.adapters[name].required_exports,
740 };
741 let world = &resolve.worlds[self.info.encoder.metadata.world];
742 for export_name in exports {
743 let export_string = resolve.name_world_key(export_name);
744 match &world.exports[export_name] {
745 WorldItem::Function(func) => {
746 let ty = self
747 .root_import_type_encoder(None)
748 .encode_func_type(resolve, func)?;
749 let core_name = func.core_export_name(None);
750 let idx = self.encode_lift(module, &core_name, func, ty)?;
751 self.component
752 .export(&export_string, ComponentExportKind::Func, idx, None);
753 }
754 WorldItem::Interface(export) => {
755 self.encode_interface_export(&export_string, module, *export)?;
756 }
757 WorldItem::Type(_) => unreachable!(),
758 }
759 }
760
761 Ok(())
762 }
763
764 fn encode_interface_export(
765 &mut self,
766 export_name: &str,
767 module: CustomModule<'_>,
768 export: InterfaceId,
769 ) -> Result<()> {
770 log::trace!("encode interface export `{export_name}`");
771 let resolve = &self.info.encoder.metadata.resolve;
772
773 let mut imports = Vec::new();
780 let mut root = self.root_export_type_encoder(Some(export));
781 for (_, func) in &resolve.interfaces[export].functions {
782 let core_name = func.core_export_name(Some(export_name));
783 let ty = root.encode_func_type(resolve, func)?;
784 let func_index = root.state.encode_lift(module, &core_name, func, ty)?;
785 imports.push((
786 import_func_name(func),
787 ComponentExportKind::Func,
788 func_index,
789 ));
790 }
791
792 let mut nested = NestedComponentTypeEncoder {
796 component: ComponentBuilder::default(),
797 type_map: Default::default(),
798 func_type_map: Default::default(),
799 export_types: false,
800 interface: export,
801 state: self,
802 imports: IndexMap::new(),
803 };
804
805 let mut types_to_import = LiveTypes::default();
815 types_to_import.add_interface(resolve, export);
816 let exports_used = &nested.state.info.exports_used[&export];
817 for ty in types_to_import.iter() {
818 if let TypeOwner::Interface(owner) = resolve.types[ty].owner {
819 if owner == export {
820 continue;
823 }
824
825 let mut encoder = if exports_used.contains(&owner) {
828 nested.state.root_export_type_encoder(Some(export))
829 } else {
830 nested.state.root_import_type_encoder(Some(export))
831 };
832 encoder.encode_valtype(resolve, &Type::Id(ty))?;
833
834 nested.interface = owner;
838 nested.encode_valtype(resolve, &Type::Id(ty))?;
839 }
840 }
841 nested.interface = export;
842
843 let imported_types = nested.type_map.clone();
847
848 let mut resources = HashMap::new();
854 for (_name, ty) in resolve.interfaces[export].types.iter() {
855 if !matches!(resolve.types[*ty].kind, TypeDefKind::Resource) {
856 continue;
857 }
858 let idx = match nested.encode_valtype(resolve, &Type::Id(*ty))? {
859 ComponentValType::Type(idx) => idx,
860 _ => unreachable!(),
861 };
862 resources.insert(*ty, idx);
863 }
864
865 for (_, func) in resolve.interfaces[export].functions.iter() {
869 let ty = nested.encode_func_type(resolve, func)?;
870 nested
871 .component
872 .import(&import_func_name(func), ComponentTypeRef::Func(ty));
873 }
874
875 let reverse_map = nested
882 .type_map
883 .drain()
884 .map(|p| (p.1, p.0))
885 .collect::<HashMap<_, _>>();
886 for (name, idx) in nested.imports.drain(..) {
887 let id = reverse_map[&idx];
888 let owner = match resolve.types[id].owner {
889 TypeOwner::Interface(id) => id,
890 _ => unreachable!(),
891 };
892 let idx = if owner == export || exports_used.contains(&owner) {
893 log::trace!("consulting exports for {id:?}");
894 nested.state.export_type_map[&id]
895 } else {
896 log::trace!("consulting imports for {id:?}");
897 nested.state.import_type_map[&id]
898 };
899 imports.push((name, ComponentExportKind::Type, idx))
900 }
901
902 nested.type_map = imported_types;
907
908 nested.export_types = true;
915 nested.func_type_map.clear();
916
917 for (_, id) in resolve.interfaces[export].types.iter() {
923 let ty = &resolve.types[*id];
924 match ty.kind {
925 TypeDefKind::Resource => {
926 let idx = nested.component.export(
927 ty.name.as_ref().expect("resources must be named"),
928 ComponentExportKind::Type,
929 resources[id],
930 None,
931 );
932 nested.type_map.insert(*id, idx);
933 }
934 _ => {
935 nested.encode_valtype(resolve, &Type::Id(*id))?;
936 }
937 }
938 }
939
940 for (i, (_, func)) in resolve.interfaces[export].functions.iter().enumerate() {
941 let ty = nested.encode_func_type(resolve, func)?;
942 nested.component.export(
943 &func.name,
944 ComponentExportKind::Func,
945 i as u32,
946 Some(ComponentTypeRef::Func(ty)),
947 );
948 }
949
950 let component = nested.component;
954 let component_index = self.component.component(component);
955 let instance_index = self.component.instantiate(component_index, imports);
956 let idx = self.component.export(
957 export_name,
958 ComponentExportKind::Instance,
959 instance_index,
960 None,
961 );
962 let prev = self.exported_instances.insert(export, idx);
963 assert!(prev.is_none());
964
965 for (_name, id) in resolve.interfaces[export].types.iter() {
973 self.export_type_map.remove(id);
974 }
975
976 return Ok(());
977
978 struct NestedComponentTypeEncoder<'state, 'a> {
979 component: ComponentBuilder,
980 type_map: HashMap<TypeId, u32>,
981 func_type_map: HashMap<types::FunctionKey<'a>, u32>,
982 export_types: bool,
983 interface: InterfaceId,
984 state: &'state mut EncodingState<'a>,
985 imports: IndexMap<String, u32>,
986 }
987
988 impl<'a> ValtypeEncoder<'a> for NestedComponentTypeEncoder<'_, 'a> {
989 fn defined_type(&mut self) -> (u32, ComponentDefinedTypeEncoder<'_>) {
990 self.component.type_defined()
991 }
992 fn define_function_type(&mut self) -> (u32, ComponentFuncTypeEncoder<'_>) {
993 self.component.type_function()
994 }
995 fn export_type(&mut self, idx: u32, name: &'a str) -> Option<u32> {
996 if self.export_types {
997 Some(
998 self.component
999 .export(name, ComponentExportKind::Type, idx, None),
1000 )
1001 } else {
1002 let name = self.unique_import_name(name);
1003 let ret = self
1004 .component
1005 .import(&name, ComponentTypeRef::Type(TypeBounds::Eq(idx)));
1006 self.imports.insert(name, ret);
1007 Some(ret)
1008 }
1009 }
1010 fn export_resource(&mut self, name: &'a str) -> u32 {
1011 if self.export_types {
1012 panic!("resources should already be exported")
1013 } else {
1014 let name = self.unique_import_name(name);
1015 let ret = self
1016 .component
1017 .import(&name, ComponentTypeRef::Type(TypeBounds::SubResource));
1018 self.imports.insert(name, ret);
1019 ret
1020 }
1021 }
1022 fn import_type(&mut self, _: InterfaceId, _id: TypeId) -> u32 {
1023 unreachable!()
1024 }
1025 fn type_map(&mut self) -> &mut HashMap<TypeId, u32> {
1026 &mut self.type_map
1027 }
1028 fn func_type_map(&mut self) -> &mut HashMap<types::FunctionKey<'a>, u32> {
1029 &mut self.func_type_map
1030 }
1031 fn interface(&self) -> Option<InterfaceId> {
1032 Some(self.interface)
1033 }
1034 }
1035
1036 impl NestedComponentTypeEncoder<'_, '_> {
1037 fn unique_import_name(&mut self, name: &str) -> String {
1038 let mut name = format!("import-type-{name}");
1039 let mut n = 0;
1040 while self.imports.contains_key(&name) {
1041 name = format!("{name}{n}");
1042 n += 1;
1043 }
1044 name
1045 }
1046 }
1047
1048 fn import_func_name(f: &Function) -> String {
1049 match f.kind {
1050 FunctionKind::Freestanding => {
1051 format!("import-func-{}", f.name)
1052 }
1053
1054 FunctionKind::Method(_)
1062 | FunctionKind::Static(_)
1063 | FunctionKind::Constructor(_) => {
1064 format!(
1065 "import-{}",
1066 f.name.replace('[', "").replace([']', '.'], "-")
1067 )
1068 }
1069 }
1070 }
1071 }
1072
1073 fn encode_lift(
1074 &mut self,
1075 module: CustomModule<'_>,
1076 core_name: &str,
1077 func: &Function,
1078 ty: u32,
1079 ) -> Result<u32> {
1080 let resolve = &self.info.encoder.metadata.resolve;
1081 let metadata = match module {
1082 CustomModule::Main => &self.info.encoder.metadata.metadata,
1083 CustomModule::Adapter(name) => &self.info.encoder.adapters[name].metadata,
1084 };
1085 let post_returns = match module {
1086 CustomModule::Main => &self.info.info.post_returns,
1087 CustomModule::Adapter(name) => &self.info.adapters[name].info.post_returns,
1088 };
1089 let instance_index = match module {
1090 CustomModule::Main => self.instance_index.expect("instantiated by now"),
1091 CustomModule::Adapter(name) => self.adapter_instances[name],
1092 };
1093 let core_func_index =
1094 self.component
1095 .core_alias_export(instance_index, core_name, ExportKind::Func);
1096
1097 let options = RequiredOptions::for_export(resolve, func);
1098
1099 let encoding = metadata.export_encodings[core_name];
1100 let realloc_index = match module {
1104 CustomModule::Main => self.realloc_index,
1105 CustomModule::Adapter(name) => self.adapter_export_reallocs[name],
1106 };
1107 let mut options = options
1108 .into_iter(encoding, self.memory_index, realloc_index)?
1109 .collect::<Vec<_>>();
1110
1111 let post_return = format!("{POST_RETURN_PREFIX}{core_name}");
1112 if post_returns.contains(&post_return[..]) {
1113 let post_return =
1114 self.component
1115 .core_alias_export(instance_index, &post_return, ExportKind::Func);
1116 options.push(CanonicalOption::PostReturn(post_return));
1117 }
1118 let func_index = self.component.lift_func(core_func_index, ty, options);
1119 Ok(func_index)
1120 }
1121
1122 fn encode_shim_instantiation(&mut self) -> Result<Shims<'a>> {
1123 let mut signatures = Vec::new();
1124 let mut ret = Shims::default();
1125 let info = &self.info.info;
1126
1127 for (core_wasm_name, required) in info.required_imports.iter() {
1130 let import_name = if *core_wasm_name == BARE_FUNC_MODULE_NAME {
1131 None
1132 } else {
1133 Some(core_wasm_name.to_string())
1134 };
1135 let import = &self.info.import_map[&import_name];
1136 ret.append_indirect(
1137 core_wasm_name,
1138 CustomModule::Main,
1139 import,
1140 &required.funcs,
1141 info.metadata,
1142 &mut signatures,
1143 )
1144 .context("failed to register indirect shims for main module")?;
1145 }
1146
1147 for (adapter_name, adapter) in self.info.adapters.iter() {
1151 for (name, required) in adapter.info.required_imports.iter() {
1152 let import_name = if *name == BARE_FUNC_MODULE_NAME {
1153 None
1154 } else {
1155 Some(name.to_string())
1156 };
1157 let import = &self.info.import_map[&import_name];
1158 ret.append_indirect(
1159 name,
1160 CustomModule::Adapter(adapter_name),
1161 import,
1162 &required.funcs,
1163 adapter.info.metadata,
1164 &mut signatures,
1165 )
1166 .with_context(|| {
1167 format!("failed to register indirect shims for adapter {adapter_name}")
1168 })?;
1169 }
1170
1171 self.encode_resource_dtors(
1172 CustomModule::Adapter(adapter_name),
1173 &adapter.info.required_resource_funcs,
1174 &mut signatures,
1175 &mut ret,
1176 );
1177
1178 let funcs = match self.info.info.adapters_required.get(adapter_name) {
1179 Some(funcs) => funcs,
1180 None => continue,
1181 };
1182 for (func, ty) in funcs {
1183 let name = ret.list.len().to_string();
1184 log::debug!("shim {name} is adapter `{adapter_name}::{func}`");
1185 signatures.push(WasmSignature {
1186 params: ty.params().iter().map(to_wasm_type).collect(),
1187 results: ty.results().iter().map(to_wasm_type).collect(),
1188 indirect_params: false,
1189 retptr: false,
1190 });
1191 ret.list.push(Shim {
1192 name,
1193 debug_name: format!("adapt-{adapter_name}-{func}"),
1194 options: RequiredOptions::MEMORY,
1198 kind: ShimKind::Adapter {
1199 adapter: adapter_name,
1200 func,
1201 },
1202 });
1203 }
1204 }
1205
1206 self.encode_resource_dtors(
1207 CustomModule::Main,
1208 &self.info.info.required_resource_funcs,
1209 &mut signatures,
1210 &mut ret,
1211 );
1212
1213 if ret.list.is_empty() {
1214 return Ok(ret);
1215 }
1216
1217 for shim in ret.list.iter() {
1218 let prev = ret.shim_names.insert(shim.kind.clone(), shim.name.clone());
1219 assert!(prev.is_none());
1220 }
1221
1222 assert!(self.shim_instance_index.is_none());
1223 assert!(self.fixups_module_index.is_none());
1224
1225 let mut types = TypeSection::new();
1234 let mut tables = TableSection::new();
1235 let mut functions = FunctionSection::new();
1236 let mut exports = ExportSection::new();
1237 let mut code = CodeSection::new();
1238 let mut sigs = IndexMap::new();
1239 let mut imports_section = ImportSection::new();
1240 let mut elements = ElementSection::new();
1241 let mut func_indexes = Vec::new();
1242 let mut func_names = NameMap::new();
1243
1244 for (i, (sig, shim)) in signatures.iter().zip(&ret.list).enumerate() {
1245 let i = i as u32;
1246 let type_index = *sigs.entry(sig).or_insert_with(|| {
1247 let index = types.len();
1248 types.function(
1249 sig.params.iter().map(to_val_type),
1250 sig.results.iter().map(to_val_type),
1251 );
1252 index
1253 });
1254
1255 functions.function(type_index);
1256 Self::encode_shim_function(type_index, i, &mut code, sig.params.len() as u32);
1257 exports.export(&shim.name, ExportKind::Func, i);
1258
1259 imports_section.import("", &shim.name, EntityType::Function(type_index));
1260 func_indexes.push(i);
1261 func_names.append(i, &shim.debug_name);
1262 }
1263 let mut names = NameSection::new();
1264 names.module("wit-component:shim");
1265 names.functions(&func_names);
1266
1267 let table_type = TableType {
1268 element_type: RefType::FUNCREF,
1269 minimum: signatures.len() as u32,
1270 maximum: Some(signatures.len() as u32),
1271 };
1272
1273 tables.table(table_type);
1274
1275 exports.export(INDIRECT_TABLE_NAME, ExportKind::Table, 0);
1276 imports_section.import("", INDIRECT_TABLE_NAME, table_type);
1277
1278 elements.active(
1279 None,
1280 &ConstExpr::i32_const(0),
1281 Elements::Functions(&func_indexes),
1282 );
1283
1284 let mut shim = Module::new();
1285 shim.section(&types);
1286 shim.section(&functions);
1287 shim.section(&tables);
1288 shim.section(&exports);
1289 shim.section(&code);
1290 shim.section(&RawCustomSection(
1291 &crate::base_producers().raw_custom_section(),
1292 ));
1293 shim.section(&names);
1294
1295 let mut fixups = Module::default();
1296 fixups.section(&types);
1297 fixups.section(&imports_section);
1298 fixups.section(&elements);
1299 fixups.section(&RawCustomSection(
1300 &crate::base_producers().raw_custom_section(),
1301 ));
1302
1303 let mut names = NameSection::new();
1304 names.module("wit-component:fixups");
1305 fixups.section(&names);
1306
1307 let shim_module_index = self.component.core_module(&shim);
1308 self.fixups_module_index = Some(self.component.core_module(&fixups));
1309 self.shim_instance_index = Some(self.component.core_instantiate(shim_module_index, []));
1310
1311 return Ok(ret);
1312
1313 fn to_wasm_type(ty: &wasmparser::ValType) -> WasmType {
1314 match ty {
1315 wasmparser::ValType::I32 => WasmType::I32,
1316 wasmparser::ValType::I64 => WasmType::I64,
1317 wasmparser::ValType::F32 => WasmType::F32,
1318 wasmparser::ValType::F64 => WasmType::F64,
1319 _ => unreachable!(),
1320 }
1321 }
1322 }
1323
1324 fn encode_shim_function(
1325 type_index: u32,
1326 func_index: u32,
1327 code: &mut CodeSection,
1328 param_count: u32,
1329 ) {
1330 let mut func = wasm_encoder::Function::new(std::iter::empty());
1331 for i in 0..param_count {
1332 func.instruction(&Instruction::LocalGet(i));
1333 }
1334 func.instruction(&Instruction::I32Const(func_index as i32));
1335 func.instruction(&Instruction::CallIndirect {
1336 ty: type_index,
1337 table: 0,
1338 });
1339 func.instruction(&Instruction::End);
1340 code.function(&func);
1341 }
1342
1343 fn encode_indirect_lowerings(&mut self, shims: &Shims<'_>) -> Result<()> {
1344 if shims.list.is_empty() {
1345 return Ok(());
1346 }
1347
1348 let shim_instance_index = self
1349 .shim_instance_index
1350 .expect("must have an instantiated shim");
1351
1352 let table_index = self.component.core_alias_export(
1353 shim_instance_index,
1354 INDIRECT_TABLE_NAME,
1355 ExportKind::Table,
1356 );
1357
1358 let mut exports = Vec::new();
1359 exports.push((INDIRECT_TABLE_NAME, ExportKind::Table, table_index));
1360
1361 for shim in shims.list.iter() {
1362 let core_func_index = match &shim.kind {
1363 ShimKind::IndirectLowering {
1370 interface,
1371 index,
1372 realloc,
1373 encoding,
1374 } => {
1375 let interface = &self.info.import_map[interface];
1376 let (name, _) = interface.lowerings.get_index(*index).unwrap();
1377 let func_index = match &interface.interface {
1378 Some(interface_id) => {
1379 let instance_index = self.imported_instances[interface_id];
1380 self.component.alias_export(
1381 instance_index,
1382 name,
1383 ComponentExportKind::Func,
1384 )
1385 }
1386 None => self.imported_funcs[name],
1387 };
1388
1389 let realloc = match realloc {
1390 CustomModule::Main => self.realloc_index,
1391 CustomModule::Adapter(name) => self.adapter_import_reallocs[name],
1392 };
1393
1394 self.component.lower_func(
1395 func_index,
1396 shim.options
1397 .into_iter(*encoding, self.memory_index, realloc)?,
1398 )
1399 }
1400
1401 ShimKind::Adapter { adapter, func } => self.component.core_alias_export(
1406 self.adapter_instances[adapter],
1407 func,
1408 ExportKind::Func,
1409 ),
1410
1411 ShimKind::ResourceDtor {
1416 module,
1417 import,
1418 resource,
1419 } => {
1420 let funcs = match module {
1421 CustomModule::Main => &self.info.info.required_resource_funcs,
1422 CustomModule::Adapter(name) => {
1423 &self.info.adapters[name].info.required_resource_funcs
1424 }
1425 };
1426
1427 self.component.core_alias_export(
1428 self.instance_index.unwrap(),
1429 funcs[*import][*resource].dtor_export.as_deref().unwrap(),
1430 ExportKind::Func,
1431 )
1432 }
1433 };
1434
1435 exports.push((shim.name.as_str(), ExportKind::Func, core_func_index));
1436 }
1437
1438 let instance_index = self.component.core_instantiate_exports(exports);
1439 self.component.core_instantiate(
1440 self.fixups_module_index.expect("must have fixup module"),
1441 [("", ModuleArg::Instance(instance_index))],
1442 );
1443 Ok(())
1444 }
1445
1446 fn instantiate_core_module<'b, A>(&mut self, args: A, info: &ValidatedModule<'_>)
1447 where
1448 A: IntoIterator<Item = (&'b str, ModuleArg)>,
1449 A::IntoIter: ExactSizeIterator,
1450 {
1451 assert!(self.instance_index.is_none());
1452
1453 let instance_index = self
1454 .component
1455 .core_instantiate(self.module_index.expect("core module encoded"), args);
1456
1457 if info.has_memory {
1458 self.memory_index = Some(self.component.core_alias_export(
1459 instance_index,
1460 "memory",
1461 ExportKind::Memory,
1462 ));
1463 }
1464
1465 if let Some(name) = &info.realloc {
1466 self.realloc_index = Some(self.component.core_alias_export(
1467 instance_index,
1468 name,
1469 ExportKind::Func,
1470 ));
1471 }
1472
1473 self.instance_index = Some(instance_index);
1474 }
1475
1476 fn encode_resource_dtors<'b>(
1477 &mut self,
1478 module: CustomModule<'b>,
1479 funcs: &'b IndexMap<String, IndexMap<String, ResourceInfo>>,
1480 signatures: &mut Vec<WasmSignature>,
1481 shims: &mut Shims<'b>,
1482 ) {
1483 for (import, info) in funcs.iter() {
1489 for (resource, info) in info {
1490 if info.dtor_export.is_none() {
1491 continue;
1492 }
1493 signatures.push(WasmSignature {
1494 params: vec![WasmType::I32],
1495 results: Vec::new(),
1496 indirect_params: false,
1497 retptr: false,
1498 });
1499 let name = shims.list.len().to_string();
1500 shims.list.push(Shim {
1501 name,
1502 debug_name: format!("dtor-{import}-{resource}"),
1503 options: RequiredOptions::empty(),
1504 kind: ShimKind::ResourceDtor {
1505 module,
1506 import,
1507 resource,
1508 },
1509 });
1510 }
1511 }
1512 }
1513
1514 fn add_resource_funcs<'b>(
1515 &mut self,
1516 module: CustomModule<'b>,
1517 funcs: &'b IndexMap<String, IndexMap<String, ResourceInfo>>,
1518 shims: &Shims,
1519 args: &mut Vec<(&'b str, ModuleArg)>,
1520 ) {
1521 for (import, info) in funcs {
1522 let mut exports = Vec::new();
1523 for (resource, info) in info {
1524 let dtor = info.dtor_export.as_deref().map(|_| {
1530 self.component.core_alias_export(
1531 self.shim_instance_index.unwrap(),
1532 &shims.shim_names[&ShimKind::ResourceDtor {
1533 module,
1534 import,
1535 resource,
1536 }],
1537 ExportKind::Func,
1538 )
1539 });
1540 let resource_idx = self.component.type_resource(ValType::I32, dtor);
1541 let prev = self.export_type_map.insert(info.id, resource_idx);
1542 assert!(prev.is_none());
1543
1544 if let Some(name) = info.drop_import.as_deref() {
1545 let index = self.component.resource_drop(resource_idx);
1546 exports.push((name, ExportKind::Func, index));
1547 }
1548 if let Some(name) = info.rep_import.as_deref() {
1549 let index = self.component.resource_rep(resource_idx);
1550 exports.push((name, ExportKind::Func, index));
1551 }
1552 if let Some(name) = info.new_import.as_deref() {
1553 let index = self.component.resource_new(resource_idx);
1554 exports.push((name, ExportKind::Func, index));
1555 }
1556 }
1557 if !exports.is_empty() {
1558 let index = self.component.core_instantiate_exports(exports);
1559 args.push((import.as_str(), ModuleArg::Instance(index)));
1560 }
1561 }
1562 }
1563
1564 fn instantiate_adapter_module(
1567 &mut self,
1568 shims: &Shims<'_>,
1569 name: &'a str,
1570 adapter: &WorldAdapter,
1571 ) {
1572 let mut args = Vec::new();
1573
1574 let mut core_exports = Vec::new();
1575 for export_name in adapter.info.needs_core_exports.iter() {
1576 let mut core_export_name = export_name.as_str();
1577 if export_name == "cabi_realloc" {
1580 if let Some(adapter_realloc) = self.info.info.adapter_realloc {
1581 core_export_name = adapter_realloc;
1582 }
1583 }
1584 let index = self.component.core_alias_export(
1585 self.instance_index
1586 .expect("adaptee index set at this point"),
1587 core_export_name,
1588 ExportKind::Func,
1589 );
1590 core_exports.push((export_name.as_str(), ExportKind::Func, index));
1591 }
1592 if !core_exports.is_empty() {
1593 let instance = self.component.core_instantiate_exports(core_exports);
1594 args.push((MAIN_MODULE_IMPORT_NAME, ModuleArg::Instance(instance)));
1595 }
1596 if let Some(library_info) = adapter.library_info {
1600 for (import_name, instance) in &library_info.arguments {
1601 let resolve = |which: &_| match which {
1602 MainOrAdapter::Main => self.instance_index.unwrap(),
1603 MainOrAdapter::Adapter(adapter_name) => *self
1604 .adapter_instances
1605 .get(adapter_name.as_str())
1606 .unwrap_or_else(|| {
1607 panic!(
1608 "adapter {name} needs {adapter_name}, \
1609 which has not yet been instantiated"
1610 )
1611 }),
1612 };
1613
1614 args.push((
1615 import_name,
1616 ModuleArg::Instance(match instance {
1617 Instance::MainOrAdapter(which) => resolve(which),
1618 Instance::Items(items) => {
1619 let exports = items
1620 .iter()
1621 .map(|item| {
1622 (
1623 item.alias.as_str(),
1624 item.kind,
1625 self.component.core_alias_export(
1626 resolve(&item.which),
1627 &item.name,
1628 item.kind,
1629 ),
1630 )
1631 })
1632 .collect::<Vec<_>>();
1633 self.component.core_instantiate_exports(exports)
1634 }
1635 }),
1636 ));
1637 }
1638 } else {
1639 if let Some((module, name)) = &adapter.info.needs_memory {
1644 for (import_name, _) in adapter.info.required_imports.iter() {
1645 assert!(module != import_name);
1646 }
1647 assert!(module != name);
1648 let memory = self.memory_index.unwrap();
1649 let instance = self.component.core_instantiate_exports([(
1650 name.as_str(),
1651 ExportKind::Memory,
1652 memory,
1653 )]);
1654 args.push((module.as_str(), ModuleArg::Instance(instance)));
1655 }
1656 }
1657 for (import_name, _) in adapter.info.required_imports.iter() {
1658 let instance = self.import_instance_to_lowered_core_instance(
1659 CustomModule::Adapter(name),
1660 import_name,
1661 shims,
1662 adapter.info.metadata,
1663 );
1664 args.push((import_name, ModuleArg::Instance(instance)));
1665 }
1666
1667 self.add_resource_funcs(
1668 CustomModule::Adapter(name),
1669 &adapter.info.required_resource_funcs,
1670 shims,
1671 &mut args,
1672 );
1673
1674 let instance = self
1675 .component
1676 .core_instantiate(self.adapter_modules[name], args);
1677 self.adapter_instances.insert(name, instance);
1678
1679 let realloc = adapter.info.export_realloc.as_ref().map(|name| {
1680 self.component
1681 .core_alias_export(instance, name, ExportKind::Func)
1682 });
1683 self.adapter_export_reallocs.insert(name, realloc);
1684 let realloc = adapter.info.import_realloc.as_ref().map(|name| {
1685 self.component
1686 .core_alias_export(instance, name, ExportKind::Func)
1687 });
1688 self.adapter_import_reallocs.insert(name, realloc);
1689 }
1690}
1691
1692#[derive(Default)]
1710struct Shims<'a> {
1711 list: Vec<Shim<'a>>,
1713
1714 shim_names: IndexMap<ShimKind<'a>, String>,
1716}
1717
1718struct Shim<'a> {
1719 options: RequiredOptions,
1722
1723 name: String,
1727
1728 debug_name: String,
1731
1732 kind: ShimKind<'a>,
1734}
1735
1736#[derive(Debug, Clone, Hash, Eq, PartialEq)]
1737enum ShimKind<'a> {
1738 IndirectLowering {
1742 interface: Option<String>,
1744 index: usize,
1746 realloc: CustomModule<'a>,
1748 encoding: StringEncoding,
1750 },
1751 Adapter {
1754 adapter: &'a str,
1756 func: &'a str,
1758 },
1759 ResourceDtor {
1762 module: CustomModule<'a>,
1764 import: &'a str,
1766 resource: &'a str,
1768 },
1769}
1770
1771#[derive(Debug, Copy, Clone, Hash, Eq, PartialEq)]
1781enum CustomModule<'a> {
1782 Main,
1785 Adapter(&'a str),
1788}
1789
1790impl<'a> Shims<'a> {
1791 fn append_indirect(
1794 &mut self,
1795 core_wasm_module: &'a str,
1796 for_module: CustomModule<'a>,
1797 import: &ImportedInterface,
1798 required: &IndexSet<String>,
1799 metadata: &ModuleMetadata,
1800 sigs: &mut Vec<WasmSignature>,
1801 ) -> Result<()> {
1802 let interface = if core_wasm_module == BARE_FUNC_MODULE_NAME {
1803 None
1804 } else {
1805 Some(core_wasm_module.to_string())
1806 };
1807 for (index, (name, lowering)) in import.lowerings.iter().enumerate() {
1808 if !required.contains(name.as_str()) {
1809 continue;
1810 }
1811 let shim_name = self.list.len().to_string();
1812 log::debug!(
1813 "shim {shim_name} is import `{core_wasm_module}` lowering {index} `{name}`",
1814 );
1815 match lowering {
1816 Lowering::Direct | Lowering::ResourceDrop(_) => {}
1817
1818 Lowering::Indirect { sig, options } => {
1819 sigs.push(sig.clone());
1820 let encoding = *metadata
1821 .import_encodings
1822 .get(&(core_wasm_module.to_string(), name.clone()))
1823 .ok_or_else(|| {
1824 anyhow::anyhow!(
1825 "missing component metadata for import of \
1826 `{core_wasm_module}::{name}`"
1827 )
1828 })?;
1829 self.list.push(Shim {
1830 name: shim_name,
1831 debug_name: format!("indirect-{core_wasm_module}-{name}"),
1832 options: *options,
1833 kind: ShimKind::IndirectLowering {
1834 interface: interface.clone(),
1835 index,
1836 realloc: for_module,
1837 encoding,
1838 },
1839 });
1840 }
1841 }
1842 }
1843 Ok(())
1844 }
1845}
1846
1847#[derive(Clone)]
1849pub struct Item {
1850 pub alias: String,
1851 pub kind: ExportKind,
1852 pub which: MainOrAdapter,
1853 pub name: String,
1854}
1855
1856#[derive(Clone)]
1858pub enum MainOrAdapter {
1859 Main,
1860 Adapter(String),
1861}
1862
1863#[derive(Clone)]
1865pub enum Instance {
1866 MainOrAdapter(MainOrAdapter),
1868
1869 Items(Vec<Item>),
1871}
1872
1873#[derive(Clone)]
1876pub struct LibraryInfo {
1877 pub instantiate_after_shims: bool,
1879
1880 pub arguments: Vec<(String, Instance)>,
1882}
1883
1884struct Adapter {
1886 wasm: Vec<u8>,
1888
1889 metadata: ModuleMetadata,
1891
1892 required_exports: IndexSet<WorldKey>,
1895
1896 library_info: Option<LibraryInfo>,
1901}
1902
1903#[derive(Default)]
1905pub struct ComponentEncoder {
1906 module: Vec<u8>,
1907 metadata: Bindgen,
1908 validate: bool,
1909 main_module_exports: IndexSet<WorldKey>,
1910 adapters: IndexMap<String, Adapter>,
1911 import_name_map: HashMap<String, String>,
1912 realloc_via_memory_grow: bool,
1913}
1914
1915impl ComponentEncoder {
1916 pub fn module(mut self, module: &[u8]) -> Result<Self> {
1922 let (wasm, metadata) = metadata::decode(module)?;
1923 let world = self
1924 .metadata
1925 .merge(metadata)
1926 .context("failed merge WIT metadata for module with previous metadata")?;
1927 self.main_module_exports
1928 .extend(self.metadata.resolve.worlds[world].exports.keys().cloned());
1929 self.module = if let Some(producers) = &self.metadata.producers {
1930 producers.add_to_wasm(&wasm)?
1931 } else {
1932 wasm
1933 };
1934 Ok(self)
1935 }
1936
1937 pub fn validate(mut self, validate: bool) -> Self {
1939 self.validate = validate;
1940 self
1941 }
1942
1943 pub fn adapter(self, name: &str, bytes: &[u8]) -> Result<Self> {
1961 self.library_or_adapter(name, bytes, None)
1962 }
1963
1964 pub fn library(self, name: &str, bytes: &[u8], library_info: LibraryInfo) -> Result<Self> {
1977 self.library_or_adapter(name, bytes, Some(library_info))
1978 }
1979
1980 fn library_or_adapter(
1981 mut self,
1982 name: &str,
1983 bytes: &[u8],
1984 library_info: Option<LibraryInfo>,
1985 ) -> Result<Self> {
1986 let (wasm, metadata) = metadata::decode(bytes)?;
1987 let world = self
1997 .metadata
1998 .resolve
1999 .merge(metadata.resolve)
2000 .with_context(|| {
2001 format!("failed to merge WIT packages of adapter `{name}` into main packages")
2002 })?
2003 .worlds[metadata.world.index()];
2004 self.metadata
2005 .resolve
2006 .merge_worlds(world, self.metadata.world)
2007 .with_context(|| {
2008 format!("failed to merge WIT world of adapter `{name}` into main package")
2009 })?;
2010 let exports = self.metadata.resolve.worlds[world]
2011 .exports
2012 .keys()
2013 .cloned()
2014 .collect();
2015 if let Some(library_info) = &library_info {
2016 for (_, instance) in &library_info.arguments {
2018 let resolve = |which: &_| match which {
2019 MainOrAdapter::Main => Ok(()),
2020 MainOrAdapter::Adapter(name) => {
2021 if self.adapters.contains_key(name.as_str()) {
2022 Ok(())
2023 } else {
2024 Err(anyhow!("instance refers to unknown adapter `{name}`"))
2025 }
2026 }
2027 };
2028
2029 match instance {
2030 Instance::MainOrAdapter(which) => resolve(which)?,
2031 Instance::Items(items) => {
2032 for item in items {
2033 resolve(&item.which)?;
2034 }
2035 }
2036 }
2037 }
2038 }
2039 self.adapters.insert(
2040 name.to_string(),
2041 Adapter {
2042 wasm,
2043 metadata: metadata.metadata,
2044 required_exports: exports,
2045 library_info,
2046 },
2047 );
2048 Ok(self)
2049 }
2050
2051 pub fn realloc_via_memory_grow(mut self, value: bool) -> Self {
2056 self.realloc_via_memory_grow = value;
2057 self
2058 }
2059
2060 pub fn import_name_map(mut self, map: HashMap<String, String>) -> Self {
2071 self.import_name_map = map;
2072 self
2073 }
2074
2075 pub fn encode(&self) -> Result<Vec<u8>> {
2077 if self.module.is_empty() {
2078 bail!("a module is required when encoding a component");
2079 }
2080
2081 let world = ComponentWorld::new(self).context("failed to decode world from module")?;
2082 let mut state = EncodingState {
2083 component: ComponentBuilder::default(),
2084 module_index: None,
2085 instance_index: None,
2086 memory_index: None,
2087 realloc_index: None,
2088 shim_instance_index: None,
2089 fixups_module_index: None,
2090 adapter_modules: IndexMap::new(),
2091 adapter_instances: IndexMap::new(),
2092 adapter_import_reallocs: IndexMap::new(),
2093 adapter_export_reallocs: IndexMap::new(),
2094 import_type_map: HashMap::new(),
2095 import_func_type_map: HashMap::new(),
2096 export_type_map: HashMap::new(),
2097 export_func_type_map: HashMap::new(),
2098 imported_instances: Default::default(),
2099 imported_funcs: Default::default(),
2100 exported_instances: Default::default(),
2101 info: &world,
2102 };
2103 state.encode_imports(&self.import_name_map)?;
2104 state.encode_core_modules();
2105 state.encode_core_instantiation()?;
2106 state.encode_exports(CustomModule::Main)?;
2107 for name in self.adapters.keys() {
2108 state.encode_exports(CustomModule::Adapter(name))?;
2109 }
2110 state
2111 .component
2112 .raw_custom_section(&crate::base_producers().raw_custom_section());
2113 let bytes = state.component.finish();
2114
2115 if self.validate {
2116 let mut validator = Validator::new_with_features(
2117 WasmFeatures::default() | WasmFeatures::COMPONENT_MODEL,
2118 );
2119
2120 validator
2121 .validate_all(&bytes)
2122 .context("failed to validate component output")?;
2123 }
2124
2125 Ok(bytes)
2126 }
2127}
2128
2129#[cfg(all(test, feature = "dummy-module"))]
2130mod test {
2131 use crate::{dummy_module, embed_component_metadata};
2132
2133 use super::*;
2134 use std::path::Path;
2135 use wit_parser::UnresolvedPackage;
2136
2137 #[test]
2138 fn it_renames_imports() {
2139 let mut resolve = Resolve::new();
2140 let pkg = resolve
2141 .push(
2142 UnresolvedPackage::parse(
2143 Path::new("test.wit"),
2144 r#"
2145package test:wit;
2146
2147interface i {
2148 f: func();
2149}
2150
2151world test {
2152 import i;
2153 import foo: interface {
2154 f: func();
2155 }
2156}
2157"#,
2158 )
2159 .unwrap(),
2160 )
2161 .unwrap();
2162
2163 let world = resolve.select_world(pkg, None).unwrap();
2164
2165 let mut module = dummy_module(&resolve, world);
2166
2167 embed_component_metadata(&mut module, &resolve, world, StringEncoding::UTF8).unwrap();
2168
2169 let encoded = ComponentEncoder::default()
2170 .import_name_map(HashMap::from([
2171 (
2172 "foo".to_string(),
2173 "unlocked-dep=<foo:bar/foo@{>=1.0.0 <1.1.0}>".to_string(),
2174 ),
2175 (
2176 "test:wit/i".to_string(),
2177 "locked-dep=<foo:bar/i@1.2.3>".to_string(),
2178 ),
2179 ]))
2180 .module(&module)
2181 .unwrap()
2182 .validate(true)
2183 .encode()
2184 .unwrap();
2185
2186 let wat = wasmprinter::print_bytes(encoded).unwrap();
2187 assert!(wat.contains("unlocked-dep=<foo:bar/foo@{>=1.0.0 <1.1.0}>"));
2188 assert!(wat.contains("locked-dep=<foo:bar/i@1.2.3>"));
2189 }
2190}