1use heck::*;
2use std::collections::{BTreeMap, BTreeSet, HashMap, HashSet};
3use std::io::{Read, Write};
4use std::mem;
5use std::process::{Command, Stdio};
6use std::str::FromStr;
7use wai_bindgen_gen_core::wai_parser::abi::{
8 AbiVariant, Bindgen, Instruction, LiftLower, WasmType,
9};
10use wai_bindgen_gen_core::{wai_parser::*, Direction, Files, Generator, Source, TypeInfo, Types};
11use wai_bindgen_gen_rust::{
12 to_rust_ident, wasm_type, FnSig, RustFlagsRepr, RustFunctionGenerator, RustGenerator, TypeMode,
13};
14
15#[derive(Default)]
16pub struct Wasmer {
17 src: Source,
18 opts: Opts,
19 needs_memory: bool,
20 needs_functions: BTreeMap<String, NeededFunction>,
21 needs_char_from_i32: bool,
22 needs_invalid_variant: bool,
23 needs_validate_flags: bool,
24 needs_raw_mem: bool,
25 needs_bad_int: bool,
26 needs_copy_slice: bool,
27 needs_buffer_glue: bool,
28 needs_le: bool,
29 needs_custom_error_to_trap: bool,
30 needs_custom_error_to_types: BTreeSet<String>,
31 needs_lazy_initialized: bool,
32 all_needed_handles: BTreeSet<String>,
33 exported_resources: BTreeSet<ResourceId>,
34 types: Types,
35 guest_imports: HashMap<String, Vec<Import>>,
36 guest_exports: HashMap<String, Exports>,
37 in_import: bool,
38 in_trait: bool,
39 trait_name: String,
40 sizes: SizeAlign,
41}
42
43enum NeededFunction {
44 Realloc,
45 Free,
46}
47
48struct Import {
49 is_async: bool,
50 name: String,
51 trait_signature: String,
52 closure: String,
53}
54
55#[derive(Default)]
56struct Exports {
57 fields: BTreeMap<String, (String, String)>,
58 funcs: Vec<String>,
59}
60
61#[derive(Default, Debug, Clone)]
62#[cfg_attr(feature = "structopt", derive(structopt::StructOpt))]
63pub struct Opts {
64 #[cfg_attr(feature = "structopt", structopt(long))]
66 pub rustfmt: bool,
67
68 #[cfg_attr(feature = "structopt", structopt(long))]
70 pub tracing: bool,
71
72 #[cfg_attr(
75 feature = "structopt",
76 structopt(long = "async", default_value = "none")
77 )]
78 pub async_: Async,
79
80 #[cfg_attr(feature = "structopt", structopt(long))]
83 pub custom_error: bool,
84}
85
86#[derive(Debug, Clone)]
87pub enum Async {
88 None,
89 All,
90 Only(HashSet<String>),
91}
92
93impl Async {
94 fn includes(&self, name: &str) -> bool {
95 match self {
96 Async::None => false,
97 Async::All => true,
98 Async::Only(list) => list.contains(name),
99 }
100 }
101
102 fn is_none(&self) -> bool {
103 match self {
104 Async::None => true,
105 _ => false,
106 }
107 }
108}
109
110impl Default for Async {
111 fn default() -> Async {
112 Async::None
113 }
114}
115
116impl FromStr for Async {
117 type Err = String;
118 fn from_str(s: &str) -> Result<Async, String> {
119 Ok(if s == "all" {
120 Async::All
121 } else if s == "none" {
122 Async::None
123 } else {
124 Async::Only(s.split(',').map(|s| s.trim().to_string()).collect())
125 })
126 }
127}
128
129impl Opts {
130 pub fn build(self) -> Wasmer {
131 let mut r = Wasmer::new();
132 r.opts = self;
133 r
134 }
135}
136
137enum FunctionRet {
138 Normal,
140 CustomToTrap,
144 CustomToError { ok: Type, err: String },
148}
149
150impl Wasmer {
151 pub fn new() -> Wasmer {
152 Wasmer::default()
153 }
154
155 fn abi_variant(dir: Direction) -> AbiVariant {
156 match dir {
165 Direction::Import => AbiVariant::GuestExport,
166 Direction::Export => AbiVariant::GuestImport,
167 }
168 }
169
170 fn print_intrinsics(&mut self) {
171 if self.needs_lazy_initialized || !self.exported_resources.is_empty() {
172 self.push_str("use wai_bindgen_wasmer::once_cell::unsync::OnceCell;\n");
173 }
174
175 self.push_str("#[allow(unused_imports)]\n");
176 self.push_str("use wasmer::AsStoreMut as _;\n");
177 self.push_str("#[allow(unused_imports)]\n");
178 self.push_str("use wasmer::AsStoreRef as _;\n");
179 if self.needs_raw_mem {
180 self.push_str("use wai_bindgen_wasmer::rt::RawMem;\n");
181 }
182 if self.needs_char_from_i32 {
183 self.push_str("use wai_bindgen_wasmer::rt::char_from_i32;\n");
184 }
185 if self.needs_invalid_variant {
186 self.push_str("use wai_bindgen_wasmer::rt::invalid_variant;\n");
187 }
188 if self.needs_bad_int {
189 self.push_str("use core::convert::TryFrom;\n");
190 self.push_str("use wai_bindgen_wasmer::rt::bad_int;\n");
191 }
192 if self.needs_validate_flags {
193 self.push_str("use wai_bindgen_wasmer::rt::validate_flags;\n");
194 }
195 if self.needs_le {
196 self.push_str("use wai_bindgen_wasmer::Le;\n");
197 }
198 if self.needs_copy_slice {
199 self.push_str("use wai_bindgen_wasmer::rt::copy_slice;\n");
200 }
201 }
202
203 fn classify_fn_ret(&mut self, iface: &Interface, f: &Function) -> FunctionRet {
206 if !self.opts.custom_error {
207 return FunctionRet::Normal;
208 }
209
210 if let Type::Id(id) = &f.result {
211 if let TypeDefKind::Expected(e) = &iface.types[*id].kind {
212 if let Type::Id(err) = e.err {
213 if let Some(name) = &iface.types[err].name {
214 self.needs_custom_error_to_types.insert(name.clone());
215 return FunctionRet::CustomToError {
216 ok: e.ok,
217 err: name.to_string(),
218 };
219 }
220 }
221 }
222 }
223
224 self.needs_custom_error_to_trap = true;
225 FunctionRet::CustomToTrap
226 }
227}
228
229impl RustGenerator for Wasmer {
230 fn default_param_mode(&self) -> TypeMode {
231 if self.in_import {
232 TypeMode::LeafBorrowed("'a")
235 } else {
236 TypeMode::AllBorrowed("'a")
240 }
241 }
242
243 fn handle_projection(&self) -> Option<(&'static str, String)> {
244 if self.in_import {
245 if self.in_trait {
246 Some(("Self", self.trait_name.clone()))
247 } else {
248 Some(("T", self.trait_name.clone()))
249 }
250 } else {
251 None
252 }
253 }
254
255 fn handle_wrapper(&self) -> Option<&'static str> {
256 None
257 }
258
259 fn push_str(&mut self, s: &str) {
260 self.src.push_str(s);
261 }
262
263 fn info(&self, ty: TypeId) -> TypeInfo {
264 self.types.get(ty)
265 }
266
267 fn types_mut(&mut self) -> &mut Types {
268 &mut self.types
269 }
270
271 fn print_borrowed_slice(
272 &mut self,
273 iface: &Interface,
274 mutbl: bool,
275 ty: &Type,
276 lifetime: &'static str,
277 ) {
278 if self.sizes.align(ty) > 1 && self.in_import {
279 self.needs_le = true;
290 self.push_str("&");
291 if lifetime != "'_" {
292 self.push_str(lifetime);
293 self.push_str(" ");
294 }
295 if mutbl {
296 self.push_str(" mut ");
297 }
298 self.push_str("[Le<");
299 self.print_ty(iface, ty, TypeMode::AllBorrowed(lifetime));
300 self.push_str(">]");
301 } else {
302 self.print_rust_slice(iface, mutbl, ty, lifetime);
303 }
304 }
305
306 fn print_borrowed_str(&mut self, lifetime: &'static str) {
307 self.push_str("&");
308 if lifetime != "'_" {
309 self.push_str(lifetime);
310 self.push_str(" ");
311 }
312 self.push_str(" str");
313 }
314}
315
316impl Generator for Wasmer {
317 fn preprocess_one(&mut self, iface: &Interface, dir: Direction) {
318 let variant = Self::abi_variant(dir);
319 self.types.analyze(iface);
320 self.in_import = variant == AbiVariant::GuestImport;
321 self.trait_name = iface.name.to_camel_case();
322 self.src.push_str(&format!(
323 "#[allow(clippy::all)]\npub mod {} {{\n",
324 iface.name.to_snake_case()
325 ));
326 self.src
327 .push_str("#[allow(unused_imports)]\nuse wai_bindgen_wasmer::{anyhow, wasmer};\n");
328 self.sizes.fill(iface);
329 }
330
331 fn type_record(
332 &mut self,
333 iface: &Interface,
334 id: TypeId,
335 name: &str,
336 record: &Record,
337 docs: &Docs,
338 ) {
339 self.print_typedef_record(iface, id, record, docs);
340
341 if !self.modes_of(iface, id).is_empty()
345 && record.fields.iter().all(|f| iface.all_bits_valid(&f.ty))
346 {
347 self.src.push_str("impl wai_bindgen_wasmer::Endian for ");
348 self.src.push_str(&name.to_camel_case());
349 self.src.push_str(" {\n");
350
351 self.src.push_str("fn into_le(self) -> Self {\n");
352 self.src.push_str("Self {\n");
353 for field in record.fields.iter() {
354 self.src.push_str(&field.name.to_snake_case());
355 self.src.push_str(": self.");
356 self.src.push_str(&field.name.to_snake_case());
357 self.src.push_str(".into_le(),\n");
358 }
359 self.src.push_str("}\n");
360 self.src.push_str("}\n");
361
362 self.src.push_str("fn from_le(self) -> Self {\n");
363 self.src.push_str("Self {\n");
364 for field in record.fields.iter() {
365 self.src.push_str(&field.name.to_snake_case());
366 self.src.push_str(": self.");
367 self.src.push_str(&field.name.to_snake_case());
368 self.src.push_str(".from_le(),\n");
369 }
370 self.src.push_str("}\n");
371 self.src.push_str("}\n");
372
373 self.src.push_str("}\n");
374
375 self.src
379 .push_str("unsafe impl wai_bindgen_wasmer::AllBytesValid for ");
380 self.src.push_str(&name.to_camel_case());
381 self.src.push_str(" {}\n");
382 }
383 }
384
385 fn type_tuple(
386 &mut self,
387 iface: &Interface,
388 id: TypeId,
389 _name: &str,
390 tuple: &Tuple,
391 docs: &Docs,
392 ) {
393 self.print_typedef_tuple(iface, id, tuple, docs);
394 }
395
396 fn type_flags(
397 &mut self,
398 _iface: &Interface,
399 _id: TypeId,
400 name: &str,
401 flags: &Flags,
402 docs: &Docs,
403 ) {
404 self.src
405 .push_str("wai_bindgen_wasmer::bitflags::bitflags! {\n");
406 self.rustdoc(docs);
407 let repr = RustFlagsRepr::new(flags);
408 self.src
409 .push_str(&format!("pub struct {}: {repr} {{", name.to_camel_case()));
410 for (i, flag) in flags.flags.iter().enumerate() {
411 self.rustdoc(&flag.docs);
412 self.src.push_str(&format!(
413 "const {} = 1 << {};\n",
414 flag.name.to_shouty_snake_case(),
415 i,
416 ));
417 }
418 self.src.push_str("}\n");
419 self.src.push_str("}\n\n");
420
421 self.src.push_str("impl core::fmt::Display for ");
422 self.src.push_str(&name.to_camel_case());
423 self.src.push_str(
424 "{\nfn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {\n",
425 );
426
427 self.src.push_str("f.write_str(\"");
428 self.src.push_str(&name.to_camel_case());
429 self.src.push_str("(\")?;\n");
430 self.src.push_str("core::fmt::Debug::fmt(self, f)?;\n");
431 self.src.push_str("f.write_str(\" (0x\")?;\n");
432 self.src
433 .push_str("core::fmt::LowerHex::fmt(&self.bits, f)?;\n");
434 self.src.push_str("f.write_str(\"))\")?;\n");
435 self.src.push_str("Ok(())");
436
437 self.src.push_str("}\n");
438 self.src.push_str("}\n\n");
439 }
440
441 fn type_variant(
442 &mut self,
443 iface: &Interface,
444 id: TypeId,
445 _name: &str,
446 variant: &Variant,
447 docs: &Docs,
448 ) {
449 self.print_typedef_variant(iface, id, variant, docs);
450 }
451
452 fn type_enum(&mut self, _iface: &Interface, id: TypeId, name: &str, enum_: &Enum, docs: &Docs) {
453 self.print_typedef_enum(id, name, enum_, docs);
454 }
455
456 fn type_union(
457 &mut self,
458 iface: &Interface,
459 id: TypeId,
460 _name: &str,
461 union: &Union,
462 docs: &Docs,
463 ) {
464 self.print_typedef_union(iface, id, union, docs);
465 }
466
467 fn type_option(
468 &mut self,
469 iface: &Interface,
470 id: TypeId,
471 _name: &str,
472 payload: &Type,
473 docs: &Docs,
474 ) {
475 self.print_typedef_option(iface, id, payload, docs);
476 }
477
478 fn type_expected(
479 &mut self,
480 iface: &Interface,
481 id: TypeId,
482 _name: &str,
483 expected: &Expected,
484 docs: &Docs,
485 ) {
486 self.print_typedef_expected(iface, id, expected, docs);
487 }
488
489 fn type_resource(&mut self, iface: &Interface, ty: ResourceId) {
490 let name = &iface.resources[ty].name;
491 self.all_needed_handles.insert(name.to_string());
492
493 if self.in_import {
496 return;
497 }
498
499 self.exported_resources.insert(ty);
500
501 let tyname = name.to_camel_case();
504 self.rustdoc(&iface.resources[ty].docs);
505 self.src.push_str("#[derive(Debug)]\n");
506 self.src.push_str(&format!(
507 "pub struct {}(wai_bindgen_wasmer::rt::ResourceIndex);\n",
508 tyname
509 ));
510 }
511
512 fn type_alias(&mut self, iface: &Interface, id: TypeId, _name: &str, ty: &Type, docs: &Docs) {
513 self.print_typedef_alias(iface, id, ty, docs);
514 }
515
516 fn type_list(&mut self, iface: &Interface, id: TypeId, _name: &str, ty: &Type, docs: &Docs) {
517 self.print_type_list(iface, id, ty, docs);
518 }
519
520 fn type_builtin(&mut self, iface: &Interface, _id: TypeId, name: &str, ty: &Type, docs: &Docs) {
521 self.rustdoc(docs);
522 self.src
523 .push_str(&format!("pub type {}", name.to_camel_case()));
524 self.src.push_str(" = ");
525 self.print_ty(iface, ty, TypeMode::Owned);
526 self.src.push_str(";\n");
527 }
528
529 fn export(&mut self, iface: &Interface, func: &Function) {
533 assert!(!func.is_async, "async not supported yet");
534 let prev = mem::take(&mut self.src);
535
536 let sig = iface.wasm_signature(AbiVariant::GuestImport, func);
539 let params = (0..sig.params.len())
540 .map(|i| format!("arg{}", i))
541 .collect::<Vec<_>>();
542 let mut f = FunctionBindgen::new(self, params);
543 iface.call(
544 AbiVariant::GuestImport,
545 LiftLower::LiftArgsLowerResults,
546 func,
547 &mut f,
548 );
549 let FunctionBindgen {
550 src,
551 cleanup,
552 needs_borrow_checker,
553 needs_memory,
554 needs_buffer_transaction,
555 needs_functions,
556 closures,
557 async_intrinsic_called,
558 ..
559 } = f;
560 assert!(cleanup.is_none());
561 assert!(!needs_buffer_transaction);
562
563 let self_arg = "&mut self".to_string();
565 self.in_trait = true;
566
567 let mut fnsig = FnSig::default();
568 fnsig.private = true;
569 fnsig.self_arg = Some(self_arg);
570 self.print_docs_and_params(iface, func, TypeMode::LeafBorrowed("'_"), &fnsig);
571 match self.classify_fn_ret(iface, func) {
574 FunctionRet::Normal => {
575 self.push_str(" -> ");
576 self.print_ty(iface, &func.result, TypeMode::Owned);
577 }
578 FunctionRet::CustomToTrap => {
579 self.push_str(" -> Result<");
580 self.print_ty(iface, &func.result, TypeMode::Owned);
581 self.push_str(", Self::Error>");
582 }
583 FunctionRet::CustomToError { ok, .. } => {
584 self.push_str(" -> Result<");
585 self.print_ty(iface, &ok, TypeMode::Owned);
586 self.push_str(", Self::Error>");
587 }
588 }
589 self.in_trait = false;
590 let trait_signature = mem::take(&mut self.src).into();
591
592 let result_ty = match &sig.results[..] {
595 &[] => "()".to_string(),
596 &[ty] => wasm_type(ty).to_string(),
597 tys => format!(
598 "({})",
599 tys.iter()
600 .map(|&ty| wasm_type(ty))
601 .collect::<Vec<_>>()
602 .join(", ")
603 ),
604 };
605 self.src
606 .push_str("move |mut store: wasmer::FunctionEnvMut<EnvWrapper<T>>");
607 for (i, param) in sig.params.iter().enumerate() {
608 let arg = format!("arg{}", i);
609 self.src.push_str(",");
610 self.src.push_str(&arg);
611 self.src.push_str(":");
612 self.wasm_type(*param);
613 }
614 self.src.push_str(&format!(
615 "| -> Result<{}, wasmer::RuntimeError> {{\n",
616 result_ty
617 ));
618
619 let is_async = if async_intrinsic_called || self.opts.async_.includes(&func.name) {
627 self.src.push_str("Box::new(async move {\n");
628 true
629 } else {
630 false
631 };
632
633 if self.opts.tracing {
634 self.src.push_str(&format!(
635 "
636 let span = wai_bindgen_wasmer::tracing::span!(
637 wai_bindgen_wasmer::tracing::Level::TRACE,
638 \"wai-bindgen abi\",
639 module = \"{}\",
640 function = \"{}\",
641 );
642 let _enter = span.enter();
643 ",
644 iface.name, func.name,
645 ));
646 }
647 self.src.push_str(&closures);
648
649 for name in needs_functions.keys() {
650 self.src.push_str(&format!(
651 "let func_{name} = store
652 .data()
653 .lazy
654 .get()
655 .unwrap()
656 .func_{name}
657 .clone();\n"
658 ));
659 }
660 self.needs_functions.extend(needs_functions);
661 self.needs_memory |= needs_memory || needs_borrow_checker;
662
663 if self.needs_memory {
664 self.src.push_str(
665 "let _memory: wasmer::Memory = store.data().lazy.get().unwrap().memory.clone();\n",
666 );
667 }
668
669 if needs_borrow_checker {
670 self.src.push_str(
673 "let _memory_view = _memory.view(&store);
674 let mut _bc = wai_bindgen_wasmer::BorrowChecker::new(unsafe {
675 _memory_view.data_unchecked_mut()
676 });\n",
677 );
678 }
679
680 self.src.push_str("let data_mut = store.data_mut();\n");
681
682 if !self.all_needed_handles.is_empty() {
683 self.src
684 .push_str("let tables = data_mut.tables.borrow_mut();\n");
685 }
686
687 self.src.push_str(&String::from(src));
688
689 if is_async {
690 self.src.push_str("})\n");
691 }
692 self.src.push_str("}");
693 let closure = mem::replace(&mut self.src, prev).into();
694
695 self.guest_imports
696 .entry(iface.name.to_string())
697 .or_default()
698 .push(Import {
699 is_async,
700 name: func.name.to_string(),
701 closure,
702 trait_signature,
703 });
704 }
705
706 fn import(&mut self, iface: &Interface, func: &Function) {
710 assert!(!func.is_async, "async not supported yet");
711 let prev = mem::take(&mut self.src);
712
713 let is_async = !self.opts.async_.is_none();
717 let mut sig = FnSig::default();
718 sig.async_ = is_async;
719
720 sig.self_arg = Some("&self, store: &mut wasmer::Store".to_string());
724 self.print_docs_and_params(iface, func, TypeMode::AllBorrowed("'_"), &sig);
725 self.push_str("-> Result<");
726 self.print_ty(iface, &func.result, TypeMode::Owned);
727 self.push_str(", wasmer::RuntimeError> {\n");
728
729 let params = func
730 .params
731 .iter()
732 .map(|(name, _)| to_rust_ident(name))
733 .collect();
734 let mut f = FunctionBindgen::new(self, params);
735 iface.call(
736 AbiVariant::GuestExport,
737 LiftLower::LowerArgsLiftResults,
738 func,
739 &mut f,
740 );
741 let FunctionBindgen {
742 needs_memory,
743 src,
744 needs_borrow_checker,
745 needs_buffer_transaction,
746 closures,
747 needs_functions,
748 ..
749 } = f;
750
751 let exports = self
752 .guest_exports
753 .entry(iface.name.to_string())
754 .or_insert_with(Exports::default);
755
756 for (name, func) in needs_functions {
757 self.src
758 .push_str(&format!("let func_{name} = &self.func_{name};\n"));
759 let get = format!("_instance.exports.get_typed_function(&store, \"{name}\")?",);
760 exports
761 .fields
762 .insert(format!("func_{name}"), (func.ty(), get));
763 }
764
765 self.src.push_str(&closures);
766
767 assert!(!needs_borrow_checker);
768 if needs_memory {
769 self.src.push_str("let _memory = &self.memory;\n");
770 exports.fields.insert(
771 "memory".to_string(),
772 (
773 "wasmer::Memory".to_string(),
774 "_instance.exports.get_memory(\"memory\")?.clone()".to_string(),
775 ),
776 );
777 }
778
779 if needs_buffer_transaction {
780 self.needs_buffer_glue = true;
781 self.src
782 .push_str("let mut buffer_transaction = self.buffer_glue.transaction();\n");
783 }
784
785 self.src.push_str(&String::from(src));
786 self.src.push_str("}\n");
787 let func_body = mem::replace(&mut self.src, prev);
788 exports.funcs.push(func_body.into());
789
790 let sig = iface.wasm_signature(AbiVariant::GuestExport, func);
794 let mut cvt = String::new();
795 if sig.params.len() == 1 {
796 cvt.push_str(wasm_type(sig.params[0]));
797 } else {
798 cvt.push('(');
799 for param in sig.params.iter() {
800 cvt.push_str(wasm_type(*param));
801 cvt.push(',');
802 }
803 cvt.push(')');
804 }
805 cvt.push_str(", ");
806 if sig.results.len() == 1 {
807 cvt.push_str(wasm_type(sig.results[0]));
808 } else {
809 cvt.push('(');
810 for result in sig.results.iter() {
811 cvt.push_str(wasm_type(*result));
812 cvt.push(',');
813 }
814 cvt.push(')');
815 }
816 exports.fields.insert(
817 format!("func_{}", to_rust_ident(&func.name)),
818 (
819 format!("wasmer::TypedFunction<{cvt}>"),
820 format!(
821 "_instance.exports.get_typed_function(&store, \"{}\")?",
822 func.name,
823 ),
824 ),
825 );
826 }
827
828 fn finish_one(&mut self, iface: &Interface, files: &mut Files) {
829 for (module, funcs) in sorted_iter(&self.guest_imports) {
830 let module_camel = module.to_camel_case();
831 let is_async = !self.opts.async_.is_none();
832 if is_async {
833 self.src.push_str("#[wai_bindgen_wasmer::async_trait]\n");
834 }
835 self.src.push_str("pub trait ");
836 self.src.push_str(&module_camel);
837 self.src.push_str(": Sized + Send + Sync + 'static");
838 self.src.push_str("{\n");
839 if !self.all_needed_handles.is_empty() {
840 for handle in self.all_needed_handles.iter() {
841 self.src.push_str("type ");
842 self.src.push_str(&handle.to_camel_case());
843 self.src.push_str(": std::fmt::Debug");
844 if is_async {
845 self.src.push_str(" + Send + Sync");
846 }
847 self.src.push_str(";\n");
848 }
849 }
850 if self.opts.custom_error {
851 self.src.push_str("type Error;\n");
852 if self.needs_custom_error_to_trap {
853 self.src.push_str(
854 "fn error_to_trap(&mut self, err: Self::Error) -> wasmer::RuntimeError;\n",
855 );
856 }
857 for ty in self.needs_custom_error_to_types.iter() {
858 self.src.push_str(&format!(
859 "fn error_to_{}(&mut self, err: Self::Error) -> Result<{}, wasmer::RuntimeError>;\n",
860 ty.to_snake_case(),
861 ty.to_camel_case(),
862 ));
863 }
864 }
865 for f in funcs {
866 self.src.push_str(&f.trait_signature);
867 self.src.push_str(";\n\n");
868 }
869 for handle in self.all_needed_handles.iter() {
870 self.src.push_str(&format!(
871 "fn drop_{}(&mut self, state: Self::{}) {{
872 drop(state);
873 }}\n",
874 handle.to_snake_case(),
875 handle.to_camel_case(),
876 ));
877 }
878 self.src.push_str("}\n");
879
880 if !self.all_needed_handles.is_empty() {
881 self.src.push_str("\npub struct ");
882 self.src.push_str(&module_camel);
883 self.src.push_str("Tables<T: ");
884 self.src.push_str(&module_camel);
885 self.src.push_str("> {\n");
886 for handle in self.all_needed_handles.iter() {
887 self.src.push_str("pub(crate) ");
888 self.src.push_str(&handle.to_snake_case());
889 self.src.push_str("_table: wai_bindgen_wasmer::Table<T::");
890 self.src.push_str(&handle.to_camel_case());
891 self.src.push_str(">,\n");
892 }
893 self.src.push_str("}\n");
894 self.src.push_str("impl<T: ");
895 self.src.push_str(&module_camel);
896 self.src.push_str("> Default for ");
897 self.src.push_str(&module_camel);
898 self.src.push_str("Tables<T> {\n");
899 self.src.push_str("fn default() -> Self { Self {");
900 for handle in self.all_needed_handles.iter() {
901 self.src.push_str(&handle.to_snake_case());
902 self.src.push_str("_table: Default::default(),");
903 }
904 self.src.push_str("}}}");
905 self.src.push_str("impl<T: ");
906 self.src.push_str(&module_camel);
907 self.src.push_str("> Clone for ");
908 self.src.push_str(&module_camel);
909 self.src.push_str("Tables<T> {\n");
910 self.src.push_str("fn clone(&self) -> Self {\n");
911 self.src.push_str("Self::default()\n");
912 self.src.push_str("}}\n");
913 }
914 }
915
916 self.needs_lazy_initialized |= self.needs_memory;
917 self.needs_lazy_initialized |= !self.needs_functions.is_empty();
918 for (module, funcs) in mem::take(&mut self.guest_imports) {
919 let module_camel = module.to_camel_case();
920
921 if self.needs_lazy_initialized {
922 self.push_str("pub struct LazyInitialized {\n");
923 if self.needs_memory {
924 self.push_str("memory: wasmer::Memory,\n");
925 }
926 for (name, func) in &self.needs_functions {
927 self.src.push_str(&format!(
928 "func_{name}: wasmer::TypedFunction<{cvt}>,\n",
929 name = name,
930 cvt = func.cvt(),
931 ));
932 }
933 self.push_str("}\n");
934 }
935
936 self.push_str("\n#[must_use = \"The returned initializer function must be called\n");
937 self.push_str("with the instance and the store before starting the runtime\"]\n");
938 self.push_str("pub fn add_to_imports<T>(store: &mut wasmer::Store, imports: &mut wasmer::Imports, data: T)\n");
939 self.push_str("-> impl FnOnce(&wasmer::Instance, &dyn wasmer::AsStoreRef) -> Result<(), anyhow::Error>\n");
940 self.push_str("where T: ");
941 self.push_str(&module_camel);
942 self.push_str("\n{\n");
943
944 self.push_str("#[derive(Clone)]");
945 self.push_str("struct EnvWrapper<T: ");
946 self.push_str(&module_camel);
947 self.push_str("> {\n");
948 self.push_str("data: T,\n");
949 if !self.all_needed_handles.is_empty() {
950 self.push_str("tables: std::rc::Rc<core::cell::RefCell<");
951 self.push_str(&module_camel);
952 self.push_str("Tables<T>>>,\n");
953 }
954 if self.needs_lazy_initialized {
955 self.push_str("lazy: std::rc::Rc<OnceCell<LazyInitialized>>,\n");
956 }
957 self.push_str("}\n");
958 self.push_str("unsafe impl<T: ");
959 self.push_str(&module_camel);
960 self.push_str("> Send for EnvWrapper<T> {}\n");
961 self.push_str("unsafe impl<T: ");
962 self.push_str(&module_camel);
963 self.push_str("> Sync for EnvWrapper<T> {}\n");
964
965 if self.needs_lazy_initialized {
966 self.push_str("let lazy = std::rc::Rc::new(OnceCell::new());\n");
967 }
968
969 self.push_str("let env = EnvWrapper {\n");
970 self.push_str("data,\n");
971 if !self.all_needed_handles.is_empty() {
972 self.push_str("tables: std::rc::Rc::default(),\n");
973 }
974 if self.needs_lazy_initialized {
975 self.push_str("lazy: std::rc::Rc::clone(&lazy),\n");
976 }
977 self.push_str("};\n");
978 self.push_str("let env = wasmer::FunctionEnv::new(&mut *store, env);\n");
979 self.push_str("let mut exports = wasmer::Exports::new();\n");
980 self.push_str("let mut store = store.as_store_mut();\n");
981
982 for f in funcs {
983 if f.is_async {
984 unimplemented!();
985 }
986 self.push_str(&format!(
987 "exports.insert(
988 \"{}\",
989 wasmer::Function::new_typed_with_env(
990 &mut store,
991 &env,
992 {}
993 ));\n",
994 f.name, f.closure,
995 ));
996 }
997 self.push_str(&format!(
998 "imports.register_namespace(\"{}\", exports);\n",
999 module
1000 ));
1001
1002 if !self.all_needed_handles.is_empty() {
1003 self.push_str("let mut canonical_abi = imports.get_namespace_exports(\"canonical_abi\").unwrap_or_else(wasmer::Exports::new);\n");
1004 for handle in self.all_needed_handles.iter() {
1005 self.src.push_str(&format!(
1006 "canonical_abi.insert(
1007 \"resource_drop_{name}\",
1008 wasmer::Function::new_typed_with_env(
1009 &mut store,
1010 &env,
1011 move |mut store: wasmer::FunctionEnvMut<EnvWrapper<T>>, handle: u32| -> Result<(), wasmer::RuntimeError> {{
1012 let data_mut = store.data_mut();
1013 let mut tables = data_mut.tables.borrow_mut();
1014 let handle = tables
1015 .{snake}_table
1016 .remove(handle)
1017 .map_err(|e| {{
1018 wasmer::RuntimeError::new(format!(\"failed to remove handle: {{}}\", e))
1019 }})?;
1020 let host = &mut data_mut.data;
1021 host.drop_{snake}(handle);
1022 Ok(())
1023 }}
1024 )
1025 );\n",
1026 name = handle,
1027 snake = handle.to_snake_case(),
1028 ));
1029 }
1030 self.push_str("imports.register_namespace(\"canonical_abi\", canonical_abi);\n");
1031 }
1032
1033 self.push_str(
1034 "move |_instance: &wasmer::Instance, _store: &dyn wasmer::AsStoreRef| {\n",
1035 );
1036 if self.needs_lazy_initialized {
1037 if self.needs_memory {
1038 self.push_str(
1039 "let memory = _instance.exports.get_memory(\"memory\")?.clone();\n",
1040 );
1041 }
1042 for name in self.needs_functions.keys() {
1043 self.src.push_str(&format!(
1044 "let func_{name} = _instance
1045 .exports
1046 .get_typed_function(
1047 &_store.as_store_ref(),
1048 \"{name}\",
1049 )
1050 .unwrap()
1051 .clone();\n"
1052 ));
1053 }
1054 self.push_str("lazy.set(LazyInitialized {\n");
1055 if self.needs_memory {
1056 self.push_str("memory,\n");
1057 }
1058 for name in self.needs_functions.keys() {
1059 self.src.push_str(&format!("func_{name},\n"));
1060 }
1061 self.push_str("})\n");
1062 self.push_str(
1063 ".map_err(|_e| anyhow::anyhow!(\"Couldn't set lazy initialized data\"))?;\n",
1064 );
1065 }
1066 self.push_str("Ok(())\n");
1067 self.push_str("}\n");
1068
1069 self.push_str("}\n");
1070 }
1071
1072 for (module, exports) in sorted_iter(&mem::take(&mut self.guest_exports)) {
1073 let name = module.to_camel_case();
1074
1075 self.push_str(
1078 "
1079 /// Auxiliary data associated with the wasm exports.
1080 ",
1081 );
1082 self.push_str("#[derive(Default)]\n");
1083 self.push_str("pub struct ");
1084 self.push_str(&name);
1085 self.push_str("Data {\n");
1086 for r in self.exported_resources.iter() {
1087 self.src.push_str(&format!(
1088 "
1089 index_slab{idx}: wai_bindgen_wasmer::rt::IndexSlab,
1090 resource_slab{idx}: wai_bindgen_wasmer::rt::ResourceSlab,
1091 dtor{idx}: OnceCell<wasmer::TypedFunction<i32, ()>>,
1092 ",
1093 idx = r.index(),
1094 ));
1095 }
1096 self.push_str("}\n\n");
1097
1098 self.push_str("pub struct ");
1099 self.push_str(&name);
1100 self.push_str(" {\n");
1101 self.push_str("#[allow(dead_code)]\n");
1102 self.push_str(&format!("env: wasmer::FunctionEnv<{}Data>,\n", name));
1103 for (name, (ty, _)) in exports.fields.iter() {
1104 self.push_str(name);
1105 self.push_str(": ");
1106 self.push_str(ty);
1107 self.push_str(",\n");
1108 }
1109 self.push_str("}\n");
1110 self.push_str(&format!("impl {} {{\n", name));
1111
1112 if self.exported_resources.is_empty() {
1113 self.push_str("#[allow(unused_variables)]\n");
1114 }
1115 self.push_str(&format!(
1116 "
1117 /// Adds any intrinsics, if necessary for this exported wasm
1118 /// functionality to the `ImportObject` provided.
1119 ///
1120 /// This function returns the `{0}Data` which needs to be
1121 /// passed through to `{0}::new`.
1122 fn add_to_imports(
1123 mut store: impl wasmer::AsStoreMut,
1124 imports: &mut wasmer::Imports,
1125 ) -> wasmer::FunctionEnv<{0}Data> {{
1126 ",
1127 name,
1128 ));
1129 self.push_str(&format!(
1130 "let env = wasmer::FunctionEnv::new(&mut store, {name}Data::default());\n"
1131 ));
1132 if !self.all_needed_handles.is_empty() {
1133 self.push_str("let mut canonical_abi = imports.get_namespace_exports(\"canonical_abi\").unwrap_or_else(wasmer::Exports::new);\n");
1134 for r in self.exported_resources.iter() {
1135 if !self.opts.async_.is_none() {
1136 unimplemented!();
1137 }
1138 self.src.push_str(&format!(
1139 "
1140 canonical_abi.insert(
1141 \"resource_drop_{resource}\",
1142 wasmer::Function::new_typed_with_env(
1143 &mut store,
1144 &env,
1145 move |mut store: wasmer::FunctionEnvMut<{name}Data>, idx: u32| -> Result<(), wasmer::RuntimeError> {{
1146 let resource_idx = store.data_mut().index_slab{idx}.remove(idx)?;
1147 let wasm = match store.data_mut().resource_slab{idx}.drop(resource_idx) {{
1148 Some(wasm) => wasm,
1149 None => return Ok(()),
1150 }};
1151 let dtor = store.data_mut().dtor{idx}.get().unwrap().clone();
1152 dtor.call(&mut store, wasm)?;
1153 Ok(())
1154 }},
1155 )
1156 );
1157 canonical_abi.insert(
1158 \"resource_clone_{resource}\",
1159 wasmer::Function::new_typed_with_env(
1160 &mut store,
1161 &env,
1162 move |mut store: wasmer::FunctionEnvMut<{name}Data>, idx: u32| -> Result<u32, wasmer::RuntimeError> {{
1163 let state = &mut *store.data_mut();
1164 let resource_idx = state.index_slab{idx}.get(idx)?;
1165 state.resource_slab{idx}.clone(resource_idx)?;
1166 Ok(state.index_slab{idx}.insert(resource_idx))
1167 }},
1168 )
1169 );
1170 canonical_abi.insert(
1171 \"resource_get_{resource}\",
1172 wasmer::Function::new_typed_with_env(
1173 &mut store,
1174 &env,
1175 move |mut store: wasmer::FunctionEnvMut<{name}Data>, idx: u32| -> Result<i32, wasmer::RuntimeError> {{
1176 let state = &mut *store.data_mut();
1177 let resource_idx = state.index_slab{idx}.get(idx)?;
1178 Ok(state.resource_slab{idx}.get(resource_idx))
1179 }},
1180 )
1181 );
1182 canonical_abi.insert(
1183 \"resource_new_{resource}\",
1184 wasmer::Function::new_typed_with_env(
1185 &mut store,
1186 &env,
1187 move |mut store: wasmer::FunctionEnvMut<{name}Data>, val: i32| -> Result<u32, wasmer::RuntimeError> {{
1188 let state = &mut *store.data_mut();
1189 let resource_idx = state.resource_slab{idx}.insert(val);
1190 Ok(state.index_slab{idx}.insert(resource_idx))
1191 }},
1192 )
1193 );
1194 ",
1195 name = name,
1196 resource = iface.resources[*r].name,
1197 idx = r.index(),
1198 ));
1199 }
1200 self.push_str("imports.register_namespace(\"canonical_abi\", canonical_abi);\n");
1201 }
1202 self.push_str("env\n");
1203 self.push_str("}\n");
1204
1205 if !self.opts.async_.is_none() {
1206 unimplemented!();
1207 }
1208 self.push_str(
1209 "
1210 /// Instantiates the provided `module` using the specified
1211 /// parameters, wrapping up the result in a structure that
1212 /// translates between wasm and the host.
1213 ///
1214 /// The `imports` provided will have intrinsics added to it
1215 /// automatically, so it's not necessary to call
1216 /// `add_to_imports` beforehand. This function will
1217 /// instantiate the `module` otherwise using `imports`, and
1218 /// both an instance of this structure and the underlying
1219 /// `wasmer::Instance` will be returned.
1220 pub fn instantiate(
1221 mut store: impl wasmer::AsStoreMut,
1222 module: &wasmer::Module,
1223 imports: &mut wasmer::Imports,
1224 ) -> anyhow::Result<(Self, wasmer::Instance)> {
1225 let env = Self::add_to_imports(&mut store, imports);
1226 let instance = wasmer::Instance::new(
1227 &mut store, module, &*imports)?;
1228 ",
1229 );
1230 if !self.exported_resources.is_empty() {
1231 self.push_str("{\n");
1232 for r in self.exported_resources.iter() {
1233 self.src.push_str(&format!(
1234 "let dtor{idx} = instance
1235 .exports
1236 .get_typed_function(
1237 &store,
1238 \"canonical_abi_drop_{name}\",
1239 )?
1240 .clone();
1241 ",
1242 name = iface.resources[*r].name,
1243 idx = r.index(),
1244 ));
1245 }
1246 self.push_str("\n");
1247
1248 for r in self.exported_resources.iter() {
1249 self.src.push_str(&format!(
1250 "env
1251 .as_mut(&mut store)
1252 .dtor{idx}
1253 .set(dtor{idx})
1254 .map_err(|_e| anyhow::anyhow!(\"Couldn't set canonical_abi_drop_{name}\"))?;
1255 ",
1256 name = iface.resources[*r].name,
1257 idx = r.index(),
1258 ));
1259 }
1260 self.push_str("}\n");
1261 }
1262 self.push_str(
1263 "
1264 Ok((Self::new(store, &instance, env)?, instance))
1265 }
1266 ",
1267 );
1268
1269 self.push_str(&format!(
1270 "
1271 /// Low-level creation wrapper for wrapping up the exports
1272 /// of the `instance` provided in this structure of wasm
1273 /// exports.
1274 ///
1275 /// This function will extract exports from the `instance`
1276 /// and wrap them all up in the returned structure which can
1277 /// be used to interact with the wasm module.
1278 pub fn new(
1279 store: impl wasmer::AsStoreMut,
1280 _instance: &wasmer::Instance,
1281 env: wasmer::FunctionEnv<{}Data>,
1282 ) -> Result<Self, wasmer::ExportError> {{
1283 ",
1284 name,
1285 ));
1286 for (name, (_, get)) in exports.fields.iter() {
1288 self.push_str("let ");
1289 self.push_str(name);
1290 self.push_str("= ");
1291 self.push_str(get);
1292 self.push_str(";\n");
1293 }
1294 self.push_str("Ok(");
1295 self.push_str(&name);
1296 self.push_str("{\n");
1297 for (name, _) in exports.fields.iter() {
1298 self.push_str(name);
1299 self.push_str(",\n");
1300 }
1301 self.push_str("env,\n");
1302 self.push_str("})\n");
1303 self.push_str("}\n");
1304
1305 for func in exports.funcs.iter() {
1306 self.push_str(func);
1307 }
1308
1309 for r in self.exported_resources.iter() {
1310 if !self.opts.async_.is_none() {
1311 unimplemented!();
1312 }
1313 self.src.push_str(&format!(
1314 "
1315 /// Drops the host-owned handle to the resource
1316 /// specified.
1317 ///
1318 /// Note that this may execute the WebAssembly-defined
1319 /// destructor for this type. This also may not run
1320 /// the destructor if there are still other references
1321 /// to this type.
1322 pub fn drop_{name_snake}(
1323 &self,
1324 store: &mut wasmer::Store,
1325 val: {name_camel},
1326 ) -> Result<(), wasmer::RuntimeError> {{
1327 let state = self.env.as_mut(store);
1328 let wasm = match state.resource_slab{idx}.drop(val.0) {{
1329 Some(val) => val,
1330 None => return Ok(()),
1331 }};
1332 let dtor{idx} = state.dtor{idx}.get().unwrap().clone();
1333 dtor{idx}.call(store, wasm)?;
1334 Ok(())
1335 }}
1336 ",
1337 name_snake = iface.resources[*r].name.to_snake_case(),
1338 name_camel = iface.resources[*r].name.to_camel_case(),
1339 idx = r.index(),
1340 ));
1341 }
1342
1343 self.push_str("}\n");
1344 }
1345 self.print_intrinsics();
1346
1347 self.push_str("}\n");
1349
1350 let mut src = mem::take(&mut self.src);
1351 if self.opts.rustfmt {
1352 let mut child = Command::new("rustfmt")
1353 .arg("--edition=2018")
1354 .stdin(Stdio::piped())
1355 .stdout(Stdio::piped())
1356 .spawn()
1357 .expect("failed to spawn `rustfmt`");
1358 child
1359 .stdin
1360 .take()
1361 .unwrap()
1362 .write_all(src.as_bytes())
1363 .unwrap();
1364 src.as_mut_string().truncate(0);
1365 child
1366 .stdout
1367 .take()
1368 .unwrap()
1369 .read_to_string(src.as_mut_string())
1370 .unwrap();
1371 let status = child.wait().unwrap();
1372 assert!(status.success());
1373 }
1374
1375 files.push("bindings.rs", src.as_bytes());
1376 }
1377}
1378
1379struct FunctionBindgen<'a> {
1380 gen: &'a mut Wasmer,
1381
1382 tmp: usize,
1384
1385 src: Source,
1387
1388 params: Vec<String>,
1390
1391 block_storage: Vec<Source>,
1393 blocks: Vec<String>,
1394
1395 after_call: bool,
1398 caller_memory_available: bool,
1401 async_intrinsic_called: bool,
1405 cleanup: Option<String>,
1408
1409 closures: Source,
1412
1413 needs_buffer_transaction: bool,
1416 needs_borrow_checker: bool,
1417 needs_memory: bool,
1418 needs_functions: HashMap<String, NeededFunction>,
1419}
1420
1421impl FunctionBindgen<'_> {
1422 fn new(gen: &mut Wasmer, params: Vec<String>) -> FunctionBindgen<'_> {
1423 FunctionBindgen {
1424 gen,
1425 block_storage: Vec::new(),
1426 blocks: Vec::new(),
1427 src: Source::default(),
1428 after_call: false,
1429 caller_memory_available: false,
1430 async_intrinsic_called: false,
1431 tmp: 0,
1432 cleanup: None,
1433 closures: Source::default(),
1434 needs_buffer_transaction: false,
1435 needs_borrow_checker: false,
1436 needs_memory: false,
1437 needs_functions: HashMap::new(),
1438 params,
1439 }
1440 }
1441
1442 fn memory_src(&mut self) -> String {
1443 if self.gen.in_import {
1444 if !self.after_call {
1445 self.needs_borrow_checker = true;
1448 return "_bc".to_string();
1449 }
1450
1451 if !self.caller_memory_available {
1452 self.needs_memory = true;
1453 self.caller_memory_available = true;
1454 self.push_str("let _memory_view = _memory.view(&store);\n");
1455 self.push_str(
1456 "let caller_memory = unsafe { _memory_view.data_unchecked_mut() };\n",
1457 );
1458 }
1459 "caller_memory".to_string()
1460 } else {
1461 self.needs_memory = true;
1462 self.push_str("let _memory_view = _memory.view(&store);\n");
1463 "unsafe { _memory_view.data_unchecked_mut() }".to_string()
1464 }
1465 }
1466
1467 fn call_intrinsic(&mut self, name: &str, args: String) {
1468 if !self.gen.opts.async_.is_none() {
1469 self.async_intrinsic_called = true;
1470 unimplemented!();
1471 };
1472 self.push_str(&format!("func_{name}.call({args})?;\n"));
1473 self.caller_memory_available = false; }
1475
1476 fn load(&mut self, offset: i32, ty: &str, operands: &[String]) -> String {
1477 let mem = self.memory_src();
1478 self.gen.needs_raw_mem = true;
1479 let tmp = self.tmp();
1480 self.push_str(&format!(
1481 "let load{} = {}.load::<{}>({} + {})?;\n",
1482 tmp, mem, ty, operands[0], offset
1483 ));
1484 format!("load{}", tmp)
1485 }
1486
1487 fn store(&mut self, offset: i32, method: &str, extra: &str, operands: &[String]) {
1488 let mem = self.memory_src();
1489 self.gen.needs_raw_mem = true;
1490 self.push_str(&format!(
1491 "{}.store({} + {}, wai_bindgen_wasmer::rt::{}({}){})?;\n",
1492 mem, operands[1], offset, method, operands[0], extra
1493 ));
1494 }
1495}
1496
1497impl RustFunctionGenerator for FunctionBindgen<'_> {
1498 fn push_str(&mut self, s: &str) {
1499 self.src.push_str(s);
1500 }
1501
1502 fn tmp(&mut self) -> usize {
1503 let ret = self.tmp;
1504 self.tmp += 1;
1505 ret
1506 }
1507
1508 fn rust_gen(&self) -> &dyn RustGenerator {
1509 self.gen
1510 }
1511
1512 fn lift_lower(&self) -> LiftLower {
1513 if self.gen.in_import {
1514 LiftLower::LiftArgsLowerResults
1515 } else {
1516 LiftLower::LowerArgsLiftResults
1517 }
1518 }
1519}
1520
1521impl Bindgen for FunctionBindgen<'_> {
1522 type Operand = String;
1523
1524 fn sizes(&self) -> &SizeAlign {
1525 &self.gen.sizes
1526 }
1527
1528 fn push_block(&mut self) {
1529 let prev = mem::take(&mut self.src);
1530 self.block_storage.push(prev);
1531 }
1532
1533 fn finish_block(&mut self, operands: &mut Vec<String>) {
1534 let to_restore = self.block_storage.pop().unwrap();
1535 let src = mem::replace(&mut self.src, to_restore);
1536 let expr = match operands.len() {
1537 0 => "()".to_string(),
1538 1 => operands[0].clone(),
1539 _ => format!("({})", operands.join(", ")),
1540 };
1541 if src.is_empty() {
1542 self.blocks.push(expr);
1543 } else if operands.is_empty() {
1544 self.blocks.push(format!("{{\n{}}}", &src[..]));
1545 } else {
1546 self.blocks.push(format!("{{\n{}{}\n}}", &src[..], expr));
1547 }
1548 self.caller_memory_available = false;
1549 }
1550
1551 fn return_pointer(&mut self, _iface: &Interface, _size: usize, _align: usize) -> String {
1552 unimplemented!()
1553 }
1554
1555 fn is_list_canonical(&self, iface: &Interface, ty: &Type) -> bool {
1556 iface.all_bits_valid(ty)
1557 }
1558
1559 fn emit(
1560 &mut self,
1561 iface: &Interface,
1562 inst: &Instruction<'_>,
1563 operands: &mut Vec<String>,
1564 results: &mut Vec<String>,
1565 ) {
1566 let mut top_as = |cvt: &str| {
1567 let mut s = operands.pop().unwrap();
1568 s.push_str(" as ");
1569 s.push_str(cvt);
1570 results.push(s);
1571 };
1572
1573 let mut try_from = |cvt: &str, operands: &[String], results: &mut Vec<String>| {
1574 self.gen.needs_bad_int = true;
1575 let result = format!("{}::try_from({}).map_err(bad_int)?", cvt, operands[0]);
1576 results.push(result);
1577 };
1578
1579 match inst {
1580 Instruction::GetArg { nth } => results.push(self.params[*nth].clone()),
1581 Instruction::I32Const { val } => results.push(format!("{}i32", val)),
1582 Instruction::ConstZero { tys } => {
1583 for ty in tys.iter() {
1584 match ty {
1585 WasmType::I32 => results.push("0i32".to_string()),
1586 WasmType::I64 => results.push("0i64".to_string()),
1587 WasmType::F32 => results.push("0.0f32".to_string()),
1588 WasmType::F64 => results.push("0.0f64".to_string()),
1589 }
1590 }
1591 }
1592
1593 Instruction::I64FromU64 | Instruction::I64FromS64 => {
1594 let s = operands.pop().unwrap();
1595 results.push(format!("wai_bindgen_wasmer::rt::as_i64({})", s));
1596 }
1597 Instruction::I32FromChar
1598 | Instruction::I32FromU8
1599 | Instruction::I32FromS8
1600 | Instruction::I32FromU16
1601 | Instruction::I32FromS16
1602 | Instruction::I32FromU32
1603 | Instruction::I32FromS32 => {
1604 let s = operands.pop().unwrap();
1605 results.push(format!("wai_bindgen_wasmer::rt::as_i32({})", s));
1606 }
1607
1608 Instruction::F32FromFloat32
1609 | Instruction::F64FromFloat64
1610 | Instruction::Float32FromF32
1611 | Instruction::Float64FromF64
1612 | Instruction::S32FromI32
1613 | Instruction::S64FromI64 => {
1614 results.push(operands.pop().unwrap());
1615 }
1616
1617 Instruction::S8FromI32 => try_from("i8", operands, results),
1622 Instruction::U8FromI32 => try_from("u8", operands, results),
1623 Instruction::S16FromI32 => try_from("i16", operands, results),
1624 Instruction::U16FromI32 => try_from("u16", operands, results),
1625
1626 Instruction::U32FromI32 => top_as("u32"),
1629 Instruction::U64FromI64 => top_as("u64"),
1630
1631 Instruction::CharFromI32 => {
1632 self.gen.needs_char_from_i32 = true;
1633 results.push(format!("char_from_i32({})?", operands[0]));
1634 }
1635
1636 Instruction::Bitcasts { casts } => {
1637 wai_bindgen_gen_rust::bitcast(casts, operands, results)
1638 }
1639
1640 Instruction::UnitLower => {
1641 self.push_str(&format!("let () = {};\n", operands[0]));
1642 }
1643 Instruction::UnitLift => {
1644 results.push("()".to_string());
1645 }
1646
1647 Instruction::I32FromBool => {
1648 results.push(format!("match {} {{ true => 1, false => 0 }}", operands[0]));
1649 }
1650 Instruction::BoolFromI32 => {
1651 self.gen.needs_invalid_variant = true;
1652 results.push(format!(
1653 "match {} {{
1654 0 => false,
1655 1 => true,
1656 _ => return Err(invalid_variant(\"bool\")),
1657 }}",
1658 operands[0],
1659 ));
1660 }
1661
1662 Instruction::I32FromOwnedHandle { ty } => {
1663 let name = &iface.resources[*ty].name;
1664 results.push(format!(
1665 "{{
1666 let data_mut = store.data_mut();
1667 let mut tables = data_mut.tables.borrow_mut();
1668 tables.{}_table.insert({}) as i32
1669 }}",
1670 name.to_snake_case(),
1671 operands[0]
1672 ));
1673 }
1674 Instruction::HandleBorrowedFromI32 { ty } => {
1675 let name = &iface.resources[*ty].name;
1676 results.push(format!(
1677 "tables
1678 .{}_table
1679 .get(({}) as u32)
1680 .ok_or_else(|| {{
1681 wasmer::RuntimeError::new(\"invalid handle index\")
1682 }})?",
1683 name.to_snake_case(),
1684 operands[0]
1685 ));
1686 }
1687 Instruction::I32FromBorrowedHandle { ty } => {
1688 let tmp = self.tmp();
1689 self.push_str(&format!(
1690 "
1691 let obj{tmp} = {op};
1692 let handle{tmp} = {{
1693 let state = self.env.as_mut(store);
1694 state.resource_slab{idx}.clone(obj{tmp}.0)?;
1695 state.index_slab{idx}.insert(obj{tmp}.0)
1696 }};
1697 ",
1698 tmp = tmp,
1699 idx = ty.index(),
1700 op = operands[0],
1701 ));
1702
1703 results.push(format!("handle{} as i32", tmp,));
1704 }
1705 Instruction::HandleOwnedFromI32 { ty } => {
1706 let tmp = self.tmp();
1707 self.push_str(&format!(
1708 "let state = self.env.as_mut(store);
1709 let handle{} = state.index_slab{}.remove({} as u32)?;\n",
1710 tmp,
1711 ty.index(),
1712 operands[0],
1713 ));
1714
1715 let name = iface.resources[*ty].name.to_camel_case();
1716 results.push(format!("{}(handle{})", name, tmp));
1717 }
1718
1719 Instruction::RecordLower { ty, record, .. } => {
1720 self.record_lower(iface, *ty, record, &operands[0], results);
1721 }
1722 Instruction::RecordLift { ty, record, .. } => {
1723 self.record_lift(iface, *ty, record, operands, results);
1724 }
1725
1726 Instruction::TupleLower { tuple, .. } => {
1727 self.tuple_lower(tuple, &operands[0], results);
1728 }
1729 Instruction::TupleLift { .. } => {
1730 self.tuple_lift(operands, results);
1731 }
1732
1733 Instruction::FlagsLower { flags, .. } => {
1734 let tmp = self.tmp();
1735 self.push_str(&format!("let flags{} = {};\n", tmp, operands[0]));
1736 for i in 0..flags.repr().count() {
1737 results.push(format!("(flags{}.bits >> {}) as i32", tmp, i * 32));
1738 }
1739 }
1740 Instruction::FlagsLift { flags, name, .. } => {
1741 self.gen.needs_validate_flags = true;
1742 let repr = RustFlagsRepr::new(flags);
1743 let mut flags = String::from("0");
1744 for (i, op) in operands.iter().enumerate() {
1745 flags.push_str(&format!("| (({} as {repr}) << {})", op, i * 32));
1746 }
1747 results.push(format!(
1748 "validate_flags(
1749 {},
1750 {name}::all().bits(),
1751 \"{name}\",
1752 |bits| {name} {{ bits }}
1753 )?",
1754 flags,
1755 name = name.to_camel_case(),
1756 ));
1757 }
1758
1759 Instruction::VariantPayloadName => results.push("e".to_string()),
1760
1761 Instruction::VariantLower {
1762 variant,
1763 results: result_types,
1764 ty,
1765 ..
1766 } => {
1767 let blocks = self
1768 .blocks
1769 .drain(self.blocks.len() - variant.cases.len()..)
1770 .collect::<Vec<_>>();
1771 self.let_results(result_types.len(), results);
1772 let op0 = &operands[0];
1773 self.push_str(&format!("match {op0} {{\n"));
1774 let name = self.typename_lower(iface, *ty);
1775 for (case, block) in variant.cases.iter().zip(blocks) {
1776 let case_name = case.name.to_camel_case();
1777 self.push_str(&format!("{name}::{case_name}"));
1778 if case.ty == Type::Unit {
1779 self.push_str(&format!(" => {{\nlet e = ();\n{block}\n}}\n"));
1780 } else {
1781 self.push_str(&format!("(e) => {block},\n"));
1782 }
1783 }
1784 self.push_str("};\n");
1785 }
1786
1787 Instruction::VariantLift { variant, ty, .. } => {
1788 let blocks = self
1789 .blocks
1790 .drain(self.blocks.len() - variant.cases.len()..)
1791 .collect::<Vec<_>>();
1792 let op0 = &operands[0];
1793 let mut result = format!("match {op0} {{\n");
1794 let name = self.typename_lift(iface, *ty);
1795 for (i, (case, block)) in variant.cases.iter().zip(blocks).enumerate() {
1796 let block = if case.ty != Type::Unit {
1797 format!("({block})")
1798 } else {
1799 String::new()
1800 };
1801 let case = case.name.to_camel_case();
1802 result.push_str(&format!("{i} => {name}::{case}{block},\n"));
1803 }
1804 result.push_str(&format!("_ => return Err(invalid_variant(\"{name}\")),\n"));
1805 result.push('}');
1806 results.push(result);
1807 self.gen.needs_invalid_variant = true;
1808 }
1809
1810 Instruction::UnionLower {
1811 union,
1812 results: result_types,
1813 ty,
1814 ..
1815 } => {
1816 let blocks = self
1817 .blocks
1818 .drain(self.blocks.len() - union.cases.len()..)
1819 .collect::<Vec<_>>();
1820 self.let_results(result_types.len(), results);
1821 let op0 = &operands[0];
1822 self.push_str(&format!("match {op0} {{\n"));
1823 let name = self.typename_lower(iface, *ty);
1824 for (case_name, block) in self
1825 .gen
1826 .union_case_names(iface, union)
1827 .into_iter()
1828 .zip(blocks)
1829 {
1830 self.push_str(&format!("{name}::{case_name}(e) => {block},\n"));
1831 }
1832 self.push_str("};\n");
1833 }
1834
1835 Instruction::UnionLift { union, ty, .. } => {
1836 let blocks = self
1837 .blocks
1838 .drain(self.blocks.len() - union.cases.len()..)
1839 .collect::<Vec<_>>();
1840 let op0 = &operands[0];
1841 let mut result = format!("match {op0} {{\n");
1842 let name = self.typename_lift(iface, *ty);
1843 for (i, (case_name, block)) in self
1844 .gen
1845 .union_case_names(iface, union)
1846 .into_iter()
1847 .zip(blocks)
1848 .enumerate()
1849 {
1850 result.push_str(&format!("{i} => {name}::{case_name}({block}),\n"));
1851 }
1852 result.push_str(&format!("_ => return Err(invalid_variant(\"{name}\")),\n"));
1853 result.push('}');
1854 results.push(result);
1855 }
1856
1857 Instruction::OptionLower {
1858 results: result_types,
1859 ..
1860 } => {
1861 let some = self.blocks.pop().unwrap();
1862 let none = self.blocks.pop().unwrap();
1863 self.let_results(result_types.len(), results);
1864 let operand = &operands[0];
1865 self.push_str(&format!(
1866 "match {operand} {{
1867 Some(e) => {some},
1868 None => {{\nlet e = ();\n{none}\n}},
1869 }};"
1870 ));
1871 }
1872
1873 Instruction::OptionLift { .. } => {
1874 let some = self.blocks.pop().unwrap();
1875 let none = self.blocks.pop().unwrap();
1876 assert_eq!(none, "()");
1877 let operand = &operands[0];
1878 results.push(format!(
1879 "match {operand} {{
1880 0 => None,
1881 1 => Some({some}),
1882 _ => return Err(invalid_variant(\"option\")),
1883 }}"
1884 ));
1885 self.gen.needs_invalid_variant = true;
1886 }
1887
1888 Instruction::ExpectedLower {
1889 results: result_types,
1890 ..
1891 } => {
1892 let err = self.blocks.pop().unwrap();
1893 let ok = self.blocks.pop().unwrap();
1894 self.let_results(result_types.len(), results);
1895 let operand = &operands[0];
1896 self.push_str(&format!(
1897 "match {operand} {{
1898 Ok(e) => {{ {ok} }},
1899 Err(e) => {{ {err} }},
1900 }};"
1901 ));
1902 }
1903
1904 Instruction::ExpectedLift { .. } => {
1905 let err = self.blocks.pop().unwrap();
1906 let ok = self.blocks.pop().unwrap();
1907 let operand = &operands[0];
1908 results.push(format!(
1909 "match {operand} {{
1910 0 => Ok({ok}),
1911 1 => Err({err}),
1912 _ => return Err(invalid_variant(\"expected\")),
1913 }}"
1914 ));
1915 self.gen.needs_invalid_variant = true;
1916 }
1917
1918 Instruction::EnumLower { .. } => {
1919 results.push(format!("{} as i32", operands[0]));
1920 }
1921
1922 Instruction::EnumLift { name, enum_, .. } => {
1923 let op0 = &operands[0];
1924 let mut result = format!("match {op0} {{\n");
1925 let name = name.to_camel_case();
1926 for (i, case) in enum_.cases.iter().enumerate() {
1927 let case = case.name.to_camel_case();
1928 result.push_str(&format!("{i} => {name}::{case},\n"));
1929 }
1930 result.push_str(&format!("_ => return Err(invalid_variant(\"{name}\")),\n"));
1931 result.push('}');
1932 results.push(result);
1933 self.gen.needs_invalid_variant = true;
1934 }
1935
1936 Instruction::ListCanonLower { element, realloc } => {
1937 let realloc = realloc.unwrap();
1941 self.needs_functions
1942 .insert(realloc.to_string(), NeededFunction::Realloc);
1943 let (size, align) = (self.gen.sizes.size(element), self.gen.sizes.align(element));
1944
1945 let tmp = self.tmp();
1947 let val = format!("vec{}", tmp);
1948 self.push_str(&format!("let {} = {};\n", val, operands[0]));
1949
1950 let ptr = format!("ptr{}", tmp);
1952 self.push_str(&format!("let {} = ", ptr));
1953 self.call_intrinsic(
1954 realloc,
1955 format!(
1956 "&mut store.as_store_mut(), 0, 0, {}, ({}.len() as i32) * {}",
1957 align, val, size
1958 ),
1959 );
1960
1961 let mem = self.memory_src();
1963 self.push_str(&format!("{}.store_many({}, &{})?;\n", mem, ptr, val));
1964 self.gen.needs_raw_mem = true;
1965 self.needs_memory = true;
1966 results.push(ptr);
1967 results.push(format!("{}.len() as i32", val));
1968 }
1969
1970 Instruction::ListCanonLift { element, free, .. } => match free {
1971 Some(free) => {
1972 self.needs_memory = true;
1973 self.gen.needs_copy_slice = true;
1974 self.needs_functions
1975 .insert(free.to_string(), NeededFunction::Free);
1976 let align = self.gen.sizes.align(element);
1977 let tmp = self.tmp();
1978 self.push_str(&format!("let ptr{} = {};\n", tmp, operands[0]));
1979 self.push_str(&format!("let len{} = {};\n", tmp, operands[1]));
1980 let result = format!(
1981 "
1982 copy_slice(
1983 store,
1984 _memory,
1985 func_{},
1986 ptr{tmp}, len{tmp}, {}
1987 )?
1988 ",
1989 free,
1990 align,
1991 tmp = tmp
1992 );
1993 results.push(result);
1994 }
1995 None => {
1996 self.needs_borrow_checker = true;
1997 let tmp = self.tmp();
1998 self.push_str(&format!("let ptr{} = {};\n", tmp, operands[0]));
1999 self.push_str(&format!("let len{} = {};\n", tmp, operands[1]));
2000 let slice = format!("_bc.slice(ptr{0}, len{0})?", tmp);
2001 results.push(slice);
2002 }
2003 },
2004
2005 Instruction::StringLower { realloc } => {
2006 let realloc = realloc.unwrap();
2008 self.needs_functions
2009 .insert(realloc.to_string(), NeededFunction::Realloc);
2010
2011 let tmp = self.tmp();
2013 let val = format!("vec{}", tmp);
2014 self.push_str(&format!("let {} = {};\n", val, operands[0]));
2015
2016 let ptr = format!("ptr{}", tmp);
2018 self.push_str(&format!("let {} = ", ptr));
2019 self.call_intrinsic(
2020 realloc,
2021 format!("&mut store.as_store_mut(), 0, 0, 1, {}.len() as i32", val),
2022 );
2023
2024 let mem = self.memory_src();
2026 self.push_str(&format!(
2027 "{}.store_many({}, {}.as_bytes())?;\n",
2028 mem, ptr, val
2029 ));
2030 self.gen.needs_raw_mem = true;
2031 self.needs_memory = true;
2032 results.push(ptr);
2033 results.push(format!("{}.len() as i32", val));
2034 }
2035
2036 Instruction::StringLift { free } => match free {
2037 Some(free) => {
2038 self.needs_memory = true;
2039 self.gen.needs_copy_slice = true;
2040 self.needs_functions
2041 .insert(free.to_string(), NeededFunction::Free);
2042 let tmp = self.tmp();
2043 self.push_str(&format!("let ptr{} = {};\n", tmp, operands[0]));
2044 self.push_str(&format!("let len{} = {};\n", tmp, operands[1]));
2045 self.push_str(&format!(
2046 "
2047 let data{tmp} = copy_slice(
2048 store,
2049 _memory,
2050 func_{},
2051 ptr{tmp}, len{tmp}, 1,
2052 )?;
2053 ",
2054 free,
2055 tmp = tmp,
2056 ));
2057 results.push(format!(
2058 "String::from_utf8(data{})
2059 .map_err(|_| wasmer::RuntimeError::new(\"invalid utf-8\"))?",
2060 tmp,
2061 ));
2062 }
2063 None => {
2064 self.needs_borrow_checker = true;
2065 let tmp = self.tmp();
2066 self.push_str(&format!("let ptr{} = {};\n", tmp, operands[0]));
2067 self.push_str(&format!("let len{} = {};\n", tmp, operands[1]));
2068 let slice = format!("_bc.slice_str(ptr{0}, len{0})?", tmp);
2069 results.push(slice);
2070 }
2071 },
2072
2073 Instruction::ListLower { element, realloc } => {
2074 let realloc = realloc.unwrap();
2075 let body = self.blocks.pop().unwrap();
2076 let tmp = self.tmp();
2077 let vec = format!("vec{}", tmp);
2078 let result = format!("result{}", tmp);
2079 let len = format!("len{}", tmp);
2080 self.needs_functions
2081 .insert(realloc.to_string(), NeededFunction::Realloc);
2082 let size = self.gen.sizes.size(element);
2083 let align = self.gen.sizes.align(element);
2084
2085 self.push_str(&format!("let {} = {};\n", vec, operands[0]));
2088 self.push_str(&format!("let {} = {}.len() as i32;\n", len, vec));
2089
2090 self.push_str(&format!("let {} = ", result));
2092 self.call_intrinsic(
2093 realloc,
2094 format!(
2095 "&mut store.as_store_mut(), 0, 0, {}, {} * {}",
2096 align, len, size
2097 ),
2098 );
2099
2100 self.push_str(&format!(
2103 "for (i, e) in {}.into_iter().enumerate() {{\n",
2104 vec
2105 ));
2106 self.push_str(&format!("let base = {} + (i as i32) * {};\n", result, size));
2107 self.push_str(&body);
2108 self.push_str("}");
2109
2110 results.push(result);
2111 results.push(len);
2112 }
2113
2114 Instruction::ListLift { element, free, .. } => {
2115 let body = self.blocks.pop().unwrap();
2116 let tmp = self.tmp();
2117 let size = self.gen.sizes.size(element);
2118 let align = self.gen.sizes.align(element);
2119 let len = format!("len{}", tmp);
2120 self.push_str(&format!("let {} = {};\n", len, operands[1]));
2121 let base = format!("base{}", tmp);
2122 self.push_str(&format!("let {} = {};\n", base, operands[0]));
2123 let result = format!("result{}", tmp);
2124 self.push_str(&format!(
2125 "let mut {} = Vec::with_capacity({} as usize);\n",
2126 result, len,
2127 ));
2128
2129 self.push_str("for i in 0..");
2130 self.push_str(&len);
2131 self.push_str(" {\n");
2132 self.push_str("let base = ");
2133 self.push_str(&base);
2134 self.push_str(" + i *");
2135 self.push_str(&size.to_string());
2136 self.push_str(";\n");
2137 self.push_str(&result);
2138 self.push_str(".push(");
2139 self.push_str(&body);
2140 self.push_str(");\n");
2141 self.push_str("}\n");
2142 results.push(result);
2143
2144 if let Some(free) = free {
2145 self.call_intrinsic(
2146 free,
2147 format!(
2148 "&mut store.as_store_mut(), {}, {} * {}, {}",
2149 base, len, size, align
2150 ),
2151 );
2152 self.needs_functions
2153 .insert(free.to_string(), NeededFunction::Free);
2154 }
2155 }
2156
2157 Instruction::IterElem { .. } => {
2158 self.caller_memory_available = false; results.push("e".to_string())
2160 }
2161
2162 Instruction::IterBasePointer => results.push("base".to_string()),
2163
2164 Instruction::CallWasm {
2165 iface: _,
2166 name,
2167 sig,
2168 } => {
2169 if !sig.results.is_empty() {
2170 let tmp = self.tmp();
2171 if sig.results.len() == 1 {
2172 self.push_str("let ");
2173 let arg = format!("result{}", tmp);
2174 self.push_str(&arg);
2175 results.push(arg);
2176 self.push_str(" = ");
2177 } else {
2178 self.push_str("let (");
2179 for i in 0..sig.results.len() {
2180 let arg = format!("result{}_{}", tmp, i);
2181 self.push_str(&arg);
2182 self.push_str(",");
2183 results.push(arg);
2184 }
2185 self.push_str(") = ");
2186 }
2187 }
2188 self.push_str("self.func_");
2189 self.push_str(&to_rust_ident(name));
2190 if self.gen.opts.async_.includes(name) {
2191 self.push_str(".call_async(store, ");
2192 } else {
2193 self.push_str(".call(store, ");
2194 }
2195 for operand in operands {
2196 self.push_str(operand);
2197 self.push_str(", ");
2198 }
2199 self.push_str(")");
2200 if self.gen.opts.async_.includes(name) {
2201 self.push_str(".await");
2202 }
2203 self.push_str("?;\n");
2204 self.after_call = true;
2205 self.caller_memory_available = false; }
2207
2208 Instruction::CallWasmAsyncImport { .. } => unimplemented!(),
2209 Instruction::CallWasmAsyncExport { .. } => unimplemented!(),
2210
2211 Instruction::CallInterface { module: _, func } => {
2212 for (i, operand) in operands.iter().enumerate() {
2213 self.push_str(&format!("let param{} = {};\n", i, operand));
2214 }
2215 if self.gen.opts.tracing && !func.params.is_empty() {
2216 self.push_str("wai_bindgen_wasmer::tracing::event!(\n");
2217 self.push_str("wai_bindgen_wasmer::tracing::Level::TRACE,\n");
2218 for (i, (name, _ty)) in func.params.iter().enumerate() {
2219 self.push_str(&format!(
2220 "{} = wai_bindgen_wasmer::tracing::field::debug(¶m{}),\n",
2221 to_rust_ident(name),
2222 i
2223 ));
2224 }
2225 self.push_str(");\n");
2226 }
2227
2228 let mut call = format!("host.{}(", func.name.to_snake_case());
2229 for i in 0..operands.len() {
2230 call.push_str(&format!("param{}, ", i));
2231 }
2232 call.push(')');
2233 if self.gen.opts.async_.includes(&func.name) {
2234 call.push_str(".await");
2235 }
2236
2237 self.push_str("let host = &mut data_mut.data;\n");
2238 self.push_str("let result = ");
2239 results.push("result".to_string());
2240 match self.gen.classify_fn_ret(iface, func) {
2241 FunctionRet::Normal => self.push_str(&call),
2242 FunctionRet::CustomToTrap => {
2245 self.push_str("match ");
2246 self.push_str(&call);
2247 self.push_str("{\n");
2248 self.push_str("Ok(val) => val,\n");
2249 self.push_str("Err(e) => return Err(host.error_to_trap(e)),\n");
2250 self.push_str("}");
2251 }
2252 FunctionRet::CustomToError { err, .. } => {
2256 self.push_str("match ");
2257 self.push_str(&call);
2258 self.push_str("{\n");
2259 self.push_str("Ok(val) => Ok(val),\n");
2260 self.push_str(&format!("Err(e) => Err(host.error_to_{}(e)?),\n", err));
2261 self.push_str("}");
2262 }
2263 }
2264 self.push_str(";\n");
2265
2266 if !self.gen.all_needed_handles.is_empty() {
2267 self.push_str("drop(tables);\n");
2268 }
2269
2270 self.after_call = true;
2271
2272 match &func.result {
2273 Type::Unit => {}
2274 _ if self.gen.opts.tracing => {
2275 self.push_str("wai_bindgen_wasmer::tracing::event!(\n");
2276 self.push_str("wai_bindgen_wasmer::tracing::Level::TRACE,\n");
2277 self.push_str(&format!(
2278 "{} = wai_bindgen_wasmer::tracing::field::debug(&{0}),\n",
2279 results[0],
2280 ));
2281 self.push_str(");\n");
2282 }
2283 _ => {}
2284 }
2285 }
2286
2287 Instruction::Return { amt, .. } => {
2288 let result = match amt {
2289 0 => "Ok(())\n".to_string(),
2290 1 => format!("Ok({})\n", operands[0]),
2291 _ => format!("Ok(({}))\n", operands.join(", ")),
2292 };
2293 match self.cleanup.take() {
2294 Some(cleanup) => {
2295 self.push_str("let ret = ");
2296 self.push_str(&result);
2297 self.push_str(";\n");
2298 self.push_str(&cleanup);
2299 self.push_str("ret");
2300 }
2301 None => self.push_str(&result),
2302 }
2303 }
2304
2305 Instruction::ReturnAsyncExport { .. } => unimplemented!(),
2306 Instruction::ReturnAsyncImport { .. } => unimplemented!(),
2307
2308 Instruction::I32Load { offset } => results.push(self.load(*offset, "i32", operands)),
2309 Instruction::I32Load8U { offset } => {
2310 results.push(format!("i32::from({})", self.load(*offset, "u8", operands)));
2311 }
2312 Instruction::I32Load8S { offset } => {
2313 results.push(format!("i32::from({})", self.load(*offset, "i8", operands)));
2314 }
2315 Instruction::I32Load16U { offset } => {
2316 results.push(format!(
2317 "i32::from({})",
2318 self.load(*offset, "u16", operands)
2319 ));
2320 }
2321 Instruction::I32Load16S { offset } => {
2322 results.push(format!(
2323 "i32::from({})",
2324 self.load(*offset, "i16", operands)
2325 ));
2326 }
2327 Instruction::I64Load { offset } => results.push(self.load(*offset, "i64", operands)),
2328 Instruction::F32Load { offset } => results.push(self.load(*offset, "f32", operands)),
2329 Instruction::F64Load { offset } => results.push(self.load(*offset, "f64", operands)),
2330
2331 Instruction::I32Store { offset } => self.store(*offset, "as_i32", "", operands),
2332 Instruction::I64Store { offset } => self.store(*offset, "as_i64", "", operands),
2333 Instruction::F32Store { offset } => self.store(*offset, "as_f32", "", operands),
2334 Instruction::F64Store { offset } => self.store(*offset, "as_f64", "", operands),
2335 Instruction::I32Store8 { offset } => self.store(*offset, "as_i32", " as u8", operands),
2336 Instruction::I32Store16 { offset } => {
2337 self.store(*offset, "as_i32", " as u16", operands)
2338 }
2339
2340 Instruction::Malloc {
2341 realloc,
2342 size,
2343 align,
2344 } => {
2345 self.needs_functions
2346 .insert(realloc.to_string(), NeededFunction::Realloc);
2347 let tmp = self.tmp();
2348 let ptr = format!("ptr{}", tmp);
2349 self.push_str(&format!("let {} = ", ptr));
2350 self.call_intrinsic(realloc, format!("store, 0, 0, {}, {}", align, size));
2351 results.push(ptr);
2352 }
2353
2354 Instruction::Free { .. } => unimplemented!(),
2355 }
2356 }
2357}
2358
2359impl NeededFunction {
2360 fn cvt(&self) -> &'static str {
2361 match self {
2362 NeededFunction::Realloc => "(i32, i32, i32, i32), i32",
2363 NeededFunction::Free => "(i32, i32, i32), ()",
2364 }
2365 }
2366
2367 fn ty(&self) -> String {
2368 format!("wasmer::TypedFunction<{}>", self.cvt())
2369 }
2370}
2371
2372fn sorted_iter<K: Ord, V>(map: &HashMap<K, V>) -> impl Iterator<Item = (&K, &V)> {
2373 let mut list = map.iter().collect::<Vec<_>>();
2374 list.sort_by_key(|p| p.0);
2375 list.into_iter()
2376}