1use anyhow::Result;
2use heck::{ToLowerCamelCase, ToShoutySnakeCase, ToUpperCamelCase};
3use std::{
4 collections::{HashMap, HashSet},
5 fmt::Write,
6 iter, mem,
7 ops::Deref,
8};
9use wit_bindgen_core::{
10 abi::{self, AbiVariant, Bindgen, Bitcast, Instruction, LiftLower, WasmType},
11 uwrite, uwriteln,
12 wit_parser::{
13 Docs, Enum, Flags, FlagsRepr, Function, FunctionKind, Int, InterfaceId, Record, Resolve,
14 Result_, SizeAlign, Tuple, Type, TypeDef, TypeDefKind, TypeId, TypeOwner, Variant, WorldId,
15 WorldKey,
16 },
17 Direction, Files, InterfaceGenerator as _, Ns, Source, WorldGenerator,
18};
19
20const IMPORTS: &str = "\
21import java.nio.charset.StandardCharsets;
22import java.util.ArrayList;
23
24import org.teavm.interop.Memory;
25import org.teavm.interop.Address;
26import org.teavm.interop.Import;
27import org.teavm.interop.Export;\
28";
29
30#[derive(Default, Debug, Clone)]
31#[cfg_attr(feature = "clap", derive(clap::Args))]
32pub struct Opts {
33 #[cfg_attr(feature = "clap", arg(long))]
35 pub generate_stub: bool,
36}
37
38impl Opts {
39 pub fn build(&self) -> Box<dyn WorldGenerator> {
40 Box::new(TeaVmJava {
41 opts: self.clone(),
42 ..TeaVmJava::default()
43 })
44 }
45}
46
47struct InterfaceFragment {
48 src: String,
49 stub: String,
50}
51
52#[derive(Default)]
53pub struct TeaVmJava {
54 opts: Opts,
55 name: String,
56 return_area_size: usize,
57 return_area_align: usize,
58 tuple_counts: HashSet<usize>,
59 needs_cleanup: bool,
60 needs_result: bool,
61 interface_fragments: HashMap<String, Vec<InterfaceFragment>>,
62 world_fragments: Vec<InterfaceFragment>,
63 sizes: SizeAlign,
64 interface_names: HashMap<InterfaceId, String>,
65}
66
67impl TeaVmJava {
68 fn qualifier(&self) -> String {
69 format!("{}.", self.name)
70 }
71
72 fn interface<'a>(&'a mut self, resolve: &'a Resolve, name: &'a str) -> InterfaceGenerator<'a> {
73 InterfaceGenerator {
74 src: String::new(),
75 stub: String::new(),
76 gen: self,
77 resolve,
78 name,
79 }
80 }
81}
82
83impl WorldGenerator for TeaVmJava {
84 fn preprocess(&mut self, resolve: &Resolve, world: WorldId) {
85 self.name = world_name(resolve, world);
86 self.sizes.fill(resolve);
87 }
88
89 fn import_interface(
90 &mut self,
91 resolve: &Resolve,
92 key: &WorldKey,
93 id: InterfaceId,
94 _files: &mut Files,
95 ) -> Result<()> {
96 let name = interface_name(resolve, key, Direction::Import);
97 self.interface_names.insert(id, name.clone());
98 let mut gen = self.interface(resolve, &name);
99 gen.types(id);
100
101 for (_, func) in resolve.interfaces[id].functions.iter() {
102 gen.import(&resolve.name_world_key(key), func);
103 }
104
105 gen.add_interface_fragment();
106
107 Ok(())
108 }
109
110 fn import_funcs(
111 &mut self,
112 resolve: &Resolve,
113 world: WorldId,
114 funcs: &[(&str, &Function)],
115 _files: &mut Files,
116 ) {
117 let name = world_name(resolve, world);
118 let mut gen = self.interface(resolve, &name);
119
120 for (_, func) in funcs {
121 gen.import("$root", func);
122 }
123
124 gen.add_world_fragment();
125 }
126
127 fn export_interface(
128 &mut self,
129 resolve: &Resolve,
130 key: &WorldKey,
131 id: InterfaceId,
132 _files: &mut Files,
133 ) -> Result<()> {
134 let name = interface_name(resolve, key, Direction::Export);
135 self.interface_names.insert(id, name.clone());
136 let mut gen = self.interface(resolve, &name);
137 gen.types(id);
138
139 for (_, func) in resolve.interfaces[id].functions.iter() {
140 gen.export(Some(&resolve.name_world_key(key)), func);
141 }
142
143 gen.add_interface_fragment();
144 Ok(())
145 }
146
147 fn export_funcs(
148 &mut self,
149 resolve: &Resolve,
150 world: WorldId,
151 funcs: &[(&str, &Function)],
152 _files: &mut Files,
153 ) -> Result<()> {
154 let name = world_name(resolve, world);
155 let mut gen = self.interface(resolve, &name);
156
157 for (_, func) in funcs {
158 gen.export(None, func);
159 }
160
161 gen.add_world_fragment();
162 Ok(())
163 }
164
165 fn import_types(
166 &mut self,
167 resolve: &Resolve,
168 world: WorldId,
169 types: &[(&str, TypeId)],
170 _files: &mut Files,
171 ) {
172 let name = world_name(resolve, world);
173 let mut gen = self.interface(resolve, &name);
174
175 for (ty_name, ty) in types {
176 gen.define_type(ty_name, *ty);
177 }
178
179 gen.add_world_fragment();
180 }
181
182 fn finish(&mut self, resolve: &Resolve, id: WorldId, files: &mut Files) -> Result<()> {
183 let name = world_name(resolve, id);
184 let (package, name) = split_qualified_name(&name);
185
186 let mut src = Source::default();
187 let version = env!("CARGO_PKG_VERSION");
188 wit_bindgen_core::generated_preamble(&mut src, version);
189
190 uwrite!(
191 src,
192 "package {package};
193
194 {IMPORTS}
195 import org.teavm.interop.CustomSection;
196
197 public final class {name} {{
198 private {name}() {{}}
199 "
200 );
201
202 src.push_str(
203 &self
204 .world_fragments
205 .iter()
206 .map(|f| f.src.deref())
207 .collect::<Vec<_>>()
208 .join("\n"),
209 );
210
211 let mut producers = wasm_metadata::Producers::empty();
212 producers.add(
213 "processed-by",
214 env!("CARGO_PKG_NAME"),
215 env!("CARGO_PKG_VERSION"),
216 );
217
218 let component_type = wit_component::metadata::encode(
219 resolve,
220 id,
221 wit_component::StringEncoding::UTF8,
222 Some(&producers),
223 )
224 .unwrap();
225
226 let component_type = component_type
227 .into_iter()
228 .map(|byte| format!("{byte:02x}"))
229 .collect::<Vec<_>>()
230 .concat();
231
232 uwriteln!(
233 src,
234 r#"
235 @CustomSection(name = "component-type:{name}")
236 private static final String __WIT_BINDGEN_COMPONENT_TYPE = "{component_type}";
237 "#
238 );
239
240 for &count in &self.tuple_counts {
241 let (type_params, instance) = if count == 0 {
242 (
243 String::new(),
244 "public static final Tuple0 INSTANCE = new Tuple0();",
245 )
246 } else {
247 (
248 format!(
249 "<{}>",
250 (0..count)
251 .map(|index| format!("T{index}"))
252 .collect::<Vec<_>>()
253 .join(", ")
254 ),
255 "",
256 )
257 };
258 let value_params = (0..count)
259 .map(|index| format!("T{index} f{index}"))
260 .collect::<Vec<_>>()
261 .join(", ");
262 let fields = (0..count)
263 .map(|index| format!("public final T{index} f{index};"))
264 .collect::<Vec<_>>()
265 .join("\n");
266 let inits = (0..count)
267 .map(|index| format!("this.f{index} = f{index};"))
268 .collect::<Vec<_>>()
269 .join("\n");
270
271 uwrite!(
272 src,
273 "
274 public static final class Tuple{count}{type_params} {{
275 {fields}
276
277 public Tuple{count}({value_params}) {{
278 {inits}
279 }}
280
281 {instance}
282 }}
283 "
284 )
285 }
286
287 if self.needs_result {
288 src.push_str(
289 r#"
290 public static final class Result<Ok, Err> {
291 public final byte tag;
292 private final Object value;
293
294 private Result(byte tag, Object value) {
295 this.tag = tag;
296 this.value = value;
297 }
298
299 public static <Ok, Err> Result<Ok, Err> ok(Ok ok) {
300 return new Result<>(OK, ok);
301 }
302
303 public static <Ok, Err> Result<Ok, Err> err(Err err) {
304 return new Result<>(ERR, err);
305 }
306
307 public Ok getOk() {
308 if (this.tag == OK) {
309 return (Ok) this.value;
310 } else {
311 throw new RuntimeException("expected OK, got " + this.tag);
312 }
313 }
314
315 public Err getErr() {
316 if (this.tag == ERR) {
317 return (Err) this.value;
318 } else {
319 throw new RuntimeException("expected ERR, got " + this.tag);
320 }
321 }
322
323 public static final byte OK = 0;
324 public static final byte ERR = 1;
325 }
326 "#,
327 )
328 }
329
330 if self.needs_cleanup {
331 src.push_str(
332 "
333 public static final class Cleanup {
334 public final int address;
335 public final int size;
336 public final int align;
337
338 public Cleanup(int address, int size, int align) {
339 this.address = address;
340 this.size = size;
341 this.align = align;
342 }
343 }
344 ",
345 );
346 }
347
348 if self.return_area_align > 0 {
349 let size = self.return_area_size;
350 let align = self.return_area_align;
351
352 uwriteln!(
353 src,
354 "public static final int RETURN_AREA = Memory.malloc({size}, {align}).toInt();",
355 );
356 }
357
358 src.push_str("}\n");
359
360 let directory = package.replace('.', "/");
361 files.push(&format!("{directory}/{name}.java"), indent(&src).as_bytes());
362
363 let generate_stub =
364 |package: &str, name, fragments: &[InterfaceFragment], files: &mut Files| {
365 let b = fragments
366 .iter()
367 .map(|f| f.stub.deref())
368 .collect::<Vec<_>>()
369 .join("\n");
370
371 let mut body = Source::default();
372 wit_bindgen_core::generated_preamble(&mut body, version);
373 uwriteln!(
374 &mut body,
375 "package {package};
376
377 {IMPORTS}
378
379 public class {name} {{
380 {b}
381 }}
382 "
383 );
384
385 let directory = package.replace('.', "/");
386 files.push(
387 &format!("{directory}/{name}.java"),
388 indent(&body).as_bytes(),
389 );
390 };
391
392 if self.opts.generate_stub {
393 generate_stub(
394 &package,
395 format!("{name}Impl"),
396 &self.world_fragments,
397 files,
398 );
399 }
400
401 for (name, fragments) in &self.interface_fragments {
402 let (package, name) = split_qualified_name(name);
403
404 let b = fragments
405 .iter()
406 .map(|f| f.src.deref())
407 .collect::<Vec<_>>()
408 .join("\n");
409
410 let mut body = Source::default();
411 wit_bindgen_core::generated_preamble(&mut body, version);
412 uwriteln!(
413 &mut body,
414 "package {package};
415
416 {IMPORTS}
417
418 public final class {name} {{
419 private {name}() {{}}
420
421 {b}
422 }}
423 "
424 );
425
426 let directory = package.replace('.', "/");
427 files.push(
428 &format!("{directory}/{name}.java"),
429 indent(&body).as_bytes(),
430 );
431
432 if self.opts.generate_stub {
433 generate_stub(&package, format!("{name}Impl"), fragments, files);
434 }
435 }
436
437 Ok(())
438 }
439}
440
441struct InterfaceGenerator<'a> {
442 src: String,
443 stub: String,
444 gen: &'a mut TeaVmJava,
445 resolve: &'a Resolve,
446 name: &'a str,
447}
448
449impl InterfaceGenerator<'_> {
450 fn qualifier(&self, when: bool, ty: &TypeDef) -> String {
451 if let TypeOwner::Interface(id) = &ty.owner {
452 if let Some(name) = self.gen.interface_names.get(id) {
453 if name != self.name {
454 return format!("{name}.");
455 }
456 }
457 }
458
459 if when {
460 format!("{}.", self.name)
461 } else {
462 String::new()
463 }
464 }
465
466 fn add_interface_fragment(self) {
467 self.gen
468 .interface_fragments
469 .entry(self.name.to_owned())
470 .or_default()
471 .push(InterfaceFragment {
472 src: self.src,
473 stub: self.stub,
474 });
475 }
476
477 fn add_world_fragment(self) {
478 self.gen.world_fragments.push(InterfaceFragment {
479 src: self.src,
480 stub: self.stub,
481 });
482 }
483
484 fn import(&mut self, module: &str, func: &Function) {
485 if func.kind != FunctionKind::Freestanding {
486 todo!("resources");
487 }
488
489 let mut bindgen = FunctionBindgen::new(
490 self,
491 &func.name,
492 func.params
493 .iter()
494 .map(|(name, _)| name.to_java_ident())
495 .collect(),
496 );
497
498 abi::call(
499 bindgen.gen.resolve,
500 AbiVariant::GuestImport,
501 LiftLower::LowerArgsLiftResults,
502 func,
503 &mut bindgen,
504 false,
505 );
506
507 let src = bindgen.src;
508
509 let cleanup_list = if bindgen.needs_cleanup_list {
510 self.gen.needs_cleanup = true;
511
512 format!(
513 "ArrayList<{}Cleanup> cleanupList = new ArrayList<>();\n",
514 self.gen.qualifier()
515 )
516 } else {
517 String::new()
518 };
519
520 let name = &func.name;
521
522 let sig = self.resolve.wasm_signature(AbiVariant::GuestImport, func);
523
524 let result_type = match &sig.results[..] {
525 [] => "void",
526 [result] => wasm_type(*result),
527 _ => unreachable!(),
528 };
529
530 let camel_name = func.name.to_upper_camel_case();
531
532 let params = sig
533 .params
534 .iter()
535 .enumerate()
536 .map(|(i, param)| {
537 let ty = wasm_type(*param);
538 format!("{ty} p{i}")
539 })
540 .collect::<Vec<_>>()
541 .join(", ");
542
543 let sig = self.sig_string(func, false);
544
545 uwrite!(
546 self.src,
547 r#"@Import(name = "{name}", module = "{module}")
548 private static native {result_type} wasmImport{camel_name}({params});
549
550 {sig} {{
551 {cleanup_list} {src}
552 }}
553 "#
554 );
555 }
556
557 fn export(&mut self, interface_name: Option<&str>, func: &Function) {
558 let sig = self.resolve.wasm_signature(AbiVariant::GuestExport, func);
559
560 let export_name = func.legacy_core_export_name(interface_name);
561
562 let mut bindgen = FunctionBindgen::new(
563 self,
564 &func.name,
565 (0..sig.params.len()).map(|i| format!("p{i}")).collect(),
566 );
567
568 abi::call(
569 bindgen.gen.resolve,
570 AbiVariant::GuestExport,
571 LiftLower::LiftArgsLowerResults,
572 func,
573 &mut bindgen,
574 false,
575 );
576
577 assert!(!bindgen.needs_cleanup_list);
578
579 let src = bindgen.src;
580
581 let result_type = match &sig.results[..] {
582 [] => "void",
583 [result] => wasm_type(*result),
584 _ => unreachable!(),
585 };
586
587 let camel_name = func.name.to_upper_camel_case();
588
589 let params = sig
590 .params
591 .iter()
592 .enumerate()
593 .map(|(i, param)| {
594 let ty = wasm_type(*param);
595 format!("{ty} p{i}")
596 })
597 .collect::<Vec<_>>()
598 .join(", ");
599
600 uwrite!(
601 self.src,
602 r#"
603 @Export(name = "{export_name}")
604 private static {result_type} wasmExport{camel_name}({params}) {{
605 {src}
606 }}
607 "#
608 );
609
610 if abi::guest_export_needs_post_return(self.resolve, func) {
611 let params = sig
612 .results
613 .iter()
614 .enumerate()
615 .map(|(i, param)| {
616 let ty = wasm_type(*param);
617 format!("{ty} p{i}")
618 })
619 .collect::<Vec<_>>()
620 .join(", ");
621
622 let mut bindgen = FunctionBindgen::new(
623 self,
624 "INVALID",
625 (0..sig.results.len()).map(|i| format!("p{i}")).collect(),
626 );
627
628 abi::post_return(bindgen.gen.resolve, func, &mut bindgen, false);
629
630 let src = bindgen.src;
631
632 uwrite!(
633 self.src,
634 r#"
635 @Export(name = "cabi_post_{export_name}")
636 private static void wasmExport{camel_name}PostReturn({params}) {{
637 {src}
638 }}
639 "#
640 );
641 }
642
643 if self.gen.opts.generate_stub {
644 let sig = self.sig_string(func, true);
645
646 uwrite!(
647 self.stub,
648 r#"
649 {sig} {{
650 throw new RuntimeException("todo");
651 }}
652 "#
653 );
654 }
655 }
656
657 fn type_name(&mut self, ty: &Type) -> String {
658 self.type_name_with_qualifier(ty, false)
659 }
660
661 fn type_name_with_qualifier(&mut self, ty: &Type, qualifier: bool) -> String {
662 match ty {
663 Type::Bool => "boolean".into(),
664 Type::U8 | Type::S8 => "byte".into(),
665 Type::U16 | Type::S16 => "short".into(),
666 Type::U32 | Type::S32 | Type::Char => "int".into(),
667 Type::U64 | Type::S64 => "long".into(),
668 Type::F32 => "float".into(),
669 Type::F64 => "double".into(),
670 Type::String => "String".into(),
671 Type::ErrorContext => todo!("error context type name"),
672 Type::Id(id) => {
673 let ty = &self.resolve.types[*id];
674 match &ty.kind {
675 TypeDefKind::Type(ty) => self.type_name_with_qualifier(ty, qualifier),
676 TypeDefKind::List(ty) => {
677 if is_primitive(ty) {
678 format!("{}[]", self.type_name(ty))
679 } else {
680 format!("ArrayList<{}>", self.type_name_boxed(ty, qualifier))
681 }
682 }
683 TypeDefKind::Tuple(tuple) => {
684 let count = tuple.types.len();
685 self.gen.tuple_counts.insert(count);
686
687 let params = if count == 0 {
688 String::new()
689 } else {
690 format!(
691 "<{}>",
692 tuple
693 .types
694 .iter()
695 .map(|ty| self.type_name_boxed(ty, qualifier))
696 .collect::<Vec<_>>()
697 .join(", ")
698 )
699 };
700
701 format!("{}Tuple{count}{params}", self.gen.qualifier())
702 }
703 TypeDefKind::Option(ty) => self.type_name_boxed(ty, qualifier),
704 TypeDefKind::Result(result) => {
705 self.gen.needs_result = true;
706 let mut name = |ty: &Option<Type>| {
707 ty.as_ref()
708 .map(|ty| self.type_name_boxed(ty, qualifier))
709 .unwrap_or_else(|| {
710 self.gen.tuple_counts.insert(0);
711
712 format!("{}Tuple0", self.gen.qualifier())
713 })
714 };
715 let ok = name(&result.ok);
716 let err = name(&result.err);
717
718 format!("{}Result<{ok}, {err}>", self.gen.qualifier())
719 }
720 _ => {
721 if let Some(name) = &ty.name {
722 format!(
723 "{}{}",
724 self.qualifier(qualifier, ty),
725 name.to_upper_camel_case()
726 )
727 } else {
728 unreachable!()
729 }
730 }
731 }
732 }
733 }
734 }
735
736 fn type_name_boxed(&mut self, ty: &Type, qualifier: bool) -> String {
737 match ty {
738 Type::Bool => "Boolean".into(),
739 Type::U8 | Type::S8 => "Byte".into(),
740 Type::U16 | Type::S16 => "Short".into(),
741 Type::U32 | Type::S32 | Type::Char => "Integer".into(),
742 Type::U64 | Type::S64 => "Long".into(),
743 Type::F32 => "Float".into(),
744 Type::F64 => "Double".into(),
745 Type::Id(id) => {
746 let def = &self.resolve.types[*id];
747 match &def.kind {
748 TypeDefKind::Type(ty) => self.type_name_boxed(ty, qualifier),
749 _ => self.type_name_with_qualifier(ty, qualifier),
750 }
751 }
752 _ => self.type_name_with_qualifier(ty, qualifier),
753 }
754 }
755
756 fn print_docs(&mut self, docs: &Docs) {
757 if let Some(docs) = &docs.contents {
758 let lines = docs
759 .trim()
760 .lines()
761 .map(|line| format!("* {line}"))
762 .collect::<Vec<_>>()
763 .join("\n");
764
765 uwrite!(
766 self.src,
767 "
768 /**
769 {lines}
770 */
771 "
772 )
773 }
774 }
775
776 fn non_empty_type<'a>(&self, ty: Option<&'a Type>) -> Option<&'a Type> {
777 if let Some(ty) = ty {
778 let id = match ty {
779 Type::Id(id) => *id,
780 _ => return Some(ty),
781 };
782 match &self.resolve.types[id].kind {
783 TypeDefKind::Type(t) => self.non_empty_type(Some(t)).map(|_| ty),
784 TypeDefKind::Record(r) => (!r.fields.is_empty()).then_some(ty),
785 TypeDefKind::Tuple(t) => (!t.types.is_empty()).then_some(ty),
786 _ => Some(ty),
787 }
788 } else {
789 None
790 }
791 }
792
793 fn sig_string(&mut self, func: &Function, qualifier: bool) -> String {
794 let name = func.name.to_java_ident();
795
796 let result_type = match &func.result {
797 None => "void".into(),
798 Some(ty) => self.type_name_with_qualifier(ty, qualifier),
799 };
800
801 let params = func
802 .params
803 .iter()
804 .map(|(name, ty)| {
805 let ty = self.type_name_with_qualifier(ty, qualifier);
806 let name = name.to_java_ident();
807 format!("{ty} {name}")
808 })
809 .collect::<Vec<_>>()
810 .join(", ");
811
812 format!("public static {result_type} {name}({params})")
813 }
814}
815
816impl<'a> wit_bindgen_core::InterfaceGenerator<'a> for InterfaceGenerator<'a> {
817 fn resolve(&self) -> &'a Resolve {
818 self.resolve
819 }
820
821 fn type_record(&mut self, _id: TypeId, name: &str, record: &Record, docs: &Docs) {
822 self.print_docs(docs);
823
824 let name = name.to_upper_camel_case();
825
826 let parameters = record
827 .fields
828 .iter()
829 .map(|field| {
830 format!(
831 "{} {}",
832 self.type_name(&field.ty),
833 field.name.to_java_ident()
834 )
835 })
836 .collect::<Vec<_>>()
837 .join(", ");
838
839 let assignments = record
840 .fields
841 .iter()
842 .map(|field| {
843 let name = field.name.to_java_ident();
844 format!("this.{name} = {name};")
845 })
846 .collect::<Vec<_>>()
847 .join("\n");
848
849 let fields = if record.fields.is_empty() {
850 format!("public static final {name} INSTANCE = new {name}();")
851 } else {
852 record
853 .fields
854 .iter()
855 .map(|field| {
856 format!(
857 "public final {} {};",
858 self.type_name(&field.ty),
859 field.name.to_java_ident()
860 )
861 })
862 .collect::<Vec<_>>()
863 .join("\n")
864 };
865
866 uwrite!(
867 self.src,
868 "
869 public static final class {name} {{
870 {fields}
871
872 public {name}({parameters}) {{
873 {assignments}
874 }}
875 }}
876 "
877 );
878 }
879
880 fn type_resource(&mut self, id: TypeId, name: &str, docs: &Docs) {
881 _ = (id, name, docs);
882 todo!()
883 }
884
885 fn type_flags(&mut self, _id: TypeId, name: &str, flags: &Flags, docs: &Docs) {
886 self.print_docs(docs);
887
888 let name = name.to_upper_camel_case();
889
890 let ty = match flags.repr() {
891 FlagsRepr::U8 => "byte",
892 FlagsRepr::U16 => "short",
893 FlagsRepr::U32(1) => "int",
894 FlagsRepr::U32(2) => "long",
895 repr => todo!("flags {repr:?}"),
896 };
897
898 let flags = flags
899 .flags
900 .iter()
901 .enumerate()
902 .map(|(i, flag)| {
903 let flag_name = flag.name.to_shouty_snake_case();
904 let suffix = if matches!(flags.repr(), FlagsRepr::U32(2)) {
905 "L"
906 } else {
907 ""
908 };
909 format!(
910 "public static final {name} {flag_name} = new {name}(({ty}) (1{suffix} << {i}));"
911 )
912 })
913 .collect::<Vec<_>>()
914 .join("\n");
915
916 uwrite!(
917 self.src,
918 "
919 public static final class {name} {{
920 public final {ty} value;
921
922 public {name}({ty} value) {{
923 this.value = value;
924 }}
925
926 {flags}
927 }}
928 "
929 );
930 }
931
932 fn type_tuple(&mut self, id: TypeId, _name: &str, _tuple: &Tuple, _docs: &Docs) {
933 self.type_name(&Type::Id(id));
934 }
935
936 fn type_variant(&mut self, _id: TypeId, name: &str, variant: &Variant, docs: &Docs) {
937 self.print_docs(docs);
938
939 let name = name.to_upper_camel_case();
940 let tag_type = int_type(variant.tag());
941
942 let constructors = variant
943 .cases
944 .iter()
945 .map(|case| {
946 let case_name = case.name.to_java_ident();
947 let tag = case.name.to_shouty_snake_case();
948 let (parameter, argument) = if let Some(ty) = self.non_empty_type(case.ty.as_ref())
949 {
950 (
951 format!("{} {case_name}", self.type_name(ty)),
952 case_name.deref(),
953 )
954 } else {
955 (String::new(), "null")
956 };
957
958 format!(
959 "public static {name} {case_name}({parameter}) {{
960 return new {name}({tag}, {argument});
961 }}
962 "
963 )
964 })
965 .collect::<Vec<_>>()
966 .join("\n");
967
968 let accessors = variant
969 .cases
970 .iter()
971 .filter_map(|case| {
972 self.non_empty_type(case.ty.as_ref()).map(|ty| {
973 let case_name = case.name.to_upper_camel_case();
974 let tag = case.name.to_shouty_snake_case();
975 let ty = self.type_name(ty);
976 format!(
977 r#"public {ty} get{case_name}() {{
978 if (this.tag == {tag}) {{
979 return ({ty}) this.value;
980 }} else {{
981 throw new RuntimeException("expected {tag}, got " + this.tag);
982 }}
983 }}
984 "#
985 )
986 })
987 })
988 .collect::<Vec<_>>()
989 .join("\n");
990
991 let tags = variant
992 .cases
993 .iter()
994 .enumerate()
995 .map(|(i, case)| {
996 let tag = case.name.to_shouty_snake_case();
997 format!("public static final {tag_type} {tag} = {i};")
998 })
999 .collect::<Vec<_>>()
1000 .join("\n");
1001
1002 uwrite!(
1003 self.src,
1004 "
1005 public static final class {name} {{
1006 public final {tag_type} tag;
1007 private final Object value;
1008
1009 private {name}({tag_type} tag, Object value) {{
1010 this.tag = tag;
1011 this.value = value;
1012 }}
1013
1014 {constructors}
1015 {accessors}
1016 {tags}
1017 }}
1018 "
1019 );
1020 }
1021
1022 fn type_option(&mut self, id: TypeId, _name: &str, _payload: &Type, _docs: &Docs) {
1023 self.type_name(&Type::Id(id));
1024 }
1025
1026 fn type_result(&mut self, id: TypeId, _name: &str, _result: &Result_, _docs: &Docs) {
1027 self.type_name(&Type::Id(id));
1028 }
1029
1030 fn type_enum(&mut self, _id: TypeId, name: &str, enum_: &Enum, docs: &Docs) {
1031 self.print_docs(docs);
1032
1033 let name = name.to_upper_camel_case();
1034
1035 let cases = enum_
1036 .cases
1037 .iter()
1038 .map(|case| case.name.to_shouty_snake_case())
1039 .collect::<Vec<_>>()
1040 .join(", ");
1041
1042 uwrite!(
1043 self.src,
1044 "
1045 public static enum {name} {{
1046 {cases}
1047 }}
1048 "
1049 );
1050 }
1051
1052 fn type_alias(&mut self, id: TypeId, _name: &str, _ty: &Type, _docs: &Docs) {
1053 self.type_name(&Type::Id(id));
1054 }
1055
1056 fn type_list(&mut self, id: TypeId, _name: &str, _ty: &Type, _docs: &Docs) {
1057 self.type_name(&Type::Id(id));
1058 }
1059
1060 fn type_future(&mut self, id: TypeId, name: &str, ty: &Option<Type>, docs: &Docs) {
1061 _ = (id, name, ty, docs);
1062 todo!()
1063 }
1064
1065 fn type_stream(&mut self, id: TypeId, name: &str, ty: &Option<Type>, docs: &Docs) {
1066 _ = (id, name, ty, docs);
1067 todo!()
1068 }
1069
1070 fn type_builtin(&mut self, _id: TypeId, _name: &str, _ty: &Type, _docs: &Docs) {
1071 unimplemented!();
1072 }
1073}
1074
1075struct Block {
1076 body: String,
1077 results: Vec<String>,
1078 element: String,
1079 base: String,
1080}
1081
1082struct Cleanup {
1083 address: String,
1084 size: String,
1085 align: usize,
1086}
1087
1088struct BlockStorage {
1089 body: String,
1090 element: String,
1091 base: String,
1092 cleanup: Vec<Cleanup>,
1093}
1094
1095struct FunctionBindgen<'a, 'b> {
1096 gen: &'b mut InterfaceGenerator<'a>,
1097 func_name: &'b str,
1098 params: Box<[String]>,
1099 src: String,
1100 locals: Ns,
1101 block_storage: Vec<BlockStorage>,
1102 blocks: Vec<Block>,
1103 payloads: Vec<String>,
1104 cleanup: Vec<Cleanup>,
1105 needs_cleanup_list: bool,
1106}
1107
1108impl<'a, 'b> FunctionBindgen<'a, 'b> {
1109 fn new(
1110 gen: &'b mut InterfaceGenerator<'a>,
1111 func_name: &'b str,
1112 params: Box<[String]>,
1113 ) -> FunctionBindgen<'a, 'b> {
1114 Self {
1115 gen,
1116 func_name,
1117 params,
1118 src: String::new(),
1119 locals: Ns::default(),
1120 block_storage: Vec::new(),
1121 blocks: Vec::new(),
1122 payloads: Vec::new(),
1123 cleanup: Vec::new(),
1124 needs_cleanup_list: false,
1125 }
1126 }
1127
1128 fn lower_variant(
1129 &mut self,
1130 cases: &[(&str, Option<Type>)],
1131 lowered_types: &[WasmType],
1132 op: &str,
1133 results: &mut Vec<String>,
1134 ) {
1135 let blocks = self
1136 .blocks
1137 .drain(self.blocks.len() - cases.len()..)
1138 .collect::<Vec<_>>();
1139
1140 let payloads = self
1141 .payloads
1142 .drain(self.payloads.len() - cases.len()..)
1143 .collect::<Vec<_>>();
1144
1145 let lowered = lowered_types
1146 .iter()
1147 .map(|_| self.locals.tmp("lowered"))
1148 .collect::<Vec<_>>();
1149
1150 results.extend(lowered.iter().cloned());
1151
1152 let declarations = lowered
1153 .iter()
1154 .zip(lowered_types)
1155 .map(|(lowered, ty)| format!("{} {lowered};", wasm_type(*ty)))
1156 .collect::<Vec<_>>()
1157 .join("\n");
1158
1159 let cases = cases
1160 .iter()
1161 .zip(blocks)
1162 .zip(payloads)
1163 .enumerate()
1164 .map(
1165 |(i, (((name, ty), Block { body, results, .. }), payload))| {
1166 let payload = if let Some(ty) = self.gen.non_empty_type(ty.as_ref()) {
1167 let ty = self.gen.type_name(ty);
1168 let name = name.to_upper_camel_case();
1169
1170 format!("{ty} {payload} = ({op}).get{name}();")
1171 } else {
1172 String::new()
1173 };
1174
1175 let assignments = lowered
1176 .iter()
1177 .zip(&results)
1178 .map(|(lowered, result)| format!("{lowered} = {result};\n"))
1179 .collect::<Vec<_>>()
1180 .concat();
1181
1182 format!(
1183 "case {i}: {{
1184 {payload}
1185 {body}
1186 {assignments}
1187 break;
1188 }}"
1189 )
1190 },
1191 )
1192 .collect::<Vec<_>>()
1193 .join("\n");
1194
1195 uwrite!(
1196 self.src,
1197 r#"
1198 {declarations}
1199
1200 switch (({op}).tag) {{
1201 {cases}
1202
1203 default: throw new AssertionError("invalid discriminant: " + ({op}).tag);
1204 }}
1205 "#
1206 );
1207 }
1208
1209 fn lift_variant(
1210 &mut self,
1211 ty: &Type,
1212 cases: &[(&str, Option<Type>)],
1213 op: &str,
1214 results: &mut Vec<String>,
1215 ) {
1216 let blocks = self
1217 .blocks
1218 .drain(self.blocks.len() - cases.len()..)
1219 .collect::<Vec<_>>();
1220
1221 let ty = self.gen.type_name(ty);
1222 let generics_position = ty.find('<');
1223 let lifted = self.locals.tmp("lifted");
1224
1225 let cases = cases
1226 .iter()
1227 .zip(blocks)
1228 .enumerate()
1229 .map(|(i, ((case_name, case_ty), Block { body, results, .. }))| {
1230 let payload = if self.gen.non_empty_type(case_ty.as_ref()).is_some() {
1231 results.into_iter().next().unwrap()
1232 } else if generics_position.is_some() {
1233 if let Some(ty) = case_ty.as_ref() {
1234 format!("{}.INSTANCE", self.gen.type_name(ty))
1235 } else {
1236 format!("{}Tuple0.INSTANCE", self.gen.gen.qualifier())
1237 }
1238 } else {
1239 String::new()
1240 };
1241
1242 let method = case_name.to_java_ident();
1243
1244 let call = if let Some(position) = generics_position {
1245 let (ty, generics) = ty.split_at(position);
1246 format!("{ty}.{generics}{method}")
1247 } else {
1248 format!("{ty}.{method}")
1249 };
1250
1251 format!(
1252 "case {i}: {{
1253 {body}
1254 {lifted} = {call}({payload});
1255 break;
1256 }}"
1257 )
1258 })
1259 .collect::<Vec<_>>()
1260 .join("\n");
1261
1262 uwrite!(
1263 self.src,
1264 r#"
1265 {ty} {lifted};
1266
1267 switch ({op}) {{
1268 {cases}
1269
1270 default: throw new AssertionError("invalid discriminant: " + ({op}));
1271 }}
1272 "#
1273 );
1274
1275 results.push(lifted);
1276 }
1277}
1278
1279impl Bindgen for FunctionBindgen<'_, '_> {
1280 type Operand = String;
1281
1282 fn emit(
1283 &mut self,
1284 _resolve: &Resolve,
1285 inst: &Instruction<'_>,
1286 operands: &mut Vec<String>,
1287 results: &mut Vec<String>,
1288 ) {
1289 match inst {
1290 Instruction::GetArg { nth } => results.push(self.params[*nth].clone()),
1291 Instruction::I32Const { val } => results.push(val.to_string()),
1292 Instruction::ConstZero { tys } => results.extend(tys.iter().map(|ty| {
1293 match ty {
1294 WasmType::I32 => "0",
1295 WasmType::I64 => "0L",
1296 WasmType::F32 => "0.0F",
1297 WasmType::F64 => "0.0D",
1298 WasmType::Pointer => "0",
1299 WasmType::PointerOrI64 => "0L",
1300 WasmType::Length => "0",
1301 }
1302 .to_owned()
1303 })),
1304
1305 Instruction::U8FromI32 => results.push(format!("(byte) ({})", operands[0])),
1307 Instruction::S8FromI32 => results.push(format!("(byte) ({})", operands[0])),
1308 Instruction::U16FromI32 => results.push(format!("(short) ({})", operands[0])),
1309 Instruction::S16FromI32 => results.push(format!("(short) ({})", operands[0])),
1310
1311 Instruction::I32FromU8 => results.push(format!("((int) ({})) & 0xFF", operands[0])),
1312 Instruction::I32FromU16 => results.push(format!("((int) ({})) & 0xFFFF", operands[0])),
1313
1314 Instruction::I32FromS8 | Instruction::I32FromS16 => {
1315 results.push(format!("(int) ({})", operands[0]))
1316 }
1317
1318 Instruction::CharFromI32
1319 | Instruction::I32FromChar
1320 | Instruction::U32FromI32
1321 | Instruction::S32FromI32
1322 | Instruction::S64FromI64
1323 | Instruction::U64FromI64
1324 | Instruction::I32FromU32
1325 | Instruction::I32FromS32
1326 | Instruction::I64FromS64
1327 | Instruction::I64FromU64
1328 | Instruction::CoreF32FromF32
1329 | Instruction::CoreF64FromF64
1330 | Instruction::F32FromCoreF32
1331 | Instruction::F64FromCoreF64 => results.push(operands[0].clone()),
1332
1333 Instruction::Bitcasts { casts } => results.extend(
1334 casts
1335 .iter()
1336 .zip(operands)
1337 .map(|(cast, op)| perform_cast(op, cast)),
1338 ),
1339
1340 Instruction::I32FromBool => {
1341 results.push(format!("({} ? 1 : 0)", operands[0]));
1342 }
1343 Instruction::BoolFromI32 => results.push(format!("({} != 0)", operands[0])),
1344
1345 Instruction::FlagsLower { flags, .. } => match flags_repr(flags) {
1347 Int::U8 | Int::U16 | Int::U32 => {
1348 results.push(format!("({}).value", operands[0]));
1349 }
1350 Int::U64 => {
1351 let op = &operands[0];
1352 results.push(format!("(int) (({op}).value & 0xffffffffL)"));
1353 results.push(format!("(int) ((({op}).value >>> 32) & 0xffffffffL)"));
1354 }
1355 },
1356
1357 Instruction::FlagsLift { flags, ty, .. } => match flags_repr(flags) {
1358 Int::U8 | Int::U16 | Int::U32 => {
1359 results.push(format!(
1360 "new {}(({}) {})",
1361 self.gen.type_name(&Type::Id(*ty)),
1362 int_type(flags_repr(flags)),
1363 operands[0]
1364 ));
1365 }
1366 Int::U64 => {
1367 results.push(format!(
1368 "new {}(((long) ({})) | (((long) ({})) << 32))",
1369 self.gen.type_name(&Type::Id(*ty)),
1370 operands[0],
1371 operands[1]
1372 ));
1373 }
1374 },
1375
1376 Instruction::HandleLower { .. } | Instruction::HandleLift { .. } => todo!(),
1377
1378 Instruction::RecordLower { record, .. } => {
1379 let op = &operands[0];
1380 for field in record.fields.iter() {
1381 results.push(format!("({op}).{}", field.name.to_java_ident()));
1382 }
1383 }
1384 Instruction::RecordLift { ty, .. } | Instruction::TupleLift { ty, .. } => {
1385 let ops = operands
1386 .iter()
1387 .map(|op| op.to_string())
1388 .collect::<Vec<_>>()
1389 .join(", ");
1390
1391 results.push(format!("new {}({ops})", self.gen.type_name(&Type::Id(*ty))));
1392 }
1393
1394 Instruction::TupleLower { tuple, .. } => {
1395 let op = &operands[0];
1396 for i in 0..tuple.types.len() {
1397 results.push(format!("({op}).f{i}"));
1398 }
1399 }
1400
1401 Instruction::VariantPayloadName => {
1402 let payload = self.locals.tmp("payload");
1403 results.push(payload.clone());
1404 self.payloads.push(payload);
1405 }
1406
1407 Instruction::VariantLower {
1408 variant,
1409 results: lowered_types,
1410 ..
1411 } => self.lower_variant(
1412 &variant
1413 .cases
1414 .iter()
1415 .map(|case| (case.name.deref(), case.ty))
1416 .collect::<Vec<_>>(),
1417 lowered_types,
1418 &operands[0],
1419 results,
1420 ),
1421
1422 Instruction::VariantLift { variant, ty, .. } => self.lift_variant(
1423 &Type::Id(*ty),
1424 &variant
1425 .cases
1426 .iter()
1427 .map(|case| (case.name.deref(), case.ty))
1428 .collect::<Vec<_>>(),
1429 &operands[0],
1430 results,
1431 ),
1432
1433 Instruction::OptionLower {
1434 results: lowered_types,
1435 payload,
1436 ..
1437 } => {
1438 let some = self.blocks.pop().unwrap();
1439 let none = self.blocks.pop().unwrap();
1440 let some_payload = self.payloads.pop().unwrap();
1441 let none_payload = self.payloads.pop().unwrap();
1442
1443 let lowered = lowered_types
1444 .iter()
1445 .map(|_| self.locals.tmp("lowered"))
1446 .collect::<Vec<_>>();
1447
1448 results.extend(lowered.iter().cloned());
1449
1450 let declarations = lowered
1451 .iter()
1452 .zip(lowered_types.iter())
1453 .map(|(lowered, ty)| format!("{} {lowered};", wasm_type(*ty)))
1454 .collect::<Vec<_>>()
1455 .join("\n");
1456
1457 let op = &operands[0];
1458
1459 let mut block = |ty: Option<&Type>, Block { body, results, .. }, payload| {
1460 let payload = if let Some(ty) = self.gen.non_empty_type(ty) {
1461 let ty = self.gen.type_name(ty);
1462
1463 format!("{ty} {payload} = ({ty}) ({op});")
1464 } else {
1465 String::new()
1466 };
1467
1468 let assignments = lowered
1469 .iter()
1470 .zip(&results)
1471 .map(|(lowered, result)| format!("{lowered} = {result};\n"))
1472 .collect::<Vec<_>>()
1473 .concat();
1474
1475 format!(
1476 "{payload}
1477 {body}
1478 {assignments}"
1479 )
1480 };
1481
1482 let none = block(None, none, none_payload);
1483 let some = block(Some(payload), some, some_payload);
1484
1485 uwrite!(
1486 self.src,
1487 r#"
1488 {declarations}
1489
1490 if (({op}) == null) {{
1491 {none}
1492 }} else {{
1493 {some}
1494 }}
1495 "#
1496 );
1497 }
1498
1499 Instruction::OptionLift { payload, ty } => {
1500 let some = self.blocks.pop().unwrap();
1501 let _none = self.blocks.pop().unwrap();
1502
1503 let ty = self.gen.type_name(&Type::Id(*ty));
1504 let lifted = self.locals.tmp("lifted");
1505 let op = &operands[0];
1506
1507 let payload = if self.gen.non_empty_type(Some(*payload)).is_some() {
1508 some.results.into_iter().next().unwrap()
1509 } else {
1510 "null".into()
1511 };
1512
1513 let some = some.body;
1514
1515 uwrite!(
1516 self.src,
1517 r#"
1518 {ty} {lifted};
1519
1520 switch ({op}) {{
1521 case 0: {{
1522 {lifted} = null;
1523 break;
1524 }}
1525
1526 case 1: {{
1527 {some}
1528 {lifted} = {payload};
1529 break;
1530 }}
1531
1532 default: throw new AssertionError("invalid discriminant: " + ({op}));
1533 }}
1534 "#
1535 );
1536
1537 results.push(lifted);
1538 }
1539
1540 Instruction::ResultLower {
1541 results: lowered_types,
1542 result,
1543 ..
1544 } => self.lower_variant(
1545 &[("ok", result.ok), ("err", result.err)],
1546 lowered_types,
1547 &operands[0],
1548 results,
1549 ),
1550
1551 Instruction::ResultLift { result, ty } => self.lift_variant(
1552 &Type::Id(*ty),
1553 &[("ok", result.ok), ("err", result.err)],
1554 &operands[0],
1555 results,
1556 ),
1557
1558 Instruction::EnumLower { .. } => results.push(format!("{}.ordinal()", operands[0])),
1559
1560 Instruction::EnumLift { ty, .. } => results.push(format!(
1561 "{}.values()[{}]",
1562 self.gen.type_name(&Type::Id(*ty)),
1563 operands[0]
1564 )),
1565
1566 Instruction::ListCanonLower { element, realloc } => {
1567 let op = &operands[0];
1568 let (size, ty) = list_element_info(element);
1569
1570 if realloc.is_none() && size <= 4 {
1573 results.push(format!("org.teavm.interop.Address.ofData({op}).toInt()"));
1574 } else {
1575 let address = self.locals.tmp("address");
1576 let ty = ty.to_upper_camel_case();
1577
1578 uwrite!(
1579 self.src,
1580 "
1581 org.teavm.interop.Address {address} = Memory.malloc({size} * ({op}).length, {size});
1582 Memory.put{ty}s({address}, {op}, 0, ({op}).length);
1583 "
1584 );
1585
1586 if realloc.is_none() {
1587 self.cleanup.push(Cleanup {
1588 address: format!("{address}.toInt()"),
1589 size: format!("{size} * ({op}).length"),
1590 align: size,
1591 });
1592 }
1593
1594 results.push(format!("{address}.toInt()"));
1595 }
1596 results.push(format!("({op}).length"));
1597 }
1598
1599 Instruction::ListCanonLift { element, .. } => {
1600 let (_, ty) = list_element_info(element);
1601 let ty_upper = ty.to_upper_camel_case();
1602 let array = self.locals.tmp("array");
1603 let address = &operands[0];
1604 let length = &operands[1];
1605
1606 uwrite!(
1607 self.src,
1608 "
1609 {ty}[] {array} = new {ty}[{length}];
1610 Memory.get{ty_upper}s(org.teavm.interop.Address.fromInt({address}), {array}, 0, ({array}).length);
1611 "
1612 );
1613
1614 results.push(array);
1615 }
1616
1617 Instruction::StringLower { realloc } => {
1618 let op = &operands[0];
1619 let bytes = self.locals.tmp("bytes");
1620 uwriteln!(
1621 self.src,
1622 "byte[] {bytes} = ({op}).getBytes(StandardCharsets.UTF_8);"
1623 );
1624
1625 if realloc.is_none() {
1626 results.push(format!("org.teavm.interop.Address.ofData({bytes}).toInt()"));
1627 } else {
1628 let address = self.locals.tmp("address");
1629
1630 uwrite!(
1631 self.src,
1632 "
1633 org.teavm.interop.Address {address} = Memory.malloc({bytes}.length, 1);
1634 Memory.putBytes({address}, {bytes}, 0, {bytes}.length);
1635 "
1636 );
1637
1638 results.push(format!("{address}.toInt()"));
1639 }
1640 results.push(format!("{bytes}.length"));
1641 }
1642
1643 Instruction::StringLift { .. } => {
1644 let bytes = self.locals.tmp("bytes");
1645 let address = &operands[0];
1646 let length = &operands[1];
1647
1648 uwrite!(
1649 self.src,
1650 "
1651 byte[] {bytes} = new byte[{length}];
1652 Memory.getBytes(org.teavm.interop.Address.fromInt({address}), {bytes}, 0, {length});
1653 "
1654 );
1655
1656 results.push(format!("new String({bytes}, StandardCharsets.UTF_8)"));
1657 }
1658
1659 Instruction::ListLower { element, realloc } => {
1660 let Block {
1661 body,
1662 results: block_results,
1663 element: block_element,
1664 base,
1665 } = self.blocks.pop().unwrap();
1666 assert!(block_results.is_empty());
1667
1668 let op = &operands[0];
1669 let size = self.gen.gen.sizes.size(element).size_wasm32();
1670 let align = self.gen.gen.sizes.align(element).align_wasm32();
1671 let address = self.locals.tmp("address");
1672 let ty = self.gen.type_name(element);
1673 let index = self.locals.tmp("index");
1674
1675 uwrite!(
1676 self.src,
1677 "
1678 int {address} = Memory.malloc(({op}).size() * {size}, {align}).toInt();
1679 for (int {index} = 0; {index} < ({op}).size(); ++{index}) {{
1680 {ty} {block_element} = ({op}).get({index});
1681 int {base} = {address} + ({index} * {size});
1682 {body}
1683 }}
1684 "
1685 );
1686
1687 if realloc.is_none() {
1688 self.cleanup.push(Cleanup {
1689 address: address.clone(),
1690 size: format!("({op}).size() * {size}"),
1691 align,
1692 });
1693 }
1694
1695 results.push(address);
1696 results.push(format!("({op}).size()"));
1697 }
1698
1699 Instruction::ListLift { element, .. } => {
1700 let Block {
1701 body,
1702 results: block_results,
1703 base,
1704 ..
1705 } = self.blocks.pop().unwrap();
1706 let address = &operands[0];
1707 let length = &operands[1];
1708 let array = self.locals.tmp("array");
1709 let ty = self.gen.type_name(element);
1710 let size = self.gen.gen.sizes.size(element).size_wasm32();
1711 let align = self.gen.gen.sizes.align(element).align_wasm32();
1712 let index = self.locals.tmp("index");
1713
1714 let result = match &block_results[..] {
1715 [result] => result,
1716 _ => todo!("result count == {}", results.len()),
1717 };
1718
1719 uwrite!(
1720 self.src,
1721 "
1722 ArrayList<{ty}> {array} = new ArrayList<>({length});
1723 for (int {index} = 0; {index} < ({length}); ++{index}) {{
1724 int {base} = ({address}) + ({index} * {size});
1725 {body}
1726 {array}.add({result});
1727 }}
1728 Memory.free(org.teavm.interop.Address.fromInt({address}), ({length}) * {size}, {align});
1729 "
1730 );
1731
1732 results.push(array);
1733 }
1734
1735 Instruction::IterElem { .. } => {
1736 results.push(self.block_storage.last().unwrap().element.clone())
1737 }
1738
1739 Instruction::IterBasePointer => {
1740 results.push(self.block_storage.last().unwrap().base.clone())
1741 }
1742
1743 Instruction::CallWasm { sig, .. } => {
1744 let assignment = match &sig.results[..] {
1745 [result] => {
1746 let ty = wasm_type(*result);
1747 let result = self.locals.tmp("result");
1748 let assignment = format!("{ty} {result} = ");
1749 results.push(result);
1750 assignment
1751 }
1752
1753 [] => String::new(),
1754
1755 _ => unreachable!(),
1756 };
1757
1758 let func_name = self.func_name.to_upper_camel_case();
1759
1760 let operands = operands.join(", ");
1761
1762 uwriteln!(self.src, "{assignment} wasmImport{func_name}({operands});");
1763 }
1764
1765 Instruction::CallInterface { func, .. } => {
1766 let (assignment, destructure) = match &func.result {
1767 None => (String::new(), String::new()),
1768 Some(ty) => {
1769 let ty = self.gen.type_name(ty);
1770 let result = self.locals.tmp("result");
1771 let assignment = format!("{ty} {result} = ");
1772 results.push(result);
1773 (assignment, String::new())
1774 }
1775 };
1776
1777 let module = self.gen.name;
1778 let name = func.name.to_java_ident();
1779
1780 let args = operands.join(", ");
1781
1782 uwrite!(
1783 self.src,
1784 "
1785 {assignment}{module}Impl.{name}({args});
1786 {destructure}
1787 "
1788 );
1789 }
1790
1791 Instruction::Return { amt, .. } => {
1792 for Cleanup {
1793 address,
1794 size,
1795 align,
1796 } in &self.cleanup
1797 {
1798 uwriteln!(
1799 self.src,
1800 "Memory.free(org.teavm.interop.Address.fromInt({address}), {size}, {align});"
1801 );
1802 }
1803
1804 if self.needs_cleanup_list {
1805 uwrite!(
1806 self.src,
1807 "
1808 for ({}Cleanup cleanup : cleanupList) {{
1809 Memory.free(org.teavm.interop.Address.fromInt(cleanup.address), cleanup.size, cleanup.align);
1810 }}
1811 ",
1812 self.gen.gen.qualifier()
1813 );
1814 }
1815
1816 match *amt {
1817 0 => (),
1818 1 => uwriteln!(self.src, "return {};", operands[0]),
1819 count => {
1820 let results = operands.join(", ");
1821 uwriteln!(
1822 self.src,
1823 "return new {}Tuple{count}<>({results});",
1824 self.gen.gen.qualifier()
1825 )
1826 }
1827 }
1828 }
1829
1830 Instruction::I32Load { offset }
1831 | Instruction::PointerLoad { offset }
1832 | Instruction::LengthLoad { offset } => results.push(format!(
1833 "org.teavm.interop.Address.fromInt(({}) + {offset}).getInt()",
1834 operands[0]
1835 )),
1836
1837 Instruction::I32Load8U { offset } => results.push(format!(
1838 "(((int) org.teavm.interop.Address.fromInt(({}) + {offset}).getByte()) & 0xFF)",
1839 operands[0]
1840 )),
1841
1842 Instruction::I32Load8S { offset } => results.push(format!(
1843 "((int) org.teavm.interop.Address.fromInt(({}) + {offset}).getByte())",
1844 operands[0]
1845 )),
1846
1847 Instruction::I32Load16U { offset } => results.push(format!(
1848 "(((int) org.teavm.interop.Address.fromInt(({}) + {offset}).getShort()) & 0xFFFF)",
1849 operands[0]
1850 )),
1851
1852 Instruction::I32Load16S { offset } => results.push(format!(
1853 "((int) org.teavm.interop.Address.fromInt(({}) + {offset}).getShort())",
1854 operands[0]
1855 )),
1856
1857 Instruction::I64Load { offset } => results.push(format!(
1858 "org.teavm.interop.Address.fromInt(({}) + {offset}).getLong()",
1859 operands[0]
1860 )),
1861
1862 Instruction::F32Load { offset } => results.push(format!(
1863 "org.teavm.interop.Address.fromInt(({}) + {offset}).getFloat()",
1864 operands[0]
1865 )),
1866
1867 Instruction::F64Load { offset } => results.push(format!(
1868 "org.teavm.interop.Address.fromInt(({}) + {offset}).getDouble()",
1869 operands[0]
1870 )),
1871
1872 Instruction::I32Store { offset }
1873 | Instruction::PointerStore { offset }
1874 | Instruction::LengthStore { offset } => uwriteln!(
1875 self.src,
1876 "org.teavm.interop.Address.fromInt(({}) + {offset}).putInt({});",
1877 operands[1],
1878 operands[0]
1879 ),
1880
1881 Instruction::I32Store8 { offset } => uwriteln!(
1882 self.src,
1883 "org.teavm.interop.Address.fromInt(({}) + {offset}).putByte((byte) ({}));",
1884 operands[1],
1885 operands[0]
1886 ),
1887
1888 Instruction::I32Store16 { offset } => uwriteln!(
1889 self.src,
1890 "org.teavm.interop.Address.fromInt(({}) + {offset}).putShort((short) ({}));",
1891 operands[1],
1892 operands[0]
1893 ),
1894
1895 Instruction::I64Store { offset } => uwriteln!(
1896 self.src,
1897 "org.teavm.interop.Address.fromInt(({}) + {offset}).putLong({});",
1898 operands[1],
1899 operands[0]
1900 ),
1901
1902 Instruction::F32Store { offset } => uwriteln!(
1903 self.src,
1904 "org.teavm.interop.Address.fromInt(({}) + {offset}).putFloat({});",
1905 operands[1],
1906 operands[0]
1907 ),
1908
1909 Instruction::F64Store { offset } => uwriteln!(
1910 self.src,
1911 "org.teavm.interop.Address.fromInt(({}) + {offset}).putDouble({});",
1912 operands[1],
1913 operands[0]
1914 ),
1915
1916 Instruction::Malloc { .. } => unimplemented!(),
1917
1918 Instruction::GuestDeallocate { size, align } => {
1919 uwriteln!(
1920 self.src,
1921 "Memory.free(org.teavm.interop.Address.fromInt({}), {size}, {align});",
1922 operands[0]
1923 )
1924 }
1925
1926 Instruction::GuestDeallocateString => uwriteln!(
1927 self.src,
1928 "Memory.free(org.teavm.interop.Address.fromInt({}), {}, 1);",
1929 operands[0],
1930 operands[1]
1931 ),
1932
1933 Instruction::GuestDeallocateVariant { blocks } => {
1934 let cases = self
1935 .blocks
1936 .drain(self.blocks.len() - blocks..)
1937 .enumerate()
1938 .map(|(i, Block { body, results, .. })| {
1939 assert!(results.is_empty());
1940
1941 format!(
1942 "case {i}: {{
1943 {body}
1944 break;
1945 }}"
1946 )
1947 })
1948 .collect::<Vec<_>>()
1949 .join("\n");
1950
1951 let op = &operands[0];
1952
1953 uwrite!(
1954 self.src,
1955 "
1956 switch ({op}) {{
1957 {cases}
1958 }}
1959 "
1960 );
1961 }
1962
1963 Instruction::GuestDeallocateList { element } => {
1964 let Block {
1965 body,
1966 results,
1967 base,
1968 ..
1969 } = self.blocks.pop().unwrap();
1970 assert!(results.is_empty());
1971
1972 let address = &operands[0];
1973 let length = &operands[1];
1974
1975 let size = self.gen.gen.sizes.size(element).size_wasm32();
1976 let align = self.gen.gen.sizes.align(element).align_wasm32();
1977
1978 if !body.trim().is_empty() {
1979 let index = self.locals.tmp("index");
1980
1981 uwrite!(
1982 self.src,
1983 "
1984 for (int {index} = 0; {index} < ({length}); ++{index}) {{
1985 int {base} = ({address}) + ({index} * {size});
1986 {body}
1987 }}
1988 "
1989 );
1990 }
1991
1992 uwriteln!(
1993 self.src,
1994 "Memory.free(org.teavm.interop.Address.fromInt({address}), ({length}) * {size}, {align});"
1995 );
1996 }
1997
1998 Instruction::Flush { amt } => {
1999 results.extend(operands.iter().take(*amt).map(|v| v.clone()));
2000 }
2001
2002 Instruction::AsyncMalloc { .. }
2003 | Instruction::AsyncPostCallInterface { .. }
2004 | Instruction::AsyncCallReturn { .. }
2005 | Instruction::FutureLower { .. }
2006 | Instruction::FutureLift { .. }
2007 | Instruction::StreamLower { .. }
2008 | Instruction::StreamLift { .. }
2009 | Instruction::ErrorContextLower { .. }
2010 | Instruction::ErrorContextLift { .. }
2011 | Instruction::AsyncCallWasm { .. } => todo!(),
2012 }
2013 }
2014
2015 fn return_pointer(&mut self, size: usize, align: usize) -> String {
2016 self.gen.gen.return_area_size = self.gen.gen.return_area_size.max(size);
2017 self.gen.gen.return_area_align = self.gen.gen.return_area_align.max(align);
2018 format!("{}RETURN_AREA", self.gen.gen.qualifier())
2019 }
2020
2021 fn push_block(&mut self) {
2022 self.block_storage.push(BlockStorage {
2023 body: mem::take(&mut self.src),
2024 element: self.locals.tmp("element"),
2025 base: self.locals.tmp("base"),
2026 cleanup: mem::take(&mut self.cleanup),
2027 });
2028 }
2029
2030 fn finish_block(&mut self, operands: &mut Vec<String>) {
2031 let BlockStorage {
2032 body,
2033 element,
2034 base,
2035 cleanup,
2036 } = self.block_storage.pop().unwrap();
2037
2038 if !self.cleanup.is_empty() {
2039 self.needs_cleanup_list = true;
2040
2041 for Cleanup {
2042 address,
2043 size,
2044 align,
2045 } in &self.cleanup
2046 {
2047 uwriteln!(
2048 self.src,
2049 "cleanupList.add(new {}Cleanup({address}, {size}, {align}));",
2050 self.gen.gen.qualifier()
2051 );
2052 }
2053 }
2054
2055 self.cleanup = cleanup;
2056
2057 self.blocks.push(Block {
2058 body: mem::replace(&mut self.src, body),
2059 results: mem::take(operands),
2060 element,
2061 base,
2062 });
2063 }
2064
2065 fn sizes(&self) -> &SizeAlign {
2066 &self.gen.gen.sizes
2067 }
2068
2069 fn is_list_canonical(&self, _resolve: &Resolve, element: &Type) -> bool {
2070 is_primitive(element)
2071 }
2072}
2073
2074fn perform_cast(op: &str, cast: &Bitcast) -> String {
2075 match cast {
2076 Bitcast::I32ToF32 => {
2077 format!("Float.intBitsToFloat({op})")
2078 }
2079 Bitcast::I64ToF32 => format!("Float.intBitsToFloat((int) ({op}))"),
2080 Bitcast::F32ToI32 => {
2081 format!("Float.floatToIntBits({op})")
2082 }
2083 Bitcast::F32ToI64 => format!("(long) Float.floatToIntBits({op})"),
2084 Bitcast::I64ToF64 => {
2085 format!("Double.longBitsToDouble({op})")
2086 }
2087 Bitcast::F64ToI64 => {
2088 format!("Double.doubleToLongBits({op})")
2089 }
2090 Bitcast::I32ToI64 => format!("(long) ({op})"),
2091 Bitcast::I64ToI32 => format!("(int) ({op})"),
2092 Bitcast::I64ToP64 => format!("{op}"),
2093 Bitcast::P64ToI64 => format!("{op}"),
2094 Bitcast::LToI64 | Bitcast::PToP64 => format!("(long) ({op})"),
2095 Bitcast::I64ToL | Bitcast::P64ToP => format!("(int) ({op})"),
2096 Bitcast::I32ToP
2097 | Bitcast::PToI32
2098 | Bitcast::I32ToL
2099 | Bitcast::LToI32
2100 | Bitcast::LToP
2101 | Bitcast::PToL
2102 | Bitcast::None => op.to_owned(),
2103
2104 Bitcast::Sequence(sequence) => {
2105 let [first, second] = &**sequence;
2106 perform_cast(&perform_cast(op, first), second)
2107 }
2108 }
2109}
2110
2111fn int_type(int: Int) -> &'static str {
2112 match int {
2113 Int::U8 => "byte",
2114 Int::U16 => "short",
2115 Int::U32 => "int",
2116 Int::U64 => "long",
2117 }
2118}
2119
2120fn wasm_type(ty: WasmType) -> &'static str {
2121 match ty {
2122 WasmType::I32 => "int",
2123 WasmType::I64 => "long",
2124 WasmType::F32 => "float",
2125 WasmType::F64 => "double",
2126 WasmType::Pointer => "int",
2127 WasmType::PointerOrI64 => "long",
2128 WasmType::Length => "int",
2129 }
2130}
2131
2132fn flags_repr(flags: &Flags) -> Int {
2133 match flags.repr() {
2134 FlagsRepr::U8 => Int::U8,
2135 FlagsRepr::U16 => Int::U16,
2136 FlagsRepr::U32(1) => Int::U32,
2137 FlagsRepr::U32(2) => Int::U64,
2138 repr => panic!("unimplemented flags {repr:?}"),
2139 }
2140}
2141
2142fn list_element_info(ty: &Type) -> (usize, &'static str) {
2143 match ty {
2144 Type::U8 | Type::S8 => (1, "byte"),
2145 Type::U16 | Type::S16 => (2, "short"),
2146 Type::U32 | Type::S32 => (4, "int"),
2147 Type::U64 | Type::S64 => (8, "long"),
2148 Type::F32 => (4, "float"),
2149 Type::F64 => (8, "double"),
2150 _ => unreachable!(),
2151 }
2152}
2153
2154fn indent(code: &str) -> String {
2155 let mut indented = String::with_capacity(code.len());
2156 let mut indent = 0;
2157 let mut was_empty = false;
2158 for line in code.lines() {
2159 let trimmed = line.trim();
2160 if trimmed.is_empty() {
2161 if was_empty {
2162 continue;
2163 }
2164 was_empty = true;
2165 } else {
2166 was_empty = false;
2167 }
2168
2169 if trimmed.starts_with('}') {
2170 indent -= 1;
2171 }
2172 indented.extend(iter::repeat(' ').take(indent * 4));
2173 indented.push_str(trimmed);
2174 if trimmed.ends_with('{') {
2175 indent += 1;
2176 }
2177 indented.push('\n');
2178 }
2179 indented
2180}
2181
2182fn is_primitive(ty: &Type) -> bool {
2183 matches!(
2184 ty,
2185 Type::U8
2186 | Type::S8
2187 | Type::U16
2188 | Type::S16
2189 | Type::U32
2190 | Type::S32
2191 | Type::U64
2192 | Type::S64
2193 | Type::F32
2194 | Type::F64
2195 )
2196}
2197
2198fn world_name(resolve: &Resolve, world: WorldId) -> String {
2199 format!(
2200 "wit.worlds.{}",
2201 resolve.worlds[world].name.to_upper_camel_case()
2202 )
2203}
2204
2205fn interface_name(resolve: &Resolve, name: &WorldKey, direction: Direction) -> String {
2206 let pkg = match name {
2207 WorldKey::Name(_) => None,
2208 WorldKey::Interface(id) => {
2209 let pkg = resolve.interfaces[*id].package.unwrap();
2210 Some(resolve.packages[pkg].name.clone())
2211 }
2212 };
2213
2214 let name = match name {
2215 WorldKey::Name(name) => name,
2216 WorldKey::Interface(id) => resolve.interfaces[*id].name.as_ref().unwrap(),
2217 }
2218 .to_upper_camel_case();
2219
2220 format!(
2221 "wit.{}.{}{name}",
2222 match direction {
2223 Direction::Import => "imports",
2224 Direction::Export => "exports",
2225 },
2226 if let Some(name) = &pkg {
2227 format!(
2228 "{}.{}.",
2229 name.namespace.to_java_ident(),
2230 name.name.to_java_ident()
2231 )
2232 } else {
2233 String::new()
2234 }
2235 )
2236}
2237
2238fn split_qualified_name(name: &str) -> (String, &str) {
2239 let tokens = name.split('.').collect::<Vec<_>>();
2240
2241 let package = tokens
2242 .iter()
2243 .copied()
2244 .take(tokens.len() - 1)
2245 .collect::<Vec<_>>()
2246 .join(".");
2247
2248 let name = tokens.last().unwrap();
2249
2250 (package, name)
2251}
2252
2253trait ToJavaIdent: ToOwned {
2254 fn to_java_ident(&self) -> Self::Owned;
2255}
2256
2257impl ToJavaIdent for str {
2258 fn to_java_ident(&self) -> String {
2259 match self {
2262 "abstract" | "continue" | "for" | "new" | "switch" | "assert" | "default" | "goto"
2263 | "package" | "synchronized" | "boolean" | "do" | "if" | "private" | "this"
2264 | "break" | "double" | "implements" | "protected" | "throw" | "byte" | "else"
2265 | "import" | "public" | "throws" | "case" | "enum" | "instanceof" | "return"
2266 | "transient" | "catch" | "extends" | "int" | "short" | "try" | "char" | "final"
2267 | "interface" | "static" | "void" | "class" | "finally" | "long" | "strictfp"
2268 | "volatile" | "const" | "float" | "native" | "super" | "while" => format!("{self}_"),
2269 _ => self.to_lower_camel_case(),
2270 }
2271 }
2272}