1use crate::StringEncoding;
75use crate::metadata::{self, Bindgen, ModuleMetadata};
76use crate::validation::{
77 Export, ExportMap, Import, ImportInstance, ImportMap, PayloadInfo, PayloadType,
78};
79use anyhow::{Context, Result, anyhow, bail};
80use indexmap::{IndexMap, IndexSet};
81use std::borrow::Cow;
82use std::collections::HashMap;
83use std::hash::Hash;
84use std::mem;
85use wasm_encoder::*;
86use wasmparser::{Validator, WasmFeatures};
87use wit_parser::{
88 Function, FunctionKind, InterfaceId, LiveTypes, Param, Resolve, Stability, Type, TypeDefKind,
89 TypeId, TypeOwner, WorldItem, WorldKey,
90 abi::{AbiVariant, WasmSignature, WasmType},
91};
92
93const INDIRECT_TABLE_NAME: &str = "$imports";
94
95mod wit;
96pub use wit::{encode, encode_world};
97
98mod types;
99use types::{InstanceTypeEncoder, RootTypeEncoder, TypeEncodingMaps, ValtypeEncoder};
100mod world;
101use world::{ComponentWorld, ImportedInterface, Lowering};
102
103mod dedupe;
104pub(crate) use dedupe::ModuleImportMap;
105use wasm_metadata::AddMetadataField;
106
107fn to_val_type(ty: &WasmType) -> ValType {
108 match ty {
109 WasmType::I32 => ValType::I32,
110 WasmType::I64 => ValType::I64,
111 WasmType::F32 => ValType::F32,
112 WasmType::F64 => ValType::F64,
113 WasmType::Pointer => ValType::I32,
114 WasmType::PointerOrI64 => ValType::I64,
115 WasmType::Length => ValType::I32,
116 }
117}
118
119fn import_func_name(f: &Function) -> String {
120 match f.kind {
121 FunctionKind::Freestanding | FunctionKind::AsyncFreestanding => {
122 format!("import-func-{}", f.item_name())
123 }
124
125 FunctionKind::Method(_)
133 | FunctionKind::AsyncMethod(_)
134 | FunctionKind::Static(_)
135 | FunctionKind::AsyncStatic(_)
136 | FunctionKind::Constructor(_) => {
137 format!(
138 "import-{}",
139 f.name.replace('[', "").replace([']', '.', ' '], "-")
140 )
141 }
142 }
143}
144
145bitflags::bitflags! {
146 #[derive(Copy, Clone, Debug)]
149 pub struct RequiredOptions: u8 {
150 const MEMORY = 1 << 0;
153 const REALLOC = 1 << 1;
156 const STRING_ENCODING = 1 << 2;
159 const ASYNC = 1 << 3;
160 }
161}
162
163impl RequiredOptions {
164 fn for_import(resolve: &Resolve, func: &Function, abi: AbiVariant) -> RequiredOptions {
165 let sig = resolve.wasm_signature(abi, func);
166 let mut ret = RequiredOptions::empty();
167 ret.add_lift(TypeContents::for_types(
169 resolve,
170 func.params.iter().map(|p| &p.ty),
171 ));
172 ret.add_lower(TypeContents::for_types(resolve, &func.result));
173
174 if sig.retptr || sig.indirect_params {
177 ret |= RequiredOptions::MEMORY;
178 }
179 if abi == AbiVariant::GuestImportAsync {
180 ret |= RequiredOptions::ASYNC;
181 }
182 ret
183 }
184
185 fn for_export(resolve: &Resolve, func: &Function, abi: AbiVariant) -> RequiredOptions {
186 let sig = resolve.wasm_signature(abi, func);
187 let mut ret = RequiredOptions::empty();
188 ret.add_lower(TypeContents::for_types(
190 resolve,
191 func.params.iter().map(|p| &p.ty),
192 ));
193 ret.add_lift(TypeContents::for_types(resolve, &func.result));
194
195 if sig.retptr || sig.indirect_params {
199 ret |= RequiredOptions::MEMORY;
200 if sig.indirect_params {
201 ret |= RequiredOptions::REALLOC;
202 }
203 }
204 if let AbiVariant::GuestExportAsync | AbiVariant::GuestExportAsyncStackful = abi {
205 ret |= RequiredOptions::ASYNC;
206 ret |= task_return_options_and_type(resolve, func).0;
207 }
208 ret
209 }
210
211 fn add_lower(&mut self, types: TypeContents) {
212 if types.contains(TypeContents::NEEDS_MEMORY) {
216 *self |= RequiredOptions::MEMORY | RequiredOptions::REALLOC;
217 }
218 if types.contains(TypeContents::STRING) {
219 *self |= RequiredOptions::MEMORY
220 | RequiredOptions::STRING_ENCODING
221 | RequiredOptions::REALLOC;
222 }
223 }
224
225 fn add_lift(&mut self, types: TypeContents) {
226 if types.contains(TypeContents::NEEDS_MEMORY) {
230 *self |= RequiredOptions::MEMORY;
231 }
232 if types.contains(TypeContents::STRING) {
233 *self |= RequiredOptions::MEMORY | RequiredOptions::STRING_ENCODING;
234 }
235 }
236
237 fn into_iter(
238 self,
239 encoding: StringEncoding,
240 memory_index: Option<u32>,
241 realloc_index: Option<u32>,
242 ) -> Result<impl ExactSizeIterator<Item = CanonicalOption>> {
243 #[derive(Default)]
244 struct Iter {
245 options: [Option<CanonicalOption>; 5],
246 current: usize,
247 count: usize,
248 }
249
250 impl Iter {
251 fn push(&mut self, option: CanonicalOption) {
252 assert!(self.count < self.options.len());
253 self.options[self.count] = Some(option);
254 self.count += 1;
255 }
256 }
257
258 impl Iterator for Iter {
259 type Item = CanonicalOption;
260
261 fn next(&mut self) -> Option<Self::Item> {
262 if self.current == self.count {
263 return None;
264 }
265 let option = self.options[self.current];
266 self.current += 1;
267 option
268 }
269
270 fn size_hint(&self) -> (usize, Option<usize>) {
271 (self.count - self.current, Some(self.count - self.current))
272 }
273 }
274
275 impl ExactSizeIterator for Iter {}
276
277 let mut iter = Iter::default();
278
279 if self.contains(RequiredOptions::MEMORY) {
280 iter.push(CanonicalOption::Memory(memory_index.ok_or_else(|| {
281 anyhow!("module does not export a memory named `memory`")
282 })?));
283 }
284
285 if self.contains(RequiredOptions::REALLOC) {
286 iter.push(CanonicalOption::Realloc(realloc_index.ok_or_else(
287 || anyhow!("module does not export a function named `cabi_realloc`"),
288 )?));
289 }
290
291 if self.contains(RequiredOptions::STRING_ENCODING) {
292 iter.push(encoding.into());
293 }
294
295 if self.contains(RequiredOptions::ASYNC) {
296 iter.push(CanonicalOption::Async);
297 }
298
299 Ok(iter)
300 }
301}
302
303bitflags::bitflags! {
304 struct TypeContents: u8 {
307 const STRING = 1 << 0;
308 const NEEDS_MEMORY = 1 << 1;
309 }
310}
311
312impl TypeContents {
313 fn for_types<'a>(resolve: &Resolve, types: impl IntoIterator<Item = &'a Type>) -> Self {
314 let mut cur = TypeContents::empty();
315 for ty in types {
316 cur |= Self::for_type(resolve, ty);
317 }
318 cur
319 }
320
321 fn for_optional_types<'a>(
322 resolve: &Resolve,
323 types: impl Iterator<Item = Option<&'a Type>>,
324 ) -> Self {
325 Self::for_types(resolve, types.flatten())
326 }
327
328 fn for_optional_type(resolve: &Resolve, ty: Option<&Type>) -> Self {
329 match ty {
330 Some(ty) => Self::for_type(resolve, ty),
331 None => Self::empty(),
332 }
333 }
334
335 fn for_type(resolve: &Resolve, ty: &Type) -> Self {
336 match ty {
337 Type::Id(id) => match &resolve.types[*id].kind {
338 TypeDefKind::Handle(h) => match h {
339 wit_parser::Handle::Own(_) => Self::empty(),
340 wit_parser::Handle::Borrow(_) => Self::empty(),
341 },
342 TypeDefKind::Resource => Self::empty(),
343 TypeDefKind::Record(r) => Self::for_types(resolve, r.fields.iter().map(|f| &f.ty)),
344 TypeDefKind::Tuple(t) => Self::for_types(resolve, t.types.iter()),
345 TypeDefKind::Flags(_) => Self::empty(),
346 TypeDefKind::Option(t) => Self::for_type(resolve, t),
347 TypeDefKind::Result(r) => {
348 Self::for_optional_type(resolve, r.ok.as_ref())
349 | Self::for_optional_type(resolve, r.err.as_ref())
350 }
351 TypeDefKind::Variant(v) => {
352 Self::for_optional_types(resolve, v.cases.iter().map(|c| c.ty.as_ref()))
353 }
354 TypeDefKind::Enum(_) => Self::empty(),
355 TypeDefKind::List(t) => Self::for_type(resolve, t) | Self::NEEDS_MEMORY,
356 TypeDefKind::Map(k, v) => {
357 Self::for_type(resolve, k) | Self::for_type(resolve, v) | Self::NEEDS_MEMORY
358 }
359 TypeDefKind::FixedLengthList(t, _elements) => Self::for_type(resolve, t),
360 TypeDefKind::Type(t) => Self::for_type(resolve, t),
361 TypeDefKind::Future(_) => Self::empty(),
362 TypeDefKind::Stream(_) => Self::empty(),
363 TypeDefKind::Unknown => unreachable!(),
364 },
365 Type::String => Self::STRING,
366 _ => Self::empty(),
367 }
368 }
369}
370
371pub struct EncodingState<'a> {
373 component: ComponentBuilder,
375 module_index: Option<u32>,
379 instance_index: Option<u32>,
383 memory_index: Option<u32>,
387 shim_instance_index: Option<u32>,
391 fixups_module_index: Option<u32>,
395
396 adapter_modules: IndexMap<&'a str, u32>,
399 adapter_instances: IndexMap<&'a str, u32>,
401
402 instances: IndexMap<InterfaceId, u32>,
404 imported_funcs: IndexMap<String, u32>,
405
406 type_encoding_maps: TypeEncodingMaps<'a>,
411
412 aliased_core_items: HashMap<(u32, String), u32>,
418
419 info: &'a ComponentWorld<'a>,
421
422 export_task_initialization_wrappers: HashMap<String, u32>,
425
426 tls_base_instance_index: Option<(u32, ValType)>,
433}
434
435const TLS_BASE_GET: &str = "get";
437const TLS_BASE_SET: &str = "set";
439
440impl<'a> EncodingState<'a> {
441 fn encode_core_modules(&mut self) {
442 assert!(self.module_index.is_none());
443 let idx = self
444 .component
445 .core_module_raw(Some("main"), &self.info.encoder.module);
446 self.module_index = Some(idx);
447
448 for (name, adapter) in self.info.adapters.iter() {
449 let debug_name = if adapter.library_info.is_some() {
450 name.to_string()
451 } else {
452 format!("wit-component:adapter:{name}")
453 };
454 let idx = if self.info.encoder.debug_names {
455 let mut add_meta = wasm_metadata::AddMetadata::default();
456 add_meta.name = AddMetadataField::Set(debug_name.clone());
457 let wasm = add_meta
458 .to_wasm(&adapter.wasm)
459 .expect("core wasm can get name added");
460 self.component.core_module_raw(Some(&debug_name), &wasm)
461 } else {
462 self.component
463 .core_module_raw(Some(&debug_name), &adapter.wasm)
464 };
465 let prev = self.adapter_modules.insert(name, idx);
466 assert!(prev.is_none());
467 }
468 }
469
470 fn root_import_type_encoder(
471 &mut self,
472 interface: Option<InterfaceId>,
473 ) -> RootTypeEncoder<'_, 'a> {
474 RootTypeEncoder {
475 state: self,
476 interface,
477 import_types: true,
478 }
479 }
480
481 fn root_export_type_encoder(
482 &mut self,
483 interface: Option<InterfaceId>,
484 ) -> RootTypeEncoder<'_, 'a> {
485 RootTypeEncoder {
486 state: self,
487 interface,
488 import_types: false,
489 }
490 }
491
492 fn instance_type_encoder(&mut self, interface: InterfaceId) -> InstanceTypeEncoder<'_, 'a> {
493 InstanceTypeEncoder {
494 state: self,
495 interface,
496 type_encoding_maps: Default::default(),
497 ty: Default::default(),
498 }
499 }
500
501 fn encode_imports(&mut self, name_map: &HashMap<String, String>) -> Result<()> {
502 let mut has_funcs = false;
503 for (name, info) in self.info.import_map.iter() {
504 match name {
505 Some(name) => {
506 self.encode_interface_import(name_map.get(name).unwrap_or(name), info)?
507 }
508 None => has_funcs = true,
509 }
510 }
511
512 let resolve = &self.info.encoder.metadata.resolve;
513 let world = &resolve.worlds[self.info.encoder.metadata.world];
514
515 for (_name, item) in world.imports.iter() {
518 if let WorldItem::Type { id, .. } = item {
519 self.root_import_type_encoder(None)
520 .encode_valtype(resolve, &Type::Id(*id))?;
521 }
522 }
523
524 if has_funcs {
525 let info = &self.info.import_map[&None];
526 self.encode_root_import_funcs(info)?;
527 }
528 Ok(())
529 }
530
531 fn encode_interface_import(&mut self, name: &str, info: &ImportedInterface) -> Result<()> {
532 let resolve = &self.info.encoder.metadata.resolve;
533 let interface_id = info.interface.as_ref().unwrap();
534 let interface_id = *interface_id;
535 let interface = &resolve.interfaces[interface_id];
536 log::trace!("encoding imports for `{name}` as {interface_id:?}");
537 let mut encoder = self.instance_type_encoder(interface_id);
538
539 if let Some(live) = encoder.state.info.live_type_imports.get(&interface_id) {
541 for ty in live {
542 log::trace!(
543 "encoding extra type {ty:?} name={:?}",
544 resolve.types[*ty].name
545 );
546 encoder.encode_valtype(resolve, &Type::Id(*ty))?;
547 }
548 }
549
550 for (_, func) in interface.functions.iter() {
553 if !(info
554 .lowerings
555 .contains_key(&(func.name.clone(), AbiVariant::GuestImport))
556 || info
557 .lowerings
558 .contains_key(&(func.name.clone(), AbiVariant::GuestImportAsync)))
559 {
560 continue;
561 }
562 log::trace!("encoding function type for `{}`", func.name);
563 let idx = encoder.encode_func_type(resolve, func)?;
564
565 encoder.ty.export(
566 crate::encoding::types::extern_name(&func.name, func.external_id.as_deref()),
567 ComponentTypeRef::Func(idx),
568 );
569 }
570
571 let ty = encoder.ty;
572 if ty.is_empty() {
575 return Ok(());
576 }
577 let instance_type_idx = self
578 .component
579 .type_instance(Some(&format!("ty-{name}")), &ty);
580 let instance_idx = self.component.import(
581 wasm_encoder::ComponentExternName {
582 name: name.into(),
583 implements: info.implements.as_deref().map(|s| s.into()),
584 external_id: info.external_id.as_deref().map(|s| s.into()),
585 version_suffix: None,
586 },
587 ComponentTypeRef::Instance(instance_type_idx),
588 );
589 let prev = self.instances.insert(interface_id, instance_idx);
590 assert!(prev.is_none());
591 Ok(())
592 }
593
594 fn encode_root_import_funcs(&mut self, info: &ImportedInterface) -> Result<()> {
595 let resolve = &self.info.encoder.metadata.resolve;
596 let world = self.info.encoder.metadata.world;
597 for (name, item) in resolve.worlds[world].imports.iter() {
598 let func = match item {
599 WorldItem::Function(f) => f,
600 WorldItem::Interface { .. } | WorldItem::Type { .. } => continue,
601 };
602 let name = resolve.name_world_key(name);
603 if !(info
604 .lowerings
605 .contains_key(&(name.clone(), AbiVariant::GuestImport))
606 || info
607 .lowerings
608 .contains_key(&(name.clone(), AbiVariant::GuestImportAsync)))
609 {
610 continue;
611 }
612 log::trace!("encoding function type for `{}`", func.name);
613 let idx = self
614 .root_import_type_encoder(None)
615 .encode_func_type(resolve, func)?;
616 let func_idx = self.component.import(
617 crate::encoding::types::extern_name(name.as_str(), func.external_id.as_deref()),
618 ComponentTypeRef::Func(idx),
619 );
620 let prev = self.imported_funcs.insert(name, func_idx);
621 assert!(prev.is_none());
622 }
623 Ok(())
624 }
625
626 fn alias_instance_type_export(&mut self, interface: InterfaceId, id: TypeId) -> u32 {
627 let ty = &self.info.encoder.metadata.resolve.types[id];
628 let name = ty.name.as_ref().expect("type must have a name");
629 let instance = self.instances[&interface];
630 self.component
631 .alias_export(instance, name, ComponentExportKind::Type)
632 }
633
634 fn encode_core_instantiation(&mut self) -> Result<()> {
635 let shims = self.encode_shim_instantiation()?;
637
638 self.declare_types_for_imported_intrinsics(&shims)?;
642
643 self.instantiate_main_module(&shims)?;
647
648 let (before, after) = self
651 .info
652 .adapters
653 .iter()
654 .partition::<Vec<_>, _>(|(_, adapter)| {
655 !matches!(
656 adapter.library_info,
657 Some(LibraryInfo {
658 instantiate_after_shims: true,
659 ..
660 })
661 )
662 });
663
664 for (name, _adapter) in before {
665 self.instantiate_adapter_module(&shims, name)?;
666 }
667
668 self.encode_indirect_lowerings(&shims)?;
671
672 for (name, _adapter) in after {
673 self.instantiate_adapter_module(&shims, name)?;
674 }
675
676 self.encode_initialize_with_start()?;
677
678 self.create_export_task_initialization_wrappers()?;
681
682 Ok(())
683 }
684
685 fn lookup_resource_index(&mut self, id: TypeId) -> u32 {
686 let resolve = &self.info.encoder.metadata.resolve;
687 let ty = &resolve.types[id];
688 match ty.owner {
689 TypeOwner::World(_) => self.type_encoding_maps.id_to_index[&id],
693 TypeOwner::Interface(i) => {
694 let instance = self.instances[&i];
695 let name = ty.name.as_ref().expect("resources must be named");
696 self.component
697 .alias_export(instance, name, ComponentExportKind::Type)
698 }
699 TypeOwner::None => panic!("resources must have an owner"),
700 }
701 }
702
703 fn encode_exports(&mut self, module: CustomModule) -> Result<()> {
704 let resolve = &self.info.encoder.metadata.resolve;
705 let exports = match module {
706 CustomModule::Main => &self.info.encoder.main_module_exports,
707 CustomModule::Adapter(name) => &self.info.encoder.adapters[name].required_exports,
708 };
709
710 if exports.is_empty() {
711 return Ok(());
712 }
713
714 let mut interface_func_core_names = IndexMap::new();
715 let mut world_func_core_names = IndexMap::new();
716 for (core_name, export) in self.info.exports_for(module).iter() {
717 match export {
718 Export::WorldFunc(_, name, _) => {
719 let prev = world_func_core_names.insert(name, core_name);
720 assert!(prev.is_none());
721 }
722 Export::InterfaceFunc(key, _, name, _) => {
723 let prev = interface_func_core_names
724 .entry(key)
725 .or_insert(IndexMap::new())
726 .insert(name.as_str(), core_name);
727 assert!(prev.is_none());
728 }
729 Export::WorldFuncCallback(..)
730 | Export::InterfaceFuncCallback(..)
731 | Export::WorldFuncPostReturn(..)
732 | Export::InterfaceFuncPostReturn(..)
733 | Export::ResourceDtor(..)
734 | Export::Memory
735 | Export::GeneralPurposeRealloc
736 | Export::GeneralPurposeExportRealloc
737 | Export::GeneralPurposeImportRealloc
738 | Export::Initialize
739 | Export::ReallocForAdapter
740 | Export::IndirectFunctionTable
741 | Export::WasmInitTask
742 | Export::WasmInitAsyncTask => continue,
743 }
744 }
745
746 let world = &resolve.worlds[self.info.encoder.metadata.world];
747
748 for export_name in exports {
749 let export_string = resolve.name_world_key(export_name);
750 match &world.exports[export_name] {
751 WorldItem::Function(func) => {
752 let ty = self
753 .root_import_type_encoder(None)
754 .encode_func_type(resolve, func)?;
755 let core_name = world_func_core_names[&func.name];
756 let idx = self.encode_lift(module, &core_name, export_name, func, ty)?;
757 self.component.export(
758 crate::encoding::types::extern_name(
759 &export_string,
760 func.external_id.as_deref(),
761 ),
762 ComponentExportKind::Func,
763 idx,
764 None,
765 );
766 }
767 item @ WorldItem::Interface { id, .. } => {
768 let core_names = interface_func_core_names.get(export_name);
769 self.encode_interface_export(
770 &export_string,
771 module,
772 export_name,
773 item,
774 *id,
775 core_names,
776 )?;
777 }
778 WorldItem::Type { .. } => unreachable!(),
779 }
780 }
781
782 Ok(())
783 }
784
785 fn encode_interface_export(
786 &mut self,
787 export_name: &str,
788 module: CustomModule<'_>,
789 key: &WorldKey,
790 item: &WorldItem,
791 export: InterfaceId,
792 interface_func_core_names: Option<&IndexMap<&str, &str>>,
793 ) -> Result<()> {
794 log::trace!("encode interface export `{export_name}`");
795 let resolve = &self.info.encoder.metadata.resolve;
796
797 let mut imports = Vec::new();
804 let mut root = self.root_export_type_encoder(Some(export));
805 for (_, func) in &resolve.interfaces[export].functions {
806 let core_name = interface_func_core_names.unwrap()[func.name.as_str()];
807 let ty = root.encode_func_type(resolve, func)?;
808 let func_index = root.state.encode_lift(module, &core_name, key, func, ty)?;
809 imports.push((
810 import_func_name(func),
811 ComponentExportKind::Func,
812 func_index,
813 ));
814 }
815
816 let mut nested = NestedComponentTypeEncoder {
820 component: ComponentBuilder::default(),
821 type_encoding_maps: Default::default(),
822 export_types: false,
823 interface: export,
824 state: self,
825 imports: IndexMap::new(),
826 };
827
828 let mut types_to_import = LiveTypes::default();
838 types_to_import.add_interface(resolve, export);
839 let exports_used = &nested.state.info.exports_used[&export];
840 for ty in types_to_import.iter() {
841 if let TypeOwner::Interface(owner) = resolve.types[ty].owner {
842 if owner == export {
843 continue;
846 }
847
848 let mut encoder = if exports_used.contains(&owner) {
851 nested.state.root_export_type_encoder(Some(export))
852 } else {
853 nested.state.root_import_type_encoder(Some(export))
854 };
855 encoder.encode_valtype(resolve, &Type::Id(ty))?;
856
857 nested.interface = owner;
861 nested.encode_valtype(resolve, &Type::Id(ty))?;
862 }
863 }
864 nested.interface = export;
865
866 let imported_type_maps = nested.type_encoding_maps.clone();
870
871 let mut resources = HashMap::new();
877 for (_name, ty) in resolve.interfaces[export].types.iter() {
878 if !matches!(resolve.types[*ty].kind, TypeDefKind::Resource) {
879 continue;
880 }
881 let idx = match nested.encode_valtype(resolve, &Type::Id(*ty))? {
882 ComponentValType::Type(idx) => idx,
883 _ => unreachable!(),
884 };
885 resources.insert(*ty, idx);
886 }
887
888 for (_, func) in resolve.interfaces[export].functions.iter() {
892 let ty = nested.encode_func_type(resolve, func)?;
893 nested
894 .component
895 .import(&import_func_name(func), ComponentTypeRef::Func(ty));
896 }
897
898 let reverse_map = nested
905 .type_encoding_maps
906 .id_to_index
907 .drain()
908 .map(|p| (p.1, p.0))
909 .collect::<HashMap<_, _>>();
910 nested.type_encoding_maps.def_to_index.clear();
911 for (name, idx) in nested.imports.drain(..) {
912 let id = reverse_map[&idx];
913 let idx = nested.state.type_encoding_maps.id_to_index[&id];
914 imports.push((name, ComponentExportKind::Type, idx))
915 }
916
917 nested.type_encoding_maps = imported_type_maps;
922
923 nested.export_types = true;
930 nested.type_encoding_maps.func_type_map.clear();
931
932 for (_, id) in resolve.interfaces[export].types.iter() {
938 let ty = &resolve.types[*id];
939 match ty.kind {
940 TypeDefKind::Resource => {
941 let idx = nested.component.export(
942 crate::encoding::types::extern_name(
943 ty.name.as_ref().expect("resources must be named"),
944 ty.external_id.as_deref(),
945 ),
946 ComponentExportKind::Type,
947 resources[id],
948 None,
949 );
950 nested.type_encoding_maps.id_to_index.insert(*id, idx);
951 }
952 _ => {
953 nested.encode_valtype(resolve, &Type::Id(*id))?;
954 }
955 }
956 }
957
958 for (i, (_, func)) in resolve.interfaces[export].functions.iter().enumerate() {
959 let ty = nested.encode_func_type(resolve, func)?;
960 nested.component.export(
961 crate::encoding::types::extern_name(&func.name, func.external_id.as_deref()),
962 ComponentExportKind::Func,
963 i as u32,
964 Some(ComponentTypeRef::Func(ty)),
965 );
966 }
967
968 let component = nested.component;
972 let component_index = self
973 .component
974 .component(Some(&format!("{export_name}-shim-component")), component);
975 let instance_index = self.component.instantiate(
976 Some(&format!("{export_name}-shim-instance")),
977 component_index,
978 imports,
979 );
980 let idx = self.component.export(
981 wasm_encoder::ComponentExternName {
982 name: export_name.into(),
983 implements: resolve.implements_value(key, item).map(|s| s.into()),
984 external_id: resolve.external_id_value(key, item).map(|s| s.into()),
985 version_suffix: None,
986 },
987 ComponentExportKind::Instance,
988 instance_index,
989 None,
990 );
991 let prev = self.instances.insert(export, idx);
992 assert!(prev.is_none());
993
994 for (_name, id) in resolve.interfaces[export].types.iter() {
1002 self.type_encoding_maps.id_to_index.remove(id);
1003 self.type_encoding_maps
1004 .def_to_index
1005 .remove(&resolve.types[*id].kind);
1006 }
1007
1008 return Ok(());
1009
1010 struct NestedComponentTypeEncoder<'state, 'a> {
1011 component: ComponentBuilder,
1012 type_encoding_maps: TypeEncodingMaps<'a>,
1013 export_types: bool,
1014 interface: InterfaceId,
1015 state: &'state mut EncodingState<'a>,
1016 imports: IndexMap<String, u32>,
1017 }
1018
1019 impl<'a> ValtypeEncoder<'a> for NestedComponentTypeEncoder<'_, 'a> {
1020 fn defined_type(&mut self) -> (u32, ComponentDefinedTypeEncoder<'_>) {
1021 self.component.type_defined(None)
1022 }
1023 fn define_function_type(&mut self) -> (u32, ComponentFuncTypeEncoder<'_>) {
1024 self.component.type_function(None)
1025 }
1026 fn export_type(
1027 &mut self,
1028 idx: u32,
1029 name: wasm_encoder::ComponentExternName<'a>,
1030 ) -> Option<u32> {
1031 if self.export_types {
1032 Some(
1033 self.component
1034 .export(name, ComponentExportKind::Type, idx, None),
1035 )
1036 } else {
1037 let name = self.unique_import_name(&name.name);
1038 let ret = self
1039 .component
1040 .import(&name, ComponentTypeRef::Type(TypeBounds::Eq(idx)));
1041 self.imports.insert(name, ret);
1042 Some(ret)
1043 }
1044 }
1045 fn export_resource(&mut self, name: wasm_encoder::ComponentExternName<'a>) -> u32 {
1046 if self.export_types {
1047 panic!("resources should already be exported")
1048 } else {
1049 let name = self.unique_import_name(&name.name);
1050 let ret = self
1051 .component
1052 .import(&name, ComponentTypeRef::Type(TypeBounds::SubResource));
1053 self.imports.insert(name, ret);
1054 ret
1055 }
1056 }
1057 fn import_type(&mut self, _: InterfaceId, _id: TypeId) -> u32 {
1058 unreachable!()
1059 }
1060 fn type_encoding_maps(&mut self) -> &mut TypeEncodingMaps<'a> {
1061 &mut self.type_encoding_maps
1062 }
1063 fn interface(&self) -> Option<InterfaceId> {
1064 Some(self.interface)
1065 }
1066 }
1067
1068 impl NestedComponentTypeEncoder<'_, '_> {
1069 fn unique_import_name(&mut self, name: &str) -> String {
1070 let mut name = format!("import-type-{name}");
1071 let mut n = 0;
1072 while self.imports.contains_key(&name) {
1073 name = format!("{name}{n}");
1074 n += 1;
1075 }
1076 name
1077 }
1078 }
1079 }
1080
1081 fn encode_lift(
1082 &mut self,
1083 module: CustomModule<'_>,
1084 core_name: &str,
1085 key: &WorldKey,
1086 func: &Function,
1087 ty: u32,
1088 ) -> Result<u32> {
1089 let resolve = &self.info.encoder.metadata.resolve;
1090 let metadata = self.info.module_metadata_for(module);
1091 let instance_index = self.instance_for(module);
1092 let core_func_index =
1095 if let Some(&wrapper_idx) = self.export_task_initialization_wrappers.get(core_name) {
1096 wrapper_idx
1097 } else {
1098 self.core_alias_export(Some(core_name), instance_index, core_name, ExportKind::Func)
1099 };
1100 let exports = self.info.exports_for(module);
1101
1102 let options = RequiredOptions::for_export(
1103 resolve,
1104 func,
1105 exports
1106 .abi(key, func)
1107 .ok_or_else(|| anyhow!("no ABI found for {}", func.name))?,
1108 );
1109
1110 let encoding = metadata
1111 .export_encodings
1112 .get(resolve, key, &func.name)
1113 .unwrap();
1114 let exports = self.info.exports_for(module);
1115 let realloc_index = exports
1116 .export_realloc_for(key, &func.name)
1117 .map(|name| self.core_alias_export(Some(name), instance_index, name, ExportKind::Func));
1118 let mut options = options
1119 .into_iter(encoding, self.memory_index, realloc_index)?
1120 .collect::<Vec<_>>();
1121
1122 if let Some(post_return) = exports.post_return(key, func) {
1123 let post_return = self.core_alias_export(
1124 Some(post_return),
1125 instance_index,
1126 post_return,
1127 ExportKind::Func,
1128 );
1129 options.push(CanonicalOption::PostReturn(post_return));
1130 }
1131 if let Some(callback) = exports.callback(key, func) {
1132 let callback =
1133 self.core_alias_export(Some(callback), instance_index, callback, ExportKind::Func);
1134 options.push(CanonicalOption::Callback(callback));
1135 }
1136 let func_index = self
1137 .component
1138 .lift_func(Some(&func.name), core_func_index, ty, options);
1139 Ok(func_index)
1140 }
1141
1142 fn encode_shim_instantiation(&mut self) -> Result<Shims<'a>> {
1143 let mut ret = Shims::default();
1144
1145 ret.append_indirect(self.info, CustomModule::Main)
1146 .context("failed to register indirect shims for main module")?;
1147
1148 for (adapter_name, _adapter) in self.info.adapters.iter() {
1152 ret.append_indirect(self.info, CustomModule::Adapter(adapter_name))
1153 .with_context(|| {
1154 format!("failed to register indirect shims for adapter {adapter_name}")
1155 })?;
1156 }
1157
1158 if ret.shims.is_empty() {
1159 return Ok(ret);
1160 }
1161
1162 assert!(self.shim_instance_index.is_none());
1163 assert!(self.fixups_module_index.is_none());
1164
1165 let mut types = TypeSection::new();
1174 let mut tables = TableSection::new();
1175 let mut functions = FunctionSection::new();
1176 let mut exports = ExportSection::new();
1177 let mut code = CodeSection::new();
1178 let mut sigs = IndexMap::new();
1179 let mut imports_section = ImportSection::new();
1180 let mut elements = ElementSection::new();
1181 let mut func_indexes = Vec::new();
1182 let mut func_names = NameMap::new();
1183
1184 for (i, shim) in ret.shims.values().enumerate() {
1185 let i = i as u32;
1186 let type_index = *sigs.entry(&shim.sig).or_insert_with(|| {
1187 let index = types.len();
1188 types.ty().function(
1189 shim.sig.params.iter().map(to_val_type),
1190 shim.sig.results.iter().map(to_val_type),
1191 );
1192 index
1193 });
1194
1195 functions.function(type_index);
1196 Self::encode_shim_function(type_index, i, &mut code, shim.sig.params.len() as u32);
1197 exports.export(&shim.name, ExportKind::Func, i);
1198
1199 imports_section.import("", &shim.name, EntityType::Function(type_index));
1200 func_indexes.push(i);
1201 func_names.append(i, &shim.debug_name);
1202 }
1203 let mut names = NameSection::new();
1204 names.module("wit-component:shim");
1205 names.functions(&func_names);
1206
1207 let table_type = TableType {
1208 element_type: RefType::FUNCREF,
1209 minimum: ret.shims.len() as u64,
1210 maximum: Some(ret.shims.len() as u64),
1211 table64: false,
1212 shared: false,
1213 };
1214
1215 tables.table(table_type);
1216
1217 exports.export(INDIRECT_TABLE_NAME, ExportKind::Table, 0);
1218 imports_section.import("", INDIRECT_TABLE_NAME, table_type);
1219
1220 elements.active(
1221 None,
1222 &ConstExpr::i32_const(0),
1223 Elements::Functions(func_indexes.into()),
1224 );
1225
1226 let mut shim = Module::new();
1227 shim.section(&types);
1228 shim.section(&functions);
1229 shim.section(&tables);
1230 shim.section(&exports);
1231 shim.section(&code);
1232 shim.section(&RawCustomSection(
1233 &crate::base_producers().raw_custom_section(),
1234 ));
1235 if self.info.encoder.debug_names {
1236 shim.section(&names);
1237 }
1238
1239 let mut fixups = Module::default();
1240 fixups.section(&types);
1241 fixups.section(&imports_section);
1242 fixups.section(&elements);
1243 fixups.section(&RawCustomSection(
1244 &crate::base_producers().raw_custom_section(),
1245 ));
1246
1247 if self.info.encoder.debug_names {
1248 let mut names = NameSection::new();
1249 names.module("wit-component:fixups");
1250 fixups.section(&names);
1251 }
1252
1253 let shim_module_index = self
1254 .component
1255 .core_module(Some("wit-component-shim-module"), &shim);
1256 let fixup_index = self
1257 .component
1258 .core_module(Some("wit-component-fixup"), &fixups);
1259 self.fixups_module_index = Some(fixup_index);
1260 let shim_instance = self.component.core_instantiate(
1261 Some("wit-component-shim-instance"),
1262 shim_module_index,
1263 [],
1264 );
1265 self.shim_instance_index = Some(shim_instance);
1266
1267 return Ok(ret);
1268 }
1269
1270 fn encode_shim_function(
1271 type_index: u32,
1272 func_index: u32,
1273 code: &mut CodeSection,
1274 param_count: u32,
1275 ) {
1276 let mut func = wasm_encoder::Function::new(std::iter::empty());
1277 for i in 0..param_count {
1278 func.instructions().local_get(i);
1279 }
1280 func.instructions().i32_const(func_index as i32);
1281 func.instructions().call_indirect(0, type_index);
1282 func.instructions().end();
1283 code.function(&func);
1284 }
1285
1286 fn encode_indirect_lowerings(&mut self, shims: &Shims<'_>) -> Result<()> {
1287 if shims.shims.is_empty() {
1288 return Ok(());
1289 }
1290
1291 let shim_instance_index = self
1292 .shim_instance_index
1293 .expect("must have an instantiated shim");
1294
1295 let table_index = self.core_alias_export(
1296 Some("shim table"),
1297 shim_instance_index,
1298 INDIRECT_TABLE_NAME,
1299 ExportKind::Table,
1300 );
1301
1302 let resolve = &self.info.encoder.metadata.resolve;
1303
1304 let mut exports = Vec::new();
1305 exports.push((INDIRECT_TABLE_NAME, ExportKind::Table, table_index));
1306
1307 for shim in shims.shims.values() {
1308 let core_func_index = match &shim.kind {
1309 ShimKind::IndirectLowering {
1316 interface,
1317 index,
1318 realloc,
1319 encoding,
1320 } => {
1321 let interface = &self.info.import_map[interface];
1322 let ((name, _), _) = interface.lowerings.get_index(*index).unwrap();
1323 let func_index = match &interface.interface {
1324 Some(interface_id) => {
1325 let instance_index = self.instances[interface_id];
1326 self.component.alias_export(
1327 instance_index,
1328 name,
1329 ComponentExportKind::Func,
1330 )
1331 }
1332 None => self.imported_funcs[name],
1333 };
1334
1335 let realloc = self
1336 .info
1337 .exports_for(*realloc)
1338 .import_realloc_for(interface.interface, name)
1339 .map(|name| {
1340 let instance = self.instance_for(*realloc);
1341 self.core_alias_export(
1342 Some("realloc"),
1343 instance,
1344 name,
1345 ExportKind::Func,
1346 )
1347 });
1348
1349 self.component.lower_func(
1350 Some(&shim.debug_name),
1351 func_index,
1352 shim.options
1353 .into_iter(*encoding, self.memory_index, realloc)?,
1354 )
1355 }
1356
1357 ShimKind::Adapter { adapter, func } => self.core_alias_export(
1362 Some(func),
1363 self.adapter_instances[adapter],
1364 func,
1365 ExportKind::Func,
1366 ),
1367
1368 ShimKind::ResourceDtor { module, export } => self.core_alias_export(
1373 Some(export),
1374 self.instance_for(*module),
1375 export,
1376 ExportKind::Func,
1377 ),
1378
1379 ShimKind::PayloadFunc {
1380 for_module,
1381 info,
1382 kind,
1383 } => {
1384 let metadata = self.info.module_metadata_for(*for_module);
1385 let exports = self.info.exports_for(*for_module);
1386 let instance_index = self.instance_for(*for_module);
1387 let (encoding, realloc) = match &info.ty {
1388 PayloadType::Type { function, .. } => {
1389 if info.imported {
1390 (
1391 metadata.import_encodings.get(resolve, &info.key, function),
1392 exports.import_realloc_for(info.interface, function),
1393 )
1394 } else {
1395 (
1396 metadata.export_encodings.get(resolve, &info.key, function),
1397 exports.export_realloc_for(&info.key, function),
1398 )
1399 }
1400 }
1401 PayloadType::UnitFuture | PayloadType::UnitStream => (None, None),
1402 };
1403 let encoding = encoding.unwrap_or(StringEncoding::UTF8);
1404 let realloc_index = realloc.map(|name| {
1405 self.core_alias_export(
1406 Some("realloc"),
1407 instance_index,
1408 name,
1409 ExportKind::Func,
1410 )
1411 });
1412 let type_index = self.payload_type_index(info)?;
1413 let options =
1414 shim.options
1415 .into_iter(encoding, self.memory_index, realloc_index)?;
1416
1417 match kind {
1418 PayloadFuncKind::FutureWrite => {
1419 self.component.future_write(type_index, options)
1420 }
1421 PayloadFuncKind::FutureRead => {
1422 self.component.future_read(type_index, options)
1423 }
1424 PayloadFuncKind::StreamWrite => {
1425 self.component.stream_write(type_index, options)
1426 }
1427 PayloadFuncKind::StreamRead => {
1428 self.component.stream_read(type_index, options)
1429 }
1430 }
1431 }
1432
1433 ShimKind::WaitableSetWait { cancellable } => self
1434 .component
1435 .waitable_set_wait(*cancellable, self.memory_index.unwrap()),
1436 ShimKind::WaitableSetPoll { cancellable } => self
1437 .component
1438 .waitable_set_poll(*cancellable, self.memory_index.unwrap()),
1439 ShimKind::ErrorContextNew { encoding } => self.component.error_context_new(
1440 shim.options.into_iter(*encoding, self.memory_index, None)?,
1441 ),
1442 ShimKind::ErrorContextDebugMessage {
1443 for_module,
1444 encoding,
1445 } => {
1446 let instance_index = self.instance_for(*for_module);
1447 let realloc = self.info.exports_for(*for_module).import_realloc_fallback();
1448 let realloc_index = realloc.map(|r| {
1449 self.core_alias_export(Some("realloc"), instance_index, r, ExportKind::Func)
1450 });
1451
1452 self.component
1453 .error_context_debug_message(shim.options.into_iter(
1454 *encoding,
1455 self.memory_index,
1456 realloc_index,
1457 )?)
1458 }
1459 ShimKind::TaskReturn {
1460 interface,
1461 func,
1462 result,
1463 encoding,
1464 for_module,
1465 } => {
1466 let mut encoder = if interface.is_none() {
1469 self.root_import_type_encoder(*interface)
1470 } else {
1471 self.root_export_type_encoder(*interface)
1472 };
1473 let result = match result {
1474 Some(ty) => Some(encoder.encode_valtype(resolve, ty)?),
1475 None => None,
1476 };
1477
1478 let exports = self.info.exports_for(*for_module);
1479 let realloc = exports.import_realloc_for(*interface, func);
1480
1481 let instance_index = self.instance_for(*for_module);
1482 let realloc_index = realloc.map(|r| {
1483 self.core_alias_export(Some("realloc"), instance_index, r, ExportKind::Func)
1484 });
1485 let options =
1486 shim.options
1487 .into_iter(*encoding, self.memory_index, realloc_index)?;
1488 self.component.task_return(result, options)
1489 }
1490 ShimKind::ThreadNewIndirect { func_ty } => {
1491 let (func_ty_idx, f) = self.component.core_type(Some("thread-start"));
1493 f.core().func_type(func_ty);
1494
1495 let exports = self.info.exports_for(CustomModule::Main);
1498 let instance_index = self.instance_for(CustomModule::Main);
1499 let table_idx = exports.indirect_function_table().map(|table| {
1500 self.core_alias_export(
1501 Some("indirect-function-table"),
1502 instance_index,
1503 table,
1504 ExportKind::Table,
1505 )
1506 }).ok_or_else(|| {
1507 anyhow!(
1508 "table __indirect_function_table must be an exported funcref table for thread.new-indirect"
1509 )
1510 })?;
1511
1512 self.component.thread_new_indirect(func_ty_idx, table_idx)
1513 }
1514 };
1515
1516 exports.push((shim.name.as_str(), ExportKind::Func, core_func_index));
1517 }
1518
1519 let instance_index = self
1520 .component
1521 .core_instantiate_exports(Some("fixup-args"), exports);
1522 self.component.core_instantiate(
1523 Some("fixup"),
1524 self.fixups_module_index.expect("must have fixup module"),
1525 [("", ModuleArg::Instance(instance_index))],
1526 );
1527 Ok(())
1528 }
1529
1530 fn payload_type_index(&mut self, info: &PayloadInfo) -> Result<u32> {
1538 let resolve = &self.info.encoder.metadata.resolve;
1539 let mut encoder = if info.imported || info.interface.is_none() {
1555 self.root_import_type_encoder(None)
1556 } else {
1557 self.root_export_type_encoder(info.interface)
1558 };
1559 match info.ty {
1560 PayloadType::Type { id, .. } => match encoder.encode_valtype(resolve, &Type::Id(id))? {
1561 ComponentValType::Type(index) => Ok(index),
1562 ComponentValType::Primitive(_) => unreachable!(),
1563 },
1564 PayloadType::UnitFuture => Ok(encoder.encode_unit_future()),
1565 PayloadType::UnitStream => Ok(encoder.encode_unit_stream()),
1566 }
1567 }
1568
1569 fn declare_types_for_imported_intrinsics(&mut self, shims: &Shims<'_>) -> Result<()> {
1576 let resolve = &self.info.encoder.metadata.resolve;
1577 let world = &resolve.worlds[self.info.encoder.metadata.world];
1578
1579 let main_module_keys = self.info.encoder.main_module_exports.iter();
1582 let main_module_keys = main_module_keys.map(|key| (CustomModule::Main, key));
1583 let adapter_keys = self.info.encoder.adapters.iter().flat_map(|(name, info)| {
1584 info.required_exports
1585 .iter()
1586 .map(move |key| (CustomModule::Adapter(name), key))
1587 });
1588 for (for_module, key) in main_module_keys.chain(adapter_keys) {
1589 let id = match &world.exports[key] {
1590 WorldItem::Interface { id, .. } => *id,
1591 WorldItem::Type { .. } => unreachable!(),
1592 WorldItem::Function(_) => continue,
1593 };
1594
1595 for ty in resolve.interfaces[id].types.values() {
1596 let def = &resolve.types[*ty];
1597 match &def.kind {
1598 TypeDefKind::Resource => {
1602 let exports = self.info.exports_for(for_module);
1605 let dtor = exports.resource_dtor(*ty).map(|name| {
1606 let shim = &shims.shims[&ShimKind::ResourceDtor {
1607 module: for_module,
1608 export: name,
1609 }];
1610 let index = self.shim_instance_index.unwrap();
1611 self.core_alias_export(
1612 Some(&shim.debug_name),
1613 index,
1614 &shim.name,
1615 ExportKind::Func,
1616 )
1617 });
1618
1619 let resource_idx = self.component.type_resource(
1623 Some(def.name.as_ref().unwrap()),
1624 ValType::I32,
1625 dtor,
1626 );
1627 let prev = self
1628 .type_encoding_maps
1629 .id_to_index
1630 .insert(*ty, resource_idx);
1631 assert!(prev.is_none());
1632 }
1633 _other => {
1634 self.root_export_type_encoder(Some(id))
1635 .encode_valtype(resolve, &Type::Id(*ty))?;
1636 }
1637 }
1638 }
1639 }
1640 Ok(())
1641 }
1642
1643 fn instantiate_main_module(&mut self, shims: &Shims<'_>) -> Result<()> {
1646 assert!(self.instance_index.is_none());
1647
1648 let instance_index = self.instantiate_core_module(shims, CustomModule::Main)?;
1649
1650 if let Some(memory) = self.info.info.exports.memory() {
1651 self.memory_index = Some(self.core_alias_export(
1652 Some("memory"),
1653 instance_index,
1654 memory,
1655 ExportKind::Memory,
1656 ));
1657 }
1658
1659 self.instance_index = Some(instance_index);
1660 Ok(())
1661 }
1662
1663 fn instantiate_adapter_module(&mut self, shims: &Shims<'_>, name: &'a str) -> Result<()> {
1666 let instance = self.instantiate_core_module(shims, CustomModule::Adapter(name))?;
1667 self.adapter_instances.insert(name, instance);
1668 Ok(())
1669 }
1670
1671 fn instantiate_core_module(
1678 &mut self,
1679 shims: &Shims,
1680 for_module: CustomModule<'_>,
1681 ) -> Result<u32> {
1682 let module = self.module_for(for_module);
1683
1684 let mut args = Vec::new();
1685 for (core_wasm_name, instance) in self.info.imports_for(for_module).modules() {
1686 match instance {
1687 ImportInstance::Names(names) => {
1693 let mut exports = Vec::new();
1694 for (name, import) in names {
1695 log::trace!(
1696 "attempting to materialize import of `{core_wasm_name}::{name}` for {for_module:?}"
1697 );
1698 let (kind, index) = self
1699 .materialize_import(&shims, for_module, import)
1700 .with_context(|| {
1701 format!("failed to satisfy import `{core_wasm_name}::{name}`")
1702 })?;
1703 exports.push((name.as_str(), kind, index));
1704 }
1705 let index = self
1706 .component
1707 .core_instantiate_exports(Some(core_wasm_name), exports);
1708 args.push((core_wasm_name.as_str(), ModuleArg::Instance(index)));
1709 }
1710
1711 ImportInstance::Whole(which) => {
1714 let instance = self.instance_for(which.to_custom_module());
1715 args.push((core_wasm_name.as_str(), ModuleArg::Instance(instance)));
1716 }
1717 }
1718 }
1719
1720 Ok(self
1722 .component
1723 .core_instantiate(Some(for_module.debug_name()), module, args))
1724 }
1725
1726 fn materialize_import(
1733 &mut self,
1734 shims: &Shims<'_>,
1735 for_module: CustomModule<'_>,
1736 import: &'a Import,
1737 ) -> Result<(ExportKind, u32)> {
1738 let resolve = &self.info.encoder.metadata.resolve;
1739 match import {
1740 Import::AdapterExport {
1743 adapter,
1744 func,
1745 ty: _,
1746 } => {
1747 assert!(self.info.encoder.adapters.contains_key(adapter));
1748 Ok(self.materialize_shim_import(shims, &ShimKind::Adapter { adapter, func }))
1749 }
1750
1751 Import::MainModuleMemory => {
1754 let index = self
1755 .memory_index
1756 .ok_or_else(|| anyhow!("main module cannot import memory"))?;
1757 Ok((ExportKind::Memory, index))
1758 }
1759
1760 Import::MainModuleExport { name, kind } => {
1762 let instance = self.instance_index.unwrap();
1763 let index = self.core_alias_export(Some(name), instance, name, *kind);
1764 Ok((*kind, index))
1765 }
1766
1767 Import::Item(item) => {
1771 let instance = self.instance_for(item.which.to_custom_module());
1772 let index =
1773 self.core_alias_export(Some(&item.name), instance, &item.name, item.kind);
1774 Ok((item.kind, index))
1775 }
1776
1777 Import::ExportedResourceDrop(_key, id) => {
1783 let index = self
1784 .component
1785 .resource_drop(self.type_encoding_maps.id_to_index[id]);
1786 Ok((ExportKind::Func, index))
1787 }
1788 Import::ExportedResourceRep(_key, id) => {
1789 let index = self
1790 .component
1791 .resource_rep(self.type_encoding_maps.id_to_index[id]);
1792 Ok((ExportKind::Func, index))
1793 }
1794 Import::ExportedResourceNew(_key, id) => {
1795 let index = self
1796 .component
1797 .resource_new(self.type_encoding_maps.id_to_index[id]);
1798 Ok((ExportKind::Func, index))
1799 }
1800
1801 Import::ImportedResourceDrop(key, iface, id) => {
1806 let ty = &resolve.types[*id];
1807 let name = ty.name.as_ref().unwrap();
1808 self.materialize_wit_import(
1809 shims,
1810 for_module,
1811 iface.map(|_| resolve.name_world_key(key)),
1812 &format!("{name}_drop"),
1813 key,
1814 AbiVariant::GuestImport,
1815 )
1816 }
1817 Import::ExportedTaskReturn(key, interface, func) => {
1818 let (options, _sig) = task_return_options_and_type(resolve, func);
1819 let result_ty = func.result;
1820 if options.is_empty() {
1821 let mut encoder = if interface.is_none() {
1827 self.root_import_type_encoder(*interface)
1828 } else {
1829 self.root_export_type_encoder(*interface)
1830 };
1831
1832 let result = match result_ty.as_ref() {
1833 Some(ty) => Some(encoder.encode_valtype(resolve, ty)?),
1834 None => None,
1835 };
1836 let index = self.component.task_return(result, []);
1837 Ok((ExportKind::Func, index))
1838 } else {
1839 let metadata = &self.info.module_metadata_for(for_module);
1840 let encoding = metadata
1841 .export_encodings
1842 .get(resolve, key, &func.name)
1843 .unwrap();
1844 Ok(self.materialize_shim_import(
1845 shims,
1846 &ShimKind::TaskReturn {
1847 for_module,
1848 interface: *interface,
1849 func: &func.name,
1850 result: result_ty,
1851 encoding,
1852 },
1853 ))
1854 }
1855 }
1856 Import::BackpressureInc => {
1857 let index = self.component.backpressure_inc();
1858 Ok((ExportKind::Func, index))
1859 }
1860 Import::BackpressureDec => {
1861 let index = self.component.backpressure_dec();
1862 Ok((ExportKind::Func, index))
1863 }
1864 Import::WaitableSetWait { cancellable } => Ok(self.materialize_shim_import(
1865 shims,
1866 &ShimKind::WaitableSetWait {
1867 cancellable: *cancellable,
1868 },
1869 )),
1870 Import::WaitableSetPoll { cancellable } => Ok(self.materialize_shim_import(
1871 shims,
1872 &ShimKind::WaitableSetPoll {
1873 cancellable: *cancellable,
1874 },
1875 )),
1876 Import::SubtaskDrop => {
1877 let index = self.component.subtask_drop();
1878 Ok((ExportKind::Func, index))
1879 }
1880 Import::SubtaskCancel { async_ } => {
1881 let index = self.component.subtask_cancel(*async_);
1882 Ok((ExportKind::Func, index))
1883 }
1884 Import::StreamNew(info) => {
1885 let ty = self.payload_type_index(info)?;
1886 let index = self.component.stream_new(ty);
1887 Ok((ExportKind::Func, index))
1888 }
1889 Import::StreamRead { info, .. } => Ok(self.materialize_payload_import(
1890 shims,
1891 for_module,
1892 info,
1893 PayloadFuncKind::StreamRead,
1894 )),
1895 Import::StreamWrite { info, .. } => Ok(self.materialize_payload_import(
1896 shims,
1897 for_module,
1898 info,
1899 PayloadFuncKind::StreamWrite,
1900 )),
1901 Import::StreamCancelRead { info, async_ } => {
1902 let ty = self.payload_type_index(info)?;
1903 let index = self.component.stream_cancel_read(ty, *async_);
1904 Ok((ExportKind::Func, index))
1905 }
1906 Import::StreamCancelWrite { info, async_ } => {
1907 let ty = self.payload_type_index(info)?;
1908 let index = self.component.stream_cancel_write(ty, *async_);
1909 Ok((ExportKind::Func, index))
1910 }
1911 Import::StreamDropReadable(info) => {
1912 let type_index = self.payload_type_index(info)?;
1913 let index = self.component.stream_drop_readable(type_index);
1914 Ok((ExportKind::Func, index))
1915 }
1916 Import::StreamDropWritable(info) => {
1917 let type_index = self.payload_type_index(info)?;
1918 let index = self.component.stream_drop_writable(type_index);
1919 Ok((ExportKind::Func, index))
1920 }
1921 Import::FutureNew(info) => {
1922 let ty = self.payload_type_index(info)?;
1923 let index = self.component.future_new(ty);
1924 Ok((ExportKind::Func, index))
1925 }
1926 Import::FutureRead { info, .. } => Ok(self.materialize_payload_import(
1927 shims,
1928 for_module,
1929 info,
1930 PayloadFuncKind::FutureRead,
1931 )),
1932 Import::FutureWrite { info, .. } => Ok(self.materialize_payload_import(
1933 shims,
1934 for_module,
1935 info,
1936 PayloadFuncKind::FutureWrite,
1937 )),
1938 Import::FutureCancelRead { info, async_ } => {
1939 let ty = self.payload_type_index(info)?;
1940 let index = self.component.future_cancel_read(ty, *async_);
1941 Ok((ExportKind::Func, index))
1942 }
1943 Import::FutureCancelWrite { info, async_ } => {
1944 let ty = self.payload_type_index(info)?;
1945 let index = self.component.future_cancel_write(ty, *async_);
1946 Ok((ExportKind::Func, index))
1947 }
1948 Import::FutureDropReadable(info) => {
1949 let type_index = self.payload_type_index(info)?;
1950 let index = self.component.future_drop_readable(type_index);
1951 Ok((ExportKind::Func, index))
1952 }
1953 Import::FutureDropWritable(info) => {
1954 let type_index = self.payload_type_index(info)?;
1955 let index = self.component.future_drop_writable(type_index);
1956 Ok((ExportKind::Func, index))
1957 }
1958 Import::ErrorContextNew { encoding } => Ok(self.materialize_shim_import(
1959 shims,
1960 &ShimKind::ErrorContextNew {
1961 encoding: *encoding,
1962 },
1963 )),
1964 Import::ErrorContextDebugMessage { encoding } => Ok(self.materialize_shim_import(
1965 shims,
1966 &ShimKind::ErrorContextDebugMessage {
1967 for_module,
1968 encoding: *encoding,
1969 },
1970 )),
1971 Import::ErrorContextDrop => {
1972 let index = self.component.error_context_drop();
1973 Ok((ExportKind::Func, index))
1974 }
1975 Import::WorldFunc(key, name, abi) => {
1976 self.materialize_wit_import(shims, for_module, None, name, key, *abi)
1977 }
1978 Import::InterfaceFunc(key, _, name, abi) => self.materialize_wit_import(
1979 shims,
1980 for_module,
1981 Some(resolve.name_world_key(key)),
1982 name,
1983 key,
1984 *abi,
1985 ),
1986
1987 Import::WaitableSetNew => {
1988 let index = self.component.waitable_set_new();
1989 Ok((ExportKind::Func, index))
1990 }
1991 Import::WaitableSetDrop => {
1992 let index = self.component.waitable_set_drop();
1993 Ok((ExportKind::Func, index))
1994 }
1995 Import::WaitableJoin => {
1996 let index = self.component.waitable_join();
1997 Ok((ExportKind::Func, index))
1998 }
1999 Import::ContextGet { ty, slot } => {
2000 let index = self.component.context_get((*ty).try_into()?, *slot);
2001 Ok((ExportKind::Func, index))
2002 }
2003 Import::ContextSet { ty, slot } => {
2004 let index = self.component.context_set((*ty).try_into()?, *slot);
2005 Ok((ExportKind::Func, index))
2006 }
2007 Import::TlsBaseGet { ty } => Ok((
2008 ExportKind::Func,
2009 self.materialize_tls_base_import(false, (*ty).try_into()?),
2010 )),
2011 Import::TlsBaseSet { ty } => Ok((
2012 ExportKind::Func,
2013 self.materialize_tls_base_import(true, (*ty).try_into()?),
2014 )),
2015 Import::ExportedTaskCancel => {
2016 let index = self.component.task_cancel();
2017 Ok((ExportKind::Func, index))
2018 }
2019 Import::ThreadIndex => {
2020 let index = self.component.thread_index();
2021 Ok((ExportKind::Func, index))
2022 }
2023 Import::ThreadNewIndirect => Ok(self.materialize_shim_import(
2024 shims,
2025 &ShimKind::ThreadNewIndirect {
2026 func_ty: FuncType::new([ValType::I32], []),
2028 },
2029 )),
2030 Import::ThreadResumeLater => {
2031 let index = self.component.thread_resume_later();
2032 Ok((ExportKind::Func, index))
2033 }
2034 Import::ThreadSuspend { cancellable } => {
2035 let index = self.component.thread_suspend(*cancellable);
2036 Ok((ExportKind::Func, index))
2037 }
2038 Import::ThreadYield { cancellable } => {
2039 let index = self.component.thread_yield(*cancellable);
2040 Ok((ExportKind::Func, index))
2041 }
2042 Import::ThreadSuspendThenResume { cancellable } => {
2043 let index = self.component.thread_suspend_then_resume(*cancellable);
2044 Ok((ExportKind::Func, index))
2045 }
2046 Import::ThreadYieldThenResume { cancellable } => {
2047 let index = self.component.thread_yield_then_resume(*cancellable);
2048 Ok((ExportKind::Func, index))
2049 }
2050 Import::ThreadSuspendThenPromote { cancellable } => {
2051 let index = self.component.thread_suspend_then_promote(*cancellable);
2052 Ok((ExportKind::Func, index))
2053 }
2054 Import::ThreadYieldThenPromote { cancellable } => {
2055 let index = self.component.thread_yield_then_promote(*cancellable);
2056 Ok((ExportKind::Func, index))
2057 }
2058 }
2059 }
2060
2061 fn materialize_tls_base_import(&mut self, set: bool, ty: ValType) -> u32 {
2065 if self.info.uses_cooperative_threading() {
2066 return if set {
2067 self.component.context_set(ty, 1)
2068 } else {
2069 self.component.context_get(ty, 1)
2070 };
2071 }
2072
2073 let instance = match self.tls_base_instance_index {
2074 Some((index, prev_ty)) => {
2075 assert_eq!(prev_ty, ty, "conflicting TLS base pointer types");
2076 index
2077 }
2078 None => {
2079 let index = self.encode_tls_base_module(ty);
2080 self.tls_base_instance_index = Some((index, ty));
2081 index
2082 }
2083 };
2084 let name = if set { TLS_BASE_SET } else { TLS_BASE_GET };
2085 self.core_alias_export(
2086 Some(&format!("tls-base-{name}")),
2087 instance,
2088 name,
2089 ExportKind::Func,
2090 )
2091 }
2092
2093 fn encode_tls_base_module(&mut self, ty: ValType) -> u32 {
2096 let mut types = TypeSection::new();
2097 types.ty().function([], [ty]);
2098 types.ty().function([ty], []);
2099
2100 let mut globals = GlobalSection::new();
2101 globals.global(
2102 wasm_encoder::GlobalType {
2103 val_type: ty,
2104 mutable: true,
2105 shared: false,
2106 },
2107 &match ty {
2108 ValType::I64 => ConstExpr::i64_const(0),
2109 ValType::I32 => ConstExpr::i32_const(0),
2110 _ => unreachable!(),
2111 },
2112 );
2113
2114 let mut functions = FunctionSection::new();
2115 let mut code = CodeSection::new();
2116
2117 functions.function(0);
2118 let mut get = wasm_encoder::Function::new([]);
2119 get.instruction(&Instruction::GlobalGet(0));
2120 get.instruction(&Instruction::End);
2121 code.function(&get);
2122
2123 functions.function(1);
2124 let mut set = wasm_encoder::Function::new([]);
2125 set.instruction(&Instruction::LocalGet(0));
2126 set.instruction(&Instruction::GlobalSet(0));
2127 set.instruction(&Instruction::End);
2128 code.function(&set);
2129
2130 let mut exports = ExportSection::new();
2131 exports.export(TLS_BASE_GET, ExportKind::Func, 0);
2132 exports.export(TLS_BASE_SET, ExportKind::Func, 1);
2133
2134 let mut module = Module::new();
2135 module.section(&types);
2136 module.section(&functions);
2137 module.section(&globals);
2138 module.section(&exports);
2139 module.section(&code);
2140
2141 let module_index = self
2142 .component
2143 .core_module(Some("wit-component:tls-base"), &module);
2144 self.component
2145 .core_instantiate(Some("wit-component:tls-base"), module_index, [])
2146 }
2147
2148 fn materialize_shim_import(&mut self, shims: &Shims<'_>, kind: &ShimKind) -> (ExportKind, u32) {
2151 let index = self.core_alias_export(
2152 Some(&shims.shims[kind].debug_name),
2153 self.shim_instance_index
2154 .expect("shim should be instantiated"),
2155 &shims.shims[kind].name,
2156 ExportKind::Func,
2157 );
2158 (ExportKind::Func, index)
2159 }
2160
2161 fn materialize_payload_import(
2164 &mut self,
2165 shims: &Shims<'_>,
2166 for_module: CustomModule<'_>,
2167 info: &PayloadInfo,
2168 kind: PayloadFuncKind,
2169 ) -> (ExportKind, u32) {
2170 self.materialize_shim_import(
2171 shims,
2172 &ShimKind::PayloadFunc {
2173 for_module,
2174 info,
2175 kind,
2176 },
2177 )
2178 }
2179
2180 fn materialize_wit_import(
2183 &mut self,
2184 shims: &Shims<'_>,
2185 for_module: CustomModule<'_>,
2186 interface_key: Option<String>,
2187 name: &String,
2188 key: &WorldKey,
2189 abi: AbiVariant,
2190 ) -> Result<(ExportKind, u32)> {
2191 let resolve = &self.info.encoder.metadata.resolve;
2192 let import = &self.info.import_map[&interface_key];
2193 let (index, _, lowering) = import.lowerings.get_full(&(name.clone(), abi)).unwrap();
2194 let metadata = self.info.module_metadata_for(for_module);
2195
2196 let index = match lowering {
2197 Lowering::Direct => {
2200 let func_index = match &import.interface {
2201 Some(interface) => {
2202 let instance_index = self.instances[interface];
2203 self.component
2204 .alias_export(instance_index, name, ComponentExportKind::Func)
2205 }
2206 None => self.imported_funcs[name],
2207 };
2208 self.component.lower_func(
2209 Some(name),
2210 func_index,
2211 if let AbiVariant::GuestImportAsync = abi {
2212 vec![CanonicalOption::Async]
2213 } else {
2214 Vec::new()
2215 },
2216 )
2217 }
2218
2219 Lowering::Indirect { .. } => {
2223 let encoding = metadata.import_encodings.get(resolve, key, name).unwrap();
2224 return Ok(self.materialize_shim_import(
2225 shims,
2226 &ShimKind::IndirectLowering {
2227 interface: interface_key,
2228 index,
2229 realloc: for_module,
2230 encoding,
2231 },
2232 ));
2233 }
2234
2235 Lowering::ResourceDrop(id) => {
2238 let resource_idx = self.lookup_resource_index(*id);
2239 self.component.resource_drop(resource_idx)
2240 }
2241 };
2242 Ok((ExportKind::Func, index))
2243 }
2244
2245 fn encode_initialize_with_start(&mut self) -> Result<()> {
2264 let initialize = match self.info.info.exports.initialize() {
2265 Some(name) => name,
2266 None => return Ok(()),
2269 };
2270 let init_task = self.info.info.exports.wasm_init_task();
2271 let initialize_index = self.core_alias_export(
2272 Some("start"),
2273 self.instance_index.unwrap(),
2274 initialize,
2275 ExportKind::Func,
2276 );
2277 let init_task_index = init_task.map(|name| {
2278 self.core_alias_export(
2279 Some("init-task-for-start"),
2280 self.instance_index.unwrap(),
2281 name,
2282 ExportKind::Func,
2283 )
2284 });
2285 let mut shim = Module::default();
2286 let mut section = TypeSection::new();
2287 section.ty().function([], []);
2288 shim.section(§ion);
2289
2290 let mut section = ImportSection::new();
2291 section.import("", "", EntityType::Function(0));
2292 if init_task.is_some() {
2293 section.import("", "init", EntityType::Function(0));
2294 }
2295 shim.section(§ion);
2296
2297 if init_task.is_some() {
2298 let mut functions = FunctionSection::new();
2299 functions.function(0);
2300 shim.section(&functions);
2301 }
2302
2303 shim.section(&StartSection {
2304 function_index: if init_task.is_some() { 2 } else { 0 },
2305 });
2306
2307 if init_task.is_some() {
2308 let mut code = CodeSection::new();
2309 let mut func = wasm_encoder::Function::new([]);
2310 func.instructions().call(1);
2311 func.instructions().call(0);
2312 func.instructions().end();
2313 code.function(&func);
2314 shim.section(&code);
2315 }
2316
2317 let shim_module_index = self.component.core_module(Some("start-shim-module"), &shim);
2322 let mut shim_args = vec![("", ExportKind::Func, initialize_index)];
2323 if let Some(i) = init_task_index {
2324 shim_args.push(("init", ExportKind::Func, i));
2325 }
2326 let shim_args_instance_index = self
2327 .component
2328 .core_instantiate_exports(Some("start-shim-args"), shim_args);
2329 self.component.core_instantiate(
2330 Some("start-shim-instance"),
2331 shim_module_index,
2332 [("", ModuleArg::Instance(shim_args_instance_index))],
2333 );
2334 Ok(())
2335 }
2336
2337 fn instance_for(&self, module: CustomModule) -> u32 {
2340 match module {
2341 CustomModule::Main => self.instance_index.expect("instantiated by now"),
2342 CustomModule::Adapter(name) => self.adapter_instances[name],
2343 }
2344 }
2345
2346 fn module_for(&self, module: CustomModule) -> u32 {
2349 match module {
2350 CustomModule::Main => self.module_index.unwrap(),
2351 CustomModule::Adapter(name) => self.adapter_modules[name],
2352 }
2353 }
2354
2355 fn core_alias_export(
2358 &mut self,
2359 debug_name: Option<&str>,
2360 instance: u32,
2361 name: &str,
2362 kind: ExportKind,
2363 ) -> u32 {
2364 *self
2365 .aliased_core_items
2366 .entry((instance, name.to_string()))
2367 .or_insert_with(|| {
2368 self.component
2369 .core_alias_export(debug_name, instance, name, kind)
2370 })
2371 }
2372
2373 fn create_export_task_initialization_wrappers(&mut self) -> Result<()> {
2383 let instance_index = self.instance_index.unwrap();
2384 let resolve = &self.info.encoder.metadata.resolve;
2385 let world = &resolve.worlds[self.info.encoder.metadata.world];
2386 let exports = self.info.exports_for(CustomModule::Main);
2387
2388 let wasm_init_task_export = exports.wasm_init_task();
2389 let wasm_init_async_task_export = exports.wasm_init_async_task();
2390 if wasm_init_task_export.is_none() || wasm_init_async_task_export.is_none() {
2391 return Ok(());
2394 }
2395 let wasm_init_task = wasm_init_task_export.unwrap();
2396 let wasm_init_async_task = wasm_init_async_task_export.unwrap();
2397
2398 let funcs_to_wrap: Vec<_> = exports
2401 .iter()
2402 .map(|v| (instance_index, v))
2403 .chain(self.info.adapters.iter().flat_map(|(name, adapter)| {
2404 let instance_index = self.adapter_instances[name];
2405 adapter
2406 .info
2407 .exports
2408 .iter()
2409 .map(move |v| (instance_index, v))
2410 }))
2411 .flat_map(|(index, (core_name, export))| match export {
2412 Export::WorldFunc(key, _, abi) => match &world.exports[key] {
2413 WorldItem::Function(f) => Some((index, core_name, f, abi)),
2414 _ => None,
2415 },
2416 Export::InterfaceFunc(_, id, func_name, abi) => {
2417 let func = &resolve.interfaces[*id].functions[func_name.as_str()];
2418 Some((index, core_name, func, abi))
2419 }
2420 _ => None,
2421 })
2422 .collect();
2423
2424 if funcs_to_wrap.is_empty() {
2425 return Ok(());
2427 }
2428
2429 let mut types = TypeSection::new();
2431 let mut imports = ImportSection::new();
2432 let mut functions = FunctionSection::new();
2433 let mut exports_section = ExportSection::new();
2434 let mut code = CodeSection::new();
2435
2436 types.ty().function([], []);
2438 let wasm_init_task_type_idx = 0;
2439
2440 imports.import(
2442 "",
2443 wasm_init_task,
2444 EntityType::Function(wasm_init_task_type_idx),
2445 );
2446 imports.import(
2447 "",
2448 wasm_init_async_task,
2449 EntityType::Function(wasm_init_task_type_idx),
2450 );
2451 let wasm_init_task_func_idx = 0u32;
2452 let wasm_init_async_task_func_idx = 1u32;
2453
2454 let mut type_indices = HashMap::new();
2455 let mut next_type_idx = 1u32;
2456 let mut next_func_idx = 2u32;
2457
2458 struct FuncInfo<'a> {
2460 name: &'a str,
2461 type_idx: u32,
2462 orig_func_idx: u32,
2463 is_async: bool,
2464 n_params: usize,
2465 }
2466 let mut func_info = Vec::new();
2467 for &(_, name, func, abi) in funcs_to_wrap.iter() {
2468 let sig = resolve.wasm_signature(*abi, func);
2469 let type_idx = *type_indices.entry(sig.clone()).or_insert_with(|| {
2470 let idx = next_type_idx;
2471 types.ty().function(
2472 sig.params.iter().map(to_val_type),
2473 sig.results.iter().map(to_val_type),
2474 );
2475 next_type_idx += 1;
2476 idx
2477 });
2478
2479 imports.import("", &import_func_name(func), EntityType::Function(type_idx));
2480 let orig_func_idx = next_func_idx;
2481 next_func_idx += 1;
2482
2483 func_info.push(FuncInfo {
2484 name,
2485 type_idx,
2486 orig_func_idx,
2487 is_async: abi.is_async(),
2488 n_params: sig.params.len(),
2489 });
2490 }
2491
2492 for info in func_info.iter() {
2494 let wrapper_func_idx = next_func_idx;
2495 functions.function(info.type_idx);
2496
2497 let mut func = wasm_encoder::Function::new([]);
2498 if info.is_async {
2499 func.instruction(&Instruction::Call(wasm_init_async_task_func_idx));
2500 } else {
2501 func.instruction(&Instruction::Call(wasm_init_task_func_idx));
2502 }
2503 for i in 0..info.n_params as u32 {
2504 func.instruction(&Instruction::LocalGet(i));
2505 }
2506 func.instruction(&Instruction::Call(info.orig_func_idx));
2507 func.instruction(&Instruction::End);
2508 code.function(&func);
2509
2510 exports_section.export(info.name, ExportKind::Func, wrapper_func_idx);
2511 next_func_idx += 1;
2512 }
2513
2514 let mut wrapper_module = Module::new();
2515 wrapper_module.section(&types);
2516 wrapper_module.section(&imports);
2517 wrapper_module.section(&functions);
2518 wrapper_module.section(&exports_section);
2519 wrapper_module.section(&code);
2520
2521 let wrapper_module_idx = self
2522 .component
2523 .core_module(Some("init-task-wrappers"), &wrapper_module);
2524
2525 let mut wrapper_imports = Vec::new();
2527 let init_idx = self.core_alias_export(
2528 Some(wasm_init_task),
2529 instance_index,
2530 wasm_init_task,
2531 ExportKind::Func,
2532 );
2533 let init_async_idx = self.core_alias_export(
2534 Some(wasm_init_async_task),
2535 instance_index,
2536 wasm_init_async_task,
2537 ExportKind::Func,
2538 );
2539 wrapper_imports.push((wasm_init_task.into(), ExportKind::Func, init_idx));
2540 wrapper_imports.push((
2541 wasm_init_async_task.into(),
2542 ExportKind::Func,
2543 init_async_idx,
2544 ));
2545
2546 for (instance_index, name, func, _) in &funcs_to_wrap {
2548 let orig_idx =
2549 self.core_alias_export(Some(name), *instance_index, name, ExportKind::Func);
2550 wrapper_imports.push((import_func_name(func), ExportKind::Func, orig_idx));
2551 }
2552
2553 let wrapper_args_idx = self.component.core_instantiate_exports(
2554 Some("init-task-wrappers-args"),
2555 wrapper_imports.iter().map(|(n, k, i)| (n.as_str(), *k, *i)),
2556 );
2557
2558 let wrapper_instance = self.component.core_instantiate(
2559 Some("init-task-wrappers-instance"),
2560 wrapper_module_idx,
2561 [("", ModuleArg::Instance(wrapper_args_idx))],
2562 );
2563
2564 for (_, name, _, _) in funcs_to_wrap {
2566 let wrapper_idx =
2567 self.core_alias_export(Some(&name), wrapper_instance, &name, ExportKind::Func);
2568 self.export_task_initialization_wrappers
2569 .insert(name.into(), wrapper_idx);
2570 }
2571
2572 Ok(())
2573 }
2574}
2575
2576#[derive(Default)]
2594struct Shims<'a> {
2595 shims: IndexMap<ShimKind<'a>, Shim<'a>>,
2597}
2598
2599struct Shim<'a> {
2600 options: RequiredOptions,
2603
2604 name: String,
2608
2609 debug_name: String,
2612
2613 kind: ShimKind<'a>,
2615
2616 sig: WasmSignature,
2618}
2619
2620#[derive(Debug, Clone, Hash, Eq, PartialEq)]
2623enum PayloadFuncKind {
2624 FutureWrite,
2625 FutureRead,
2626 StreamWrite,
2627 StreamRead,
2628}
2629
2630#[derive(Debug, Clone, Hash, Eq, PartialEq)]
2631enum ShimKind<'a> {
2632 IndirectLowering {
2636 interface: Option<String>,
2638 index: usize,
2640 realloc: CustomModule<'a>,
2642 encoding: StringEncoding,
2644 },
2645 Adapter {
2648 adapter: &'a str,
2650 func: &'a str,
2652 },
2653 ResourceDtor {
2656 module: CustomModule<'a>,
2658 export: &'a str,
2660 },
2661 PayloadFunc {
2665 for_module: CustomModule<'a>,
2668 info: &'a PayloadInfo,
2673 kind: PayloadFuncKind,
2675 },
2676 WaitableSetWait { cancellable: bool },
2680 WaitableSetPoll { cancellable: bool },
2684 TaskReturn {
2686 interface: Option<InterfaceId>,
2689 func: &'a str,
2692 result: Option<Type>,
2694 for_module: CustomModule<'a>,
2696 encoding: StringEncoding,
2698 },
2699 ErrorContextNew {
2703 encoding: StringEncoding,
2705 },
2706 ErrorContextDebugMessage {
2710 for_module: CustomModule<'a>,
2712 encoding: StringEncoding,
2714 },
2715 ThreadNewIndirect {
2718 func_ty: FuncType,
2720 },
2721}
2722
2723#[derive(Debug, Copy, Clone, Hash, Eq, PartialEq)]
2733enum CustomModule<'a> {
2734 Main,
2737 Adapter(&'a str),
2740}
2741
2742impl<'a> CustomModule<'a> {
2743 fn debug_name(&self) -> &'a str {
2744 match self {
2745 CustomModule::Main => "main",
2746 CustomModule::Adapter(s) => s,
2747 }
2748 }
2749}
2750
2751impl<'a> Shims<'a> {
2752 fn append_indirect(
2757 &mut self,
2758 world: &'a ComponentWorld<'a>,
2759 for_module: CustomModule<'a>,
2760 ) -> Result<()> {
2761 let module_imports = world.imports_for(for_module);
2762 let module_exports = world.exports_for(for_module);
2763 let resolve = &world.encoder.metadata.resolve;
2764
2765 for (module, field, import) in module_imports.imports() {
2766 match import {
2767 Import::ImportedResourceDrop(..)
2770 | Import::MainModuleMemory
2771 | Import::MainModuleExport { .. }
2772 | Import::Item(_)
2773 | Import::ExportedResourceDrop(..)
2774 | Import::ExportedResourceRep(..)
2775 | Import::ExportedResourceNew(..)
2776 | Import::ExportedTaskCancel
2777 | Import::ErrorContextDrop
2778 | Import::BackpressureInc
2779 | Import::BackpressureDec
2780 | Import::SubtaskDrop
2781 | Import::SubtaskCancel { .. }
2782 | Import::FutureNew(..)
2783 | Import::StreamNew(..)
2784 | Import::FutureCancelRead { .. }
2785 | Import::FutureCancelWrite { .. }
2786 | Import::FutureDropWritable { .. }
2787 | Import::FutureDropReadable { .. }
2788 | Import::StreamCancelRead { .. }
2789 | Import::StreamCancelWrite { .. }
2790 | Import::StreamDropWritable { .. }
2791 | Import::StreamDropReadable { .. }
2792 | Import::WaitableSetNew
2793 | Import::WaitableSetDrop
2794 | Import::WaitableJoin
2795 | Import::ContextGet { .. }
2796 | Import::ContextSet { .. }
2797 | Import::TlsBaseGet { .. }
2798 | Import::TlsBaseSet { .. }
2799 | Import::ThreadIndex
2800 | Import::ThreadResumeLater
2801 | Import::ThreadSuspend { .. }
2802 | Import::ThreadYield { .. }
2803 | Import::ThreadSuspendThenResume { .. }
2804 | Import::ThreadYieldThenResume { .. }
2805 | Import::ThreadSuspendThenPromote { .. }
2806 | Import::ThreadYieldThenPromote { .. } => {}
2807
2808 Import::ExportedTaskReturn(key, interface, func) => {
2812 let (options, sig) = task_return_options_and_type(resolve, func);
2813 if options.is_empty() {
2814 continue;
2815 }
2816 let name = self.shims.len().to_string();
2817 let encoding = world
2818 .module_metadata_for(for_module)
2819 .export_encodings
2820 .get(resolve, key, &func.name)
2821 .ok_or_else(|| {
2822 anyhow::anyhow!(
2823 "missing component metadata for export of \
2824 `{module}::{field}`"
2825 )
2826 })?;
2827 self.push(Shim {
2828 name,
2829 debug_name: format!("task-return-{}", func.name),
2830 options,
2831 kind: ShimKind::TaskReturn {
2832 interface: *interface,
2833 func: &func.name,
2834 result: func.result,
2835 for_module,
2836 encoding,
2837 },
2838 sig,
2839 });
2840 }
2841
2842 Import::FutureWrite { async_, info } => {
2843 self.append_indirect_payload_push(
2844 resolve,
2845 for_module,
2846 module,
2847 *async_,
2848 info,
2849 PayloadFuncKind::FutureWrite,
2850 vec![WasmType::I32; 2],
2851 vec![WasmType::I32],
2852 );
2853 }
2854 Import::FutureRead { async_, info } => {
2855 self.append_indirect_payload_push(
2856 resolve,
2857 for_module,
2858 module,
2859 *async_,
2860 info,
2861 PayloadFuncKind::FutureRead,
2862 vec![WasmType::I32; 2],
2863 vec![WasmType::I32],
2864 );
2865 }
2866 Import::StreamWrite { async_, info } => {
2867 self.append_indirect_payload_push(
2868 resolve,
2869 for_module,
2870 module,
2871 *async_,
2872 info,
2873 PayloadFuncKind::StreamWrite,
2874 vec![WasmType::I32; 3],
2875 vec![WasmType::I32],
2876 );
2877 }
2878 Import::StreamRead { async_, info } => {
2879 self.append_indirect_payload_push(
2880 resolve,
2881 for_module,
2882 module,
2883 *async_,
2884 info,
2885 PayloadFuncKind::StreamRead,
2886 vec![WasmType::I32; 3],
2887 vec![WasmType::I32],
2888 );
2889 }
2890
2891 Import::WaitableSetWait { cancellable } => {
2892 let name = self.shims.len().to_string();
2893 self.push(Shim {
2894 name,
2895 debug_name: "waitable-set.wait".to_string(),
2896 options: RequiredOptions::empty(),
2897 kind: ShimKind::WaitableSetWait {
2898 cancellable: *cancellable,
2899 },
2900 sig: WasmSignature {
2901 params: vec![WasmType::I32; 2],
2902 results: vec![WasmType::I32],
2903 indirect_params: false,
2904 retptr: false,
2905 },
2906 });
2907 }
2908
2909 Import::WaitableSetPoll { cancellable } => {
2910 let name = self.shims.len().to_string();
2911 self.push(Shim {
2912 name,
2913 debug_name: "waitable-set.poll".to_string(),
2914 options: RequiredOptions::empty(),
2915 kind: ShimKind::WaitableSetPoll {
2916 cancellable: *cancellable,
2917 },
2918 sig: WasmSignature {
2919 params: vec![WasmType::I32; 2],
2920 results: vec![WasmType::I32],
2921 indirect_params: false,
2922 retptr: false,
2923 },
2924 });
2925 }
2926
2927 Import::ErrorContextNew { encoding } => {
2928 let name = self.shims.len().to_string();
2929 self.push(Shim {
2930 name,
2931 debug_name: "error-new".to_string(),
2932 options: RequiredOptions::MEMORY | RequiredOptions::STRING_ENCODING,
2933 kind: ShimKind::ErrorContextNew {
2934 encoding: *encoding,
2935 },
2936 sig: WasmSignature {
2937 params: vec![WasmType::I32; 2],
2938 results: vec![WasmType::I32],
2939 indirect_params: false,
2940 retptr: false,
2941 },
2942 });
2943 }
2944
2945 Import::ErrorContextDebugMessage { encoding } => {
2946 let name = self.shims.len().to_string();
2947 self.push(Shim {
2948 name,
2949 debug_name: "error-debug-message".to_string(),
2950 options: RequiredOptions::MEMORY
2951 | RequiredOptions::STRING_ENCODING
2952 | RequiredOptions::REALLOC,
2953 kind: ShimKind::ErrorContextDebugMessage {
2954 for_module,
2955 encoding: *encoding,
2956 },
2957 sig: WasmSignature {
2958 params: vec![WasmType::I32; 2],
2959 results: vec![],
2960 indirect_params: false,
2961 retptr: false,
2962 },
2963 });
2964 }
2965
2966 Import::ThreadNewIndirect => {
2967 let name = self.shims.len().to_string();
2968 self.push(Shim {
2969 name,
2970 debug_name: "thread.new-indirect".to_string(),
2971 options: RequiredOptions::empty(),
2972 kind: ShimKind::ThreadNewIndirect {
2973 func_ty: FuncType::new([ValType::I32], vec![]),
2975 },
2976 sig: WasmSignature {
2977 params: vec![WasmType::I32; 2],
2978 results: vec![WasmType::I32],
2979 indirect_params: false,
2980 retptr: false,
2981 },
2982 });
2983 }
2984
2985 Import::AdapterExport { adapter, func, ty } => {
2988 let name = self.shims.len().to_string();
2989 log::debug!("shim {name} is adapter `{module}::{field}`");
2990 self.push(Shim {
2991 name,
2992 debug_name: format!("adapt-{module}-{field}"),
2993 options: RequiredOptions::MEMORY,
2997 kind: ShimKind::Adapter { adapter, func },
2998 sig: WasmSignature {
2999 params: ty.params().iter().map(to_wasm_type).collect(),
3000 results: ty.results().iter().map(to_wasm_type).collect(),
3001 indirect_params: false,
3002 retptr: false,
3003 },
3004 });
3005
3006 fn to_wasm_type(ty: &wasmparser::ValType) -> WasmType {
3007 match ty {
3008 wasmparser::ValType::I32 => WasmType::I32,
3009 wasmparser::ValType::I64 => WasmType::I64,
3010 wasmparser::ValType::F32 => WasmType::F32,
3011 wasmparser::ValType::F64 => WasmType::F64,
3012 _ => unreachable!(),
3013 }
3014 }
3015 }
3016
3017 Import::InterfaceFunc(key, _, name, abi) => {
3021 self.append_indirect_wit_func(
3022 world,
3023 for_module,
3024 module,
3025 field,
3026 key,
3027 name,
3028 Some(resolve.name_world_key(key)),
3029 *abi,
3030 )?;
3031 }
3032 Import::WorldFunc(key, name, abi) => {
3033 self.append_indirect_wit_func(
3034 world, for_module, module, field, key, name, None, *abi,
3035 )?;
3036 }
3037 }
3038 }
3039
3040 for (export_name, export) in module_exports.iter() {
3046 let id = match export {
3047 Export::ResourceDtor(id) => id,
3048 _ => continue,
3049 };
3050 let resource = resolve.types[*id].name.as_ref().unwrap();
3051 let name = self.shims.len().to_string();
3052 self.push(Shim {
3053 name,
3054 debug_name: format!("dtor-{resource}"),
3055 options: RequiredOptions::empty(),
3056 kind: ShimKind::ResourceDtor {
3057 module: for_module,
3058 export: export_name,
3059 },
3060 sig: WasmSignature {
3061 params: vec![WasmType::I32],
3062 results: Vec::new(),
3063 indirect_params: false,
3064 retptr: false,
3065 },
3066 });
3067 }
3068
3069 Ok(())
3070 }
3071
3072 fn append_indirect_payload_push(
3075 &mut self,
3076 resolve: &Resolve,
3077 for_module: CustomModule<'a>,
3078 module: &str,
3079 async_: bool,
3080 info: &'a PayloadInfo,
3081 kind: PayloadFuncKind,
3082 params: Vec<WasmType>,
3083 results: Vec<WasmType>,
3084 ) {
3085 let debug_name = format!("{module}-{}", info.name);
3086 let name = self.shims.len().to_string();
3087
3088 let payload = info.payload(resolve);
3089 let (wit_param, wit_result) = match kind {
3090 PayloadFuncKind::StreamRead | PayloadFuncKind::FutureRead => (None, payload),
3091 PayloadFuncKind::StreamWrite | PayloadFuncKind::FutureWrite => (payload, None),
3092 };
3093 self.push(Shim {
3094 name,
3095 debug_name,
3096 options: RequiredOptions::MEMORY
3097 | RequiredOptions::for_import(
3098 resolve,
3099 &Function {
3100 name: String::new(),
3101 kind: FunctionKind::Freestanding,
3102 params: match wit_param {
3103 Some(ty) => vec![Param {
3104 name: "a".to_string(),
3105 ty,
3106 span: Default::default(),
3107 }],
3108 None => Vec::new(),
3109 },
3110 result: wit_result,
3111 docs: Default::default(),
3112 stability: Stability::Unknown,
3113 span: Default::default(),
3114 external_id: None,
3115 },
3116 if async_ {
3117 AbiVariant::GuestImportAsync
3118 } else {
3119 AbiVariant::GuestImport
3120 },
3121 ),
3122 kind: ShimKind::PayloadFunc {
3123 for_module,
3124 info,
3125 kind,
3126 },
3127 sig: WasmSignature {
3128 params,
3129 results,
3130 indirect_params: false,
3131 retptr: false,
3132 },
3133 });
3134 }
3135
3136 fn append_indirect_wit_func(
3139 &mut self,
3140 world: &'a ComponentWorld<'a>,
3141 for_module: CustomModule<'a>,
3142 module: &str,
3143 field: &str,
3144 key: &WorldKey,
3145 name: &String,
3146 interface_key: Option<String>,
3147 abi: AbiVariant,
3148 ) -> Result<()> {
3149 let resolve = &world.encoder.metadata.resolve;
3150 let metadata = world.module_metadata_for(for_module);
3151 let interface = &world.import_map[&interface_key];
3152 let (index, _, lowering) = interface.lowerings.get_full(&(name.clone(), abi)).unwrap();
3153 let shim_name = self.shims.len().to_string();
3154 match lowering {
3155 Lowering::Direct | Lowering::ResourceDrop(_) => {}
3156
3157 Lowering::Indirect { sig, options } => {
3158 log::debug!(
3159 "shim {shim_name} is import `{module}::{field}` lowering {index} `{name}`",
3160 );
3161 let encoding = metadata
3162 .import_encodings
3163 .get(resolve, key, name)
3164 .ok_or_else(|| {
3165 anyhow::anyhow!(
3166 "missing component metadata for import of \
3167 `{module}::{field}`"
3168 )
3169 })?;
3170 self.push(Shim {
3171 name: shim_name,
3172 debug_name: format!("indirect-{module}-{field}"),
3173 options: *options,
3174 kind: ShimKind::IndirectLowering {
3175 interface: interface_key,
3176 index,
3177 realloc: for_module,
3178 encoding,
3179 },
3180 sig: sig.clone(),
3181 });
3182 }
3183 }
3184
3185 Ok(())
3186 }
3187
3188 fn push(&mut self, shim: Shim<'a>) {
3189 if !self.shims.contains_key(&shim.kind) {
3193 self.shims.insert(shim.kind.clone(), shim);
3194 }
3195 }
3196}
3197
3198fn task_return_options_and_type(
3199 resolve: &Resolve,
3200 func: &Function,
3201) -> (RequiredOptions, WasmSignature) {
3202 let func_tmp = Function {
3203 name: String::new(),
3204 kind: FunctionKind::Freestanding,
3205 params: match &func.result {
3206 Some(ty) => vec![Param {
3207 name: "a".to_string(),
3208 ty: *ty,
3209 span: Default::default(),
3210 }],
3211 None => Vec::new(),
3212 },
3213 result: None,
3214 docs: Default::default(),
3215 stability: Stability::Unknown,
3216 span: Default::default(),
3217 external_id: None,
3218 };
3219 let abi = AbiVariant::GuestImport;
3220 let mut options = RequiredOptions::for_import(resolve, func, abi);
3221 options.remove(RequiredOptions::REALLOC);
3223 let sig = resolve.wasm_signature(abi, &func_tmp);
3224 (options, sig)
3225}
3226
3227#[derive(Clone, Debug)]
3229pub struct Item {
3230 pub alias: String,
3231 pub kind: ExportKind,
3232 pub which: MainOrAdapter,
3233 pub name: String,
3234}
3235
3236#[derive(Debug, PartialEq, Clone)]
3238pub enum MainOrAdapter {
3239 Main,
3240 Adapter(String),
3241}
3242
3243impl MainOrAdapter {
3244 fn to_custom_module(&self) -> CustomModule<'_> {
3245 match self {
3246 MainOrAdapter::Main => CustomModule::Main,
3247 MainOrAdapter::Adapter(s) => CustomModule::Adapter(s),
3248 }
3249 }
3250}
3251
3252#[derive(Clone)]
3254pub enum Instance {
3255 MainOrAdapter(MainOrAdapter),
3257
3258 Items(Vec<Item>),
3260}
3261
3262#[derive(Clone)]
3265pub struct LibraryInfo {
3266 pub instantiate_after_shims: bool,
3268
3269 pub arguments: Vec<(String, Instance)>,
3271}
3272
3273pub(super) struct Adapter {
3275 wasm: Vec<u8>,
3277
3278 metadata: ModuleMetadata,
3280
3281 required_exports: IndexSet<WorldKey>,
3284
3285 library_info: Option<LibraryInfo>,
3290}
3291
3292#[derive(Default)]
3294pub struct ComponentEncoder {
3295 module: Vec<u8>,
3296 module_import_map: Option<ModuleImportMap>,
3297 pub(super) metadata: Bindgen,
3298 validate: bool,
3299 pub(super) main_module_exports: IndexSet<WorldKey>,
3300 pub(super) adapters: IndexMap<String, Adapter>,
3301 import_name_map: HashMap<String, String>,
3302 realloc_via_memory_grow: bool,
3303 merge_imports_based_on_semver: Option<bool>,
3304 pub(super) reject_legacy_names: bool,
3305 debug_names: bool,
3306}
3307
3308impl ComponentEncoder {
3309 pub fn module(mut self, module: &[u8]) -> Result<Self> {
3315 let (wasm, metadata) = self.decode(module.as_ref())?;
3316 let (wasm, module_import_map) = ModuleImportMap::new(wasm)?;
3317 let exports = self
3318 .merge_metadata(metadata)
3319 .context("failed merge WIT metadata for module with previous metadata")?;
3320 self.main_module_exports.extend(exports);
3321 self.module = if let Some(producers) = &self.metadata.producers {
3322 producers.add_to_wasm(&wasm)?
3323 } else {
3324 wasm.to_vec()
3325 };
3326 self.module_import_map = module_import_map;
3327 Ok(self)
3328 }
3329
3330 fn decode<'a>(&self, wasm: &'a [u8]) -> Result<(Cow<'a, [u8]>, Bindgen)> {
3331 let (bytes, metadata) = metadata::decode(wasm)?;
3332 match bytes {
3333 Some(wasm) => Ok((Cow::Owned(wasm), metadata)),
3334 None => Ok((Cow::Borrowed(wasm), metadata)),
3335 }
3336 }
3337
3338 fn merge_metadata(&mut self, metadata: Bindgen) -> Result<IndexSet<WorldKey>> {
3339 self.metadata.merge(metadata)
3340 }
3341
3342 pub fn validate(mut self, validate: bool) -> Self {
3344 self.validate = validate;
3345 self
3346 }
3347
3348 pub fn debug_names(mut self, debug_names: bool) -> Self {
3350 self.debug_names = debug_names;
3351 self
3352 }
3353
3354 pub fn merge_imports_based_on_semver(mut self, merge: bool) -> Self {
3362 self.merge_imports_based_on_semver = Some(merge);
3363 self
3364 }
3365
3366 pub fn reject_legacy_names(mut self, reject: bool) -> Self {
3375 self.reject_legacy_names = reject;
3376 self
3377 }
3378
3379 pub fn adapter(self, name: &str, bytes: &[u8]) -> Result<Self> {
3397 self.library_or_adapter(name, bytes, None)
3398 }
3399
3400 pub fn library(self, name: &str, bytes: &[u8], library_info: LibraryInfo) -> Result<Self> {
3413 self.library_or_adapter(name, bytes, Some(library_info))
3414 }
3415
3416 fn library_or_adapter(
3417 mut self,
3418 name: &str,
3419 bytes: &[u8],
3420 library_info: Option<LibraryInfo>,
3421 ) -> Result<Self> {
3422 let (wasm, mut metadata) = self.decode(bytes)?;
3423 let adapter_metadata = mem::take(&mut metadata.metadata);
3431 let exports = self.merge_metadata(metadata).with_context(|| {
3432 format!("failed to merge WIT packages of adapter `{name}` into main packages")
3433 })?;
3434 if let Some(library_info) = &library_info {
3435 for (_, instance) in &library_info.arguments {
3437 let resolve = |which: &_| match which {
3438 MainOrAdapter::Main => Ok(()),
3439 MainOrAdapter::Adapter(name) => {
3440 if self.adapters.contains_key(name.as_str()) {
3441 Ok(())
3442 } else {
3443 Err(anyhow!("instance refers to unknown adapter `{name}`"))
3444 }
3445 }
3446 };
3447
3448 match instance {
3449 Instance::MainOrAdapter(which) => resolve(which)?,
3450 Instance::Items(items) => {
3451 for item in items {
3452 resolve(&item.which)?;
3453 }
3454 }
3455 }
3456 }
3457 }
3458 self.adapters.insert(
3459 name.to_string(),
3460 Adapter {
3461 wasm: wasm.to_vec(),
3462 metadata: adapter_metadata,
3463 required_exports: exports,
3464 library_info,
3465 },
3466 );
3467 Ok(self)
3468 }
3469
3470 pub fn realloc_via_memory_grow(mut self, value: bool) -> Self {
3475 self.realloc_via_memory_grow = value;
3476 self
3477 }
3478
3479 pub fn import_name_map(mut self, map: HashMap<String, String>) -> Self {
3490 self.import_name_map = map;
3491 self
3492 }
3493
3494 pub fn encode(&mut self) -> Result<Vec<u8>> {
3496 if self.module.is_empty() {
3497 bail!("a module is required when encoding a component");
3498 }
3499
3500 if self.merge_imports_based_on_semver.unwrap_or(true) {
3501 self.metadata
3502 .resolve
3503 .merge_world_imports_based_on_semver(self.metadata.world)?;
3504 }
3505
3506 self.finalize_resolve_with_nominal_ids();
3507
3508 let world = ComponentWorld::new(self).context("failed to decode world from module")?;
3509 let mut state = EncodingState {
3510 component: ComponentBuilder::default(),
3511 module_index: None,
3512 instance_index: None,
3513 memory_index: None,
3514 shim_instance_index: None,
3515 fixups_module_index: None,
3516 adapter_modules: IndexMap::new(),
3517 adapter_instances: IndexMap::new(),
3518 type_encoding_maps: Default::default(),
3519 instances: Default::default(),
3520 imported_funcs: Default::default(),
3521 aliased_core_items: Default::default(),
3522 info: &world,
3523 export_task_initialization_wrappers: HashMap::new(),
3524 tls_base_instance_index: None,
3525 };
3526 state.encode_imports(&self.import_name_map)?;
3527 state.encode_core_modules();
3528 state.encode_core_instantiation()?;
3529 state.encode_exports(CustomModule::Main)?;
3530 for name in self.adapters.keys() {
3531 state.encode_exports(CustomModule::Adapter(name))?;
3532 }
3533 state.component.append_names();
3534 state
3535 .component
3536 .raw_custom_section(&crate::base_producers().raw_custom_section());
3537 let bytes = state.component.finish();
3538
3539 if self.validate {
3540 Validator::new_with_features(WasmFeatures::all())
3541 .validate_all(&bytes)
3542 .context("failed to validate component output")?;
3543 }
3544
3545 Ok(bytes)
3546 }
3547
3548 fn finalize_resolve_with_nominal_ids(&mut self) {
3557 let world = &self.metadata.resolve.worlds[self.metadata.world];
3564 let main_module_exports = self
3565 .main_module_exports
3566 .iter()
3567 .map(|i| world.exports.get_index_of(i).unwrap())
3568 .collect::<Vec<_>>();
3569 let adapter_exports = self
3570 .adapters
3571 .values()
3572 .map(|adapter| {
3573 adapter
3574 .required_exports
3575 .iter()
3576 .map(|i| world.exports.get_index_of(i).unwrap())
3577 .collect::<Vec<_>>()
3578 })
3579 .collect::<Vec<_>>();
3580
3581 self.metadata
3585 .resolve
3586 .generate_nominal_type_ids(self.metadata.world);
3587
3588 self.main_module_exports.clear();
3591 let world = &self.metadata.resolve.worlds[self.metadata.world];
3592 for index in main_module_exports {
3593 let (key, _) = world.exports.get_index(index).unwrap();
3594 self.main_module_exports.insert(key.clone());
3595 }
3596 for (exports, adapter) in adapter_exports.into_iter().zip(self.adapters.values_mut()) {
3597 adapter.required_exports.clear();
3598 for index in exports {
3599 let (key, _) = world.exports.get_index(index).unwrap();
3600 adapter.required_exports.insert(key.clone());
3601 }
3602 }
3603 }
3604}
3605
3606impl ComponentWorld<'_> {
3607 fn imports_for(&self, module: CustomModule) -> &ImportMap {
3609 match module {
3610 CustomModule::Main => &self.info.imports,
3611 CustomModule::Adapter(name) => &self.adapters[name].info.imports,
3612 }
3613 }
3614
3615 fn exports_for(&self, module: CustomModule) -> &ExportMap {
3617 match module {
3618 CustomModule::Main => &self.info.exports,
3619 CustomModule::Adapter(name) => &self.adapters[name].info.exports,
3620 }
3621 }
3622
3623 fn module_metadata_for(&self, module: CustomModule) -> &ModuleMetadata {
3625 match module {
3626 CustomModule::Main => &self.encoder.metadata.metadata,
3627 CustomModule::Adapter(name) => &self.encoder.adapters[name].metadata,
3628 }
3629 }
3630}
3631
3632#[cfg(all(test, feature = "dummy-module"))]
3633mod test {
3634 use super::*;
3635 use crate::{dummy_module, embed_component_metadata};
3636 use wit_parser::ManglingAndAbi;
3637
3638 #[test]
3639 fn it_renames_imports() {
3640 let mut resolve = Resolve::new();
3641 let pkg = resolve
3642 .push_str(
3643 "test.wit",
3644 r#"
3645package test:wit;
3646
3647interface i {
3648 f: func();
3649}
3650
3651world test {
3652 import i;
3653 import foo: interface {
3654 f: func();
3655 }
3656}
3657"#,
3658 )
3659 .unwrap();
3660 let world = resolve.select_world(&[pkg], None).unwrap();
3661
3662 let mut module = dummy_module(&resolve, world, ManglingAndAbi::Standard32);
3663
3664 embed_component_metadata(&mut module, &resolve, world, StringEncoding::UTF8).unwrap();
3665
3666 let encoded = ComponentEncoder::default()
3667 .import_name_map(HashMap::from([
3668 (
3669 "foo".to_string(),
3670 "unlocked-dep=<foo:bar/foo@{>=1.0.0 <1.1.0}>".to_string(),
3671 ),
3672 (
3673 "test:wit/i".to_string(),
3674 "locked-dep=<foo:bar/i@1.2.3>".to_string(),
3675 ),
3676 ]))
3677 .module(&module)
3678 .unwrap()
3679 .validate(true)
3680 .encode()
3681 .unwrap();
3682
3683 let wat = wasmprinter::print_bytes(encoded).unwrap();
3684 assert!(wat.contains("unlocked-dep=<foo:bar/foo@{>=1.0.0 <1.1.0}>"));
3685 assert!(wat.contains("locked-dep=<foo:bar/i@1.2.3>"));
3686 }
3687}