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