1use std::borrow::Cow;
2use std::collections::{HashMap, HashSet};
3use std::mem;
4use wasm_encoder::{
5 CodeSection, ConstExpr, CustomSection, DataSection, ElementSection, Elements, Encode,
6 EntityType, ExportKind, ExportSection, Function, FunctionSection, GlobalType, ImportSection,
7 MemoryType, Module, NameMap, NameSection, RefType, TableType, TypeSection, ValType,
8};
9use wit_parser::abi::{WasmSignature, WasmType};
10use wit_parser::{
11 Handle, LiftLowerAbi, LiveTypes, ManglingAndAbi, Resolve, ResourceIntrinsic, SizeAlign, Type,
12 TypeDefKind, TypeId, TypeOwner, WasmExport, WasmExportKind, WasmImport, WorldId, WorldItem,
13 WorldKey,
14};
15
16mod async_;
17mod bindgen;
18mod metadata;
19pub use crate::async_::AsyncFilterSet;
20pub use crate::metadata::Metadata;
21
22pub const C_HEADER: &'static str = include_str!("../wit_dylib.h");
23
24#[derive(Default, Clone, Debug)]
25#[cfg_attr(feature = "clap", derive(clap::Parser))]
26pub struct DylibOpts {
27 #[cfg_attr(feature = "clap", clap(long))]
30 pub interpreter: Option<String>,
31
32 #[cfg_attr(feature = "clap", clap(flatten))]
33 pub async_: AsyncFilterSet,
34}
35
36pub fn create(resolve: &Resolve, world_id: WorldId, opts: Option<&mut DylibOpts>) -> Vec<u8> {
37 create_with_metadata(resolve, world_id, opts).0
38}
39
40pub fn create_with_metadata(
41 resolve: &Resolve,
42 world_id: WorldId,
43 mut opts: Option<&mut DylibOpts>,
44) -> (Vec<u8>, Metadata) {
45 let mut adapter = Adapter::default();
46 if let Some(opts) = &mut opts {
47 adapter.opts = opts.clone();
48 }
49 let result = adapter.encode(resolve, world_id);
50 if let Some(opts) = &mut opts {
51 **opts = adapter.opts;
52 }
53 (result, adapter.metadata)
54}
55
56#[derive(Default)]
57struct Adapter {
58 types: TypeSection,
59 wasm_type_map: HashMap<(Vec<ValType>, Vec<ValType>), u32>,
60 imports: ImportSection,
61 imports_done: bool,
62 global_index: u32,
63 table_base: Option<u32>,
64 memory_base: Option<u32>,
65 stack_pointer: Option<u32>,
66 func_index: u32,
67 functions: FunctionSection,
68 exports: ExportSection,
69 code: CodeSection,
70 global_names: NameMap,
71 function_names: NameMap,
72 metadata: Metadata,
73 type_map: HashMap<TypeId, metadata::Type>,
74 resource_map: HashMap<TypeId, usize>,
75 export_resource_map: HashMap<TypeId, usize>,
76 intrinsics: Option<bindgen::WitInterpreterIntrinsics>,
77 sizes: SizeAlign,
78 opts: DylibOpts,
79
80 elem_segment: Vec<u32>,
86}
87
88#[derive(Default)]
89struct Imports<'a> {
90 wit_imports: Vec<WitImport<'a>>,
91 wit_exports: Vec<WitExport<'a>>,
92}
93
94struct WitImport<'a> {
95 interface: Option<&'a WorldKey>,
96 func: &'a wit_parser::Function,
97 import_index: u32,
98}
99
100struct WitExport<'a> {
101 interface: Option<&'a WorldKey>,
102 func: &'a wit_parser::Function,
103 async_task_return_index: Option<u32>,
104}
105
106struct PayloadData {
109 new_elem_index: u32,
111 read_elem_index: u32,
113 write_elem_index: u32,
115 cancel_read_elem_index: u32,
117 cancel_write_elem_index: u32,
119 drop_readable_elem_index: u32,
121 drop_writable_elem_index: u32,
123 ordinal: usize,
127 function: String,
130}
131
132impl Adapter {
133 pub fn encode(&mut self, resolve: &Resolve, world_id: WorldId) -> Vec<u8> {
134 self.sizes.fill(resolve);
135
136 let imports = self.add_imports(resolve, world_id);
141
142 let mut payload_data = HashMap::new();
143 self.collect_payload_data(resolve, world_id, &mut payload_data);
144
145 self.imports_done = true;
146
147 let cabi_realloc = self.intrinsics().cabi_realloc;
151 self.exports
152 .export("cabi_realloc", ExportKind::Func, cabi_realloc);
153
154 self.bindgen_world(resolve, world_id, &imports, &payload_data);
157
158 let (metadata_offset, metadata) = self.encode_metadata();
164 let mut ctor = Function::new([]);
165 ctor.instructions().i32_const(metadata_offset as i32);
166 ctor.instructions().global_get(self.memory_base());
167 ctor.instructions().i32_add();
168 ctor.instructions().call(self.intrinsics().initialize);
169 ctor.instructions().end();
170 let ty = self.define_ty([], []);
171 self.define_func("__wasm_call_ctors", ty, ctor, true);
172
173 self.finish(&metadata)
174 }
175
176 fn mangling(
177 &mut self,
178 resolve: &Resolve,
179 interface: Option<&WorldKey>,
180 func: &wit_parser::Function,
181 is_import: bool,
182 ) -> ManglingAndAbi {
183 let abi = if self
184 .opts
185 .async_
186 .is_async(resolve, interface, func, is_import)
187 {
188 LiftLowerAbi::AsyncCallback
189 } else {
190 LiftLowerAbi::Sync
191 };
192 ManglingAndAbi::Legacy(abi)
193 }
194
195 fn resource_intrinsic_mangling(&mut self) -> ManglingAndAbi {
196 ManglingAndAbi::Legacy(LiftLowerAbi::Sync)
197 }
198
199 fn collect_payload_data_for_func(
203 &mut self,
204 resolve: &Resolve,
205 interface: Option<&WorldKey>,
206 func: &wit_parser::Function,
207 prefix: &str,
208 data: &mut HashMap<TypeId, PayloadData>,
209 ) {
210 let mut make = |arg_count, kind, ordinal| {
211 let module = format!(
212 "{prefix}{}",
213 interface
214 .map(|name| resolve.name_world_key(name))
215 .unwrap_or_else(|| "$root".into())
216 );
217 let function = func.name.clone();
218
219 let import = |me: &mut Self, prefix, name, params, results| {
220 let ty = me.define_ty(params, results);
221 let import = me.import_func(
222 &module,
223 &format!("{prefix}[{kind}-{name}-{ordinal}]{function}"),
224 ty,
225 );
226 me.push_elem(import)
227 };
228
229 let new_elem_index = import(self, "", "new", vec![], vec![ValType::I64]);
230 let read_elem_index = import(
231 self,
232 "[async-lower]",
233 "read",
234 vec![ValType::I32; arg_count],
235 vec![ValType::I32],
236 );
237 let write_elem_index = import(
238 self,
239 "[async-lower]",
240 "write",
241 vec![ValType::I32; arg_count],
242 vec![ValType::I32],
243 );
244 let cancel_read_elem_index = import(
245 self,
246 "",
247 "cancel-read",
248 vec![ValType::I32],
249 vec![ValType::I32],
250 );
251 let cancel_write_elem_index = import(
252 self,
253 "",
254 "cancel-write",
255 vec![ValType::I32],
256 vec![ValType::I32],
257 );
258 let drop_readable_elem_index =
259 import(self, "", "drop-readable", vec![ValType::I32], vec![]);
260 let drop_writable_elem_index =
261 import(self, "", "drop-writable", vec![ValType::I32], vec![]);
262
263 PayloadData {
264 new_elem_index,
265 read_elem_index,
266 write_elem_index,
267 cancel_read_elem_index,
268 cancel_write_elem_index,
269 drop_readable_elem_index,
270 drop_writable_elem_index,
271 ordinal,
272 function,
273 }
274 };
275
276 for (ordinal, ty) in func
277 .find_futures_and_streams(resolve)
278 .into_iter()
279 .enumerate()
280 {
281 match &resolve.types[ty].kind {
282 TypeDefKind::Future(_) => {
283 data.entry(ty).or_insert_with(|| make(2, "future", ordinal))
284 }
285 TypeDefKind::Stream(_) => {
286 data.entry(ty).or_insert_with(|| make(3, "stream", ordinal))
287 }
288 _ => unreachable!(),
289 };
290 }
291 }
292
293 fn collect_payload_data(
294 &mut self,
295 resolve: &Resolve,
296 world_id: WorldId,
297 data: &mut HashMap<TypeId, PayloadData>,
298 ) {
299 let world = &resolve.worlds[world_id];
300
301 for (key, import) in world.imports.iter() {
302 match import {
303 WorldItem::Interface { id, .. } => {
304 for (_, func) in resolve.interfaces[*id].functions.iter() {
305 self.collect_payload_data_for_func(resolve, Some(key), func, "", data);
306 }
307 }
308 WorldItem::Type { .. } => {}
309 WorldItem::Function(func) => {
310 self.collect_payload_data_for_func(resolve, None, func, "", data);
311 }
312 }
313 }
314
315 for (key, export) in world.exports.iter() {
316 match export {
317 WorldItem::Interface { id, .. } => {
318 for (_, func) in resolve.interfaces[*id].functions.iter() {
319 self.collect_payload_data_for_func(
320 resolve,
321 Some(key),
322 func,
323 "[export]",
324 data,
325 );
326 }
327 }
328 WorldItem::Type { .. } => unreachable!(),
329 WorldItem::Function(func) => {
330 self.collect_payload_data_for_func(resolve, None, func, "[export]", data);
331 }
332 }
333 }
334 }
335
336 fn add_imports<'a>(&mut self, resolve: &'a Resolve, world_id: WorldId) -> Imports<'a> {
337 let mut ret = Imports::default();
338 let world = &resolve.worlds[world_id];
339
340 self.intrinsics = Some(bindgen::WitInterpreterIntrinsics::new(self));
343
344 for (interface, import) in world.imports.iter() {
349 match import {
350 WorldItem::Interface { id, .. } => {
351 for (_, func) in resolve.interfaces[*id].functions.iter() {
352 self.add_imported_func(resolve, Some(interface), func, &mut ret);
353 }
354 for (_, ty) in resolve.interfaces[*id].types.iter() {
355 self.add_imported_type_intrinsics(resolve, Some(interface), *ty);
356 }
357 }
358 WorldItem::Type { id, .. } => {
359 self.add_imported_type_intrinsics(resolve, None, *id);
360 }
361 WorldItem::Function(func) => {
362 self.add_imported_func(resolve, None, func, &mut ret);
363 }
364 }
365 }
366
367 for (name, export) in world.exports.iter() {
370 match export {
371 WorldItem::Function(func) => {
372 self.add_imported_func_intrinsics_for_export(resolve, None, func, &mut ret);
373 }
374 WorldItem::Interface { id: export, .. } => {
375 for (_, ty) in resolve.interfaces[*export].types.iter() {
376 self.add_imported_type_intrinsics_for_export(resolve, Some(name), *ty);
377 }
378 for (_, func) in resolve.interfaces[*export].functions.iter() {
379 self.add_imported_func_intrinsics_for_export(
380 resolve,
381 Some(name),
382 func,
383 &mut ret,
384 );
385 }
386 }
387 WorldItem::Type { .. } => unreachable!(),
388 }
389 }
390
391 let const_i32_global = GlobalType {
392 val_type: ValType::I32,
393 mutable: false,
394 shared: false,
395 };
396 let mut_i32_global = GlobalType {
397 val_type: ValType::I32,
398 mutable: true,
399 shared: false,
400 };
401
402 self.table_base = Some(self.import_global("env", "__table_base", const_i32_global));
403 self.memory_base = Some(self.import_global("env", "__memory_base", const_i32_global));
404 self.stack_pointer = Some(self.import_global("env", "__stack_pointer", mut_i32_global));
405
406 self.imports.import(
407 "env",
408 "memory",
409 EntityType::Memory(MemoryType {
410 minimum: 0,
411 maximum: None,
412 memory64: false,
413 shared: false,
414 page_size_log2: None,
415 }),
416 );
417
418 self.imports.import(
419 "env",
420 "__indirect_function_table",
421 EntityType::Table(TableType {
422 element_type: RefType::FUNCREF,
423 minimum: 0,
424 maximum: None,
425 table64: false,
426 shared: false,
427 }),
428 );
429 ret
430 }
431
432 fn add_imported_func<'a>(
433 &mut self,
434 resolve: &'a Resolve,
435 interface: Option<&'a WorldKey>,
436 func: &'a wit_parser::Function,
437 imports: &mut Imports<'a>,
438 ) {
439 let mangling = self.mangling(resolve, interface, func, true);
440 let (module, name) =
441 resolve.wasm_import_name(mangling, WasmImport::Func { interface, func });
442 let sig = resolve.wasm_signature(mangling.import_variant(), func);
443 let ty = self.define_wasm_sig(sig);
444 let import_index = self.import_func(&module, &name, ty);
445 imports.wit_imports.push(WitImport {
446 func,
447 interface,
448 import_index,
449 });
450 }
451
452 fn add_imported_type_intrinsics<'a>(
453 &mut self,
454 resolve: &Resolve,
455 interface: Option<&'a WorldKey>,
456 id: TypeId,
457 ) {
458 let mangling = self.resource_intrinsic_mangling();
459 let ty = &resolve.types[id];
460 match ty.kind {
461 TypeDefKind::Resource => {
462 let (module, name) = resolve.wasm_import_name(
463 mangling,
464 WasmImport::ResourceIntrinsic {
465 interface,
466 resource: id,
467 intrinsic: ResourceIntrinsic::ImportedDrop,
468 },
469 );
470 let core_ty = self.define_ty([ValType::I32], []);
471 let drop = self.import_func(&module, &name, core_ty);
472 let drop_elem_index = self.push_elem(drop);
473 let resource_index = self.metadata.resources.len();
474 self.metadata.resources.push(metadata::Resource {
475 id,
476 interface: interface.map(|i| resolve.name_world_key(i)),
477 name: ty.name.clone().unwrap(),
478 drop_elem_index,
479 new_elem_index: None,
480 rep_elem_index: None,
481 });
482 let prev = self.resource_map.insert(id, resource_index);
483 assert!(prev.is_none());
484 }
485
486 _ => {}
489 }
490 }
491
492 fn add_imported_type_intrinsics_for_export<'a>(
493 &mut self,
494 resolve: &Resolve,
495 interface: Option<&'a WorldKey>,
496 id: TypeId,
497 ) {
498 let ty = &resolve.types[id];
499 let mangling = self.resource_intrinsic_mangling();
500 match ty.kind {
501 TypeDefKind::Resource => {
502 let drop_ty = self.define_ty([ValType::I32], []);
503 let new_rep_ty = self.define_ty([ValType::I32], [ValType::I32]);
504
505 let mut import = |ty, intrinsic| {
506 let (module, name) = resolve.wasm_import_name(
507 mangling,
508 WasmImport::ResourceIntrinsic {
509 interface,
510 resource: id,
511 intrinsic,
512 },
513 );
514 self.import_func(&module, &name, ty)
515 };
516
517 let drop = import(drop_ty, ResourceIntrinsic::ExportedDrop);
518 let new = import(new_rep_ty, ResourceIntrinsic::ExportedNew);
519 let rep = import(new_rep_ty, ResourceIntrinsic::ExportedRep);
520
521 let drop_elem_index = self.push_elem(drop);
522 let new_elem_index = Some(self.push_elem(new));
523 let rep_elem_index = Some(self.push_elem(rep));
524
525 let resource_index = self.metadata.resources.len();
526 self.metadata.resources.push(metadata::Resource {
527 id,
528 interface: interface.map(|i| resolve.name_world_key(i)),
529 name: ty.name.clone().unwrap(),
530 drop_elem_index,
531 new_elem_index,
532 rep_elem_index,
533 });
534
535 let prev = self.export_resource_map.insert(id, resource_index);
541 assert!(prev.is_none());
542 }
543
544 _ => {}
547 }
548 }
549
550 fn add_imported_func_intrinsics_for_export<'a>(
553 &mut self,
554 resolve: &Resolve,
555 interface: Option<&'a WorldKey>,
556 func: &'a wit_parser::Function,
557 ret: &mut Imports<'a>,
558 ) {
559 let mangling = self.mangling(resolve, interface, func, false);
560 let async_task_return_index = if mangling.is_async() {
561 let (module, name, sig) =
562 func.task_return_import(resolve, interface, mangling.mangling());
563 let ty = self.define_wasm_sig(sig);
564 Some(self.import_func(&module, &name, ty))
565 } else {
566 None
567 };
568 ret.wit_exports.push(WitExport {
569 interface,
570 func,
571 async_task_return_index,
572 });
573 }
574
575 fn bindgen_world(
576 &mut self,
577 resolve: &Resolve,
578 world_id: WorldId,
579 imports: &Imports<'_>,
580 payload_data: &HashMap<TypeId, PayloadData>,
581 ) {
582 let world = &resolve.worlds[world_id];
583
584 let mut import_types = LiveTypes::default();
588 let mut interface_names = HashMap::new();
589 for (interface, import) in world.imports.iter() {
590 import_types.add_world_item(resolve, import);
591 if let WorldItem::Interface { id, .. } = import {
592 interface_names.insert(*id, interface);
593 }
594 }
595 for (_, export) in world.exports.iter() {
596 match export {
597 WorldItem::Function(func) => import_types.add_func(resolve, func),
598 WorldItem::Interface { .. } => {}
599 WorldItem::Type { .. } => unreachable!(),
600 }
601 }
602 for ty in import_types.iter() {
603 let key = match resolve.types[ty].owner {
604 TypeOwner::Interface(id) => Some(interface_names[&id]),
605 _ => None,
606 };
607 self.register_type(resolve, key, ty, payload_data);
608 }
609
610 for import in imports.wit_imports.iter() {
614 self.bindgen_world_func_import(resolve, import);
615 }
616 for export in imports.wit_exports.iter().filter(|i| i.interface.is_none()) {
617 self.bindgen_world_func_export(resolve, export);
618 }
619
620 let to_keep = imported_types_used_by_exported_interfaces(resolve, world_id);
627 self.type_map.retain(|id, _| to_keep.contains(*id));
628 let mut exported_types = LiveTypes::default();
629 let mut export_names = HashMap::new();
630 for (interface, import) in world.exports.iter() {
631 if let WorldItem::Interface { id, .. } = import {
632 exported_types.add_world_item(resolve, import);
633 export_names.insert(*id, interface);
634 }
635 }
636 for (ty, index) in mem::take(&mut self.export_resource_map) {
637 self.resource_map.insert(ty, index);
638 }
639 for ty in exported_types.iter() {
640 if self.type_map.contains_key(&ty) {
641 continue;
642 }
643 let key = match resolve.types[ty].owner {
644 TypeOwner::Interface(id) => Some(export_names[&id]),
645 _ => None,
646 };
647 self.register_type(resolve, key, ty, payload_data);
648
649 if let Some(index) = self.resource_map.get(&ty) {
650 self.bindgen_world_export_resource_dtor(resolve, key.unwrap(), ty, *index);
651 }
652 }
653
654 for export in imports.wit_exports.iter().filter(|i| i.interface.is_some()) {
657 self.bindgen_world_func_export(resolve, export);
658 }
659 }
660
661 fn register_type(
667 &mut self,
668 resolve: &Resolve,
669 key: Option<&WorldKey>,
670 id: TypeId,
671 payload_data: &HashMap<TypeId, PayloadData>,
672 ) {
673 let ty = &resolve.types[id];
674 let interface = key.map(|key| resolve.name_world_key(key));
675 let name = ty.name.clone();
676 let result = match &ty.kind {
677 TypeDefKind::Record(r) => {
678 let index = self.metadata.records.len();
679 let fields = r
680 .fields
681 .iter()
682 .map(|field| (field.name.clone(), self.lookup_ty(&field.ty)))
683 .collect();
684 self.metadata.records.push(metadata::Record {
685 id,
686 interface,
687 name: name.unwrap(),
688 fields,
689 });
690 metadata::Type::Record(index)
691 }
692 TypeDefKind::Flags(t) => {
693 let index = self.metadata.flags.len();
694 let names = t.flags.iter().map(|f| f.name.clone()).collect();
695 self.metadata.flags.push(metadata::Flags {
696 id,
697 interface,
698 name: name.unwrap(),
699 names,
700 });
701 metadata::Type::Flags(index)
702 }
703 TypeDefKind::Tuple(t) => {
704 let index = self.metadata.tuples.len();
705 let types = t.types.iter().map(|t| self.lookup_ty(t)).collect();
706 self.metadata.tuples.push(metadata::Tuple {
707 id,
708 interface,
709 name,
710 types,
711 });
712 metadata::Type::Tuple(index)
713 }
714 TypeDefKind::Variant(t) => {
715 let index = self.metadata.variants.len();
716 let cases = t
717 .cases
718 .iter()
719 .map(|c| (c.name.clone(), c.ty.map(|t| self.lookup_ty(&t))))
720 .collect();
721 self.metadata.variants.push(metadata::Variant {
722 id,
723 interface,
724 name: name.unwrap(),
725 cases,
726 });
727 metadata::Type::Variant(index)
728 }
729 TypeDefKind::Enum(t) => {
730 let index = self.metadata.enums.len();
731 let names = t.cases.iter().map(|f| f.name.clone()).collect();
732 self.metadata.enums.push(metadata::Enum {
733 id,
734 interface,
735 name: name.unwrap(),
736 names,
737 });
738 metadata::Type::Enum(index)
739 }
740 TypeDefKind::Option(t) => {
741 let index = self.metadata.options.len();
742 self.metadata.options.push(metadata::WitOption {
743 id,
744 interface,
745 name,
746 ty: self.lookup_ty(t),
747 });
748 metadata::Type::Option(index)
749 }
750 TypeDefKind::Result(t) => {
751 let index = self.metadata.results.len();
752 self.metadata.results.push(metadata::WitResult {
753 id,
754 interface,
755 name,
756 ok: t.ok.map(|t| self.lookup_ty(&t)),
757 err: t.err.map(|t| self.lookup_ty(&t)),
758 });
759 metadata::Type::Result(index)
760 }
761 TypeDefKind::List(t) => {
762 let index = self.metadata.lists.len();
763 self.metadata.lists.push(metadata::List {
764 id,
765 interface,
766 name,
767 ty: self.lookup_ty(t),
768 });
769 metadata::Type::List(index)
770 }
771 TypeDefKind::FixedLengthList(t, len) => {
772 let index = self.metadata.fixed_length_lists.len();
773 self.metadata
774 .fixed_length_lists
775 .push(metadata::FixedLengthList {
776 id,
777 interface,
778 name,
779 len: *len,
780 ty: self.lookup_ty(t),
781 });
782 metadata::Type::FixedLengthList(index)
783 }
784 TypeDefKind::Future(t) => {
785 let index = self.metadata.futures.len();
786
787 let Some(&PayloadData {
788 new_elem_index,
789 read_elem_index,
790 write_elem_index,
791 cancel_read_elem_index,
792 cancel_write_elem_index,
793 drop_readable_elem_index,
794 drop_writable_elem_index,
795 ordinal,
796 ref function,
797 }) = payload_data.get(&id)
798 else {
799 panic!("encountered future type not used in any function")
801 };
802
803 let lift_elem_index = t.map(|t| {
807 let ty = self.define_ty([ValType::I32; 2], []);
808 let func = bindgen::lift_payload(self, resolve, t);
809 let func = self.define_func(
810 &format!("[future-lift-{ordinal}]{function}"),
811 ty,
812 func,
813 false,
814 );
815 self.push_elem(func)
816 });
817
818 let lower_elem_index = t.map(|t| {
819 let ty = self.define_ty([ValType::I32; 2], []);
820 let func = bindgen::lower_payload(self, resolve, t);
821 let func = self.define_func(
822 &format!("[future-lower-{ordinal}]{function}"),
823 ty,
824 func,
825 false,
826 );
827 self.push_elem(func)
828 });
829
830 self.metadata.futures.push(metadata::Future {
831 id,
832 interface,
833 name,
834 ty: t.map(|t| self.lookup_ty(&t)),
835 new_elem_index,
836 read_elem_index,
837 write_elem_index,
838 cancel_read_elem_index,
839 cancel_write_elem_index,
840 drop_readable_elem_index,
841 drop_writable_elem_index,
842 lift_elem_index,
843 lower_elem_index,
844 abi_payload_size: t.map(|t| self.sizes.size(&t).size_wasm32()).unwrap_or(0),
845 abi_payload_align: t.map(|t| self.sizes.align(&t).align_wasm32()).unwrap_or(1),
846 });
847 metadata::Type::Future(index)
848 }
849 TypeDefKind::Stream(t) => {
850 let index = self.metadata.streams.len();
851
852 let Some(&PayloadData {
853 new_elem_index,
854 read_elem_index,
855 write_elem_index,
856 cancel_read_elem_index,
857 cancel_write_elem_index,
858 drop_readable_elem_index,
859 drop_writable_elem_index,
860 ordinal,
861 ref function,
862 }) = payload_data.get(&id)
863 else {
864 panic!("encountered stream type not used in any function")
866 };
867
868 let lift_elem_index = t.map(|t| {
879 let ty = self.define_ty([ValType::I32; 2], []);
880 let func = bindgen::lift_payload(self, resolve, t);
881 let func = self.define_func(
882 &format!("[stream-lift-{ordinal}]{function}"),
883 ty,
884 func,
885 false,
886 );
887 self.push_elem(func)
888 });
889
890 let lower_elem_index = t.map(|t| {
891 let ty = self.define_ty([ValType::I32; 2], []);
892 let func = bindgen::lower_payload(self, resolve, t);
893 let func = self.define_func(
894 &format!("[stream-lower-{ordinal}]{function}"),
895 ty,
896 func,
897 false,
898 );
899 self.push_elem(func)
900 });
901
902 self.metadata.streams.push(metadata::Stream {
903 id,
904 interface,
905 name,
906 ty: t.map(|t| self.lookup_ty(&t)),
907 new_elem_index,
908 read_elem_index,
909 write_elem_index,
910 cancel_read_elem_index,
911 cancel_write_elem_index,
912 drop_readable_elem_index,
913 drop_writable_elem_index,
914 lift_elem_index,
915 lower_elem_index,
916 abi_payload_size: t.map(|t| self.sizes.size(&t).size_wasm32()).unwrap_or(0),
917 abi_payload_align: t.map(|t| self.sizes.align(&t).align_wasm32()).unwrap_or(1),
918 });
919 metadata::Type::Stream(index)
920 }
921 TypeDefKind::Type(t) => {
922 let index = self.metadata.aliases.len();
923 self.metadata.aliases.push(metadata::Alias {
924 id,
925 interface,
926 name: name.unwrap(),
927 ty: self.lookup_ty(t),
928 });
929 metadata::Type::Alias(index)
930 }
931 TypeDefKind::Resource => metadata::Type::Own(self.resource_map[&id]),
932
933 TypeDefKind::Handle(Handle::Own(t)) => {
936 metadata::Type::Own(self.resource_map[&dealias(resolve, *t)])
937 }
938 TypeDefKind::Handle(Handle::Borrow(t)) => {
939 metadata::Type::Borrow(self.resource_map[&dealias(resolve, *t)])
940 }
941 TypeDefKind::Map(_, _) => {
942 todo!("map")
943 }
944 TypeDefKind::Unknown => unreachable!(),
945 };
946 self.type_map.insert(id, result);
947 }
948
949 fn lookup_ty(&self, ty: &Type) -> metadata::Type {
950 match ty {
951 Type::U8 => metadata::Type::U8,
952 Type::U16 => metadata::Type::U16,
953 Type::U32 => metadata::Type::U32,
954 Type::U64 => metadata::Type::U64,
955 Type::S8 => metadata::Type::S8,
956 Type::S16 => metadata::Type::S16,
957 Type::S32 => metadata::Type::S32,
958 Type::S64 => metadata::Type::S64,
959 Type::F32 => metadata::Type::F32,
960 Type::F64 => metadata::Type::F64,
961 Type::Bool => metadata::Type::Bool,
962 Type::Char => metadata::Type::Char,
963 Type::String => metadata::Type::String,
964 Type::ErrorContext => metadata::Type::ErrorContext,
965 Type::Id(id) => self.type_map[id],
969 }
970 }
971
972 fn bindgen_world_func_import(&mut self, resolve: &Resolve, import: &WitImport<'_>) {
973 let func = import.func;
974 let mangling = self.mangling(resolve, import.interface, func, true);
975 let body = bindgen::import(
976 self,
977 resolve,
978 func,
979 mangling.import_variant(),
980 import.import_index,
981 );
982
983 let ty = if mangling.is_async() {
984 self.define_ty([ValType::I32; 2], [ValType::I32])
986 } else {
987 self.define_ty([ValType::I32], [])
989 };
990
991 let idx = self.define_func(&format!("adapter {}", func.name), ty, body, false);
992 let elem_index = self.push_elem(idx);
993
994 let sync_import_elem_index;
995 let async_import_elem_index;
996 let async_import_lift_results_elem_index;
997
998 if mangling.is_async() {
999 sync_import_elem_index = None;
1000 async_import_elem_index = Some(elem_index);
1001 let body =
1002 bindgen::lift_async_import_results(self, resolve, func, mangling.import_variant());
1003 let ty = self.define_ty([ValType::I32; 2], []);
1004 let idx = self.define_func(&format!("lift results {}", func.name), ty, body, false);
1005 async_import_lift_results_elem_index = Some(self.push_elem(idx));
1006 } else {
1007 sync_import_elem_index = Some(elem_index);
1008 async_import_elem_index = None;
1009 async_import_lift_results_elem_index = None;
1010 }
1011
1012 self.metadata.import_funcs.push(metadata::ImportFunc {
1013 interface: import.interface.map(|k| resolve.name_world_key(k)),
1014 name: func.name.clone(),
1015 sync_import_elem_index,
1016 async_import_elem_index,
1017 async_import_lift_results_elem_index,
1018 args: func.params.iter().map(|p| self.lookup_ty(&p.ty)).collect(),
1019 result: func.result.map(|t| self.lookup_ty(&t)),
1020 async_abi_area: self.async_import_abi_area(resolve, mangling, func),
1021 })
1022 }
1023
1024 fn async_import_abi_area(
1027 &self,
1028 resolve: &Resolve,
1029 mangling: ManglingAndAbi,
1030 func: &wit_parser::Function,
1031 ) -> Option<(usize, usize)> {
1032 if !mangling.is_async() {
1033 return None;
1034 }
1035
1036 let info = self
1037 .sizes
1038 .record(bindgen::async_import_abi_area_types(resolve, func));
1039 Some((info.size.size_wasm32(), info.align.align_wasm32()))
1040 }
1041
1042 fn bindgen_world_func_export(&mut self, resolve: &Resolve, export: &WitExport<'_>) {
1043 let func = export.func;
1044 let mangling = self.mangling(resolve, export.interface, func, false);
1045 let sig = resolve.wasm_signature(mangling.export_variant(), func);
1046 let ty = self.define_wasm_sig(sig);
1047 let name = resolve.wasm_export_name(
1048 mangling,
1049 WasmExport::Func {
1050 interface: export.interface,
1051 func,
1052 kind: WasmExportKind::Normal,
1053 },
1054 );
1055
1056 let metadata_func_index = self.metadata.export_funcs.len();
1057 let body = bindgen::export(
1058 self,
1059 resolve,
1060 func,
1061 mangling.export_variant(),
1062 metadata_func_index,
1063 );
1064 self.define_func(&name, ty, body, true);
1065
1066 let mut async_export_task_return_elem_index = None;
1067 match mangling {
1068 ManglingAndAbi::Standard32 | ManglingAndAbi::Legacy(LiftLowerAbi::Sync) => {
1072 let post_return_name = resolve.wasm_export_name(
1073 mangling,
1074 WasmExport::Func {
1075 interface: export.interface,
1076 func,
1077 kind: WasmExportKind::PostReturn,
1078 },
1079 );
1080 let post_return = bindgen::post_return(
1081 self,
1082 resolve,
1083 func,
1084 mangling.export_variant(),
1085 metadata_func_index,
1086 );
1087 let mut sig = resolve.wasm_signature(mangling.export_variant(), func);
1088 sig.params = mem::take(&mut sig.results);
1089 let post_return_ty = self.define_wasm_sig(sig);
1090 self.define_func(&post_return_name, post_return_ty, post_return, true);
1091 }
1092
1093 ManglingAndAbi::Legacy(LiftLowerAbi::AsyncCallback) => {
1100 let callback_name = resolve.wasm_export_name(
1101 mangling,
1102 WasmExport::Func {
1103 interface: export.interface,
1104 func,
1105 kind: WasmExportKind::Callback,
1106 },
1107 );
1108 let mut callback = Function::new([]);
1113 let mut ins = callback.instructions();
1114 ins.local_get(0);
1115 ins.local_get(1);
1116 ins.local_get(2);
1117 ins.i32_const(metadata_func_index.try_into().unwrap());
1118 let export_async_callback = self.intrinsics().export_async_callback;
1119 ins.call(export_async_callback);
1120 ins.end();
1121 let callback_ty = self.define_ty([ValType::I32; 3], [ValType::I32]);
1122 self.define_func(&callback_name, callback_ty, callback, true);
1123
1124 let task_return = bindgen::task_return(
1125 self,
1126 resolve,
1127 func,
1128 mangling.export_variant(),
1129 export.async_task_return_index.unwrap(),
1130 );
1131 let task_return_ty = self.define_ty([ValType::I32], []);
1132 let task_return = self.define_func(
1133 &format!("task.return {}", func.name),
1134 task_return_ty,
1135 task_return,
1136 false,
1137 );
1138 async_export_task_return_elem_index = Some(self.push_elem(task_return));
1139 }
1140
1141 ManglingAndAbi::Legacy(LiftLowerAbi::AsyncStackful) => unimplemented!(),
1142 }
1143
1144 self.metadata.export_funcs.push(metadata::ExportFunc {
1145 interface: export.interface.map(|k| resolve.name_world_key(k)),
1146 name: func.name.clone(),
1147 async_export_task_return_elem_index,
1148 args: func.params.iter().map(|p| self.lookup_ty(&p.ty)).collect(),
1149 result: func.result.map(|t| self.lookup_ty(&t)),
1150 })
1151 }
1152
1153 fn bindgen_world_export_resource_dtor(
1154 &mut self,
1155 resolve: &Resolve,
1156 interface: &WorldKey,
1157 resource: TypeId,
1158 index: usize,
1159 ) {
1160 let mangling = self.resource_intrinsic_mangling();
1161 let name = resolve.wasm_export_name(
1162 mangling,
1163 WasmExport::ResourceDtor {
1164 interface,
1165 resource,
1166 },
1167 );
1168 let dtor = self.intrinsics().resource_dtor;
1169 let mut func = Function::new([]);
1170 let mut ins = func.instructions();
1171 ins.i32_const(index.try_into().unwrap());
1172 ins.local_get(0);
1173 ins.call(dtor);
1174 ins.end();
1175 let ty = self.define_ty([ValType::I32], []);
1176 self.define_func(&name, ty, func, true);
1177 }
1178
1179 fn encode_metadata(&mut self) -> (u32, Vec<u8>) {
1180 let (metadata_offset, metadata, apply_relocs) =
1181 self.metadata.encode(self.table_base(), self.memory_base());
1182 if let Some(apply_relocs) = apply_relocs {
1183 let ty = self.define_ty([], []);
1184 self.define_func("__wasm_apply_data_relocs", ty, apply_relocs, true);
1185 }
1186 (metadata_offset, metadata)
1187 }
1188
1189 fn table_base(&self) -> u32 {
1190 self.table_base.unwrap()
1191 }
1192
1193 fn intrinsics(&self) -> &bindgen::WitInterpreterIntrinsics {
1194 self.intrinsics.as_ref().unwrap()
1195 }
1196
1197 fn stack_pointer(&self) -> u32 {
1198 self.stack_pointer.unwrap()
1199 }
1200
1201 fn memory_base(&self) -> u32 {
1202 self.memory_base.unwrap()
1203 }
1204
1205 fn push_elem(&mut self, elem: u32) -> u32 {
1206 let ret = self.elem_segment.len();
1207 self.elem_segment.push(elem);
1208 u32::try_from(ret).unwrap()
1209 }
1210
1211 fn finish(&mut self, metadata: &[u8]) -> Vec<u8> {
1212 let mut elements = ElementSection::new();
1214 if !self.elem_segment.is_empty() {
1215 elements.active(
1216 Some(0),
1217 &ConstExpr::global_get(self.table_base()),
1218 Elements::Functions(Cow::Borrowed(&self.elem_segment)),
1219 );
1220 }
1221
1222 let mut data = DataSection::new();
1224 data.active(
1225 0,
1226 &ConstExpr::global_get(self.memory_base()),
1227 metadata.iter().copied(),
1228 );
1229
1230 let mut names = NameSection::new();
1231 names.functions(&self.function_names);
1232 names.globals(&self.global_names);
1233
1234 let dylink0 = {
1235 struct MemInfo {
1236 memory_size: u32,
1237 memory_alignment: u32,
1238 table_size: u32,
1239 table_alignment: u32,
1240 }
1241
1242 let mem_info = MemInfo {
1243 memory_size: metadata.len().try_into().unwrap(),
1244 memory_alignment: 2,
1245 table_size: self.elem_segment.len().try_into().unwrap(),
1246 table_alignment: 0,
1247 };
1248
1249 let mut mem_info_subsection = Vec::new();
1250 mem_info.memory_size.encode(&mut mem_info_subsection);
1251 mem_info.memory_alignment.encode(&mut mem_info_subsection);
1252 mem_info.table_size.encode(&mut mem_info_subsection);
1253 mem_info.table_alignment.encode(&mut mem_info_subsection);
1254
1255 let mut needed_subsection = Vec::new();
1256 if let Some(name) = &self.opts.interpreter {
1257 [name.as_str()].encode(&mut needed_subsection);
1258 }
1259
1260 const WASM_DYLINK_MEM_INFO: u8 = 1;
1261 const WASM_DYLINK_NEEDED: u8 = 2;
1262
1263 let mut dylink0 = Vec::new();
1264 dylink0.push(WASM_DYLINK_MEM_INFO);
1265 mem_info_subsection.encode(&mut dylink0);
1266 if self.opts.interpreter.is_some() {
1267 dylink0.push(WASM_DYLINK_NEEDED);
1268 needed_subsection.encode(&mut dylink0);
1269 }
1270 dylink0
1271 };
1272
1273 let mut result = Module::new();
1274 result.section(&CustomSection {
1275 name: Cow::Borrowed("dylink.0"),
1276 data: Cow::Borrowed(&dylink0),
1277 });
1278 result.section(&self.types);
1279 result.section(&self.imports);
1280 result.section(&self.functions);
1281 result.section(&self.exports);
1282 if !elements.is_empty() {
1283 result.section(&elements);
1284 }
1285 result.section(&self.code);
1286 result.section(&data);
1287 result.section(&names);
1288
1289 result.finish()
1290 }
1291
1292 fn define_wasm_sig(&mut self, sig: WasmSignature) -> u32 {
1293 let ret = self.define_ty(
1294 sig.params
1295 .iter()
1296 .map(|t| self.map_wasm_type(*t))
1297 .collect::<Vec<_>>(),
1298 sig.results
1299 .iter()
1300 .map(|t| self.map_wasm_type(*t))
1301 .collect::<Vec<_>>(),
1302 );
1303 return ret;
1304 }
1305
1306 fn map_wasm_type(&self, a: WasmType) -> ValType {
1307 match a {
1308 WasmType::I32 => ValType::I32,
1309 WasmType::I64 => ValType::I64,
1310 WasmType::F32 => ValType::F32,
1311 WasmType::F64 => ValType::F64,
1312 WasmType::PointerOrI64 => ValType::I64,
1313 WasmType::Length | WasmType::Pointer => ValType::I32,
1314 }
1315 }
1316
1317 fn import_global(&mut self, module: &str, name: &str, ty: GlobalType) -> u32 {
1318 assert!(!self.imports_done);
1319 self.imports.import(module, name, ty);
1320 let ret = self.global_index;
1321 self.global_index += 1;
1322 self.global_names.append(ret, name);
1323 ret
1324 }
1325
1326 fn import_func(&mut self, module: &str, name: &str, ty: u32) -> u32 {
1327 assert!(!self.imports_done);
1328 self.imports.import(module, name, EntityType::Function(ty));
1329 let ret = self.func_index;
1330 self.func_index += 1;
1331 self.function_names.append(ret, name);
1332 ret
1333 }
1334
1335 fn define_func(&mut self, name: &str, ty: u32, body: Function, export: bool) -> u32 {
1336 assert!(self.imports_done);
1337 let ret = self.func_index;
1338 self.func_index += 1;
1339 self.functions.function(ty);
1340 self.code.function(&body);
1341 self.function_names.append(ret, name);
1342 if export {
1343 self.exports.export(name, ExportKind::Func, ret);
1344 }
1345 ret
1346 }
1347
1348 fn define_ty<P, R>(&mut self, params: P, results: R) -> u32
1349 where
1350 P: IntoIterator<Item = ValType> + Clone,
1351 P::IntoIter: ExactSizeIterator,
1352 R: IntoIterator<Item = ValType> + Clone,
1353 R::IntoIter: ExactSizeIterator,
1354 {
1355 let param_vec = params.clone().into_iter().collect::<Vec<_>>();
1356 let result_vec = results.clone().into_iter().collect::<Vec<_>>();
1357 *self
1358 .wasm_type_map
1359 .entry((param_vec, result_vec))
1360 .or_insert_with(|| {
1361 let ret = self.types.len();
1362 self.types.ty().function(params, results);
1363 ret
1364 })
1365 }
1366}
1367
1368fn imported_types_used_by_exported_interfaces(resolve: &Resolve, world: WorldId) -> LiveTypes {
1369 let mut live_export_types = LiveTypes::default();
1372 let mut exported_interfaces = HashSet::new();
1373 for (_, export) in resolve.worlds[world].exports.iter() {
1374 match export {
1375 WorldItem::Function(_) => {}
1376 WorldItem::Interface { id, .. } => {
1377 exported_interfaces.insert(*id);
1378 live_export_types.add_interface(resolve, *id)
1379 }
1380 WorldItem::Type { .. } => unreachable!(),
1381 }
1382 }
1383
1384 let mut live_import_types = LiveTypes::default();
1388 for ty in live_export_types.iter() {
1389 if let TypeOwner::Interface(id) = resolve.types[ty].owner {
1390 if !exported_interfaces.contains(&id) {
1391 live_import_types.add_interface(resolve, id);
1392 }
1393 }
1394 }
1395
1396 live_import_types
1397}
1398
1399fn dealias(resolve: &Resolve, mut id: TypeId) -> TypeId {
1400 loop {
1401 match resolve.types[id].kind {
1402 TypeDefKind::Type(Type::Id(other)) => id = other,
1403 _ => break id,
1404 }
1405 }
1406}