1use heck::*;
2use std::collections::{BTreeMap, BTreeSet, HashMap};
3use std::io::{Read, Write};
4use std::mem;
5use std::process::{Command, Stdio};
6use wit_bindgen_core::wit_parser::abi::{AbiVariant, Bindgen, Instruction, LiftLower, WasmType};
7use wit_bindgen_core::{wit_parser::*, Direction, Files, Generator, Source, TypeInfo, Types};
8use wit_bindgen_gen_rust_lib::{
9 to_rust_ident, wasm_type, FnSig, RustFlagsRepr, RustFunctionGenerator, RustGenerator, TypeMode,
10};
11
12#[derive(Default)]
13pub struct Wasmtime {
14 src: Source,
15 opts: Opts,
16 needs_get_memory: bool,
17 needs_get_func: bool,
18 needs_char_from_i32: bool,
19 needs_invalid_variant: bool,
20 needs_validate_flags: bool,
21 needs_raw_mem: bool,
22 needs_bad_int: bool,
23 needs_copy_slice: bool,
24 needs_buffer_glue: bool,
25 needs_le: bool,
26 needs_custom_error_to_trap: bool,
27 needs_custom_error_to_types: BTreeSet<String>,
28 all_needed_handles: BTreeSet<String>,
29 exported_resources: BTreeSet<ResourceId>,
30 types: Types,
31 guest_imports: HashMap<String, Vec<Import>>,
32 guest_exports: HashMap<String, Exports>,
33 in_import: bool,
34 in_trait: bool,
35 trait_name: String,
36 sizes: SizeAlign,
37}
38
39enum NeededFunction {
40 Realloc,
41 Free,
42}
43
44struct Import {
45 name: String,
46 trait_signature: String,
47 closure: String,
48}
49
50#[derive(Default)]
51struct Exports {
52 fields: BTreeMap<String, (String, String)>,
53 funcs: Vec<String>,
54}
55
56#[derive(Default, Debug, Clone)]
57#[cfg_attr(feature = "structopt", derive(structopt::StructOpt))]
58pub struct Opts {
59 #[cfg_attr(feature = "structopt", structopt(long))]
61 pub rustfmt: bool,
62
63 #[cfg_attr(feature = "structopt", structopt(long))]
65 pub tracing: bool,
66
67 #[cfg_attr(feature = "structopt", structopt(long))]
70 pub custom_error: bool,
71}
72
73impl Opts {
74 pub fn build(self) -> Wasmtime {
75 let mut r = Wasmtime::new();
76 r.opts = self;
77 r
78 }
79}
80
81enum FunctionRet {
82 Normal,
84 CustomToTrap,
88 CustomToError { ok: Type, err: String },
92}
93
94impl Wasmtime {
95 pub fn new() -> Wasmtime {
96 Wasmtime::default()
97 }
98
99 fn abi_variant(dir: Direction) -> AbiVariant {
100 match dir {
109 Direction::Import => AbiVariant::GuestExport,
110 Direction::Export => AbiVariant::GuestImport,
111 }
112 }
113
114 fn print_intrinsics(&mut self) {
115 if self.needs_raw_mem {
116 self.push_str("use wit_bindgen_host_wasmtime_rust::rt::RawMem;\n");
117 }
118 if self.needs_char_from_i32 {
119 self.push_str("use wit_bindgen_host_wasmtime_rust::rt::char_from_i32;\n");
120 }
121 if self.needs_invalid_variant {
122 self.push_str("use wit_bindgen_host_wasmtime_rust::rt::invalid_variant;\n");
123 }
124 if self.needs_bad_int {
125 self.push_str("use core::convert::TryFrom;\n");
126 self.push_str("use wit_bindgen_host_wasmtime_rust::rt::bad_int;\n");
127 }
128 if self.needs_validate_flags {
129 self.push_str("use wit_bindgen_host_wasmtime_rust::rt::validate_flags;\n");
130 }
131 if self.needs_le {
132 self.push_str("use wit_bindgen_host_wasmtime_rust::Le;\n");
133 }
134 if self.needs_copy_slice {
135 self.push_str("use wit_bindgen_host_wasmtime_rust::rt::copy_slice;\n");
136 }
137 }
138
139 fn classify_fn_ret(&mut self, iface: &Interface, f: &Function) -> FunctionRet {
142 if !self.opts.custom_error {
143 return FunctionRet::Normal;
144 }
145
146 if let Type::Id(id) = &f.result {
147 if let TypeDefKind::Result(r) = &iface.types[*id].kind {
148 if let Type::Id(err) = r.err {
149 if let Some(name) = &iface.types[err].name {
150 self.needs_custom_error_to_types.insert(name.clone());
151 return FunctionRet::CustomToError {
152 ok: r.ok,
153 err: name.to_string(),
154 };
155 }
156 }
157 }
158 }
159
160 self.needs_custom_error_to_trap = true;
161 FunctionRet::CustomToTrap
162 }
163}
164
165impl RustGenerator for Wasmtime {
166 fn default_param_mode(&self) -> TypeMode {
167 if self.in_import {
168 TypeMode::LeafBorrowed("'a")
171 } else {
172 TypeMode::AllBorrowed("'a")
176 }
177 }
178
179 fn handle_projection(&self) -> Option<(&'static str, String)> {
180 if self.in_import {
181 if self.in_trait {
182 Some(("Self", self.trait_name.clone()))
183 } else {
184 Some(("T", self.trait_name.clone()))
185 }
186 } else {
187 None
188 }
189 }
190
191 fn handle_wrapper(&self) -> Option<String> {
192 None
193 }
194
195 fn push_str(&mut self, s: &str) {
196 self.src.push_str(s);
197 }
198
199 fn info(&self, ty: TypeId) -> TypeInfo {
200 self.types.get(ty)
201 }
202
203 fn types_mut(&mut self) -> &mut Types {
204 &mut self.types
205 }
206
207 fn print_borrowed_slice(
208 &mut self,
209 iface: &Interface,
210 mutbl: bool,
211 ty: &Type,
212 lifetime: &'static str,
213 ) {
214 if self.sizes.align(ty) > 1 && self.in_import {
215 self.needs_le = true;
226 self.push_str("&");
227 if lifetime != "'_" {
228 self.push_str(lifetime);
229 self.push_str(" ");
230 }
231 if mutbl {
232 self.push_str(" mut ");
233 }
234 self.push_str("[Le<");
235 self.print_ty(iface, ty, TypeMode::AllBorrowed(lifetime));
236 self.push_str(">]");
237 } else {
238 self.print_rust_slice(iface, mutbl, ty, lifetime);
239 }
240 }
241
242 fn print_borrowed_str(&mut self, lifetime: &'static str) {
243 self.push_str("&");
244 if lifetime != "'_" {
245 self.push_str(lifetime);
246 self.push_str(" ");
247 }
248 self.push_str(" str");
249 }
250}
251
252impl Generator for Wasmtime {
253 fn preprocess_one(&mut self, iface: &Interface, dir: Direction) {
254 let variant = Self::abi_variant(dir);
255 self.types.analyze(iface);
256 self.in_import = variant == AbiVariant::GuestImport;
257 self.trait_name = iface.name.to_camel_case();
258 self.src.push_str(&format!(
259 "#[allow(clippy::all)]\npub mod {} {{\n",
260 iface.name.to_snake_case(),
261 ));
262 self.src.push_str(
263 "#[allow(unused_imports)]\nuse wit_bindgen_host_wasmtime_rust::{wasmtime, anyhow};\n",
264 );
265 self.sizes.fill(iface);
266 }
267
268 fn type_record(
269 &mut self,
270 iface: &Interface,
271 id: TypeId,
272 name: &str,
273 record: &Record,
274 docs: &Docs,
275 ) {
276 self.print_typedef_record(iface, id, record, docs);
277
278 if self.modes_of(iface, id).len() > 0
282 && record.fields.iter().all(|f| iface.all_bits_valid(&f.ty))
283 {
284 self.src
285 .push_str("impl wit_bindgen_host_wasmtime_rust::Endian for ");
286 self.src.push_str(&name.to_camel_case());
287 self.src.push_str(" {\n");
288
289 self.src.push_str("fn into_le(self) -> Self {\n");
290 self.src.push_str("Self {\n");
291 for field in record.fields.iter() {
292 self.src.push_str(&field.name.to_snake_case());
293 self.src.push_str(": self.");
294 self.src.push_str(&field.name.to_snake_case());
295 self.src.push_str(".into_le(),\n");
296 }
297 self.src.push_str("}\n");
298 self.src.push_str("}\n");
299
300 self.src.push_str("fn from_le(self) -> Self {\n");
301 self.src.push_str("Self {\n");
302 for field in record.fields.iter() {
303 self.src.push_str(&field.name.to_snake_case());
304 self.src.push_str(": self.");
305 self.src.push_str(&field.name.to_snake_case());
306 self.src.push_str(".from_le(),\n");
307 }
308 self.src.push_str("}\n");
309 self.src.push_str("}\n");
310
311 self.src.push_str("}\n");
312
313 self.src
317 .push_str("unsafe impl wit_bindgen_host_wasmtime_rust::AllBytesValid for ");
318 self.src.push_str(&name.to_camel_case());
319 self.src.push_str(" {}\n");
320 }
321 }
322
323 fn type_tuple(
324 &mut self,
325 iface: &Interface,
326 id: TypeId,
327 _name: &str,
328 tuple: &Tuple,
329 docs: &Docs,
330 ) {
331 self.print_typedef_tuple(iface, id, tuple, docs);
332 }
333
334 fn type_flags(
335 &mut self,
336 _iface: &Interface,
337 _id: TypeId,
338 name: &str,
339 flags: &Flags,
340 docs: &Docs,
341 ) {
342 self.src
343 .push_str("wit_bindgen_host_wasmtime_rust::bitflags::bitflags! {\n");
344 self.rustdoc(docs);
345 let repr = RustFlagsRepr::new(flags);
346 self.src
347 .push_str(&format!("pub struct {}: {repr} {{\n", name.to_camel_case()));
348 for (i, flag) in flags.flags.iter().enumerate() {
349 self.rustdoc(&flag.docs);
350 self.src.push_str(&format!(
351 "const {} = 1 << {};\n",
352 flag.name.to_shouty_snake_case(),
353 i,
354 ));
355 }
356 self.src.push_str("}\n");
357 self.src.push_str("}\n\n");
358
359 self.src.push_str("impl core::fmt::Display for ");
360 self.src.push_str(&name.to_camel_case());
361 self.src.push_str(
362 "{\nfn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {\n",
363 );
364
365 self.src.push_str("f.write_str(\"");
366 self.src.push_str(&name.to_camel_case());
367 self.src.push_str("(\")?;\n");
368 self.src.push_str("core::fmt::Debug::fmt(self, f)?;\n");
369 self.src.push_str("f.write_str(\" (0x\")?;\n");
370 self.src
371 .push_str("core::fmt::LowerHex::fmt(&self.bits, f)?;\n");
372 self.src.push_str("f.write_str(\"))\")?;\n");
373 self.src.push_str("Ok(())");
374
375 self.src.push_str("}\n");
376 self.src.push_str("}\n\n");
377 }
378
379 fn type_variant(
380 &mut self,
381 iface: &Interface,
382 id: TypeId,
383 _name: &str,
384 variant: &Variant,
385 docs: &Docs,
386 ) {
387 self.print_typedef_variant(iface, id, variant, docs);
388 }
389
390 fn type_union(
391 &mut self,
392 iface: &Interface,
393 id: TypeId,
394 _name: &str,
395 union: &Union,
396 docs: &Docs,
397 ) {
398 self.print_typedef_union(iface, id, union, docs);
399 }
400
401 fn type_option(
402 &mut self,
403 iface: &Interface,
404 id: TypeId,
405 _name: &str,
406 payload: &Type,
407 docs: &Docs,
408 ) {
409 self.print_typedef_option(iface, id, payload, docs);
410 }
411
412 fn type_result(
413 &mut self,
414 iface: &Interface,
415 id: TypeId,
416 _name: &str,
417 result: &Result_,
418 docs: &Docs,
419 ) {
420 self.print_typedef_result(iface, id, result, docs);
421 }
422
423 fn type_enum(&mut self, _iface: &Interface, id: TypeId, name: &str, enum_: &Enum, docs: &Docs) {
424 self.print_typedef_enum(id, name, enum_, docs);
425 }
426
427 fn type_resource(&mut self, iface: &Interface, ty: ResourceId) {
428 let name = &iface.resources[ty].name;
429 self.all_needed_handles.insert(name.to_string());
430
431 if self.in_import {
434 return;
435 }
436
437 self.exported_resources.insert(ty);
438
439 let tyname = name.to_camel_case();
442 self.rustdoc(&iface.resources[ty].docs);
443 self.src.push_str("#[derive(Debug)]\n");
444 self.src.push_str(&format!(
445 "pub struct {}(wit_bindgen_host_wasmtime_rust::rt::ResourceIndex);\n",
446 tyname
447 ));
448 }
449
450 fn type_alias(&mut self, iface: &Interface, id: TypeId, _name: &str, ty: &Type, docs: &Docs) {
451 self.print_typedef_alias(iface, id, ty, docs);
452 }
453
454 fn type_list(&mut self, iface: &Interface, id: TypeId, _name: &str, ty: &Type, docs: &Docs) {
455 self.print_type_list(iface, id, ty, docs);
456 }
457
458 fn type_builtin(&mut self, iface: &Interface, _id: TypeId, name: &str, ty: &Type, docs: &Docs) {
459 self.rustdoc(docs);
460 self.src
461 .push_str(&format!("pub type {}", name.to_camel_case()));
462 self.src.push_str(" = ");
463 self.print_ty(iface, ty, TypeMode::Owned);
464 self.src.push_str(";\n");
465 }
466
467 fn export(&mut self, iface: &Interface, func: &Function) {
471 let prev = mem::take(&mut self.src);
472
473 let sig = iface.wasm_signature(AbiVariant::GuestImport, func);
476 let params = (0..sig.params.len())
477 .map(|i| format!("arg{}", i))
478 .collect::<Vec<_>>();
479 let mut f = FunctionBindgen::new(self, params);
480 iface.call(
481 AbiVariant::GuestImport,
482 LiftLower::LiftArgsLowerResults,
483 func,
484 &mut f,
485 );
486 let FunctionBindgen {
487 src,
488 cleanup,
489 needs_borrow_checker,
490 needs_memory,
491 needs_buffer_transaction,
492 needs_functions,
493 closures,
494 ..
495 } = f;
496 assert!(cleanup.is_none());
497 assert!(!needs_buffer_transaction);
498
499 let self_arg = "&mut self".to_string();
501 self.in_trait = true;
502
503 let mut fnsig = FnSig::default();
504 fnsig.private = true;
505 fnsig.self_arg = Some(self_arg);
506 self.print_docs_and_params(iface, func, TypeMode::LeafBorrowed("'_"), &fnsig);
507 match self.classify_fn_ret(iface, func) {
510 FunctionRet::Normal => {
511 self.push_str(" -> ");
512 self.print_ty(iface, &func.result, TypeMode::Owned);
513 }
514 FunctionRet::CustomToTrap => {
515 self.push_str(" -> Result<");
516 self.print_ty(iface, &func.result, TypeMode::Owned);
517 self.push_str(", Self::Error>");
518 }
519 FunctionRet::CustomToError { ok, .. } => {
520 self.push_str(" -> Result<");
521 self.print_ty(iface, &ok, TypeMode::Owned);
522 self.push_str(", Self::Error>");
523 }
524 }
525 self.in_trait = false;
526 let trait_signature = mem::take(&mut self.src).into();
527
528 self.src
531 .push_str("move |mut caller: wasmtime::Caller<'_, T>");
532 for (i, param) in sig.params.iter().enumerate() {
533 let arg = format!("arg{}", i);
534 self.src.push_str(",");
535 self.src.push_str(&arg);
536 self.src.push_str(":");
537 self.wasm_type(*param);
538 }
539 self.src.push_str("| {\n");
540
541 if self.opts.tracing {
542 self.src.push_str(&format!(
543 "
544 let span = wit_bindgen_host_wasmtime_rust::tracing::span!(
545 wit_bindgen_host_wasmtime_rust::tracing::Level::TRACE,
546 \"wit-bindgen abi\",
547 module = \"{}\",
548 function = \"{}\",
549 );
550 let _enter = span.enter();
551 ",
552 iface.name, func.name,
553 ));
554 }
555 self.src.push_str(&closures);
556
557 for (name, func) in needs_functions {
558 self.src.push_str(&format!(
559 "
560 let func = get_func(&mut caller, \"{name}\")?;
561 let func_{name} = func.typed::<{cvt}, _>(&caller)?;
562 ",
563 name = name,
564 cvt = func.cvt(),
565 ));
566 self.needs_get_func = true;
567 }
568
569 if needs_memory || needs_borrow_checker {
570 self.src
571 .push_str("let memory = &get_memory(&mut caller, \"memory\")?;\n");
572 self.needs_get_memory = true;
573 }
574
575 if needs_borrow_checker {
576 self.src.push_str(
577 "let (mem, data) = memory.data_and_store_mut(&mut caller);
578 let mut _bc = wit_bindgen_host_wasmtime_rust::BorrowChecker::new(mem);
579 let host = get(data);\n",
580 );
581 } else {
582 self.src.push_str("let host = get(caller.data_mut());\n");
583 }
584
585 if self.all_needed_handles.len() > 0 {
586 self.src.push_str("let (host, _tables) = host;\n");
587 }
588
589 self.src.push_str(&String::from(src));
590
591 self.src.push_str("}");
592 let closure = mem::replace(&mut self.src, prev).into();
593
594 self.guest_imports
595 .entry(iface.name.to_string())
596 .or_insert(Vec::new())
597 .push(Import {
598 name: iface.mangle_funcname(func),
599 closure,
600 trait_signature,
601 });
602 }
603
604 fn import(&mut self, iface: &Interface, func: &Function) {
608 let prev = mem::take(&mut self.src);
609
610 let mut sig = FnSig::default();
611 sig.self_arg = Some("&self, mut caller: impl wasmtime::AsContextMut<Data = T>".to_string());
612 self.print_docs_and_params(iface, func, TypeMode::AllBorrowed("'_"), &sig);
613 self.push_str("-> Result<");
614 self.print_ty(iface, &func.result, TypeMode::Owned);
615 self.push_str(", wasmtime::Trap> {\n");
616
617 let params = func
618 .params
619 .iter()
620 .map(|(name, _)| to_rust_ident(name).to_string())
621 .collect();
622 let mut f = FunctionBindgen::new(self, params);
623 iface.call(
624 AbiVariant::GuestExport,
625 LiftLower::LowerArgsLiftResults,
626 func,
627 &mut f,
628 );
629 let FunctionBindgen {
630 needs_memory,
631 src,
632 needs_borrow_checker,
633 needs_buffer_transaction,
634 closures,
635 needs_functions,
636 ..
637 } = f;
638
639 let exports = self
640 .guest_exports
641 .entry(iface.name.to_string())
642 .or_insert_with(Exports::default);
643 for (name, func) in needs_functions {
644 self.src
645 .push_str(&format!("let func_{0} = &self.{0};\n", name));
646 let get = format!(
647 "instance.get_typed_func::<{}, _>(&mut store, \"{}\")?",
648 func.cvt(),
649 name
650 );
651 exports.fields.insert(name, (func.ty(), get));
652 }
653
654 self.src.push_str(&closures);
655
656 assert!(!needs_borrow_checker);
657 if needs_memory {
658 self.src.push_str("let memory = &self.memory;\n");
659 exports.fields.insert(
660 "memory".to_string(),
661 (
662 "wasmtime::Memory".to_string(),
663 "instance
664 .get_memory(&mut store, \"memory\")
665 .ok_or_else(|| {
666 anyhow::anyhow!(\"`memory` export not a memory\")
667 })?
668 "
669 .to_string(),
670 ),
671 );
672 }
673
674 if needs_buffer_transaction {
675 self.needs_buffer_glue = true;
676 self.src
677 .push_str("let mut buffer_transaction = self.buffer_glue.transaction();\n");
678 }
679
680 self.src.push_str(&String::from(src));
681 self.src.push_str("}\n");
682 let func_body = mem::replace(&mut self.src, prev);
683 exports.funcs.push(func_body.into());
684
685 let sig = iface.wasm_signature(AbiVariant::GuestExport, func);
689 let mut cvt = "(".to_string();
690 for param in sig.params.iter() {
691 cvt.push_str(wasm_type(*param));
692 cvt.push_str(",");
693 }
694 cvt.push_str("), (");
695 for result in sig.results.iter() {
696 cvt.push_str(wasm_type(*result));
697 cvt.push_str(",");
698 }
699 cvt.push_str(")");
700 exports.fields.insert(
701 to_rust_ident(&func.name),
702 (
703 format!("wasmtime::TypedFunc<{}>", cvt),
704 format!(
705 "instance.get_typed_func::<{}, _>(&mut store, \"{}\")?",
706 cvt,
707 iface.mangle_funcname(func),
708 ),
709 ),
710 );
711 }
712
713 fn finish_one(&mut self, iface: &Interface, files: &mut Files) {
714 for (module, funcs) in sorted_iter(&self.guest_imports) {
715 let module_camel = module.to_camel_case();
716 self.src.push_str("pub trait ");
717 self.src.push_str(&module_camel);
718 self.src.push_str(": Sized ");
719 self.src.push_str("{\n");
720 if self.all_needed_handles.len() > 0 {
721 for handle in self.all_needed_handles.iter() {
722 self.src.push_str("type ");
723 self.src.push_str(&handle.to_camel_case());
724 self.src.push_str(": std::fmt::Debug");
725 self.src.push_str(";\n");
726 }
727 }
728 if self.opts.custom_error {
729 self.src.push_str("type Error;\n");
730 if self.needs_custom_error_to_trap {
731 self.src.push_str(
732 "fn error_to_trap(&mut self, err: Self::Error) -> wasmtime::Trap;\n",
733 );
734 }
735 for ty in self.needs_custom_error_to_types.iter() {
736 self.src.push_str(&format!(
737 "fn error_to_{}(&mut self, err: Self::Error) -> Result<{}, wasmtime::Trap>;\n",
738 ty.to_snake_case(),
739 ty.to_camel_case(),
740 ));
741 }
742 }
743 for f in funcs {
744 self.src.push_str(&f.trait_signature);
745 self.src.push_str(";\n\n");
746 }
747 for handle in self.all_needed_handles.iter() {
748 self.src.push_str(&format!(
749 "fn drop_{}(&mut self, state: Self::{}) {{
750 drop(state);
751 }}\n",
752 handle.to_snake_case(),
753 handle.to_camel_case(),
754 ));
755 }
756 self.src.push_str("}\n");
757
758 if self.all_needed_handles.len() > 0 {
759 self.src.push_str("\npub struct ");
760 self.src.push_str(&module_camel);
761 self.src.push_str("Tables<T: ");
762 self.src.push_str(&module_camel);
763 self.src.push_str("> {\n");
764 for handle in self.all_needed_handles.iter() {
765 self.src.push_str("pub(crate) ");
766 self.src.push_str(&handle.to_snake_case());
767 self.src
768 .push_str("_table: wit_bindgen_host_wasmtime_rust::Table<T::");
769 self.src.push_str(&handle.to_camel_case());
770 self.src.push_str(">,\n");
771 }
772 self.src.push_str("}\n");
773 self.src.push_str("impl<T: ");
774 self.src.push_str(&module_camel);
775 self.src.push_str("> Default for ");
776 self.src.push_str(&module_camel);
777 self.src.push_str("Tables<T> {\n");
778 self.src.push_str("fn default() -> Self { Self {");
779 for handle in self.all_needed_handles.iter() {
780 self.src.push_str(&handle.to_snake_case());
781 self.src.push_str("_table: Default::default(),");
782 }
783 self.src.push_str("}}}");
784 }
785 }
786
787 for (module, funcs) in mem::take(&mut self.guest_imports) {
788 let module_camel = module.to_camel_case();
789 self.push_str("\npub fn add_to_linker<T, U>(linker: &mut wasmtime::Linker<T>");
790 self.push_str(", get: impl Fn(&mut T) -> ");
791 if self.all_needed_handles.is_empty() {
792 self.push_str("&mut U");
793 } else {
794 self.push_str(&format!("(&mut U, &mut {}Tables<U>)", module_camel));
795 }
796 self.push_str("+ Send + Sync + Copy + 'static) -> anyhow::Result<()> \n");
797 self.push_str("where U: ");
798 self.push_str(&module_camel);
799 self.push_str("\n{\n");
800 if self.needs_get_memory {
801 self.push_str("use wit_bindgen_host_wasmtime_rust::rt::get_memory;\n");
802 }
803 if self.needs_get_func {
804 self.push_str("use wit_bindgen_host_wasmtime_rust::rt::get_func;\n");
805 }
806 for f in funcs {
807 let method = String::from("func_wrap");
808 self.push_str(&format!(
809 "linker.{}(\"{}\", \"{}\", {})?;\n",
810 method, module, f.name, f.closure,
811 ));
812 }
813 for handle in self.all_needed_handles.iter() {
814 self.src.push_str(&format!(
815 "linker.func_wrap(
816 \"canonical_abi\",
817 \"resource_drop_{name}\",
818 move |mut caller: wasmtime::Caller<'_, T>, handle: u32| {{
819 let (host, tables) = get(caller.data_mut());
820 let handle = tables
821 .{snake}_table
822 .remove(handle)
823 .map_err(|e| {{
824 wasmtime::Trap::new(format!(\"failed to remove handle: {{}}\", e))
825 }})?;
826 host.drop_{snake}(handle);
827 Ok(())
828 }}
829 )?;\n",
830 name = handle,
831 snake = handle.to_snake_case(),
832 ));
833 }
834 self.push_str("Ok(())\n}\n");
835 }
836
837 for (module, exports) in sorted_iter(&mem::take(&mut self.guest_exports)) {
838 let name = module.to_camel_case();
839
840 self.push_str(
844 "
845 /// Auxiliary data associated with the wasm exports.
846 ///
847 /// This is required to be stored within the data of a
848 /// `Store<T>` itself so lifting/lowering state can be managed
849 /// when translating between the host and wasm.
850 ",
851 );
852 self.push_str("#[derive(Default)]\n");
853 self.push_str("pub struct ");
854 self.push_str(&name);
855 self.push_str("Data {\n");
856 for r in self.exported_resources.iter() {
857 self.src.push_str(&format!(
858 "
859 index_slab{}: wit_bindgen_host_wasmtime_rust::rt::IndexSlab,
860 resource_slab{0}: wit_bindgen_host_wasmtime_rust::rt::ResourceSlab,
861 dtor{0}: Option<wasmtime::TypedFunc<i32, ()>>,
862 ",
863 r.index()
864 ));
865 }
866 self.push_str("}\n");
867
868 self.push_str("pub struct ");
869 self.push_str(&name);
870 self.push_str("<T> {\n");
871 self.push_str(&format!(
872 "get_state: Box<dyn Fn(&mut T) -> &mut {}Data + Send + Sync>,\n",
873 name
874 ));
875 for (name, (ty, _)) in exports.fields.iter() {
876 self.push_str(name);
877 self.push_str(": ");
878 self.push_str(ty);
879 self.push_str(",\n");
880 }
881 self.push_str("}\n");
882 let bound = "";
883 self.push_str(&format!("impl<T{}> {}<T> {{\n", bound, name));
884
885 if self.exported_resources.len() == 0 {
886 self.push_str("#[allow(unused_variables)]\n");
887 }
888 self.push_str(&format!(
889 "
890 /// Adds any intrinsics, if necessary for this exported wasm
891 /// functionality to the `linker` provided.
892 ///
893 /// The `get_state` closure is required to access the
894 /// auxiliary data necessary for these wasm exports from
895 /// the general store's state.
896 pub fn add_to_linker(
897 linker: &mut wasmtime::Linker<T>,
898 get_state: impl Fn(&mut T) -> &mut {}Data + Send + Sync + Copy + 'static,
899 ) -> anyhow::Result<()> {{
900 ",
901 name,
902 ));
903 for r in self.exported_resources.iter() {
904 let (func_wrap, call, wait, prefix, suffix) = ("func_wrap", "call", "", "", "");
905 self.src.push_str(&format!(
906 "
907 linker.{func_wrap}(
908 \"canonical_abi\",
909 \"resource_drop_{name}\",
910 move |mut caller: wasmtime::Caller<'_, T>, idx: u32| {prefix}{{
911 let state = get_state(caller.data_mut());
912 let resource_idx = state.index_slab{idx}.remove(idx)?;
913 let wasm = match state.resource_slab{idx}.drop(resource_idx) {{
914 Some(wasm) => wasm,
915 None => return Ok(()),
916 }};
917 let dtor = state.dtor{idx}.expect(\"destructor not set yet\");
918 dtor.{call}(&mut caller, wasm){wait}?;
919 Ok(())
920 }}{suffix},
921 )?;
922 linker.func_wrap(
923 \"canonical_abi\",
924 \"resource_clone_{name}\",
925 move |mut caller: wasmtime::Caller<'_, T>, idx: u32| {{
926 let state = get_state(caller.data_mut());
927 let resource_idx = state.index_slab{idx}.get(idx)?;
928 state.resource_slab{idx}.clone(resource_idx)?;
929 Ok(state.index_slab{idx}.insert(resource_idx))
930 }},
931 )?;
932 linker.func_wrap(
933 \"canonical_abi\",
934 \"resource_get_{name}\",
935 move |mut caller: wasmtime::Caller<'_, T>, idx: u32| {{
936 let state = get_state(caller.data_mut());
937 let resource_idx = state.index_slab{idx}.get(idx)?;
938 Ok(state.resource_slab{idx}.get(resource_idx))
939 }},
940 )?;
941 linker.func_wrap(
942 \"canonical_abi\",
943 \"resource_new_{name}\",
944 move |mut caller: wasmtime::Caller<'_, T>, val: i32| {{
945 let state = get_state(caller.data_mut());
946 let resource_idx = state.resource_slab{idx}.insert(val);
947 Ok(state.index_slab{idx}.insert(resource_idx))
948 }},
949 )?;
950 ",
951 name = iface.resources[*r].name,
952 idx = r.index(),
953 func_wrap = func_wrap,
954 call = call,
955 wait = wait,
956 prefix = prefix,
957 suffix = suffix,
958 ));
959 }
960 self.push_str("Ok(())\n");
961 self.push_str("}\n");
962
963 let (instantiate, wait) = ("", "");
964 self.push_str(&format!(
965 "
966 /// Instantiates the provided `module` using the specified
967 /// parameters, wrapping up the result in a structure that
968 /// translates between wasm and the host.
969 ///
970 /// The `linker` provided will have intrinsics added to it
971 /// automatically, so it's not necessary to call
972 /// `add_to_linker` beforehand. This function will
973 /// instantiate the `module` otherwise using `linker`, and
974 /// both an instance of this structure and the underlying
975 /// `wasmtime::Instance` will be returned.
976 ///
977 /// The `get_state` parameter is used to access the
978 /// auxiliary state necessary for these wasm exports from
979 /// the general store state `T`.
980 pub fn instantiate(
981 mut store: impl wasmtime::AsContextMut<Data = T>,
982 module: &wasmtime::Module,
983 linker: &mut wasmtime::Linker<T>,
984 get_state: impl Fn(&mut T) -> &mut {}Data + Send + Sync + Copy + 'static,
985 ) -> anyhow::Result<(Self, wasmtime::Instance)> {{
986 Self::add_to_linker(linker, get_state)?;
987 let instance = linker.instantiate{}(&mut store, module){}?;
988 Ok((Self::new(store, &instance,get_state)?, instance))
989 }}
990 ",
991 name, instantiate, wait,
992 ));
993
994 self.push_str(&format!(
995 "
996 /// Low-level creation wrapper for wrapping up the exports
997 /// of the `instance` provided in this structure of wasm
998 /// exports.
999 ///
1000 /// This function will extract exports from the `instance`
1001 /// defined within `store` and wrap them all up in the
1002 /// returned structure which can be used to interact with
1003 /// the wasm module.
1004 pub fn new(
1005 mut store: impl wasmtime::AsContextMut<Data = T>,
1006 instance: &wasmtime::Instance,
1007 get_state: impl Fn(&mut T) -> &mut {}Data + Send + Sync + Copy + 'static,
1008 ) -> anyhow::Result<Self> {{
1009 ",
1010 name,
1011 ));
1012 self.push_str("let mut store = store.as_context_mut();\n");
1013 assert!(!self.needs_get_func);
1014 for (name, (_, get)) in exports.fields.iter() {
1015 self.push_str("let ");
1016 self.push_str(&name);
1017 self.push_str("= ");
1018 self.push_str(&get);
1019 self.push_str(";\n");
1020 }
1021 for r in self.exported_resources.iter() {
1022 self.src.push_str(&format!(
1023 "
1024 get_state(store.data_mut()).dtor{} = \
1025 Some(instance.get_typed_func::<i32, (), _>(\
1026 &mut store, \
1027 \"canonical_abi_drop_{}\", \
1028 )?);\n
1029 ",
1030 r.index(),
1031 iface.resources[*r].name,
1032 ));
1033 }
1034 self.push_str("Ok(");
1035 self.push_str(&name);
1036 self.push_str("{\n");
1037 for (name, _) in exports.fields.iter() {
1038 self.push_str(name);
1039 self.push_str(",\n");
1040 }
1041 self.push_str("get_state: Box::new(get_state),\n");
1042 self.push_str("\n})\n");
1043 self.push_str("}\n");
1044
1045 for func in exports.funcs.iter() {
1046 self.push_str(func);
1047 }
1048
1049 for r in self.exported_resources.iter() {
1050 let (call, wait) = ("call", "");
1051 self.src.push_str(&format!(
1052 "
1053 /// Drops the host-owned handle to the resource
1054 /// specified.
1055 ///
1056 /// Note that this may execute the WebAssembly-defined
1057 /// destructor for this type. This also may not run
1058 /// the destructor if there are still other references
1059 /// to this type.
1060 pub fn drop_{name_snake}(
1061 &self,
1062 mut store: impl wasmtime::AsContextMut<Data = T>,
1063 val: {name_camel},
1064 ) -> Result<(), wasmtime::Trap> {{
1065 let mut store = store.as_context_mut();
1066 let data = (self.get_state)(store.data_mut());
1067 let wasm = match data.resource_slab{idx}.drop(val.0) {{
1068 Some(val) => val,
1069 None => return Ok(()),
1070 }};
1071 data.dtor{idx}.unwrap().{call}(&mut store, wasm){wait}?;
1072 Ok(())
1073 }}
1074 ",
1075 name_snake = iface.resources[*r].name.to_snake_case(),
1076 name_camel = iface.resources[*r].name.to_camel_case(),
1077 idx = r.index(),
1078 call = call,
1079 wait = wait,
1080 ));
1081 }
1082
1083 self.push_str("}\n");
1084 }
1085 self.print_intrinsics();
1086
1087 self.push_str("}\n");
1089
1090 let mut src = mem::take(&mut self.src);
1091 if self.opts.rustfmt {
1092 let mut child = Command::new("rustfmt")
1093 .arg("--edition=2018")
1094 .stdin(Stdio::piped())
1095 .stdout(Stdio::piped())
1096 .spawn()
1097 .expect("failed to spawn `rustfmt`");
1098 child
1099 .stdin
1100 .take()
1101 .unwrap()
1102 .write_all(src.as_bytes())
1103 .unwrap();
1104 src.as_mut_string().truncate(0);
1105 child
1106 .stdout
1107 .take()
1108 .unwrap()
1109 .read_to_string(src.as_mut_string())
1110 .unwrap();
1111 let status = child.wait().unwrap();
1112 assert!(status.success());
1113 }
1114
1115 files.push("bindings.rs", src.as_bytes());
1116 }
1117}
1118
1119struct FunctionBindgen<'a> {
1120 gen: &'a mut Wasmtime,
1121
1122 tmp: usize,
1124
1125 src: Source,
1127
1128 params: Vec<String>,
1130
1131 block_storage: Vec<Source>,
1133 blocks: Vec<String>,
1134
1135 after_call: bool,
1138 caller_memory_available: bool,
1141 cleanup: Option<String>,
1144
1145 closures: Source,
1148
1149 needs_buffer_transaction: bool,
1152 needs_borrow_checker: bool,
1153 needs_memory: bool,
1154 needs_functions: HashMap<String, NeededFunction>,
1155}
1156
1157impl FunctionBindgen<'_> {
1158 fn new(gen: &mut Wasmtime, params: Vec<String>) -> FunctionBindgen<'_> {
1159 FunctionBindgen {
1160 gen,
1161 block_storage: Vec::new(),
1162 blocks: Vec::new(),
1163 src: Source::default(),
1164 after_call: false,
1165 caller_memory_available: false,
1166 tmp: 0,
1167 cleanup: None,
1168 closures: Source::default(),
1169 needs_buffer_transaction: false,
1170 needs_borrow_checker: false,
1171 needs_memory: false,
1172 needs_functions: HashMap::new(),
1173 params,
1174 }
1175 }
1176
1177 fn memory_src(&mut self) -> String {
1178 if self.gen.in_import {
1179 if !self.after_call {
1180 self.needs_borrow_checker = true;
1183 return format!("_bc");
1184 }
1185
1186 if !self.caller_memory_available {
1187 self.needs_memory = true;
1188 self.caller_memory_available = true;
1189 if self.gen.all_needed_handles.len() > 0 {
1193 self.push_str(
1194 "let (caller_memory, data) = memory.data_and_store_mut(&mut caller);\n",
1195 );
1196 self.push_str("let (_, _tables) = get(data);\n");
1197 } else {
1198 self.push_str("let caller_memory = memory.data_mut(&mut caller);\n");
1199 }
1200 }
1201 format!("caller_memory")
1202 } else {
1203 self.needs_memory = true;
1204 format!("memory.data_mut(&mut caller)")
1205 }
1206 }
1207
1208 fn call_intrinsic(&mut self, name: &str, args: String) {
1209 let (method, suffix) = ("call", "");
1210 self.push_str(&format!(
1211 "func_{}.{}(&mut caller, {}){}?;\n",
1212 name, method, args, suffix
1213 ));
1214 self.caller_memory_available = false; }
1216
1217 fn load(&mut self, offset: i32, ty: &str, operands: &[String]) -> String {
1218 let mem = self.memory_src();
1219 self.gen.needs_raw_mem = true;
1220 let tmp = self.tmp();
1221 self.push_str(&format!(
1222 "let load{} = {}.load::<{}>({} + {})?;\n",
1223 tmp, mem, ty, operands[0], offset
1224 ));
1225 format!("load{}", tmp)
1226 }
1227
1228 fn store(&mut self, offset: i32, method: &str, extra: &str, operands: &[String]) {
1229 let mem = self.memory_src();
1230 self.gen.needs_raw_mem = true;
1231 self.push_str(&format!(
1232 "{}.store({} + {}, wit_bindgen_host_wasmtime_rust::rt::{}({}){})?;\n",
1233 mem, operands[1], offset, method, operands[0], extra
1234 ));
1235 }
1236}
1237
1238impl RustFunctionGenerator for FunctionBindgen<'_> {
1239 fn push_str(&mut self, s: &str) {
1240 self.src.push_str(s);
1241 }
1242
1243 fn tmp(&mut self) -> usize {
1244 let ret = self.tmp;
1245 self.tmp += 1;
1246 ret
1247 }
1248
1249 fn rust_gen(&self) -> &dyn RustGenerator {
1250 self.gen
1251 }
1252
1253 fn lift_lower(&self) -> LiftLower {
1254 if self.gen.in_import {
1255 LiftLower::LiftArgsLowerResults
1256 } else {
1257 LiftLower::LowerArgsLiftResults
1258 }
1259 }
1260}
1261
1262impl Bindgen for FunctionBindgen<'_> {
1263 type Operand = String;
1264
1265 fn sizes(&self) -> &SizeAlign {
1266 &self.gen.sizes
1267 }
1268
1269 fn push_block(&mut self) {
1270 let prev = mem::take(&mut self.src);
1271 self.block_storage.push(prev);
1272 }
1273
1274 fn finish_block(&mut self, operands: &mut Vec<String>) {
1275 let to_restore = self.block_storage.pop().unwrap();
1276 let src = mem::replace(&mut self.src, to_restore);
1277 let expr = match operands.len() {
1278 0 => "()".to_string(),
1279 1 => operands[0].clone(),
1280 _ => format!("({})", operands.join(", ")),
1281 };
1282 if src.is_empty() {
1283 self.blocks.push(expr);
1284 } else if operands.is_empty() {
1285 self.blocks.push(format!("{{\n{}}}", &src[..]));
1286 } else {
1287 self.blocks.push(format!("{{\n{}{}\n}}", &src[..], expr));
1288 }
1289 self.caller_memory_available = false;
1290 }
1291
1292 fn return_pointer(&mut self, _iface: &Interface, _size: usize, _align: usize) -> String {
1293 unimplemented!()
1294 }
1295
1296 fn is_list_canonical(&self, iface: &Interface, ty: &Type) -> bool {
1297 iface.all_bits_valid(ty)
1298 }
1299
1300 fn emit(
1301 &mut self,
1302 iface: &Interface,
1303 inst: &Instruction<'_>,
1304 operands: &mut Vec<String>,
1305 results: &mut Vec<String>,
1306 ) {
1307 let mut top_as = |cvt: &str| {
1308 let mut s = operands.pop().unwrap();
1309 s.push_str(" as ");
1310 s.push_str(cvt);
1311 results.push(s);
1312 };
1313
1314 let mut try_from = |cvt: &str, operands: &[String], results: &mut Vec<String>| {
1315 self.gen.needs_bad_int = true;
1316 let result = format!("{}::try_from({}).map_err(bad_int)?", cvt, operands[0]);
1317 results.push(result);
1318 };
1319
1320 match inst {
1321 Instruction::GetArg { nth } => results.push(self.params[*nth].clone()),
1322 Instruction::I32Const { val } => results.push(format!("{}i32", val)),
1323 Instruction::ConstZero { tys } => {
1324 for ty in tys.iter() {
1325 match ty {
1326 WasmType::I32 => results.push("0i32".to_string()),
1327 WasmType::I64 => results.push("0i64".to_string()),
1328 WasmType::F32 => results.push("0.0f32".to_string()),
1329 WasmType::F64 => results.push("0.0f64".to_string()),
1330 }
1331 }
1332 }
1333
1334 Instruction::I64FromU64 | Instruction::I64FromS64 => {
1335 let s = operands.pop().unwrap();
1336 results.push(format!("wit_bindgen_host_wasmtime_rust::rt::as_i64({})", s));
1337 }
1338 Instruction::I32FromChar
1339 | Instruction::I32FromU8
1340 | Instruction::I32FromS8
1341 | Instruction::I32FromU16
1342 | Instruction::I32FromS16
1343 | Instruction::I32FromU32
1344 | Instruction::I32FromS32 => {
1345 let s = operands.pop().unwrap();
1346 results.push(format!("wit_bindgen_host_wasmtime_rust::rt::as_i32({})", s));
1347 }
1348
1349 Instruction::F32FromFloat32
1350 | Instruction::F64FromFloat64
1351 | Instruction::Float32FromF32
1352 | Instruction::Float64FromF64
1353 | Instruction::S32FromI32
1354 | Instruction::S64FromI64 => {
1355 results.push(operands.pop().unwrap());
1356 }
1357
1358 Instruction::S8FromI32 => try_from("i8", operands, results),
1363 Instruction::U8FromI32 => try_from("u8", operands, results),
1364 Instruction::S16FromI32 => try_from("i16", operands, results),
1365 Instruction::U16FromI32 => try_from("u16", operands, results),
1366
1367 Instruction::U32FromI32 => top_as("u32"),
1370 Instruction::U64FromI64 => top_as("u64"),
1371
1372 Instruction::CharFromI32 => {
1373 self.gen.needs_char_from_i32 = true;
1374 results.push(format!("char_from_i32({})?", operands[0]));
1375 }
1376
1377 Instruction::Bitcasts { casts } => {
1378 wit_bindgen_gen_rust_lib::bitcast(casts, operands, results)
1379 }
1380
1381 Instruction::UnitLower => {
1382 self.push_str(&format!("let () = {};\n", operands[0]));
1383 }
1384 Instruction::UnitLift => {
1385 results.push("()".to_string());
1386 }
1387
1388 Instruction::I32FromBool => {
1389 results.push(format!("match {} {{ true => 1, false => 0 }}", operands[0]));
1390 }
1391 Instruction::BoolFromI32 => {
1392 self.gen.needs_invalid_variant = true;
1393 results.push(format!(
1394 "match {} {{
1395 0 => false,
1396 1 => true,
1397 _ => return Err(invalid_variant(\"bool\")),
1398 }}",
1399 operands[0],
1400 ));
1401 }
1402
1403 Instruction::I32FromOwnedHandle { ty } => {
1404 let name = &iface.resources[*ty].name;
1405 results.push(format!(
1406 "_tables.{}_table.insert({}) as i32",
1407 name.to_snake_case(),
1408 operands[0]
1409 ));
1410 }
1411 Instruction::HandleBorrowedFromI32 { ty } => {
1412 let name = &iface.resources[*ty].name;
1413 results.push(format!(
1414 "_tables.{}_table.get(({}) as u32).ok_or_else(|| {{
1415 wasmtime::Trap::new(\"invalid handle index\")
1416 }})?",
1417 name.to_snake_case(),
1418 operands[0]
1419 ));
1420 }
1421 Instruction::I32FromBorrowedHandle { ty } => {
1422 let tmp = self.tmp();
1423 self.push_str(&format!(
1424 "
1425 let obj{tmp} = {op};
1426 (self.get_state)(caller.as_context_mut().data_mut()).resource_slab{idx}.clone(obj{tmp}.0)?;
1427 let handle{tmp} = (self.get_state)(caller.as_context_mut().data_mut()).index_slab{idx}.insert(obj{tmp}.0);
1428 ",
1429 tmp = tmp,
1430 idx = ty.index(),
1431 op = operands[0],
1432 ));
1433
1434 results.push(format!("handle{} as i32", tmp,));
1435 }
1436 Instruction::HandleOwnedFromI32 { ty } => {
1437 let tmp = self.tmp();
1438 self.push_str(&format!(
1439 "let handle{} = (self.get_state)(caller.as_context_mut().data_mut()).index_slab{}.remove({} as u32)?;\n",
1440 tmp,
1441 ty.index(),
1442 operands[0],
1443 ));
1444
1445 let name = iface.resources[*ty].name.to_camel_case();
1446 results.push(format!("{}(handle{})", name, tmp));
1447 }
1448
1449 Instruction::RecordLower { ty, record, .. } => {
1450 self.record_lower(iface, *ty, record, &operands[0], results);
1451 }
1452 Instruction::RecordLift { ty, record, .. } => {
1453 self.record_lift(iface, *ty, record, operands, results);
1454 }
1455
1456 Instruction::TupleLower { tuple, .. } => {
1457 self.tuple_lower(tuple, &operands[0], results);
1458 }
1459 Instruction::TupleLift { .. } => {
1460 self.tuple_lift(operands, results);
1461 }
1462
1463 Instruction::FlagsLower { flags, .. } => {
1464 let tmp = self.tmp();
1465 self.push_str(&format!("let flags{} = {};\n", tmp, operands[0]));
1466 for i in 0..flags.repr().count() {
1467 results.push(format!("(flags{}.bits >> {}) as i32", tmp, i * 32));
1468 }
1469 }
1470 Instruction::FlagsLift { flags, name, .. } => {
1471 self.gen.needs_validate_flags = true;
1472 let repr = RustFlagsRepr::new(flags);
1473 let mut flags = String::from("0");
1474 for (i, op) in operands.iter().enumerate() {
1475 flags.push_str(&format!("| (({} as {repr}) << {})", op, i * 32));
1476 }
1477 results.push(format!(
1478 "validate_flags(
1479 {},
1480 {name}::all().bits(),
1481 \"{name}\",
1482 |bits| {name} {{ bits }}
1483 )?",
1484 flags,
1485 name = name.to_camel_case(),
1486 ));
1487 }
1488
1489 Instruction::VariantPayloadName => results.push("e".to_string()),
1490
1491 Instruction::VariantLower {
1492 variant,
1493 results: result_types,
1494 ty,
1495 ..
1496 } => {
1497 let blocks = self
1498 .blocks
1499 .drain(self.blocks.len() - variant.cases.len()..)
1500 .collect::<Vec<_>>();
1501 self.let_results(result_types.len(), results);
1502 let op0 = &operands[0];
1503 self.push_str(&format!("match {op0} {{\n"));
1504 let name = self.typename_lower(iface, *ty);
1505 for (case, block) in variant.cases.iter().zip(blocks) {
1506 let case_name = case.name.to_camel_case();
1507 self.push_str(&format!("{name}::{case_name}"));
1508 if case.ty == Type::Unit {
1509 self.push_str(&format!(" => {{\nlet e = ();\n{block}\n}}\n"));
1510 } else {
1511 self.push_str(&format!("(e) => {block},\n"));
1512 }
1513 }
1514 self.push_str("};\n");
1515 }
1516
1517 Instruction::VariantLift { variant, ty, .. } => {
1518 let blocks = self
1519 .blocks
1520 .drain(self.blocks.len() - variant.cases.len()..)
1521 .collect::<Vec<_>>();
1522 let op0 = &operands[0];
1523 let mut result = format!("match {op0} {{\n");
1524 let name = self.typename_lift(iface, *ty);
1525 for (i, (case, block)) in variant.cases.iter().zip(blocks).enumerate() {
1526 let block = if case.ty != Type::Unit {
1527 format!("({block})")
1528 } else {
1529 String::new()
1530 };
1531 let case = case.name.to_camel_case();
1532 result.push_str(&format!("{i} => {name}::{case}{block},\n"));
1533 }
1534 result.push_str(&format!("_ => return Err(invalid_variant(\"{name}\")),\n"));
1535 result.push_str("}");
1536 results.push(result);
1537 self.gen.needs_invalid_variant = true;
1538 }
1539
1540 Instruction::UnionLower {
1541 union,
1542 results: result_types,
1543 ty,
1544 ..
1545 } => {
1546 let blocks = self
1547 .blocks
1548 .drain(self.blocks.len() - union.cases.len()..)
1549 .collect::<Vec<_>>();
1550 self.let_results(result_types.len(), results);
1551 let op0 = &operands[0];
1552 self.push_str(&format!("match {op0} {{\n"));
1553 let name = self.typename_lower(iface, *ty);
1554 for (case_name, block) in self
1555 .gen
1556 .union_case_names(iface, union)
1557 .into_iter()
1558 .zip(blocks)
1559 {
1560 self.push_str(&format!("{name}::{case_name}(e) => {block},\n"));
1561 }
1562 self.push_str("};\n");
1563 }
1564
1565 Instruction::UnionLift { union, ty, .. } => {
1566 let blocks = self
1567 .blocks
1568 .drain(self.blocks.len() - union.cases.len()..)
1569 .collect::<Vec<_>>();
1570 let op0 = &operands[0];
1571 let mut result = format!("match {op0} {{\n");
1572 let name = self.typename_lift(iface, *ty);
1573 for (i, (case_name, block)) in self
1574 .gen
1575 .union_case_names(iface, union)
1576 .into_iter()
1577 .zip(blocks)
1578 .enumerate()
1579 {
1580 result.push_str(&format!("{i} => {name}::{case_name}({block}),\n"));
1581 }
1582 result.push_str(&format!("_ => return Err(invalid_variant(\"{name}\")),\n"));
1583 result.push_str("}");
1584 results.push(result);
1585 }
1586
1587 Instruction::OptionLower {
1588 results: result_types,
1589 ..
1590 } => {
1591 let some = self.blocks.pop().unwrap();
1592 let none = self.blocks.pop().unwrap();
1593 self.let_results(result_types.len(), results);
1594 let operand = &operands[0];
1595 self.push_str(&format!(
1596 "match {operand} {{
1597 Some(e) => {some},
1598 None => {{\nlet e = ();\n{none}\n}},
1599 }};"
1600 ));
1601 }
1602
1603 Instruction::OptionLift { .. } => {
1604 let some = self.blocks.pop().unwrap();
1605 let none = self.blocks.pop().unwrap();
1606 assert_eq!(none, "()");
1607 let operand = &operands[0];
1608 results.push(format!(
1609 "match {operand} {{
1610 0 => None,
1611 1 => Some({some}),
1612 _ => return Err(invalid_variant(\"option\")),
1613 }}"
1614 ));
1615 self.gen.needs_invalid_variant = true;
1616 }
1617
1618 Instruction::ResultLower {
1619 results: result_types,
1620 ..
1621 } => {
1622 let err = self.blocks.pop().unwrap();
1623 let ok = self.blocks.pop().unwrap();
1624 self.let_results(result_types.len(), results);
1625 let operand = &operands[0];
1626 self.push_str(&format!(
1627 "match {operand} {{
1628 Ok(e) => {{ {ok} }},
1629 Err(e) => {{ {err} }},
1630 }};"
1631 ));
1632 }
1633
1634 Instruction::ResultLift { .. } => {
1635 let err = self.blocks.pop().unwrap();
1636 let ok = self.blocks.pop().unwrap();
1637 let operand = &operands[0];
1638 results.push(format!(
1639 "match {operand} {{
1640 0 => Ok({ok}),
1641 1 => Err({err}),
1642 _ => return Err(invalid_variant(\"result\")),
1643 }}"
1644 ));
1645 self.gen.needs_invalid_variant = true;
1646 }
1647
1648 Instruction::EnumLower { .. } => {
1649 results.push(format!("{} as i32", operands[0]));
1650 }
1651
1652 Instruction::EnumLift { name, enum_, .. } => {
1653 let op0 = &operands[0];
1654 let mut result = format!("match {op0} {{\n");
1655 let name = name.to_camel_case();
1656 for (i, case) in enum_.cases.iter().enumerate() {
1657 let case = case.name.to_camel_case();
1658 result.push_str(&format!("{i} => {name}::{case},\n"));
1659 }
1660 result.push_str(&format!("_ => return Err(invalid_variant(\"{name}\")),\n"));
1661 result.push_str("}");
1662 results.push(result);
1663 self.gen.needs_invalid_variant = true;
1664 }
1665
1666 Instruction::ListCanonLower { element, realloc } => {
1667 let realloc = realloc.unwrap();
1671 self.needs_functions
1672 .insert(realloc.to_string(), NeededFunction::Realloc);
1673 let (size, align) = (self.gen.sizes.size(element), self.gen.sizes.align(element));
1674
1675 let tmp = self.tmp();
1677 let val = format!("vec{}", tmp);
1678 self.push_str(&format!("let {} = {};\n", val, operands[0]));
1679
1680 let ptr = format!("ptr{}", tmp);
1682 self.push_str(&format!("let {} = ", ptr));
1683 self.call_intrinsic(
1684 realloc,
1685 format!("(0, 0, {}, ({}.len() as i32) * {})", align, val, size),
1686 );
1687
1688 let mem = self.memory_src();
1690 self.push_str(&format!("{}.store_many({}, &{})?;\n", mem, ptr, val));
1691 self.gen.needs_raw_mem = true;
1692 self.needs_memory = true;
1693 results.push(ptr);
1694 results.push(format!("{}.len() as i32", val));
1695 }
1696
1697 Instruction::ListCanonLift { element, free, .. } => match free {
1698 Some(free) => {
1699 self.needs_memory = true;
1700 self.gen.needs_copy_slice = true;
1701 self.needs_functions
1702 .insert(free.to_string(), NeededFunction::Free);
1703 let (align, el_size) =
1704 (self.sizes().align(element), self.sizes().size(element));
1705 let tmp = self.tmp();
1706 self.push_str(&format!("let ptr{} = {};\n", tmp, operands[0]));
1707 self.push_str(&format!("let len{} = {};\n", tmp, operands[1]));
1708 self.push_str(&format!(
1709 "
1710 let data{tmp} = copy_slice(
1711 &mut caller,
1712 memory,
1713 ptr{tmp}, len{tmp}, {}
1714 )?;
1715 ",
1716 align,
1717 tmp = tmp,
1718 ));
1719 self.call_intrinsic(
1720 free,
1721 format!("(ptr{tmp}, len{tmp} * {}, {})", el_size, align, tmp = tmp),
1724 );
1725 results.push(format!("data{}", tmp));
1726 }
1727 None => {
1728 self.needs_borrow_checker = true;
1729 let tmp = self.tmp();
1730 self.push_str(&format!("let ptr{} = {};\n", tmp, operands[0]));
1731 self.push_str(&format!("let len{} = {};\n", tmp, operands[1]));
1732 let slice = format!("_bc.slice(ptr{0}, len{0})?", tmp);
1733 results.push(slice);
1734 }
1735 },
1736
1737 Instruction::StringLower { realloc } => {
1738 let realloc = realloc.unwrap();
1740 self.needs_functions
1741 .insert(realloc.to_string(), NeededFunction::Realloc);
1742
1743 let tmp = self.tmp();
1745 let val = format!("vec{}", tmp);
1746 self.push_str(&format!("let {} = {};\n", val, operands[0]));
1747
1748 let ptr = format!("ptr{}", tmp);
1750 self.push_str(&format!("let {} = ", ptr));
1751 self.call_intrinsic(realloc, format!("(0, 0, 1, {}.len() as i32)", val));
1752
1753 let mem = self.memory_src();
1755 self.push_str(&format!(
1756 "{}.store_many({}, {}.as_bytes())?;\n",
1757 mem, ptr, val
1758 ));
1759 self.gen.needs_raw_mem = true;
1760 self.needs_memory = true;
1761 results.push(ptr);
1762 results.push(format!("{}.len() as i32", val));
1763 }
1764
1765 Instruction::StringLift { free } => match free {
1766 Some(free) => {
1767 self.needs_memory = true;
1768 self.gen.needs_copy_slice = true;
1769 self.needs_functions
1770 .insert(free.to_string(), NeededFunction::Free);
1771 let tmp = self.tmp();
1772 self.push_str(&format!("let ptr{} = {};\n", tmp, operands[0]));
1773 self.push_str(&format!("let len{} = {};\n", tmp, operands[1]));
1774 self.push_str(&format!(
1775 "
1776 let data{tmp} = copy_slice(
1777 &mut caller,
1778 memory,
1779 ptr{tmp}, len{tmp}, 1,
1780 )?;
1781 ",
1782 tmp = tmp,
1783 ));
1784 self.call_intrinsic(
1785 free,
1786 format!("(ptr{tmp}, len{tmp}, 1)", tmp = tmp),
1789 );
1790 results.push(format!(
1791 "String::from_utf8(data{})
1792 .map_err(|_| wasmtime::Trap::new(\"invalid utf-8\"))?",
1793 tmp,
1794 ));
1795 }
1796 None => {
1797 self.needs_borrow_checker = true;
1798 let tmp = self.tmp();
1799 self.push_str(&format!("let ptr{} = {};\n", tmp, operands[0]));
1800 self.push_str(&format!("let len{} = {};\n", tmp, operands[1]));
1801 let slice = format!("_bc.slice_str(ptr{0}, len{0})?", tmp);
1802 results.push(slice);
1803 }
1804 },
1805
1806 Instruction::ListLower { element, realloc } => {
1807 let realloc = realloc.unwrap();
1808 let body = self.blocks.pop().unwrap();
1809 let tmp = self.tmp();
1810 let vec = format!("vec{}", tmp);
1811 let result = format!("result{}", tmp);
1812 let len = format!("len{}", tmp);
1813 self.needs_functions
1814 .insert(realloc.to_string(), NeededFunction::Realloc);
1815 let size = self.gen.sizes.size(element);
1816 let align = self.gen.sizes.align(element);
1817
1818 self.push_str(&format!("let {} = {};\n", vec, operands[0]));
1821 self.push_str(&format!("let {} = {}.len() as i32;\n", len, vec));
1822
1823 self.push_str(&format!("let {} = ", result));
1825 self.call_intrinsic(realloc, format!("(0, 0, {}, {} * {})", align, len, size));
1826
1827 self.push_str(&format!(
1830 "for (i, e) in {}.into_iter().enumerate() {{\n",
1831 vec
1832 ));
1833 self.push_str(&format!("let base = {} + (i as i32) * {};\n", result, size));
1834 self.push_str(&body);
1835 self.push_str("}");
1836
1837 results.push(result);
1838 results.push(len);
1839 }
1840
1841 Instruction::ListLift { element, free, .. } => {
1842 let body = self.blocks.pop().unwrap();
1843 let tmp = self.tmp();
1844 let size = self.gen.sizes.size(element);
1845 let align = self.gen.sizes.align(element);
1846 let len = format!("len{}", tmp);
1847 self.push_str(&format!("let {} = {};\n", len, operands[1]));
1848 let base = format!("base{}", tmp);
1849 self.push_str(&format!("let {} = {};\n", base, operands[0]));
1850 let result = format!("result{}", tmp);
1851 self.push_str(&format!(
1852 "let mut {} = Vec::with_capacity({} as usize);\n",
1853 result, len,
1854 ));
1855
1856 self.push_str("for i in 0..");
1857 self.push_str(&len);
1858 self.push_str(" {\n");
1859 self.push_str("let base = ");
1860 self.push_str(&base);
1861 self.push_str(" + i *");
1862 self.push_str(&size.to_string());
1863 self.push_str(";\n");
1864 self.push_str(&result);
1865 self.push_str(".push(");
1866 self.push_str(&body);
1867 self.push_str(");\n");
1868 self.push_str("}\n");
1869 results.push(result);
1870
1871 if let Some(free) = free {
1872 self.call_intrinsic(free, format!("({}, {} * {}, {})", base, len, size, align));
1873 self.needs_functions
1874 .insert(free.to_string(), NeededFunction::Free);
1875 }
1876 }
1877
1878 Instruction::IterElem { .. } => {
1879 self.caller_memory_available = false; results.push("e".to_string())
1881 }
1882
1883 Instruction::IterBasePointer => results.push("base".to_string()),
1884
1885 Instruction::CallWasm {
1886 iface: _,
1887 base_name,
1888 mangled_name: _,
1889 sig,
1890 } => {
1891 if sig.results.len() > 0 {
1892 let tmp = self.tmp();
1893 self.push_str("let (");
1894 for i in 0..sig.results.len() {
1895 let arg = format!("result{}_{}", tmp, i);
1896 self.push_str(&arg);
1897 self.push_str(",");
1898 results.push(arg);
1899 }
1900 self.push_str(") = ");
1901 }
1902 self.push_str("self.");
1903 self.push_str(&to_rust_ident(base_name));
1904 self.push_str(".call(");
1905 self.push_str("&mut caller, (");
1906 for operand in operands {
1907 self.push_str(operand);
1908 self.push_str(", ");
1909 }
1910 self.push_str("))");
1911 self.push_str("?;\n");
1912 self.after_call = true;
1913 self.caller_memory_available = false; }
1915
1916 Instruction::CallInterface { module: _, func } => {
1917 for (i, operand) in operands.iter().enumerate() {
1918 self.push_str(&format!("let param{} = {};\n", i, operand));
1919 }
1920 if self.gen.opts.tracing && func.params.len() > 0 {
1921 self.push_str("wit_bindgen_host_wasmtime_rust::tracing::event!(\n");
1922 self.push_str("wit_bindgen_host_wasmtime_rust::tracing::Level::TRACE,\n");
1923 for (i, (name, _ty)) in func.params.iter().enumerate() {
1924 self.push_str(&format!(
1925 "{} = wit_bindgen_host_wasmtime_rust::tracing::field::debug(¶m{}),\n",
1926 to_rust_ident(name),
1927 i
1928 ));
1929 }
1930 self.push_str(");\n");
1931 }
1932
1933 let mut call = format!("host.{}(", func.name.to_snake_case());
1934 for i in 0..operands.len() {
1935 call.push_str(&format!("param{}, ", i));
1936 }
1937 call.push_str(")");
1938
1939 self.push_str("let result = ");
1940 results.push("result".to_string());
1941 match self.gen.classify_fn_ret(iface, func) {
1942 FunctionRet::Normal => self.push_str(&call),
1943 FunctionRet::CustomToTrap => {
1946 self.push_str("match ");
1947 self.push_str(&call);
1948 self.push_str("{\n");
1949 self.push_str("Ok(val) => val,\n");
1950 self.push_str("Err(e) => return Err(host.error_to_trap(e)),\n");
1951 self.push_str("}");
1952 }
1953 FunctionRet::CustomToError { err, .. } => {
1957 self.push_str("match ");
1958 self.push_str(&call);
1959 self.push_str("{\n");
1960 self.push_str("Ok(val) => Ok(val),\n");
1961 self.push_str(&format!(
1962 "Err(e) => Err(host.error_to_{}(e)?),\n",
1963 err.to_snake_case()
1964 ));
1965 self.push_str("}");
1966 }
1967 }
1968 self.push_str(";\n");
1969 self.after_call = true;
1970 match &func.result {
1971 Type::Unit => {}
1972 _ if self.gen.opts.tracing => {
1973 self.push_str("wit_bindgen_host_wasmtime_rust::tracing::event!(\n");
1974 self.push_str("wit_bindgen_host_wasmtime_rust::tracing::Level::TRACE,\n");
1975 self.push_str(&format!(
1976 "{} = wit_bindgen_host_wasmtime_rust::tracing::field::debug(&{0}),\n",
1977 results[0],
1978 ));
1979 self.push_str(");\n");
1980 }
1981 _ => {}
1982 }
1983 }
1984
1985 Instruction::Return { amt, .. } => {
1986 let result = match amt {
1987 0 => format!("Ok(())\n"),
1988 1 => format!("Ok({})\n", operands[0]),
1989 _ => format!("Ok(({}))\n", operands.join(", ")),
1990 };
1991 match self.cleanup.take() {
1992 Some(cleanup) => {
1993 self.push_str("let ret = ");
1994 self.push_str(&result);
1995 self.push_str(";\n");
1996 self.push_str(&cleanup);
1997 self.push_str("ret");
1998 }
1999 None => self.push_str(&result),
2000 }
2001 }
2002
2003 Instruction::I32Load { offset } => results.push(self.load(*offset, "i32", operands)),
2004 Instruction::I32Load8U { offset } => {
2005 results.push(format!("i32::from({})", self.load(*offset, "u8", operands)));
2006 }
2007 Instruction::I32Load8S { offset } => {
2008 results.push(format!("i32::from({})", self.load(*offset, "i8", operands)));
2009 }
2010 Instruction::I32Load16U { offset } => {
2011 results.push(format!(
2012 "i32::from({})",
2013 self.load(*offset, "u16", operands)
2014 ));
2015 }
2016 Instruction::I32Load16S { offset } => {
2017 results.push(format!(
2018 "i32::from({})",
2019 self.load(*offset, "i16", operands)
2020 ));
2021 }
2022 Instruction::I64Load { offset } => results.push(self.load(*offset, "i64", operands)),
2023 Instruction::F32Load { offset } => results.push(self.load(*offset, "f32", operands)),
2024 Instruction::F64Load { offset } => results.push(self.load(*offset, "f64", operands)),
2025
2026 Instruction::I32Store { offset } => self.store(*offset, "as_i32", "", operands),
2027 Instruction::I64Store { offset } => self.store(*offset, "as_i64", "", operands),
2028 Instruction::F32Store { offset } => self.store(*offset, "as_f32", "", operands),
2029 Instruction::F64Store { offset } => self.store(*offset, "as_f64", "", operands),
2030 Instruction::I32Store8 { offset } => self.store(*offset, "as_i32", " as u8", operands),
2031 Instruction::I32Store16 { offset } => {
2032 self.store(*offset, "as_i32", " as u16", operands)
2033 }
2034
2035 Instruction::Malloc {
2036 realloc,
2037 size,
2038 align,
2039 } => {
2040 self.needs_functions
2041 .insert(realloc.to_string(), NeededFunction::Realloc);
2042 let tmp = self.tmp();
2043 let ptr = format!("ptr{}", tmp);
2044 self.push_str(&format!("let {} = ", ptr));
2045 self.call_intrinsic(realloc, format!("(0, 0, {}, {})", align, size));
2046 results.push(ptr);
2047 }
2048
2049 Instruction::Free { .. } => unimplemented!(),
2050 }
2051 }
2052}
2053
2054impl NeededFunction {
2055 fn cvt(&self) -> &'static str {
2056 match self {
2057 NeededFunction::Realloc => "(i32, i32, i32, i32), i32",
2058 NeededFunction::Free => "(i32, i32, i32), ()",
2059 }
2060 }
2061
2062 fn ty(&self) -> String {
2063 format!("wasmtime::TypedFunc<{}>", self.cvt())
2064 }
2065}
2066
2067fn sorted_iter<K: Ord, V>(map: &HashMap<K, V>) -> impl Iterator<Item = (&K, &V)> {
2068 let mut list = map.into_iter().collect::<Vec<_>>();
2069 list.sort_by_key(|p| p.0);
2070 list.into_iter()
2071}