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::Type(t) => Self::for_type(resolve, t),
324 TypeDefKind::Future(_) => Self::empty(),
325 TypeDefKind::Stream(_) => Self::empty(),
326 TypeDefKind::Unknown => unreachable!(),
327 },
328 Type::String => Self::STRING,
329 _ => Self::empty(),
330 }
331 }
332}
333
334pub struct EncodingState<'a> {
336 component: ComponentBuilder,
338 module_index: Option<u32>,
342 instance_index: Option<u32>,
346 memory_index: Option<u32>,
350 shim_instance_index: Option<u32>,
354 fixups_module_index: Option<u32>,
358
359 adapter_modules: IndexMap<&'a str, u32>,
362 adapter_instances: IndexMap<&'a str, 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 aliased_core_items: HashMap<(u32, String), u32>,
385
386 info: &'a ComponentWorld<'a>,
388}
389
390impl<'a> EncodingState<'a> {
391 fn encode_core_modules(&mut self) {
392 assert!(self.module_index.is_none());
393 let idx = self.component.core_module_raw(&self.info.encoder.module);
394 self.module_index = Some(idx);
395
396 for (name, adapter) in self.info.adapters.iter() {
397 let mut add_meta = wasm_metadata::AddMetadata::default();
398 add_meta.name = Some(if adapter.library_info.is_some() {
399 name.to_string()
400 } else {
401 format!("wit-component:adapter:{name}")
402 });
403 let wasm = add_meta
404 .to_wasm(&adapter.wasm)
405 .expect("core wasm can get name added");
406 let idx = self.component.core_module_raw(&wasm);
407 let prev = self.adapter_modules.insert(name, idx);
408 assert!(prev.is_none());
409 }
410 }
411
412 fn root_import_type_encoder(
413 &mut self,
414 interface: Option<InterfaceId>,
415 ) -> RootTypeEncoder<'_, 'a> {
416 RootTypeEncoder {
417 state: self,
418 interface,
419 import_types: true,
420 }
421 }
422
423 fn root_export_type_encoder(
424 &mut self,
425 interface: Option<InterfaceId>,
426 ) -> RootTypeEncoder<'_, 'a> {
427 RootTypeEncoder {
428 state: self,
429 interface,
430 import_types: false,
431 }
432 }
433
434 fn instance_type_encoder(&mut self, interface: InterfaceId) -> InstanceTypeEncoder<'_, 'a> {
435 InstanceTypeEncoder {
436 state: self,
437 interface,
438 type_map: Default::default(),
439 func_type_map: Default::default(),
440 ty: Default::default(),
441 }
442 }
443
444 fn encode_imports(&mut self, name_map: &HashMap<String, String>) -> Result<()> {
445 let mut has_funcs = false;
446 for (name, info) in self.info.import_map.iter() {
447 match name {
448 Some(name) => {
449 self.encode_interface_import(name_map.get(name).unwrap_or(name), info)?
450 }
451 None => has_funcs = true,
452 }
453 }
454
455 let resolve = &self.info.encoder.metadata.resolve;
456 let world = &resolve.worlds[self.info.encoder.metadata.world];
457
458 for (_name, item) in world.imports.iter() {
461 if let WorldItem::Type(ty) = item {
462 self.root_import_type_encoder(None)
463 .encode_valtype(resolve, &Type::Id(*ty))?;
464 }
465 }
466
467 if has_funcs {
468 let info = &self.info.import_map[&None];
469 self.encode_root_import_funcs(info)?;
470 }
471 Ok(())
472 }
473
474 fn encode_interface_import(&mut self, name: &str, info: &ImportedInterface) -> Result<()> {
475 let resolve = &self.info.encoder.metadata.resolve;
476 let interface_id = info.interface.as_ref().unwrap();
477 let interface_id = *interface_id;
478 let interface = &resolve.interfaces[interface_id];
479 log::trace!("encoding imports for `{name}` as {:?}", interface_id);
480 let mut encoder = self.instance_type_encoder(interface_id);
481
482 if let Some(live) = encoder.state.info.live_type_imports.get(&interface_id) {
484 for ty in live {
485 log::trace!(
486 "encoding extra type {ty:?} name={:?}",
487 resolve.types[*ty].name
488 );
489 encoder.encode_valtype(resolve, &Type::Id(*ty))?;
490 }
491 }
492
493 for (_, func) in interface.functions.iter() {
496 if !(info
497 .lowerings
498 .contains_key(&(func.name.clone(), AbiVariant::GuestImport))
499 || info
500 .lowerings
501 .contains_key(&(func.name.clone(), AbiVariant::GuestImportAsync)))
502 {
503 continue;
504 }
505 log::trace!("encoding function type for `{}`", func.name);
506 let idx = encoder.encode_func_type(resolve, func)?;
507
508 encoder.ty.export(&func.name, ComponentTypeRef::Func(idx));
509 }
510
511 let ty = encoder.ty;
512 if ty.is_empty() {
515 return Ok(());
516 }
517 let instance_type_idx = self.component.type_instance(&ty);
518 let instance_idx = self
519 .component
520 .import(name, ComponentTypeRef::Instance(instance_type_idx));
521 let prev = self.imported_instances.insert(interface_id, instance_idx);
522 assert!(prev.is_none());
523 Ok(())
524 }
525
526 fn encode_root_import_funcs(&mut self, info: &ImportedInterface) -> Result<()> {
527 let resolve = &self.info.encoder.metadata.resolve;
528 let world = self.info.encoder.metadata.world;
529 for (name, item) in resolve.worlds[world].imports.iter() {
530 let func = match item {
531 WorldItem::Function(f) => f,
532 WorldItem::Interface { .. } | WorldItem::Type(_) => continue,
533 };
534 let name = resolve.name_world_key(name);
535 if !(info
536 .lowerings
537 .contains_key(&(name.clone(), AbiVariant::GuestImport))
538 || info
539 .lowerings
540 .contains_key(&(name.clone(), AbiVariant::GuestImportAsync)))
541 {
542 continue;
543 }
544 log::trace!("encoding function type for `{}`", func.name);
545 let idx = self
546 .root_import_type_encoder(None)
547 .encode_func_type(resolve, func)?;
548 let func_idx = self.component.import(&name, ComponentTypeRef::Func(idx));
549 let prev = self.imported_funcs.insert(name, func_idx);
550 assert!(prev.is_none());
551 }
552 Ok(())
553 }
554
555 fn alias_imported_type(&mut self, interface: InterfaceId, id: TypeId) -> u32 {
556 let ty = &self.info.encoder.metadata.resolve.types[id];
557 let name = ty.name.as_ref().expect("type must have a name");
558 let instance = self.imported_instances[&interface];
559 self.component
560 .alias_export(instance, name, ComponentExportKind::Type)
561 }
562
563 fn alias_exported_type(&mut self, interface: InterfaceId, id: TypeId) -> u32 {
564 let ty = &self.info.encoder.metadata.resolve.types[id];
565 let name = ty.name.as_ref().expect("type must have a name");
566 let instance = self.exported_instances[&interface];
567 self.component
568 .alias_export(instance, name, ComponentExportKind::Type)
569 }
570
571 fn encode_core_instantiation(&mut self) -> Result<()> {
572 let shims = self.encode_shim_instantiation()?;
574
575 self.declare_types_for_imported_intrinsics(&shims)?;
579
580 self.instantiate_main_module(&shims)?;
584
585 let (before, after) = self
588 .info
589 .adapters
590 .iter()
591 .partition::<Vec<_>, _>(|(_, adapter)| {
592 !matches!(
593 adapter.library_info,
594 Some(LibraryInfo {
595 instantiate_after_shims: true,
596 ..
597 })
598 )
599 });
600
601 for (name, _adapter) in before {
602 self.instantiate_adapter_module(&shims, name)?;
603 }
604
605 self.encode_indirect_lowerings(&shims)?;
608
609 for (name, _adapter) in after {
610 self.instantiate_adapter_module(&shims, name)?;
611 }
612
613 self.encode_initialize_with_start()?;
614
615 Ok(())
616 }
617
618 fn lookup_resource_index(&mut self, id: TypeId) -> u32 {
619 let resolve = &self.info.encoder.metadata.resolve;
620 let ty = &resolve.types[id];
621 match ty.owner {
622 TypeOwner::World(_) => self.import_type_map[&id],
626 TypeOwner::Interface(i) => {
627 let instance = self.imported_instances[&i];
628 let name = ty.name.as_ref().expect("resources must be named");
629 self.component
630 .alias_export(instance, name, ComponentExportKind::Type)
631 }
632 TypeOwner::None => panic!("resources must have an owner"),
633 }
634 }
635
636 fn encode_exports(&mut self, module: CustomModule) -> Result<()> {
637 let resolve = &self.info.encoder.metadata.resolve;
638 let exports = match module {
639 CustomModule::Main => &self.info.encoder.main_module_exports,
640 CustomModule::Adapter(name) => &self.info.encoder.adapters[name].required_exports,
641 };
642
643 if exports.is_empty() {
644 return Ok(());
645 }
646
647 let mut interface_func_core_names = IndexMap::new();
648 let mut world_func_core_names = IndexMap::new();
649 for (core_name, export) in self.info.exports_for(module).iter() {
650 match export {
651 Export::WorldFunc(_, name, _) => {
652 let prev = world_func_core_names.insert(name, core_name);
653 assert!(prev.is_none());
654 }
655 Export::InterfaceFunc(_, id, name, _) => {
656 let prev = interface_func_core_names
657 .entry(id)
658 .or_insert(IndexMap::new())
659 .insert(name.as_str(), core_name);
660 assert!(prev.is_none());
661 }
662 Export::WorldFuncCallback(..)
663 | Export::InterfaceFuncCallback(..)
664 | Export::WorldFuncPostReturn(..)
665 | Export::InterfaceFuncPostReturn(..)
666 | Export::ResourceDtor(..)
667 | Export::Memory
668 | Export::GeneralPurposeRealloc
669 | Export::GeneralPurposeExportRealloc
670 | Export::GeneralPurposeImportRealloc
671 | Export::Initialize
672 | Export::ReallocForAdapter => continue,
673 }
674 }
675
676 let world = &resolve.worlds[self.info.encoder.metadata.world];
677
678 for export_name in exports {
679 let export_string = resolve.name_world_key(export_name);
680 match &world.exports[export_name] {
681 WorldItem::Function(func) => {
682 let ty = self
683 .root_import_type_encoder(None)
684 .encode_func_type(resolve, func)?;
685 let core_name = world_func_core_names[&func.name];
686 let idx = self.encode_lift(module, &core_name, export_name, func, ty)?;
687 self.component
688 .export(&export_string, ComponentExportKind::Func, idx, None);
689 }
690 WorldItem::Interface { id, .. } => {
691 let core_names = interface_func_core_names.get(id);
692 self.encode_interface_export(
693 &export_string,
694 module,
695 export_name,
696 *id,
697 core_names,
698 )?;
699 }
700 WorldItem::Type(_) => unreachable!(),
701 }
702 }
703
704 Ok(())
705 }
706
707 fn encode_interface_export(
708 &mut self,
709 export_name: &str,
710 module: CustomModule<'_>,
711 key: &WorldKey,
712 export: InterfaceId,
713 interface_func_core_names: Option<&IndexMap<&str, &str>>,
714 ) -> Result<()> {
715 log::trace!("encode interface export `{export_name}`");
716 let resolve = &self.info.encoder.metadata.resolve;
717
718 let mut imports = Vec::new();
725 let mut root = self.root_export_type_encoder(Some(export));
726 for (_, func) in &resolve.interfaces[export].functions {
727 let core_name = interface_func_core_names.unwrap()[func.name.as_str()];
728 let ty = root.encode_func_type(resolve, func)?;
729 let func_index = root.state.encode_lift(module, &core_name, key, func, ty)?;
730 imports.push((
731 import_func_name(func),
732 ComponentExportKind::Func,
733 func_index,
734 ));
735 }
736
737 let mut nested = NestedComponentTypeEncoder {
741 component: ComponentBuilder::default(),
742 type_map: Default::default(),
743 func_type_map: Default::default(),
744 export_types: false,
745 interface: export,
746 state: self,
747 imports: IndexMap::new(),
748 };
749
750 let mut types_to_import = LiveTypes::default();
760 types_to_import.add_interface(resolve, export);
761 let exports_used = &nested.state.info.exports_used[&export];
762 for ty in types_to_import.iter() {
763 if let TypeOwner::Interface(owner) = resolve.types[ty].owner {
764 if owner == export {
765 continue;
768 }
769
770 let mut encoder = if exports_used.contains(&owner) {
773 nested.state.root_export_type_encoder(Some(export))
774 } else {
775 nested.state.root_import_type_encoder(Some(export))
776 };
777 encoder.encode_valtype(resolve, &Type::Id(ty))?;
778
779 nested.interface = owner;
783 nested.encode_valtype(resolve, &Type::Id(ty))?;
784 }
785 }
786 nested.interface = export;
787
788 let imported_types = nested.type_map.clone();
792
793 let mut resources = HashMap::new();
799 for (_name, ty) in resolve.interfaces[export].types.iter() {
800 if !matches!(resolve.types[*ty].kind, TypeDefKind::Resource) {
801 continue;
802 }
803 let idx = match nested.encode_valtype(resolve, &Type::Id(*ty))? {
804 ComponentValType::Type(idx) => idx,
805 _ => unreachable!(),
806 };
807 resources.insert(*ty, idx);
808 }
809
810 for (_, func) in resolve.interfaces[export].functions.iter() {
814 let ty = nested.encode_func_type(resolve, func)?;
815 nested
816 .component
817 .import(&import_func_name(func), ComponentTypeRef::Func(ty));
818 }
819
820 let reverse_map = nested
827 .type_map
828 .drain()
829 .map(|p| (p.1, p.0))
830 .collect::<HashMap<_, _>>();
831 for (name, idx) in nested.imports.drain(..) {
832 let id = reverse_map[&idx];
833 let owner = match resolve.types[id].owner {
834 TypeOwner::Interface(id) => id,
835 _ => unreachable!(),
836 };
837 let idx = if owner == export || exports_used.contains(&owner) {
838 log::trace!("consulting exports for {id:?}");
839 nested.state.export_type_map[&id]
840 } else {
841 log::trace!("consulting imports for {id:?}");
842 nested.state.import_type_map[&id]
843 };
844 imports.push((name, ComponentExportKind::Type, idx))
845 }
846
847 nested.type_map = imported_types;
852
853 nested.export_types = true;
860 nested.func_type_map.clear();
861
862 for (_, id) in resolve.interfaces[export].types.iter() {
868 let ty = &resolve.types[*id];
869 match ty.kind {
870 TypeDefKind::Resource => {
871 let idx = nested.component.export(
872 ty.name.as_ref().expect("resources must be named"),
873 ComponentExportKind::Type,
874 resources[id],
875 None,
876 );
877 nested.type_map.insert(*id, idx);
878 }
879 _ => {
880 nested.encode_valtype(resolve, &Type::Id(*id))?;
881 }
882 }
883 }
884
885 for (i, (_, func)) in resolve.interfaces[export].functions.iter().enumerate() {
886 let ty = nested.encode_func_type(resolve, func)?;
887 nested.component.export(
888 &func.name,
889 ComponentExportKind::Func,
890 i as u32,
891 Some(ComponentTypeRef::Func(ty)),
892 );
893 }
894
895 let component = nested.component;
899 let component_index = self.component.component(component);
900 let instance_index = self.component.instantiate(component_index, imports);
901 let idx = self.component.export(
902 export_name,
903 ComponentExportKind::Instance,
904 instance_index,
905 None,
906 );
907 let prev = self.exported_instances.insert(export, idx);
908 assert!(prev.is_none());
909
910 for (_name, id) in resolve.interfaces[export].types.iter() {
918 self.export_type_map.remove(id);
919 }
920
921 return Ok(());
922
923 struct NestedComponentTypeEncoder<'state, 'a> {
924 component: ComponentBuilder,
925 type_map: HashMap<TypeId, u32>,
926 func_type_map: HashMap<types::FunctionKey<'a>, u32>,
927 export_types: bool,
928 interface: InterfaceId,
929 state: &'state mut EncodingState<'a>,
930 imports: IndexMap<String, u32>,
931 }
932
933 impl<'a> ValtypeEncoder<'a> for NestedComponentTypeEncoder<'_, 'a> {
934 fn defined_type(&mut self) -> (u32, ComponentDefinedTypeEncoder<'_>) {
935 self.component.type_defined()
936 }
937 fn define_function_type(&mut self) -> (u32, ComponentFuncTypeEncoder<'_>) {
938 self.component.type_function()
939 }
940 fn export_type(&mut self, idx: u32, name: &'a str) -> Option<u32> {
941 if self.export_types {
942 Some(
943 self.component
944 .export(name, ComponentExportKind::Type, idx, None),
945 )
946 } else {
947 let name = self.unique_import_name(name);
948 let ret = self
949 .component
950 .import(&name, ComponentTypeRef::Type(TypeBounds::Eq(idx)));
951 self.imports.insert(name, ret);
952 Some(ret)
953 }
954 }
955 fn export_resource(&mut self, name: &'a str) -> u32 {
956 if self.export_types {
957 panic!("resources should already be exported")
958 } else {
959 let name = self.unique_import_name(name);
960 let ret = self
961 .component
962 .import(&name, ComponentTypeRef::Type(TypeBounds::SubResource));
963 self.imports.insert(name, ret);
964 ret
965 }
966 }
967 fn import_type(&mut self, _: InterfaceId, _id: TypeId) -> u32 {
968 unreachable!()
969 }
970 fn type_map(&mut self) -> &mut HashMap<TypeId, u32> {
971 &mut self.type_map
972 }
973 fn func_type_map(&mut self) -> &mut HashMap<types::FunctionKey<'a>, u32> {
974 &mut self.func_type_map
975 }
976 fn interface(&self) -> Option<InterfaceId> {
977 Some(self.interface)
978 }
979 }
980
981 impl NestedComponentTypeEncoder<'_, '_> {
982 fn unique_import_name(&mut self, name: &str) -> String {
983 let mut name = format!("import-type-{name}");
984 let mut n = 0;
985 while self.imports.contains_key(&name) {
986 name = format!("{name}{n}");
987 n += 1;
988 }
989 name
990 }
991 }
992
993 fn import_func_name(f: &Function) -> String {
994 match f.kind {
995 FunctionKind::Freestanding | FunctionKind::AsyncFreestanding => {
996 format!("import-func-{}", f.item_name())
997 }
998
999 FunctionKind::Method(_)
1007 | FunctionKind::AsyncMethod(_)
1008 | FunctionKind::Static(_)
1009 | FunctionKind::AsyncStatic(_)
1010 | FunctionKind::Constructor(_) => {
1011 format!(
1012 "import-{}",
1013 f.name.replace('[', "").replace([']', '.', ' '], "-")
1014 )
1015 }
1016 }
1017 }
1018 }
1019
1020 fn encode_lift(
1021 &mut self,
1022 module: CustomModule<'_>,
1023 core_name: &str,
1024 key: &WorldKey,
1025 func: &Function,
1026 ty: u32,
1027 ) -> Result<u32> {
1028 let resolve = &self.info.encoder.metadata.resolve;
1029 let metadata = self.info.module_metadata_for(module);
1030 let instance_index = self.instance_for(module);
1031 let core_func_index = self.core_alias_export(instance_index, core_name, ExportKind::Func);
1032 let exports = self.info.exports_for(module);
1033
1034 let options = RequiredOptions::for_export(
1035 resolve,
1036 func,
1037 exports
1038 .abi(key, func)
1039 .ok_or_else(|| anyhow!("no ABI found for {}", func.name))?,
1040 );
1041
1042 let encoding = metadata
1043 .export_encodings
1044 .get(resolve, key, &func.name)
1045 .unwrap();
1046 let exports = self.info.exports_for(module);
1047 let realloc_index = exports
1048 .export_realloc_for(key, &func.name)
1049 .map(|name| self.core_alias_export(instance_index, name, ExportKind::Func));
1050 let mut options = options
1051 .into_iter(encoding, self.memory_index, realloc_index)?
1052 .collect::<Vec<_>>();
1053
1054 if let Some(post_return) = exports.post_return(key, func) {
1055 let post_return = self.core_alias_export(instance_index, post_return, ExportKind::Func);
1056 options.push(CanonicalOption::PostReturn(post_return));
1057 }
1058 if let Some(callback) = exports.callback(key, func) {
1059 let callback = self.core_alias_export(instance_index, callback, ExportKind::Func);
1060 options.push(CanonicalOption::Callback(callback));
1061 }
1062 let func_index = self.component.lift_func(core_func_index, ty, options);
1063 Ok(func_index)
1064 }
1065
1066 fn encode_shim_instantiation(&mut self) -> Result<Shims<'a>> {
1067 let mut ret = Shims::default();
1068
1069 ret.append_indirect(self.info, CustomModule::Main)
1070 .context("failed to register indirect shims for main module")?;
1071
1072 for (adapter_name, _adapter) in self.info.adapters.iter() {
1076 ret.append_indirect(self.info, CustomModule::Adapter(adapter_name))
1077 .with_context(|| {
1078 format!("failed to register indirect shims for adapter {adapter_name}")
1079 })?;
1080 }
1081
1082 if ret.shims.is_empty() {
1083 return Ok(ret);
1084 }
1085
1086 assert!(self.shim_instance_index.is_none());
1087 assert!(self.fixups_module_index.is_none());
1088
1089 let mut types = TypeSection::new();
1098 let mut tables = TableSection::new();
1099 let mut functions = FunctionSection::new();
1100 let mut exports = ExportSection::new();
1101 let mut code = CodeSection::new();
1102 let mut sigs = IndexMap::new();
1103 let mut imports_section = ImportSection::new();
1104 let mut elements = ElementSection::new();
1105 let mut func_indexes = Vec::new();
1106 let mut func_names = NameMap::new();
1107
1108 for (i, shim) in ret.shims.values().enumerate() {
1109 let i = i as u32;
1110 let type_index = *sigs.entry(&shim.sig).or_insert_with(|| {
1111 let index = types.len();
1112 types.ty().function(
1113 shim.sig.params.iter().map(to_val_type),
1114 shim.sig.results.iter().map(to_val_type),
1115 );
1116 index
1117 });
1118
1119 functions.function(type_index);
1120 Self::encode_shim_function(type_index, i, &mut code, shim.sig.params.len() as u32);
1121 exports.export(&shim.name, ExportKind::Func, i);
1122
1123 imports_section.import("", &shim.name, EntityType::Function(type_index));
1124 func_indexes.push(i);
1125 func_names.append(i, &shim.debug_name);
1126 }
1127 let mut names = NameSection::new();
1128 names.module("wit-component:shim");
1129 names.functions(&func_names);
1130
1131 let table_type = TableType {
1132 element_type: RefType::FUNCREF,
1133 minimum: ret.shims.len() as u64,
1134 maximum: Some(ret.shims.len() as u64),
1135 table64: false,
1136 shared: false,
1137 };
1138
1139 tables.table(table_type);
1140
1141 exports.export(INDIRECT_TABLE_NAME, ExportKind::Table, 0);
1142 imports_section.import("", INDIRECT_TABLE_NAME, table_type);
1143
1144 elements.active(
1145 None,
1146 &ConstExpr::i32_const(0),
1147 Elements::Functions(func_indexes.into()),
1148 );
1149
1150 let mut shim = Module::new();
1151 shim.section(&types);
1152 shim.section(&functions);
1153 shim.section(&tables);
1154 shim.section(&exports);
1155 shim.section(&code);
1156 shim.section(&RawCustomSection(
1157 &crate::base_producers().raw_custom_section(),
1158 ));
1159 shim.section(&names);
1160
1161 let mut fixups = Module::default();
1162 fixups.section(&types);
1163 fixups.section(&imports_section);
1164 fixups.section(&elements);
1165 fixups.section(&RawCustomSection(
1166 &crate::base_producers().raw_custom_section(),
1167 ));
1168
1169 let mut names = NameSection::new();
1170 names.module("wit-component:fixups");
1171 fixups.section(&names);
1172
1173 let shim_module_index = self.component.core_module(&shim);
1174 self.fixups_module_index = Some(self.component.core_module(&fixups));
1175 self.shim_instance_index = Some(self.component.core_instantiate(shim_module_index, []));
1176
1177 return Ok(ret);
1178 }
1179
1180 fn encode_shim_function(
1181 type_index: u32,
1182 func_index: u32,
1183 code: &mut CodeSection,
1184 param_count: u32,
1185 ) {
1186 let mut func = wasm_encoder::Function::new(std::iter::empty());
1187 for i in 0..param_count {
1188 func.instructions().local_get(i);
1189 }
1190 func.instructions().i32_const(func_index as i32);
1191 func.instructions().call_indirect(0, type_index);
1192 func.instructions().end();
1193 code.function(&func);
1194 }
1195
1196 fn encode_indirect_lowerings(&mut self, shims: &Shims<'_>) -> Result<()> {
1197 if shims.shims.is_empty() {
1198 return Ok(());
1199 }
1200
1201 let shim_instance_index = self
1202 .shim_instance_index
1203 .expect("must have an instantiated shim");
1204
1205 let table_index =
1206 self.core_alias_export(shim_instance_index, INDIRECT_TABLE_NAME, ExportKind::Table);
1207
1208 let resolve = &self.info.encoder.metadata.resolve;
1209
1210 let mut exports = Vec::new();
1211 exports.push((INDIRECT_TABLE_NAME, ExportKind::Table, table_index));
1212
1213 for shim in shims.shims.values() {
1214 let core_func_index = match &shim.kind {
1215 ShimKind::IndirectLowering {
1222 interface,
1223 index,
1224 realloc,
1225 encoding,
1226 } => {
1227 let interface = &self.info.import_map[interface];
1228 let ((name, _), _) = interface.lowerings.get_index(*index).unwrap();
1229 let func_index = match &interface.interface {
1230 Some(interface_id) => {
1231 let instance_index = self.imported_instances[interface_id];
1232 self.component.alias_export(
1233 instance_index,
1234 name,
1235 ComponentExportKind::Func,
1236 )
1237 }
1238 None => self.imported_funcs[name],
1239 };
1240
1241 let realloc = self
1242 .info
1243 .exports_for(*realloc)
1244 .import_realloc_for(interface.interface, name)
1245 .map(|name| {
1246 let instance = self.instance_for(*realloc);
1247 self.core_alias_export(instance, name, ExportKind::Func)
1248 });
1249
1250 self.component.lower_func(
1251 func_index,
1252 shim.options
1253 .into_iter(*encoding, self.memory_index, realloc)?,
1254 )
1255 }
1256
1257 ShimKind::Adapter { adapter, func } => {
1262 self.core_alias_export(self.adapter_instances[adapter], func, ExportKind::Func)
1263 }
1264
1265 ShimKind::ResourceDtor { module, export } => {
1270 self.core_alias_export(self.instance_for(*module), export, ExportKind::Func)
1271 }
1272
1273 ShimKind::PayloadFunc {
1274 for_module,
1275 info,
1276 kind,
1277 } => {
1278 let metadata = self.info.module_metadata_for(*for_module);
1279 let exports = self.info.exports_for(*for_module);
1280 let instance_index = self.instance_for(*for_module);
1281 let (encoding, realloc) = if info.imported {
1282 (
1283 metadata
1284 .import_encodings
1285 .get(resolve, &info.key, &info.function),
1286 exports.import_realloc_for(info.interface, &info.function),
1287 )
1288 } else {
1289 (
1290 metadata
1291 .export_encodings
1292 .get(resolve, &info.key, &info.function),
1293 exports.export_realloc_for(&info.key, &info.function),
1294 )
1295 };
1296 let encoding = encoding.unwrap_or(StringEncoding::UTF8);
1297 let realloc_index = realloc
1298 .map(|name| self.core_alias_export(instance_index, name, ExportKind::Func));
1299 let type_index = self.payload_type_index(info)?;
1300 let options =
1301 shim.options
1302 .into_iter(encoding, self.memory_index, realloc_index)?;
1303
1304 match kind {
1305 PayloadFuncKind::FutureWrite => {
1306 self.component.future_write(type_index, options)
1307 }
1308 PayloadFuncKind::FutureRead => {
1309 self.component.future_read(type_index, options)
1310 }
1311 PayloadFuncKind::StreamWrite => {
1312 self.component.stream_write(type_index, options)
1313 }
1314 PayloadFuncKind::StreamRead => {
1315 self.component.stream_read(type_index, options)
1316 }
1317 }
1318 }
1319
1320 ShimKind::WaitableSetWait { async_ } => self
1321 .component
1322 .waitable_set_wait(*async_, self.memory_index.unwrap()),
1323 ShimKind::WaitableSetPoll { async_ } => self
1324 .component
1325 .waitable_set_poll(*async_, self.memory_index.unwrap()),
1326 ShimKind::ErrorContextNew { encoding } => self.component.error_context_new(
1327 shim.options.into_iter(*encoding, self.memory_index, None)?,
1328 ),
1329 ShimKind::ErrorContextDebugMessage {
1330 for_module,
1331 encoding,
1332 } => {
1333 let instance_index = self.instance_for(*for_module);
1334 let realloc = self.info.exports_for(*for_module).import_realloc_fallback();
1335 let realloc_index = realloc
1336 .map(|r| self.core_alias_export(instance_index, r, ExportKind::Func));
1337
1338 self.component
1339 .error_context_debug_message(shim.options.into_iter(
1340 *encoding,
1341 self.memory_index,
1342 realloc_index,
1343 )?)
1344 }
1345 ShimKind::TaskReturn {
1346 interface,
1347 func,
1348 result,
1349 encoding,
1350 for_module,
1351 } => {
1352 let mut encoder = if interface.is_none() {
1355 self.root_import_type_encoder(*interface)
1356 } else {
1357 self.root_export_type_encoder(*interface)
1358 };
1359 let result = match result {
1360 Some(ty) => Some(encoder.encode_valtype(resolve, ty)?),
1361 None => None,
1362 };
1363
1364 let exports = self.info.exports_for(*for_module);
1365 let realloc = exports.import_realloc_for(*interface, func);
1366
1367 let instance_index = self.instance_for(*for_module);
1368 let realloc_index = realloc
1369 .map(|r| self.core_alias_export(instance_index, r, ExportKind::Func));
1370 let options =
1371 shim.options
1372 .into_iter(*encoding, self.memory_index, realloc_index)?;
1373 self.component.task_return(result, options)
1374 }
1375 };
1376
1377 exports.push((shim.name.as_str(), ExportKind::Func, core_func_index));
1378 }
1379
1380 let instance_index = self.component.core_instantiate_exports(exports);
1381 self.component.core_instantiate(
1382 self.fixups_module_index.expect("must have fixup module"),
1383 [("", ModuleArg::Instance(instance_index))],
1384 );
1385 Ok(())
1386 }
1387
1388 fn payload_type_index(&mut self, info: &PayloadInfo) -> Result<u32> {
1396 let resolve = &self.info.encoder.metadata.resolve;
1397 let ComponentValType::Type(type_index) = if info.imported || info.interface.is_none() {
1413 self.root_import_type_encoder(None)
1414 } else {
1415 self.root_export_type_encoder(info.interface)
1416 }
1417 .encode_valtype(resolve, &Type::Id(info.ty))?
1418 else {
1419 unreachable!()
1420 };
1421 Ok(type_index)
1422 }
1423
1424 fn declare_types_for_imported_intrinsics(&mut self, shims: &Shims<'_>) -> Result<()> {
1431 let resolve = &self.info.encoder.metadata.resolve;
1432 let world = &resolve.worlds[self.info.encoder.metadata.world];
1433
1434 let main_module_keys = self.info.encoder.main_module_exports.iter();
1437 let main_module_keys = main_module_keys.map(|key| (CustomModule::Main, key));
1438 let adapter_keys = self.info.encoder.adapters.iter().flat_map(|(name, info)| {
1439 info.required_exports
1440 .iter()
1441 .map(move |key| (CustomModule::Adapter(name), key))
1442 });
1443 for (for_module, key) in main_module_keys.chain(adapter_keys) {
1444 let id = match &world.exports[key] {
1445 WorldItem::Interface { id, .. } => *id,
1446 WorldItem::Type { .. } => unreachable!(),
1447 WorldItem::Function(_) => continue,
1448 };
1449
1450 for ty in resolve.interfaces[id].types.values() {
1451 match &resolve.types[*ty].kind {
1452 TypeDefKind::Resource => {
1456 let exports = self.info.exports_for(for_module);
1459 let dtor = exports.resource_dtor(*ty).map(|name| {
1460 let name = &shims.shims[&ShimKind::ResourceDtor {
1461 module: for_module,
1462 export: name,
1463 }]
1464 .name;
1465 let shim = self.shim_instance_index.unwrap();
1466 self.core_alias_export(shim, name, ExportKind::Func)
1467 });
1468
1469 let resource_idx = self.component.type_resource(ValType::I32, dtor);
1473 let prev = self.export_type_map.insert(*ty, resource_idx);
1474 assert!(prev.is_none());
1475 }
1476 _other => {
1477 self.root_export_type_encoder(Some(id))
1478 .encode_valtype(resolve, &Type::Id(*ty))?;
1479 }
1480 }
1481 }
1482 }
1483 Ok(())
1484 }
1485
1486 fn instantiate_main_module(&mut self, shims: &Shims<'_>) -> Result<()> {
1489 assert!(self.instance_index.is_none());
1490
1491 let instance_index = self.instantiate_core_module(shims, CustomModule::Main)?;
1492
1493 if let Some(memory) = self.info.info.exports.memory() {
1494 self.memory_index =
1495 Some(self.core_alias_export(instance_index, memory, ExportKind::Memory));
1496 }
1497
1498 self.instance_index = Some(instance_index);
1499 Ok(())
1500 }
1501
1502 fn instantiate_adapter_module(&mut self, shims: &Shims<'_>, name: &'a str) -> Result<()> {
1505 let instance = self.instantiate_core_module(shims, CustomModule::Adapter(name))?;
1506 self.adapter_instances.insert(name, instance);
1507 Ok(())
1508 }
1509
1510 fn instantiate_core_module(
1517 &mut self,
1518 shims: &Shims,
1519 for_module: CustomModule<'_>,
1520 ) -> Result<u32> {
1521 let module = self.module_for(for_module);
1522
1523 let mut args = Vec::new();
1524 for (core_wasm_name, instance) in self.info.imports_for(for_module).modules() {
1525 match instance {
1526 ImportInstance::Names(names) => {
1532 let mut exports = Vec::new();
1533 for (name, import) in names {
1534 let (kind, index) = self
1535 .materialize_import(&shims, for_module, core_wasm_name, name, import)
1536 .with_context(|| {
1537 format!("failed to satisfy import `{core_wasm_name}::{name}`")
1538 })?;
1539 exports.push((name.as_str(), kind, index));
1540 }
1541 let index = self.component.core_instantiate_exports(exports);
1542 args.push((core_wasm_name.as_str(), ModuleArg::Instance(index)));
1543 }
1544
1545 ImportInstance::Whole(which) => {
1548 let instance = self.instance_for(which.to_custom_module());
1549 args.push((core_wasm_name.as_str(), ModuleArg::Instance(instance)));
1550 }
1551 }
1552 }
1553
1554 Ok(self.component.core_instantiate(module, args))
1556 }
1557
1558 fn materialize_import(
1565 &mut self,
1566 shims: &Shims<'_>,
1567 for_module: CustomModule<'_>,
1568 module: &str,
1569 field: &str,
1570 import: &'a Import,
1571 ) -> Result<(ExportKind, u32)> {
1572 log::trace!("attempting to materialize import of `{module}::{field}` for {for_module:?}");
1573 let resolve = &self.info.encoder.metadata.resolve;
1574 match import {
1575 Import::AdapterExport(_) => {
1578 assert!(self.info.encoder.adapters.contains_key(module));
1579 Ok(self.materialize_shim_import(
1580 shims,
1581 &ShimKind::Adapter {
1582 adapter: module,
1583 func: field,
1584 },
1585 ))
1586 }
1587
1588 Import::MainModuleMemory => {
1591 let index = self
1592 .memory_index
1593 .ok_or_else(|| anyhow!("main module cannot import memory"))?;
1594 Ok((ExportKind::Memory, index))
1595 }
1596
1597 Import::MainModuleExport { name, kind } => {
1599 let instance = self.instance_index.unwrap();
1600 let index = self.core_alias_export(instance, name, *kind);
1601 Ok((*kind, index))
1602 }
1603
1604 Import::Item(item) => {
1608 let instance = self.instance_for(item.which.to_custom_module());
1609 let index = self.core_alias_export(instance, &item.name, item.kind);
1610 Ok((item.kind, index))
1611 }
1612
1613 Import::ExportedResourceDrop(_key, id) => {
1619 let index = self.component.resource_drop(self.export_type_map[id]);
1620 Ok((ExportKind::Func, index))
1621 }
1622 Import::ExportedResourceRep(_key, id) => {
1623 let index = self.component.resource_rep(self.export_type_map[id]);
1624 Ok((ExportKind::Func, index))
1625 }
1626 Import::ExportedResourceNew(_key, id) => {
1627 let index = self.component.resource_new(self.export_type_map[id]);
1628 Ok((ExportKind::Func, index))
1629 }
1630
1631 Import::ImportedResourceDrop(key, iface, id) => {
1636 let ty = &resolve.types[*id];
1637 let name = ty.name.as_ref().unwrap();
1638 self.materialize_wit_import(
1639 shims,
1640 for_module,
1641 iface.map(|_| resolve.name_world_key(key)),
1642 &format!("{name}_drop"),
1643 key,
1644 AbiVariant::GuestImport,
1645 )
1646 }
1647 Import::ExportedTaskReturn(key, interface, func, result) => {
1648 let (options, _sig) = task_return_options_and_type(resolve, *result);
1649 if options.is_empty() {
1650 let mut encoder = if interface.is_none() {
1656 self.root_import_type_encoder(*interface)
1657 } else {
1658 self.root_export_type_encoder(*interface)
1659 };
1660
1661 let result = match result {
1662 Some(ty) => Some(encoder.encode_valtype(resolve, ty)?),
1663 None => None,
1664 };
1665 let index = self.component.task_return(result, []);
1666 Ok((ExportKind::Func, index))
1667 } else {
1668 let metadata = &self.info.encoder.metadata.metadata;
1669 let encoding = metadata.export_encodings.get(resolve, key, func).unwrap();
1670 Ok(self.materialize_shim_import(
1671 shims,
1672 &ShimKind::TaskReturn {
1673 for_module,
1674 interface: *interface,
1675 func,
1676 result: *result,
1677 encoding,
1678 },
1679 ))
1680 }
1681 }
1682 Import::BackpressureSet => {
1683 let index = self.component.backpressure_set();
1684 Ok((ExportKind::Func, index))
1685 }
1686 Import::WaitableSetWait { async_ } => {
1687 Ok(self
1688 .materialize_shim_import(shims, &ShimKind::WaitableSetWait { async_: *async_ }))
1689 }
1690 Import::WaitableSetPoll { async_ } => {
1691 Ok(self
1692 .materialize_shim_import(shims, &ShimKind::WaitableSetPoll { async_: *async_ }))
1693 }
1694 Import::Yield { async_ } => {
1695 let index = self.component.yield_(*async_);
1696 Ok((ExportKind::Func, index))
1697 }
1698 Import::SubtaskDrop => {
1699 let index = self.component.subtask_drop();
1700 Ok((ExportKind::Func, index))
1701 }
1702 Import::StreamNew(info) => {
1703 let ty = self.payload_type_index(info)?;
1704 let index = self.component.stream_new(ty);
1705 Ok((ExportKind::Func, index))
1706 }
1707 Import::StreamRead { info, .. } => Ok(self.materialize_payload_import(
1708 shims,
1709 for_module,
1710 info,
1711 PayloadFuncKind::StreamRead,
1712 )),
1713 Import::StreamWrite { info, .. } => Ok(self.materialize_payload_import(
1714 shims,
1715 for_module,
1716 info,
1717 PayloadFuncKind::StreamWrite,
1718 )),
1719 Import::StreamCancelRead { info, async_ } => {
1720 let ty = self.payload_type_index(info)?;
1721 let index = self.component.stream_cancel_read(ty, *async_);
1722 Ok((ExportKind::Func, index))
1723 }
1724 Import::StreamCancelWrite { info, async_ } => {
1725 let ty = self.payload_type_index(info)?;
1726 let index = self.component.stream_cancel_write(ty, *async_);
1727 Ok((ExportKind::Func, index))
1728 }
1729 Import::StreamCloseReadable(info) => {
1730 let type_index = self.payload_type_index(info)?;
1731 let index = self.component.stream_close_readable(type_index);
1732 Ok((ExportKind::Func, index))
1733 }
1734 Import::StreamCloseWritable(info) => {
1735 let type_index = self.payload_type_index(info)?;
1736 let index = self.component.stream_close_writable(type_index);
1737 Ok((ExportKind::Func, index))
1738 }
1739 Import::FutureNew(info) => {
1740 let ty = self.payload_type_index(info)?;
1741 let index = self.component.future_new(ty);
1742 Ok((ExportKind::Func, index))
1743 }
1744 Import::FutureRead { info, .. } => Ok(self.materialize_payload_import(
1745 shims,
1746 for_module,
1747 info,
1748 PayloadFuncKind::FutureRead,
1749 )),
1750 Import::FutureWrite { info, .. } => Ok(self.materialize_payload_import(
1751 shims,
1752 for_module,
1753 info,
1754 PayloadFuncKind::FutureWrite,
1755 )),
1756 Import::FutureCancelRead { info, async_ } => {
1757 let ty = self.payload_type_index(info)?;
1758 let index = self.component.future_cancel_read(ty, *async_);
1759 Ok((ExportKind::Func, index))
1760 }
1761 Import::FutureCancelWrite { info, async_ } => {
1762 let ty = self.payload_type_index(info)?;
1763 let index = self.component.future_cancel_write(ty, *async_);
1764 Ok((ExportKind::Func, index))
1765 }
1766 Import::FutureCloseReadable(info) => {
1767 let type_index = self.payload_type_index(info)?;
1768 let index = self.component.future_close_readable(type_index);
1769 Ok((ExportKind::Func, index))
1770 }
1771 Import::FutureCloseWritable(info) => {
1772 let type_index = self.payload_type_index(info)?;
1773 let index = self.component.future_close_writable(type_index);
1774 Ok((ExportKind::Func, index))
1775 }
1776 Import::ErrorContextNew { encoding } => Ok(self.materialize_shim_import(
1777 shims,
1778 &ShimKind::ErrorContextNew {
1779 encoding: *encoding,
1780 },
1781 )),
1782 Import::ErrorContextDebugMessage { encoding } => Ok(self.materialize_shim_import(
1783 shims,
1784 &ShimKind::ErrorContextDebugMessage {
1785 for_module,
1786 encoding: *encoding,
1787 },
1788 )),
1789 Import::ErrorContextDrop => {
1790 let index = self.component.error_context_drop();
1791 Ok((ExportKind::Func, index))
1792 }
1793 Import::WorldFunc(key, name, abi) => {
1794 self.materialize_wit_import(shims, for_module, None, name, key, *abi)
1795 }
1796 Import::InterfaceFunc(key, _, name, abi) => self.materialize_wit_import(
1797 shims,
1798 for_module,
1799 Some(resolve.name_world_key(key)),
1800 name,
1801 key,
1802 *abi,
1803 ),
1804
1805 Import::WaitableSetNew => {
1806 let index = self.component.waitable_set_new();
1807 Ok((ExportKind::Func, index))
1808 }
1809 Import::WaitableSetDrop => {
1810 let index = self.component.waitable_set_drop();
1811 Ok((ExportKind::Func, index))
1812 }
1813 Import::WaitableJoin => {
1814 let index = self.component.waitable_join();
1815 Ok((ExportKind::Func, index))
1816 }
1817 Import::ContextGet(n) => {
1818 let index = self.component.context_get(*n);
1819 Ok((ExportKind::Func, index))
1820 }
1821 Import::ContextSet(n) => {
1822 let index = self.component.context_set(*n);
1823 Ok((ExportKind::Func, index))
1824 }
1825 }
1826 }
1827
1828 fn materialize_shim_import(&mut self, shims: &Shims<'_>, kind: &ShimKind) -> (ExportKind, u32) {
1831 let index = self.core_alias_export(
1832 self.shim_instance_index
1833 .expect("shim should be instantiated"),
1834 &shims.shims[kind].name,
1835 ExportKind::Func,
1836 );
1837 (ExportKind::Func, index)
1838 }
1839
1840 fn materialize_payload_import(
1843 &mut self,
1844 shims: &Shims<'_>,
1845 for_module: CustomModule<'_>,
1846 info: &PayloadInfo,
1847 kind: PayloadFuncKind,
1848 ) -> (ExportKind, u32) {
1849 self.materialize_shim_import(
1850 shims,
1851 &ShimKind::PayloadFunc {
1852 for_module,
1853 info,
1854 kind,
1855 },
1856 )
1857 }
1858
1859 fn materialize_wit_import(
1862 &mut self,
1863 shims: &Shims<'_>,
1864 for_module: CustomModule<'_>,
1865 interface_key: Option<String>,
1866 name: &String,
1867 key: &WorldKey,
1868 abi: AbiVariant,
1869 ) -> Result<(ExportKind, u32)> {
1870 let resolve = &self.info.encoder.metadata.resolve;
1871 let import = &self.info.import_map[&interface_key];
1872 let (index, _, lowering) = import.lowerings.get_full(&(name.clone(), abi)).unwrap();
1873 let metadata = self.info.module_metadata_for(for_module);
1874
1875 let index = match lowering {
1876 Lowering::Direct => {
1879 let func_index = match &import.interface {
1880 Some(interface) => {
1881 let instance_index = self.imported_instances[interface];
1882 self.component
1883 .alias_export(instance_index, name, ComponentExportKind::Func)
1884 }
1885 None => self.imported_funcs[name],
1886 };
1887 self.component.lower_func(
1888 func_index,
1889 if let AbiVariant::GuestImportAsync = abi {
1890 vec![CanonicalOption::Async]
1891 } else {
1892 Vec::new()
1893 },
1894 )
1895 }
1896
1897 Lowering::Indirect { .. } => {
1901 let encoding = metadata.import_encodings.get(resolve, key, name).unwrap();
1902 return Ok(self.materialize_shim_import(
1903 shims,
1904 &ShimKind::IndirectLowering {
1905 interface: interface_key,
1906 index,
1907 realloc: for_module,
1908 encoding,
1909 },
1910 ));
1911 }
1912
1913 Lowering::ResourceDrop(id) => {
1916 let resource_idx = self.lookup_resource_index(*id);
1917 self.component.resource_drop(resource_idx)
1918 }
1919 };
1920 Ok((ExportKind::Func, index))
1921 }
1922
1923 fn encode_initialize_with_start(&mut self) -> Result<()> {
1942 let initialize = match self.info.info.exports.initialize() {
1943 Some(name) => name,
1944 None => return Ok(()),
1947 };
1948 let initialize_index =
1949 self.core_alias_export(self.instance_index.unwrap(), initialize, ExportKind::Func);
1950 let mut shim = Module::default();
1951 let mut section = TypeSection::new();
1952 section.ty().function([], []);
1953 shim.section(§ion);
1954 let mut section = ImportSection::new();
1955 section.import("", "", EntityType::Function(0));
1956 shim.section(§ion);
1957 shim.section(&StartSection { function_index: 0 });
1958
1959 let shim_module_index = self.component.core_module(&shim);
1964 let shim_args_instance_index =
1965 self.component
1966 .core_instantiate_exports([("", ExportKind::Func, initialize_index)]);
1967 self.component.core_instantiate(
1968 shim_module_index,
1969 [("", ModuleArg::Instance(shim_args_instance_index))],
1970 );
1971 Ok(())
1972 }
1973
1974 fn instance_for(&self, module: CustomModule) -> u32 {
1977 match module {
1978 CustomModule::Main => self.instance_index.expect("instantiated by now"),
1979 CustomModule::Adapter(name) => self.adapter_instances[name],
1980 }
1981 }
1982
1983 fn module_for(&self, module: CustomModule) -> u32 {
1986 match module {
1987 CustomModule::Main => self.module_index.unwrap(),
1988 CustomModule::Adapter(name) => self.adapter_modules[name],
1989 }
1990 }
1991
1992 fn core_alias_export(&mut self, instance: u32, name: &str, kind: ExportKind) -> u32 {
1995 *self
1996 .aliased_core_items
1997 .entry((instance, name.to_string()))
1998 .or_insert_with(|| self.component.core_alias_export(instance, name, kind))
1999 }
2000}
2001
2002#[derive(Default)]
2020struct Shims<'a> {
2021 shims: IndexMap<ShimKind<'a>, Shim<'a>>,
2023}
2024
2025struct Shim<'a> {
2026 options: RequiredOptions,
2029
2030 name: String,
2034
2035 debug_name: String,
2038
2039 kind: ShimKind<'a>,
2041
2042 sig: WasmSignature,
2044}
2045
2046#[derive(Debug, Clone, Hash, Eq, PartialEq)]
2049enum PayloadFuncKind {
2050 FutureWrite,
2051 FutureRead,
2052 StreamWrite,
2053 StreamRead,
2054}
2055
2056#[derive(Debug, Clone, Hash, Eq, PartialEq)]
2057enum ShimKind<'a> {
2058 IndirectLowering {
2062 interface: Option<String>,
2064 index: usize,
2066 realloc: CustomModule<'a>,
2068 encoding: StringEncoding,
2070 },
2071 Adapter {
2074 adapter: &'a str,
2076 func: &'a str,
2078 },
2079 ResourceDtor {
2082 module: CustomModule<'a>,
2084 export: &'a str,
2086 },
2087 PayloadFunc {
2091 for_module: CustomModule<'a>,
2094 info: &'a PayloadInfo,
2099 kind: PayloadFuncKind,
2101 },
2102 WaitableSetWait { async_: bool },
2106 WaitableSetPoll { async_: bool },
2110 TaskReturn {
2112 interface: Option<InterfaceId>,
2115 func: &'a str,
2118 result: Option<Type>,
2120 for_module: CustomModule<'a>,
2122 encoding: StringEncoding,
2124 },
2125 ErrorContextNew {
2129 encoding: StringEncoding,
2131 },
2132 ErrorContextDebugMessage {
2136 for_module: CustomModule<'a>,
2138 encoding: StringEncoding,
2140 },
2141}
2142
2143#[derive(Debug, Copy, Clone, Hash, Eq, PartialEq)]
2153enum CustomModule<'a> {
2154 Main,
2157 Adapter(&'a str),
2160}
2161
2162impl<'a> Shims<'a> {
2163 fn append_indirect(
2168 &mut self,
2169 world: &'a ComponentWorld<'a>,
2170 for_module: CustomModule<'a>,
2171 ) -> Result<()> {
2172 let module_imports = world.imports_for(for_module);
2173 let module_exports = world.exports_for(for_module);
2174 let resolve = &world.encoder.metadata.resolve;
2175
2176 for (module, field, import) in module_imports.imports() {
2177 match import {
2178 Import::ImportedResourceDrop(..)
2181 | Import::MainModuleMemory
2182 | Import::MainModuleExport { .. }
2183 | Import::Item(_)
2184 | Import::ExportedResourceDrop(..)
2185 | Import::ExportedResourceRep(..)
2186 | Import::ExportedResourceNew(..)
2187 | Import::ErrorContextDrop
2188 | Import::BackpressureSet
2189 | Import::Yield { .. }
2190 | Import::SubtaskDrop
2191 | Import::FutureNew(..)
2192 | Import::StreamNew(..)
2193 | Import::FutureCancelRead { .. }
2194 | Import::FutureCancelWrite { .. }
2195 | Import::FutureCloseWritable { .. }
2196 | Import::FutureCloseReadable { .. }
2197 | Import::StreamCancelRead { .. }
2198 | Import::StreamCancelWrite { .. }
2199 | Import::StreamCloseWritable { .. }
2200 | Import::StreamCloseReadable { .. }
2201 | Import::WaitableSetNew
2202 | Import::WaitableSetDrop
2203 | Import::WaitableJoin
2204 | Import::ContextGet(_)
2205 | Import::ContextSet(_) => {}
2206
2207 Import::ExportedTaskReturn(key, interface, func, ty) => {
2211 let (options, sig) = task_return_options_and_type(resolve, *ty);
2212 if options.is_empty() {
2213 continue;
2214 }
2215 let name = self.shims.len().to_string();
2216 let encoding = world
2217 .module_metadata_for(for_module)
2218 .export_encodings
2219 .get(resolve, key, func)
2220 .ok_or_else(|| {
2221 anyhow::anyhow!(
2222 "missing component metadata for export of \
2223 `{module}::{field}`"
2224 )
2225 })?;
2226 self.push(Shim {
2227 name,
2228 debug_name: format!("task-return-{func}"),
2229 options,
2230 kind: ShimKind::TaskReturn {
2231 interface: *interface,
2232 func,
2233 result: *ty,
2234 for_module,
2235 encoding,
2236 },
2237 sig,
2238 });
2239 }
2240
2241 Import::FutureWrite { async_, info } => {
2242 self.append_indirect_payload_push(
2243 resolve,
2244 for_module,
2245 module,
2246 *async_,
2247 info,
2248 PayloadFuncKind::FutureWrite,
2249 vec![WasmType::I32; 2],
2250 vec![WasmType::I32],
2251 );
2252 }
2253 Import::FutureRead { async_, info } => {
2254 self.append_indirect_payload_push(
2255 resolve,
2256 for_module,
2257 module,
2258 *async_,
2259 info,
2260 PayloadFuncKind::FutureRead,
2261 vec![WasmType::I32; 2],
2262 vec![WasmType::I32],
2263 );
2264 }
2265 Import::StreamWrite { async_, info } => {
2266 self.append_indirect_payload_push(
2267 resolve,
2268 for_module,
2269 module,
2270 *async_,
2271 info,
2272 PayloadFuncKind::StreamWrite,
2273 vec![WasmType::I32; 3],
2274 vec![WasmType::I32],
2275 );
2276 }
2277 Import::StreamRead { async_, info } => {
2278 self.append_indirect_payload_push(
2279 resolve,
2280 for_module,
2281 module,
2282 *async_,
2283 info,
2284 PayloadFuncKind::StreamRead,
2285 vec![WasmType::I32; 3],
2286 vec![WasmType::I32],
2287 );
2288 }
2289
2290 Import::WaitableSetWait { async_ } => {
2291 let name = self.shims.len().to_string();
2292 self.push(Shim {
2293 name,
2294 debug_name: "waitable-set.wait".to_string(),
2295 options: RequiredOptions::empty(),
2296 kind: ShimKind::WaitableSetWait { async_: *async_ },
2297 sig: WasmSignature {
2298 params: vec![WasmType::I32; 2],
2299 results: vec![WasmType::I32],
2300 indirect_params: false,
2301 retptr: false,
2302 },
2303 });
2304 }
2305
2306 Import::WaitableSetPoll { async_ } => {
2307 let name = self.shims.len().to_string();
2308 self.push(Shim {
2309 name,
2310 debug_name: "waitable-set.poll".to_string(),
2311 options: RequiredOptions::empty(),
2312 kind: ShimKind::WaitableSetPoll { async_: *async_ },
2313 sig: WasmSignature {
2314 params: vec![WasmType::I32; 2],
2315 results: vec![WasmType::I32],
2316 indirect_params: false,
2317 retptr: false,
2318 },
2319 });
2320 }
2321
2322 Import::ErrorContextNew { encoding } => {
2323 let name = self.shims.len().to_string();
2324 self.push(Shim {
2325 name,
2326 debug_name: "error-new".to_string(),
2327 options: RequiredOptions::MEMORY | RequiredOptions::STRING_ENCODING,
2328 kind: ShimKind::ErrorContextNew {
2329 encoding: *encoding,
2330 },
2331 sig: WasmSignature {
2332 params: vec![WasmType::I32; 2],
2333 results: vec![WasmType::I32],
2334 indirect_params: false,
2335 retptr: false,
2336 },
2337 });
2338 }
2339
2340 Import::ErrorContextDebugMessage { encoding } => {
2341 let name = self.shims.len().to_string();
2342 self.push(Shim {
2343 name,
2344 debug_name: "error-debug-message".to_string(),
2345 options: RequiredOptions::MEMORY
2346 | RequiredOptions::STRING_ENCODING
2347 | RequiredOptions::REALLOC,
2348 kind: ShimKind::ErrorContextDebugMessage {
2349 for_module,
2350 encoding: *encoding,
2351 },
2352 sig: WasmSignature {
2353 params: vec![WasmType::I32; 2],
2354 results: vec![],
2355 indirect_params: false,
2356 retptr: false,
2357 },
2358 });
2359 }
2360
2361 Import::AdapterExport(ty) => {
2364 let name = self.shims.len().to_string();
2365 log::debug!("shim {name} is adapter `{module}::{field}`");
2366 self.push(Shim {
2367 name,
2368 debug_name: format!("adapt-{module}-{field}"),
2369 options: RequiredOptions::MEMORY,
2373 kind: ShimKind::Adapter {
2374 adapter: module,
2375 func: field,
2376 },
2377 sig: WasmSignature {
2378 params: ty.params().iter().map(to_wasm_type).collect(),
2379 results: ty.results().iter().map(to_wasm_type).collect(),
2380 indirect_params: false,
2381 retptr: false,
2382 },
2383 });
2384
2385 fn to_wasm_type(ty: &wasmparser::ValType) -> WasmType {
2386 match ty {
2387 wasmparser::ValType::I32 => WasmType::I32,
2388 wasmparser::ValType::I64 => WasmType::I64,
2389 wasmparser::ValType::F32 => WasmType::F32,
2390 wasmparser::ValType::F64 => WasmType::F64,
2391 _ => unreachable!(),
2392 }
2393 }
2394 }
2395
2396 Import::InterfaceFunc(key, _, name, abi) => {
2400 self.append_indirect_wit_func(
2401 world,
2402 for_module,
2403 module,
2404 field,
2405 key,
2406 name,
2407 Some(resolve.name_world_key(key)),
2408 *abi,
2409 )?;
2410 }
2411 Import::WorldFunc(key, name, abi) => {
2412 self.append_indirect_wit_func(
2413 world, for_module, module, field, key, name, None, *abi,
2414 )?;
2415 }
2416 }
2417 }
2418
2419 for (export_name, export) in module_exports.iter() {
2425 let id = match export {
2426 Export::ResourceDtor(id) => id,
2427 _ => continue,
2428 };
2429 let resource = resolve.types[*id].name.as_ref().unwrap();
2430 let name = self.shims.len().to_string();
2431 self.push(Shim {
2432 name,
2433 debug_name: format!("dtor-{resource}"),
2434 options: RequiredOptions::empty(),
2435 kind: ShimKind::ResourceDtor {
2436 module: for_module,
2437 export: export_name,
2438 },
2439 sig: WasmSignature {
2440 params: vec![WasmType::I32],
2441 results: Vec::new(),
2442 indirect_params: false,
2443 retptr: false,
2444 },
2445 });
2446 }
2447
2448 Ok(())
2449 }
2450
2451 fn append_indirect_payload_push(
2454 &mut self,
2455 resolve: &Resolve,
2456 for_module: CustomModule<'a>,
2457 module: &str,
2458 async_: bool,
2459 info: &'a PayloadInfo,
2460 kind: PayloadFuncKind,
2461 params: Vec<WasmType>,
2462 results: Vec<WasmType>,
2463 ) {
2464 let debug_name = format!("{module}-{}", info.name);
2465 let name = self.shims.len().to_string();
2466
2467 let payload = info.payload(resolve);
2468 let (wit_param, wit_result) = match kind {
2469 PayloadFuncKind::StreamRead | PayloadFuncKind::FutureRead => (None, payload),
2470 PayloadFuncKind::StreamWrite | PayloadFuncKind::FutureWrite => (payload, None),
2471 };
2472 self.push(Shim {
2473 name,
2474 debug_name,
2475 options: RequiredOptions::MEMORY
2476 | RequiredOptions::for_import(
2477 resolve,
2478 &Function {
2479 name: String::new(),
2480 kind: FunctionKind::Freestanding,
2481 params: match wit_param {
2482 Some(ty) => vec![("a".to_string(), ty)],
2483 None => Vec::new(),
2484 },
2485 result: wit_result,
2486 docs: Default::default(),
2487 stability: Stability::Unknown,
2488 },
2489 if async_ {
2490 AbiVariant::GuestImportAsync
2491 } else {
2492 AbiVariant::GuestImport
2493 },
2494 ),
2495 kind: ShimKind::PayloadFunc {
2496 for_module,
2497 info,
2498 kind,
2499 },
2500 sig: WasmSignature {
2501 params,
2502 results,
2503 indirect_params: false,
2504 retptr: false,
2505 },
2506 });
2507 }
2508
2509 fn append_indirect_wit_func(
2512 &mut self,
2513 world: &'a ComponentWorld<'a>,
2514 for_module: CustomModule<'a>,
2515 module: &str,
2516 field: &str,
2517 key: &WorldKey,
2518 name: &String,
2519 interface_key: Option<String>,
2520 abi: AbiVariant,
2521 ) -> Result<()> {
2522 let resolve = &world.encoder.metadata.resolve;
2523 let metadata = world.module_metadata_for(for_module);
2524 let interface = &world.import_map[&interface_key];
2525 let (index, _, lowering) = interface.lowerings.get_full(&(name.clone(), abi)).unwrap();
2526 let shim_name = self.shims.len().to_string();
2527 match lowering {
2528 Lowering::Direct | Lowering::ResourceDrop(_) => {}
2529
2530 Lowering::Indirect { sig, options } => {
2531 log::debug!(
2532 "shim {shim_name} is import `{module}::{field}` lowering {index} `{name}`",
2533 );
2534 let encoding = metadata
2535 .import_encodings
2536 .get(resolve, key, name)
2537 .ok_or_else(|| {
2538 anyhow::anyhow!(
2539 "missing component metadata for import of \
2540 `{module}::{field}`"
2541 )
2542 })?;
2543 self.push(Shim {
2544 name: shim_name,
2545 debug_name: format!("indirect-{module}-{field}"),
2546 options: *options,
2547 kind: ShimKind::IndirectLowering {
2548 interface: interface_key,
2549 index,
2550 realloc: for_module,
2551 encoding,
2552 },
2553 sig: sig.clone(),
2554 });
2555 }
2556 }
2557
2558 Ok(())
2559 }
2560
2561 fn push(&mut self, shim: Shim<'a>) {
2562 if !self.shims.contains_key(&shim.kind) {
2566 self.shims.insert(shim.kind.clone(), shim);
2567 }
2568 }
2569}
2570
2571fn task_return_options_and_type(
2572 resolve: &Resolve,
2573 ty: Option<Type>,
2574) -> (RequiredOptions, WasmSignature) {
2575 let func_tmp = Function {
2576 name: String::new(),
2577 kind: FunctionKind::Freestanding,
2578 params: match ty {
2579 Some(ty) => vec![("a".to_string(), ty)],
2580 None => Vec::new(),
2581 },
2582 result: None,
2583 docs: Default::default(),
2584 stability: Stability::Unknown,
2585 };
2586 let abi = AbiVariant::GuestImport;
2587 let options = RequiredOptions::for_import(resolve, &func_tmp, abi);
2588 let sig = resolve.wasm_signature(abi, &func_tmp);
2589 (options, sig)
2590}
2591
2592#[derive(Clone, Debug)]
2594pub struct Item {
2595 pub alias: String,
2596 pub kind: ExportKind,
2597 pub which: MainOrAdapter,
2598 pub name: String,
2599}
2600
2601#[derive(Debug, PartialEq, Clone)]
2603pub enum MainOrAdapter {
2604 Main,
2605 Adapter(String),
2606}
2607
2608impl MainOrAdapter {
2609 fn to_custom_module(&self) -> CustomModule<'_> {
2610 match self {
2611 MainOrAdapter::Main => CustomModule::Main,
2612 MainOrAdapter::Adapter(s) => CustomModule::Adapter(s),
2613 }
2614 }
2615}
2616
2617#[derive(Clone)]
2619pub enum Instance {
2620 MainOrAdapter(MainOrAdapter),
2622
2623 Items(Vec<Item>),
2625}
2626
2627#[derive(Clone)]
2630pub struct LibraryInfo {
2631 pub instantiate_after_shims: bool,
2633
2634 pub arguments: Vec<(String, Instance)>,
2636}
2637
2638pub(super) struct Adapter {
2640 wasm: Vec<u8>,
2642
2643 metadata: ModuleMetadata,
2645
2646 required_exports: IndexSet<WorldKey>,
2649
2650 library_info: Option<LibraryInfo>,
2655}
2656
2657#[derive(Default)]
2659pub struct ComponentEncoder {
2660 module: Vec<u8>,
2661 pub(super) metadata: Bindgen,
2662 validate: bool,
2663 pub(super) main_module_exports: IndexSet<WorldKey>,
2664 pub(super) adapters: IndexMap<String, Adapter>,
2665 import_name_map: HashMap<String, String>,
2666 realloc_via_memory_grow: bool,
2667 merge_imports_based_on_semver: Option<bool>,
2668 pub(super) reject_legacy_names: bool,
2669}
2670
2671impl ComponentEncoder {
2672 pub fn module(mut self, module: &[u8]) -> Result<Self> {
2678 let (wasm, metadata) = self.decode(module)?;
2679 let exports = self
2680 .merge_metadata(metadata)
2681 .context("failed merge WIT metadata for module with previous metadata")?;
2682 self.main_module_exports.extend(exports);
2683 self.module = if let Some(producers) = &self.metadata.producers {
2684 producers.add_to_wasm(&wasm)?
2685 } else {
2686 wasm.to_vec()
2687 };
2688 Ok(self)
2689 }
2690
2691 fn decode<'a>(&self, wasm: &'a [u8]) -> Result<(Cow<'a, [u8]>, Bindgen)> {
2692 let (bytes, metadata) = metadata::decode(wasm)?;
2693 match bytes {
2694 Some(wasm) => Ok((Cow::Owned(wasm), metadata)),
2695 None => Ok((Cow::Borrowed(wasm), metadata)),
2696 }
2697 }
2698
2699 fn merge_metadata(&mut self, metadata: Bindgen) -> Result<IndexSet<WorldKey>> {
2700 self.metadata.merge(metadata)
2701 }
2702
2703 pub fn validate(mut self, validate: bool) -> Self {
2705 self.validate = validate;
2706 self
2707 }
2708
2709 pub fn merge_imports_based_on_semver(mut self, merge: bool) -> Self {
2717 self.merge_imports_based_on_semver = Some(merge);
2718 self
2719 }
2720
2721 pub fn reject_legacy_names(mut self, reject: bool) -> Self {
2730 self.reject_legacy_names = reject;
2731 self
2732 }
2733
2734 pub fn adapter(self, name: &str, bytes: &[u8]) -> Result<Self> {
2752 self.library_or_adapter(name, bytes, None)
2753 }
2754
2755 pub fn library(self, name: &str, bytes: &[u8], library_info: LibraryInfo) -> Result<Self> {
2768 self.library_or_adapter(name, bytes, Some(library_info))
2769 }
2770
2771 fn library_or_adapter(
2772 mut self,
2773 name: &str,
2774 bytes: &[u8],
2775 library_info: Option<LibraryInfo>,
2776 ) -> Result<Self> {
2777 let (wasm, mut metadata) = self.decode(bytes)?;
2778 let adapter_metadata = mem::take(&mut metadata.metadata);
2786 let exports = self.merge_metadata(metadata).with_context(|| {
2787 format!("failed to merge WIT packages of adapter `{name}` into main packages")
2788 })?;
2789 if let Some(library_info) = &library_info {
2790 for (_, instance) in &library_info.arguments {
2792 let resolve = |which: &_| match which {
2793 MainOrAdapter::Main => Ok(()),
2794 MainOrAdapter::Adapter(name) => {
2795 if self.adapters.contains_key(name.as_str()) {
2796 Ok(())
2797 } else {
2798 Err(anyhow!("instance refers to unknown adapter `{name}`"))
2799 }
2800 }
2801 };
2802
2803 match instance {
2804 Instance::MainOrAdapter(which) => resolve(which)?,
2805 Instance::Items(items) => {
2806 for item in items {
2807 resolve(&item.which)?;
2808 }
2809 }
2810 }
2811 }
2812 }
2813 self.adapters.insert(
2814 name.to_string(),
2815 Adapter {
2816 wasm: wasm.to_vec(),
2817 metadata: adapter_metadata,
2818 required_exports: exports,
2819 library_info,
2820 },
2821 );
2822 Ok(self)
2823 }
2824
2825 pub fn realloc_via_memory_grow(mut self, value: bool) -> Self {
2830 self.realloc_via_memory_grow = value;
2831 self
2832 }
2833
2834 pub fn import_name_map(mut self, map: HashMap<String, String>) -> Self {
2845 self.import_name_map = map;
2846 self
2847 }
2848
2849 pub fn encode(&mut self) -> Result<Vec<u8>> {
2851 if self.module.is_empty() {
2852 bail!("a module is required when encoding a component");
2853 }
2854
2855 if self.merge_imports_based_on_semver.unwrap_or(true) {
2856 self.metadata
2857 .resolve
2858 .merge_world_imports_based_on_semver(self.metadata.world)?;
2859 }
2860
2861 let world = ComponentWorld::new(self).context("failed to decode world from module")?;
2862 let mut state = EncodingState {
2863 component: ComponentBuilder::default(),
2864 module_index: None,
2865 instance_index: None,
2866 memory_index: None,
2867 shim_instance_index: None,
2868 fixups_module_index: None,
2869 adapter_modules: IndexMap::new(),
2870 adapter_instances: IndexMap::new(),
2871 import_type_map: HashMap::new(),
2872 import_func_type_map: HashMap::new(),
2873 export_type_map: HashMap::new(),
2874 export_func_type_map: HashMap::new(),
2875 imported_instances: Default::default(),
2876 imported_funcs: Default::default(),
2877 exported_instances: Default::default(),
2878 aliased_core_items: Default::default(),
2879 info: &world,
2880 };
2881 state.encode_imports(&self.import_name_map)?;
2882 state.encode_core_modules();
2883 state.encode_core_instantiation()?;
2884 state.encode_exports(CustomModule::Main)?;
2885 for name in self.adapters.keys() {
2886 state.encode_exports(CustomModule::Adapter(name))?;
2887 }
2888 state
2889 .component
2890 .raw_custom_section(&crate::base_producers().raw_custom_section());
2891 let bytes = state.component.finish();
2892
2893 if self.validate {
2894 Validator::new_with_features(WasmFeatures::all())
2895 .validate_all(&bytes)
2896 .context("failed to validate component output")?;
2897 }
2898
2899 Ok(bytes)
2900 }
2901}
2902
2903impl ComponentWorld<'_> {
2904 fn imports_for(&self, module: CustomModule) -> &ImportMap {
2906 match module {
2907 CustomModule::Main => &self.info.imports,
2908 CustomModule::Adapter(name) => &self.adapters[name].info.imports,
2909 }
2910 }
2911
2912 fn exports_for(&self, module: CustomModule) -> &ExportMap {
2914 match module {
2915 CustomModule::Main => &self.info.exports,
2916 CustomModule::Adapter(name) => &self.adapters[name].info.exports,
2917 }
2918 }
2919
2920 fn module_metadata_for(&self, module: CustomModule) -> &ModuleMetadata {
2922 match module {
2923 CustomModule::Main => &self.encoder.metadata.metadata,
2924 CustomModule::Adapter(name) => &self.encoder.adapters[name].metadata,
2925 }
2926 }
2927}
2928
2929#[cfg(all(test, feature = "dummy-module"))]
2930mod test {
2931 use super::*;
2932 use crate::{dummy_module, embed_component_metadata};
2933 use wit_parser::ManglingAndAbi;
2934
2935 #[test]
2936 fn it_renames_imports() {
2937 let mut resolve = Resolve::new();
2938 let pkg = resolve
2939 .push_str(
2940 "test.wit",
2941 r#"
2942package test:wit;
2943
2944interface i {
2945 f: func();
2946}
2947
2948world test {
2949 import i;
2950 import foo: interface {
2951 f: func();
2952 }
2953}
2954"#,
2955 )
2956 .unwrap();
2957 let world = resolve.select_world(pkg, None).unwrap();
2958
2959 let mut module = dummy_module(&resolve, world, ManglingAndAbi::Standard32);
2960
2961 embed_component_metadata(&mut module, &resolve, world, StringEncoding::UTF8).unwrap();
2962
2963 let encoded = ComponentEncoder::default()
2964 .import_name_map(HashMap::from([
2965 (
2966 "foo".to_string(),
2967 "unlocked-dep=<foo:bar/foo@{>=1.0.0 <1.1.0}>".to_string(),
2968 ),
2969 (
2970 "test:wit/i".to_string(),
2971 "locked-dep=<foo:bar/i@1.2.3>".to_string(),
2972 ),
2973 ]))
2974 .module(&module)
2975 .unwrap()
2976 .validate(true)
2977 .encode()
2978 .unwrap();
2979
2980 let wat = wasmprinter::print_bytes(encoded).unwrap();
2981 assert!(wat.contains("unlocked-dep=<foo:bar/foo@{>=1.0.0 <1.1.0}>"));
2982 assert!(wat.contains("locked-dep=<foo:bar/i@1.2.3>"));
2983 }
2984}