From 8ddd1bea6daeab5fa26d01465f17eef42d00b32b Mon Sep 17 00:00:00 2001 From: Christof Petig Date: Tue, 11 Feb 2025 17:17:16 +0100 Subject: [PATCH 1/3] Automatic adaption to 64bit architectures in guest code --- Cargo.lock | 80 +++++++---- Cargo.toml | 10 +- crates/c/src/lib.rs | 67 +++++++--- crates/core/src/abi.rs | 242 ++++++++++++++++------------------ crates/csharp/src/function.rs | 59 +++++---- crates/moonbit/src/lib.rs | 70 ++++++---- crates/rust/src/bindgen.rs | 126 ++++++++++++------ crates/rust/src/interface.rs | 40 ++++-- crates/rust/src/lib.rs | 4 +- crates/teavm-java/src/lib.rs | 76 +++++++---- 10 files changed, 466 insertions(+), 308 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index da4a42cac..7717b7acb 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1509,7 +1509,7 @@ name = "test-helpers" version = "0.0.0" dependencies = [ "codegen-macro", - "wasm-encoder 0.225.0", + "wasm-encoder 0.225.0 (git+https://github.com/bytecodealliance/wasm-tools.git)", "wit-bindgen-core", "wit-component", "wit-parser 0.225.0", @@ -1792,14 +1792,22 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6f7eac0445cac73bcf09e6a97f83248d64356dccf9f2b100199769b6b42464e5" dependencies = [ "leb128fmt", - "wasmparser 0.225.0", + "wasmparser 0.225.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "wasm-encoder" +version = "0.225.0" +source = "git+https://github.com/bytecodealliance/wasm-tools.git#beac7de36a6747a9061b8fa497a130aa4f7da185" +dependencies = [ + "leb128fmt", + "wasmparser 0.225.0 (git+https://github.com/bytecodealliance/wasm-tools.git)", ] [[package]] name = "wasm-metadata" version = "0.225.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f1d20d0bf2c73c32a5114cf35a5c10ccf9f9aa37a3a2c0114b3e11cbf6faac12" +source = "git+https://github.com/bytecodealliance/wasm-tools.git#beac7de36a6747a9061b8fa497a130aa4f7da185" dependencies = [ "anyhow", "indexmap", @@ -1808,8 +1816,8 @@ dependencies = [ "serde_json", "spdx", "url", - "wasm-encoder 0.225.0", - "wasmparser 0.225.0", + "wasm-encoder 0.225.0 (git+https://github.com/bytecodealliance/wasm-tools.git)", + "wasmparser 0.225.0 (git+https://github.com/bytecodealliance/wasm-tools.git)", ] [[package]] @@ -1831,6 +1839,16 @@ name = "wasmparser" version = "0.225.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "36e5456165f81e64cb9908a0fe9b9d852c2c74582aa3fe2be3c2da57f937d3ae" +dependencies = [ + "bitflags", + "indexmap", + "semver", +] + +[[package]] +name = "wasmparser" +version = "0.225.0" +source = "git+https://github.com/bytecodealliance/wasm-tools.git#beac7de36a6747a9061b8fa497a130aa4f7da185" dependencies = [ "bitflags", "hashbrown 0.15.2", @@ -1902,7 +1920,7 @@ dependencies = [ "wasmtime-slab", "wasmtime-versioned-export-macros", "wasmtime-winch", - "wat", + "wat 1.225.0 (registry+https://github.com/rust-lang/crates.io-index)", "windows-sys 0.52.0", ] @@ -2157,7 +2175,19 @@ dependencies = [ "leb128fmt", "memchr", "unicode-width", - "wasm-encoder 0.225.0", + "wasm-encoder 0.225.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "wast" +version = "225.0.0" +source = "git+https://github.com/bytecodealliance/wasm-tools.git#beac7de36a6747a9061b8fa497a130aa4f7da185" +dependencies = [ + "bumpalo", + "leb128fmt", + "memchr", + "unicode-width", + "wasm-encoder 0.225.0 (git+https://github.com/bytecodealliance/wasm-tools.git)", ] [[package]] @@ -2166,7 +2196,15 @@ version = "1.225.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "89e72a33942234fd0794bcdac30e43b448de3187512414267678e511c6755f11" dependencies = [ - "wast 225.0.0", + "wast 225.0.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "wat" +version = "1.225.0" +source = "git+https://github.com/bytecodealliance/wasm-tools.git#beac7de36a6747a9061b8fa497a130aa4f7da185" +dependencies = [ + "wast 225.0.0 (git+https://github.com/bytecodealliance/wasm-tools.git)", ] [[package]] @@ -2385,7 +2423,7 @@ dependencies = [ "clap", "heck 0.5.0", "test-helpers", - "wasm-encoder 0.225.0", + "wasm-encoder 0.225.0 (git+https://github.com/bytecodealliance/wasm-tools.git)", "wasm-metadata", "wit-bindgen-core", "wit-component", @@ -2400,8 +2438,8 @@ dependencies = [ "clap", "heck 0.5.0", "test-artifacts", - "wasm-encoder 0.225.0", - "wasmparser 0.225.0", + "wasm-encoder 0.225.0 (git+https://github.com/bytecodealliance/wasm-tools.git)", + "wasmparser 0.225.0 (git+https://github.com/bytecodealliance/wasm-tools.git)", "wasmtime", "wasmtime-wasi", "wit-bindgen-c", @@ -2434,9 +2472,9 @@ dependencies = [ "heck 0.5.0", "indexmap", "test-helpers", - "wasm-encoder 0.225.0", + "wasm-encoder 0.225.0 (git+https://github.com/bytecodealliance/wasm-tools.git)", "wasm-metadata", - "wasmparser 0.225.0", + "wasmparser 0.225.0 (git+https://github.com/bytecodealliance/wasm-tools.git)", "wit-bindgen-core", "wit-component", "wit-parser 0.225.0", @@ -2535,8 +2573,7 @@ dependencies = [ [[package]] name = "wit-component" version = "0.225.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2505c917564c1d74774563bbcd3e4f8c216a6508050862fd5f449ee56e3c5125" +source = "git+https://github.com/bytecodealliance/wasm-tools.git#beac7de36a6747a9061b8fa497a130aa4f7da185" dependencies = [ "anyhow", "bitflags", @@ -2545,10 +2582,10 @@ dependencies = [ "serde", "serde_derive", "serde_json", - "wasm-encoder 0.225.0", + "wasm-encoder 0.225.0 (git+https://github.com/bytecodealliance/wasm-tools.git)", "wasm-metadata", - "wasmparser 0.225.0", - "wat", + "wasmparser 0.225.0 (git+https://github.com/bytecodealliance/wasm-tools.git)", + "wat 1.225.0 (git+https://github.com/bytecodealliance/wasm-tools.git)", "wit-parser 0.225.0", ] @@ -2573,8 +2610,7 @@ dependencies = [ [[package]] name = "wit-parser" version = "0.225.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ebefaa234e47224f10ce60480c5bfdece7497d0f3b87a12b41ff39e5c8377a78" +source = "git+https://github.com/bytecodealliance/wasm-tools.git#beac7de36a6747a9061b8fa497a130aa4f7da185" dependencies = [ "anyhow", "id-arena", @@ -2585,7 +2621,7 @@ dependencies = [ "serde_derive", "serde_json", "unicode-xid", - "wasmparser 0.225.0", + "wasmparser 0.225.0 (git+https://github.com/bytecodealliance/wasm-tools.git)", ] [[package]] diff --git a/Cargo.toml b/Cargo.toml index 7caf0cb58..26952c48b 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -33,11 +33,11 @@ prettyplease = "0.2.20" syn = { version = "2.0.89", features = ["printing"] } futures = "0.3.31" -wasmparser = "0.225.0" -wasm-encoder = "0.225.0" -wasm-metadata = "0.225.0" -wit-parser = "0.225.0" -wit-component = "0.225.0" +wasmparser = { git = "https://github.com/bytecodealliance/wasm-tools.git" } +wasm-encoder = { git = "https://github.com/bytecodealliance/wasm-tools.git" } +wasm-metadata = { git = "https://github.com/bytecodealliance/wasm-tools.git" } +wit-parser = { git = "https://github.com/bytecodealliance/wasm-tools.git" } +wit-component = { git = "https://github.com/bytecodealliance/wasm-tools.git" } wit-bindgen-core = { path = 'crates/core', version = '0.39.0' } wit-bindgen-c = { path = 'crates/c', version = '0.39.0' } diff --git a/crates/c/src/lib.rs b/crates/c/src/lib.rs index 5da00ff5c..fb561e52a 100644 --- a/crates/c/src/lib.rs +++ b/crates/c/src/lib.rs @@ -18,8 +18,8 @@ struct C { opts: Opts, h_includes: Vec, c_includes: Vec, - return_pointer_area_size: usize, - return_pointer_area_align: usize, + return_pointer_area_size: ArchitectureSize, + return_pointer_area_align: Alignment, names: Ns, needs_string: bool, needs_union_int32_float: bool, @@ -463,7 +463,7 @@ impl WorldGenerator for C { // Declare a statically-allocated return area, if needed. We only do // this for export bindings, because import bindings allocate their // return-area on the stack. - if self.return_pointer_area_size > 0 { + if !self.return_pointer_area_size.is_empty() { // Automatic indentation avoided due to `extern "C" {` declaration uwrite!( c_str, @@ -471,8 +471,10 @@ impl WorldGenerator for C { __attribute__((__aligned__({}))) static uint8_t RET_AREA[{}]; ", - self.return_pointer_area_align, - self.return_pointer_area_size, + self.return_pointer_area_align + .format(POINTER_SIZE_EXPRESSION), + self.return_pointer_area_size + .format(POINTER_SIZE_EXPRESSION), ); } c_str.push_str(&self.src.c_adapters); @@ -1788,12 +1790,14 @@ impl InterfaceGenerator<'_> { .. } = f; - if import_return_pointer_area_size > 0 { + if !import_return_pointer_area_size.is_empty() { self.src.c_adapters(&format!( "\ - __attribute__((__aligned__({import_return_pointer_area_align}))) - uint8_t ret_area[{import_return_pointer_area_size}]; + __attribute__((__aligned__({}))) + uint8_t ret_area[{}]; ", + import_return_pointer_area_align.format(POINTER_SIZE_EXPRESSION), + import_return_pointer_area_size.format(POINTER_SIZE_EXPRESSION), )); } @@ -2136,8 +2140,8 @@ struct FunctionBindgen<'a, 'b> { params: Vec, wasm_return: Option, ret_store_cnt: usize, - import_return_pointer_area_size: usize, - import_return_pointer_area_align: usize, + import_return_pointer_area_size: ArchitectureSize, + import_return_pointer_area_align: Alignment, /// Borrows observed during lifting an export, that will need to be dropped when the guest /// function exits. @@ -2165,8 +2169,8 @@ impl<'a, 'b> FunctionBindgen<'a, 'b> { params: Vec::new(), wasm_return: None, ret_store_cnt: 0, - import_return_pointer_area_size: 0, - import_return_pointer_area_align: 0, + import_return_pointer_area_size: Default::default(), + import_return_pointer_area_align: Default::default(), borrow_decls: Default::default(), borrows: Vec::new(), } @@ -2179,23 +2183,40 @@ impl<'a, 'b> FunctionBindgen<'a, 'b> { self.src.push_str(";\n"); } - fn load(&mut self, ty: &str, offset: i32, operands: &[String], results: &mut Vec) { - results.push(format!("*(({}*) ({} + {}))", ty, operands[0], offset)); + fn load( + &mut self, + ty: &str, + offset: ArchitectureSize, + operands: &[String], + results: &mut Vec, + ) { + results.push(format!( + "*(({}*) ({} + {}))", + ty, + operands[0], + offset.format(POINTER_SIZE_EXPRESSION) + )); } - fn load_ext(&mut self, ty: &str, offset: i32, operands: &[String], results: &mut Vec) { + fn load_ext( + &mut self, + ty: &str, + offset: ArchitectureSize, + operands: &[String], + results: &mut Vec, + ) { self.load(ty, offset, operands, results); let result = results.pop().unwrap(); results.push(format!("(int32_t) {}", result)); } - fn store(&mut self, ty: &str, offset: i32, operands: &[String]) { + fn store(&mut self, ty: &str, offset: ArchitectureSize, operands: &[String]) { uwriteln!( self.src, "*(({}*)({} + {})) = {};", ty, operands[1], - offset, + offset.format(POINTER_SIZE_EXPRESSION), operands[0] ); } @@ -2245,7 +2266,7 @@ impl Bindgen for FunctionBindgen<'_, '_> { self.blocks.push((src.into(), mem::take(operands))); } - fn return_pointer(&mut self, size: usize, align: usize) -> String { + fn return_pointer(&mut self, size: ArchitectureSize, align: Alignment) -> String { let ptr = self.locals.tmp("ptr"); // Use a stack-based return area for imports, because exports need @@ -3049,8 +3070,12 @@ impl Bindgen for FunctionBindgen<'_, '_> { uwriteln!(self.src, "uint8_t *{ptr} = {};", operands[0]); let i = self.locals.tmp("i"); uwriteln!(self.src, "for (size_t {i} = 0; {i} < {len}; {i}++) {{"); - let size = self.gen.gen.sizes.size(element).size_wasm32(); - uwriteln!(self.src, "uint8_t *base = {ptr} + {i} * {size};"); + let size = self.gen.gen.sizes.size(element); + uwriteln!( + self.src, + "uint8_t *base = {ptr} + {i} * {};", + size.format(POINTER_SIZE_EXPRESSION) + ); uwriteln!(self.src, "(void) base;"); uwrite!(self.src, "{body}"); uwriteln!(self.src, "}}"); @@ -3288,3 +3313,5 @@ pub fn to_c_ident(name: &str) -> String { s => s.to_snake_case(), } } + +const POINTER_SIZE_EXPRESSION: &str = "sizeof(void*)"; diff --git a/crates/core/src/abi.rs b/crates/core/src/abi.rs index 915af7018..a4fa35029 100644 --- a/crates/core/src/abi.rs +++ b/crates/core/src/abi.rs @@ -1,7 +1,8 @@ pub use wit_parser::abi::{AbiVariant, WasmSignature, WasmType}; use wit_parser::{ - ElementInfo, Enum, Flags, FlagsRepr, Function, Handle, Int, Record, Resolve, Result_, Results, - SizeAlign, Tuple, Type, TypeDefKind, TypeId, Variant, + align_to_arch, Alignment, ArchitectureSize, ElementInfo, Enum, Flags, FlagsRepr, Function, + Handle, Int, Record, Resolve, Result_, Results, SizeAlign, Tuple, Type, TypeDefKind, TypeId, + Variant, }; // Helper macro for defining instructions without having to have tons of @@ -86,67 +87,67 @@ def_instruction! { /// Pops a pointer from the stack and loads a little-endian `i32` from /// it, using the specified constant offset. - I32Load { offset: i32 } : [1] => [1], + I32Load { offset: ArchitectureSize } : [1] => [1], /// Pops a pointer from the stack and loads a little-endian `i8` from /// it, using the specified constant offset. The value loaded is the /// zero-extended to 32-bits - I32Load8U { offset: i32 } : [1] => [1], + I32Load8U { offset: ArchitectureSize } : [1] => [1], /// Pops a pointer from the stack and loads a little-endian `i8` from /// it, using the specified constant offset. The value loaded is the /// sign-extended to 32-bits - I32Load8S { offset: i32 } : [1] => [1], + I32Load8S { offset: ArchitectureSize } : [1] => [1], /// Pops a pointer from the stack and loads a little-endian `i16` from /// it, using the specified constant offset. The value loaded is the /// zero-extended to 32-bits - I32Load16U { offset: i32 } : [1] => [1], + I32Load16U { offset: ArchitectureSize } : [1] => [1], /// Pops a pointer from the stack and loads a little-endian `i16` from /// it, using the specified constant offset. The value loaded is the /// sign-extended to 32-bits - I32Load16S { offset: i32 } : [1] => [1], + I32Load16S { offset: ArchitectureSize } : [1] => [1], /// Pops a pointer from the stack and loads a little-endian `i64` from /// it, using the specified constant offset. - I64Load { offset: i32 } : [1] => [1], + I64Load { offset: ArchitectureSize } : [1] => [1], /// Pops a pointer from the stack and loads a little-endian `f32` from /// it, using the specified constant offset. - F32Load { offset: i32 } : [1] => [1], + F32Load { offset: ArchitectureSize } : [1] => [1], /// Pops a pointer from the stack and loads a little-endian `f64` from /// it, using the specified constant offset. - F64Load { offset: i32 } : [1] => [1], + F64Load { offset: ArchitectureSize } : [1] => [1], /// Like `I32Load` or `I64Load`, but for loading pointer values. - PointerLoad { offset: i32 } : [1] => [1], + PointerLoad { offset: ArchitectureSize } : [1] => [1], /// Like `I32Load` or `I64Load`, but for loading array length values. - LengthLoad { offset: i32 } : [1] => [1], + LengthLoad { offset: ArchitectureSize } : [1] => [1], /// Pops a pointer from the stack and then an `i32` value. /// Stores the value in little-endian at the pointer specified plus the /// constant `offset`. - I32Store { offset: i32 } : [2] => [0], + I32Store { offset: ArchitectureSize } : [2] => [0], /// Pops a pointer from the stack and then an `i32` value. /// Stores the low 8 bits of the value in little-endian at the pointer /// specified plus the constant `offset`. - I32Store8 { offset: i32 } : [2] => [0], + I32Store8 { offset: ArchitectureSize } : [2] => [0], /// Pops a pointer from the stack and then an `i32` value. /// Stores the low 16 bits of the value in little-endian at the pointer /// specified plus the constant `offset`. - I32Store16 { offset: i32 } : [2] => [0], + I32Store16 { offset: ArchitectureSize } : [2] => [0], /// Pops a pointer from the stack and then an `i64` value. /// Stores the value in little-endian at the pointer specified plus the /// constant `offset`. - I64Store { offset: i32 } : [2] => [0], + I64Store { offset: ArchitectureSize } : [2] => [0], /// Pops a pointer from the stack and then an `f32` value. /// Stores the value in little-endian at the pointer specified plus the /// constant `offset`. - F32Store { offset: i32 } : [2] => [0], + F32Store { offset: ArchitectureSize } : [2] => [0], /// Pops a pointer from the stack and then an `f64` value. /// Stores the value in little-endian at the pointer specified plus the /// constant `offset`. - F64Store { offset: i32 } : [2] => [0], + F64Store { offset: ArchitectureSize } : [2] => [0], /// Like `I32Store` or `I64Store`, but for storing pointer values. - PointerStore { offset: i32 } : [2] => [0], + PointerStore { offset: ArchitectureSize } : [2] => [0], /// Like `I32Store` or `I64Store`, but for storing array length values. - LengthStore { offset: i32 } : [2] => [0], + LengthStore { offset: ArchitectureSize } : [2] => [0], // Scalar lifting/lowering @@ -517,8 +518,8 @@ def_instruction! { /// Pushes the returned pointer onto the stack. Malloc { realloc: &'static str, - size: usize, - align: usize, + size: ArchitectureSize, + align: Alignment, } : [0] => [1], /// Used exclusively for guest-code generation this indicates that @@ -527,8 +528,8 @@ def_instruction! { /// /// This will pop a pointer from the stack and push nothing. GuestDeallocate { - size: usize, - align: usize, + size: ArchitectureSize, + align: Alignment, } : [1] => [0], /// Used exclusively for guest-code generation this indicates that @@ -561,13 +562,13 @@ def_instruction! { /// This cannot be allocated on the (shadow-)stack since it needs to /// remain valid until the callee has finished using the buffers, which /// may be after we pop the current stack frame. - AsyncMalloc { size: usize, align: usize } : [0] => [1], + AsyncMalloc { size: ArchitectureSize, align: Alignment } : [0] => [1], /// Call an async-lowered import. /// /// `size` and `align` are used to deallocate the parameter area /// allocated using `AsyncMalloc` after the callee task returns a value. - AsyncCallWasm { name: &'a str, size: usize, align: usize } : [2] => [0], + AsyncCallWasm { name: &'a str, size: ArchitectureSize, align: Alignment } : [2] => [0], /// Generate code to run after `CallInterface` for an async-lifted export. /// @@ -693,7 +694,7 @@ pub trait Bindgen { /// Gets a operand reference to the return pointer area. /// /// The provided size and alignment is for the function's return type. - fn return_pointer(&mut self, size: usize, align: usize) -> Self::Operand; + fn return_pointer(&mut self, size: ArchitectureSize, align: Alignment) -> Self::Operand; /// Enters a new block of code to generate code for. /// @@ -772,7 +773,7 @@ pub fn lower_to_memory( true, ); generator.stack.push(value); - generator.write_to_memory(ty, address, 0); + generator.write_to_memory(ty, address, Default::default()); } pub fn lift_from_memory( @@ -789,7 +790,7 @@ pub fn lift_from_memory( bindgen, true, ); - generator.read_from_memory(ty, address, 0); + generator.read_from_memory(ty, address, Default::default()); generator.stack.pop().unwrap() } @@ -905,12 +906,12 @@ impl<'a, B: Bindgen> Generator<'a, B> { } let lower_to_memory = |self_: &mut Self, ptr: B::Operand| { - let mut offset = 0usize; + let mut offset = ArchitectureSize::default(); for (nth, (_, ty)) in func.params.iter().enumerate() { self_.emit(&Instruction::GetArg { nth }); - offset = align_to(offset, self_.bindgen.sizes().align(ty).align_wasm32()); - self_.write_to_memory(ty, ptr.clone(), offset as i32); - offset += self_.bindgen.sizes().size(ty).size_wasm32(); + offset = align_to_arch(offset, self_.bindgen.sizes().align(ty)); + self_.write_to_memory(ty, ptr.clone(), offset); + offset += self_.bindgen.sizes().size(ty); } self_.stack.push(ptr); @@ -921,10 +922,7 @@ impl<'a, B: Bindgen> Generator<'a, B> { .bindgen .sizes() .record(func.params.iter().map(|(_, ty)| ty)); - self.emit(&Instruction::AsyncMalloc { - size: size.size_wasm32(), - align: align.align_wasm32(), - }); + self.emit(&Instruction::AsyncMalloc { size, align }); let ptr = self.stack.pop().unwrap(); lower_to_memory(self, ptr); Some((size, align)) @@ -941,23 +939,21 @@ impl<'a, B: Bindgen> Generator<'a, B> { // ... otherwise if parameters are indirect space is // allocated from them and each argument is lowered // individually into memory. - let info = self + let ElementInfo { size, align } = self .bindgen .sizes() .record(func.params.iter().map(|t| &t.1)); let ptr = match self.variant { // When a wasm module calls an import it will provide // space that isn't explicitly deallocated. - AbiVariant::GuestImport => self - .bindgen - .return_pointer(info.size.size_wasm32(), info.align.align_wasm32()), + AbiVariant::GuestImport => self.bindgen.return_pointer(size, align), // When calling a wasm module from the outside, though, // malloc needs to be called. AbiVariant::GuestExport => { self.emit(&Instruction::Malloc { realloc: "cabi_realloc", - size: info.size.size_wasm32(), - align: info.align.align_wasm32(), + size, + align, }); self.stack.pop().unwrap() } @@ -978,10 +974,7 @@ impl<'a, B: Bindgen> Generator<'a, B> { if let Some((params_size, params_align)) = params_size_align { let ElementInfo { size, align } = self.bindgen.sizes().record(func.results.iter_types()); - self.emit(&Instruction::AsyncMalloc { - size: size.size_wasm32(), - align: align.align_wasm32(), - }); + self.emit(&Instruction::AsyncMalloc { size, align }); let ptr = self.stack.pop().unwrap(); self.return_pointer = Some(ptr.clone()); self.stack.push(ptr); @@ -989,16 +982,15 @@ impl<'a, B: Bindgen> Generator<'a, B> { assert_eq!(self.stack.len(), 2); self.emit(&Instruction::AsyncCallWasm { name: &format!("[async]{}", func.name), - size: params_size.size_wasm32(), - align: params_align.align_wasm32(), + size: params_size, + align: params_align, }); Some((size, align)) } else { if self.variant == AbiVariant::GuestImport && sig.retptr { - let info = self.bindgen.sizes().params(func.results.iter_types()); - let ptr = self - .bindgen - .return_pointer(info.size.size_wasm32(), info.align.align_wasm32()); + let ElementInfo { size, align } = + self.bindgen.sizes().params(func.results.iter_types()); + let ptr = self.bindgen.return_pointer(size, align); self.return_pointer = Some(ptr.clone()); self.stack.push(ptr); } @@ -1042,17 +1034,18 @@ impl<'a, B: Bindgen> Generator<'a, B> { } }; - self.read_results_from_memory(&func.results, ptr.clone(), 0); + self.read_results_from_memory( + &func.results, + ptr.clone(), + ArchitectureSize::default(), + ); self.emit(&Instruction::Flush { amt: func.results.len(), }); if let Some((size, align)) = dealloc_size_align { self.stack.push(ptr); - self.emit(&Instruction::GuestDeallocate { - size: size.size_wasm32(), - align: align.align_wasm32(), - }); + self.emit(&Instruction::GuestDeallocate { size, align }); } } @@ -1067,15 +1060,15 @@ impl<'a, B: Bindgen> Generator<'a, B> { } let read_from_memory = |self_: &mut Self| { - let mut offset = 0usize; + let mut offset = ArchitectureSize::default(); let ptr = self_.stack.pop().unwrap(); for (_, ty) in func.params.iter() { - offset = align_to(offset, self_.bindgen.sizes().align(ty).align_wasm32()); - self_.read_from_memory(ty, ptr.clone(), offset as i32); - offset += self_.bindgen.sizes().size(ty).size_wasm32(); + offset = align_to_arch(offset, self_.bindgen.sizes().align(ty)); + self_.read_from_memory(ty, ptr.clone(), offset); + offset += self_.bindgen.sizes().size(ty); } }; - + if !sig.indirect_params { // If parameters are not passed indirectly then we lift each // argument in succession from the component wasm types that @@ -1122,15 +1115,12 @@ impl<'a, B: Bindgen> Generator<'a, B> { // deallocate it. if let AbiVariant::GuestExport = self.variant { if sig.indirect_params && !self.async_ { - let info = self + let ElementInfo { size, align } = self .bindgen .sizes() .record(func.params.iter().map(|t| &t.1)); self.emit(&Instruction::GetArg { nth: 0 }); - self.emit(&Instruction::GuestDeallocate { - size: info.size.size_wasm32(), - align: info.align.align_wasm32(), - }); + self.emit(&Instruction::GuestDeallocate { size, align }); } } @@ -1158,7 +1148,11 @@ impl<'a, B: Bindgen> Generator<'a, B> { nth: sig.params.len() - 1, }); let ptr = self.stack.pop().unwrap(); - self.write_params_to_memory(func.results.iter_types(), ptr, 0); + self.write_params_to_memory( + func.results.iter_types(), + ptr, + Default::default(), + ); } // For a guest import this is a function defined in @@ -1167,11 +1161,14 @@ impl<'a, B: Bindgen> Generator<'a, B> { // (statically) and then write the result into that // memory, returning the pointer at the end. AbiVariant::GuestExport => { - let info = self.bindgen.sizes().params(func.results.iter_types()); - let ptr = self - .bindgen - .return_pointer(info.size.size_wasm32(), info.align.align_wasm32()); - self.write_params_to_memory(func.results.iter_types(), ptr.clone(), 0); + let ElementInfo { size, align } = + self.bindgen.sizes().params(func.results.iter_types()); + let ptr = self.bindgen.return_pointer(size, align); + self.write_params_to_memory( + func.results.iter_types(), + ptr.clone(), + Default::default(), + ); self.stack.push(ptr); } @@ -1227,8 +1224,6 @@ impl<'a, B: Bindgen> Generator<'a, B> { .sizes() .field_offsets(func.results.iter_types()) { - let offset = offset.size_wasm32(); - let offset = i32::try_from(offset).unwrap(); self.deallocate(ty, addr.clone(), offset); } self.emit(&Instruction::Return { func, amt: 0 }); @@ -1314,7 +1309,7 @@ impl<'a, B: Bindgen> Generator<'a, B> { self.emit(&IterElem { element }); self.emit(&IterBasePointer); let addr = self.stack.pop().unwrap(); - self.write_to_memory(element, addr, 0); + self.write_to_memory(element, addr, Default::default()); self.finish_block(0); self.emit(&ListLower { element, realloc }); } @@ -1512,7 +1507,7 @@ impl<'a, B: Bindgen> Generator<'a, B> { self.push_block(); self.emit(&IterBasePointer); let addr = self.stack.pop().unwrap(); - self.read_from_memory(element, addr, 0); + self.read_from_memory(element, addr, Default::default()); self.finish_block(1); self.emit(&ListLift { element, ty: id }); } @@ -1657,7 +1652,7 @@ impl<'a, B: Bindgen> Generator<'a, B> { } } - fn write_to_memory(&mut self, ty: &Type, addr: B::Operand, offset: i32) { + fn write_to_memory(&mut self, ty: &Type, addr: B::Operand, offset: ArchitectureSize) { use Instruction::*; match *ty { @@ -1717,7 +1712,7 @@ impl<'a, B: Bindgen> Generator<'a, B> { for i in (0..n).rev() { self.stack.push(addr.clone()); self.emit(&I32Store { - offset: offset + (i as i32) * 4, + offset: offset.add_bytes(i * 4), }); } } @@ -1781,24 +1776,19 @@ impl<'a, B: Bindgen> Generator<'a, B> { &mut self, params: impl IntoIterator + ExactSizeIterator, addr: B::Operand, - offset: i32, + offset: ArchitectureSize, ) { self.write_fields_to_memory(params, addr, offset); } fn write_variant_arms_to_memory<'b>( &mut self, - offset: i32, + offset: ArchitectureSize, addr: B::Operand, tag: Int, cases: impl IntoIterator> + Clone, ) { - let payload_offset = offset - + (self - .bindgen - .sizes() - .payload_offset(tag, cases.clone()) - .size_wasm32() as i32); + let payload_offset = offset + (self.bindgen.sizes().payload_offset(tag, cases.clone())); for (i, ty) in cases.into_iter().enumerate() { self.push_block(); self.emit(&Instruction::VariantPayloadName); @@ -1814,13 +1804,15 @@ impl<'a, B: Bindgen> Generator<'a, B> { } } - fn write_list_to_memory(&mut self, ty: &Type, addr: B::Operand, offset: i32) { + fn write_list_to_memory(&mut self, ty: &Type, addr: B::Operand, offset: ArchitectureSize) { // After lowering the list there's two i32 values on the stack // which we write into memory, writing the pointer into the low address // and the length into the high address. self.lower(ty); self.stack.push(addr.clone()); - self.emit(&Instruction::LengthStore { offset: offset + 4 }); + self.emit(&Instruction::LengthStore { + offset: offset + self.bindgen.sizes().align(ty).into(), + }); self.stack.push(addr); self.emit(&Instruction::PointerStore { offset }); } @@ -1829,7 +1821,7 @@ impl<'a, B: Bindgen> Generator<'a, B> { &mut self, tys: impl IntoIterator + ExactSizeIterator, addr: B::Operand, - offset: i32, + offset: ArchitectureSize, ) { let fields = self .stack @@ -1843,8 +1835,7 @@ impl<'a, B: Bindgen> Generator<'a, B> { .zip(fields) { self.stack.push(op); - let field_offset = field_offset.size_wasm32(); - self.write_to_memory(ty, addr.clone(), offset + (field_offset as i32)); + self.write_to_memory(ty, addr.clone(), offset + (field_offset)); } } @@ -1854,7 +1845,7 @@ impl<'a, B: Bindgen> Generator<'a, B> { self.emit(instr); } - fn read_from_memory(&mut self, ty: &Type, addr: B::Operand, offset: i32) { + fn read_from_memory(&mut self, ty: &Type, addr: B::Operand, offset: ArchitectureSize) { use Instruction::*; match *ty { @@ -1914,7 +1905,7 @@ impl<'a, B: Bindgen> Generator<'a, B> { for i in 0..n { self.stack.push(addr.clone()); self.emit(&I32Load { - offset: offset + (i as i32) * 4, + offset: offset.add_bytes(i * 4), }); } } @@ -1966,25 +1957,25 @@ impl<'a, B: Bindgen> Generator<'a, B> { } } - fn read_results_from_memory(&mut self, results: &Results, addr: B::Operand, offset: i32) { + fn read_results_from_memory( + &mut self, + results: &Results, + addr: B::Operand, + offset: ArchitectureSize, + ) { self.read_fields_from_memory(results.iter_types(), addr, offset) } fn read_variant_arms_from_memory<'b>( &mut self, - offset: i32, + offset: ArchitectureSize, addr: B::Operand, tag: Int, cases: impl IntoIterator> + Clone, ) { self.stack.push(addr.clone()); self.load_intrepr(offset, tag); - let payload_offset = offset - + (self - .bindgen - .sizes() - .payload_offset(tag, cases.clone()) - .size_wasm32() as i32); + let payload_offset = offset + (self.bindgen.sizes().payload_offset(tag, cases.clone())); for ty in cases { self.push_block(); if let Some(ty) = ty { @@ -1994,13 +1985,15 @@ impl<'a, B: Bindgen> Generator<'a, B> { } } - fn read_list_from_memory(&mut self, ty: &Type, addr: B::Operand, offset: i32) { + fn read_list_from_memory(&mut self, ty: &Type, addr: B::Operand, offset: ArchitectureSize) { // Read the pointer/len and then perform the standard lifting // proceses. self.stack.push(addr.clone()); self.emit(&Instruction::PointerLoad { offset }); self.stack.push(addr); - self.emit(&Instruction::LengthLoad { offset: offset + 4 }); + self.emit(&Instruction::LengthLoad { + offset: offset + self.bindgen.sizes().align(ty).into(), + }); self.lift(ty); } @@ -2008,11 +2001,10 @@ impl<'a, B: Bindgen> Generator<'a, B> { &mut self, tys: impl IntoIterator, addr: B::Operand, - offset: i32, + offset: ArchitectureSize, ) { for (field_offset, ty) in self.bindgen.sizes().field_offsets(tys).iter() { - let field_offset = field_offset.size_wasm32(); - self.read_from_memory(ty, addr.clone(), offset + (field_offset as i32)); + self.read_from_memory(ty, addr.clone(), offset + (*field_offset)); } } @@ -2022,7 +2014,7 @@ impl<'a, B: Bindgen> Generator<'a, B> { self.lift(ty); } - fn load_intrepr(&mut self, offset: i32, repr: Int) { + fn load_intrepr(&mut self, offset: ArchitectureSize, repr: Int) { self.emit(&match repr { Int::U64 => Instruction::I64Load { offset }, Int::U32 => Instruction::I32Load { offset }, @@ -2031,7 +2023,7 @@ impl<'a, B: Bindgen> Generator<'a, B> { }); } - fn store_intrepr(&mut self, offset: i32, repr: Int) { + fn store_intrepr(&mut self, offset: ArchitectureSize, repr: Int) { self.emit(&match repr { Int::U64 => Instruction::I64Store { offset }, Int::U32 => Instruction::I32Store { offset }, @@ -2040,7 +2032,7 @@ impl<'a, B: Bindgen> Generator<'a, B> { }); } - fn deallocate(&mut self, ty: &Type, addr: B::Operand, offset: i32) { + fn deallocate(&mut self, ty: &Type, addr: B::Operand, offset: ArchitectureSize) { use Instruction::*; // No need to execute any instructions if this type itself doesn't @@ -2054,7 +2046,9 @@ impl<'a, B: Bindgen> Generator<'a, B> { self.stack.push(addr.clone()); self.emit(&Instruction::PointerLoad { offset }); self.stack.push(addr); - self.emit(&Instruction::LengthLoad { offset: offset + 4 }); + self.emit(&Instruction::LengthLoad { + offset: offset + self.bindgen.sizes().align(ty).into(), + }); self.emit(&Instruction::GuestDeallocateString); } @@ -2078,12 +2072,14 @@ impl<'a, B: Bindgen> Generator<'a, B> { self.stack.push(addr.clone()); self.emit(&Instruction::PointerLoad { offset }); self.stack.push(addr); - self.emit(&Instruction::LengthLoad { offset: offset + 4 }); + self.emit(&Instruction::LengthLoad { + offset: offset + self.bindgen.sizes().align(ty).into(), + }); self.push_block(); self.emit(&IterBasePointer); let elemaddr = self.stack.pop().unwrap(); - self.deallocate(element, elemaddr, 0); + self.deallocate(element, elemaddr, Default::default()); self.finish_block(0); self.emit(&Instruction::GuestDeallocateList { element }); @@ -2145,19 +2141,14 @@ impl<'a, B: Bindgen> Generator<'a, B> { fn deallocate_variant<'b>( &mut self, - offset: i32, + offset: ArchitectureSize, addr: B::Operand, tag: Int, cases: impl IntoIterator> + Clone, ) { self.stack.push(addr.clone()); self.load_intrepr(offset, tag); - let payload_offset = offset - + (self - .bindgen - .sizes() - .payload_offset(tag, cases.clone()) - .size_wasm32() as i32); + let payload_offset = offset + (self.bindgen.sizes().payload_offset(tag, cases.clone())); for ty in cases { self.push_block(); if let Some(ty) = ty { @@ -2167,10 +2158,9 @@ impl<'a, B: Bindgen> Generator<'a, B> { } } - fn deallocate_fields(&mut self, tys: &[Type], addr: B::Operand, offset: i32) { + fn deallocate_fields(&mut self, tys: &[Type], addr: B::Operand, offset: ArchitectureSize) { for (field_offset, ty) in self.bindgen.sizes().field_offsets(tys) { - let field_offset = field_offset.size_wasm32(); - self.deallocate(ty, addr.clone(), offset + (field_offset as i32)); + self.deallocate(ty, addr.clone(), offset + (field_offset)); } } } @@ -2230,7 +2220,3 @@ fn cast(from: WasmType, to: WasmType) -> Bitcast { } } } - -fn align_to(val: usize, align: usize) -> usize { - (val + align - 1) & !(align - 1) -} diff --git a/crates/csharp/src/function.rs b/crates/csharp/src/function.rs index bfdeb1b3e..7b89ee176 100644 --- a/crates/csharp/src/function.rs +++ b/crates/csharp/src/function.rs @@ -8,7 +8,10 @@ use std::ops::Deref; use wit_bindgen_core::abi::{Bindgen, Bitcast, Instruction}; use wit_bindgen_core::{uwrite, uwriteln, Direction, Ns}; use wit_parser::abi::WasmType; -use wit_parser::{Docs, FunctionKind, Handle, Resolve, SizeAlign, Type, TypeDefKind, TypeId}; +use wit_parser::{ + Alignment, ArchitectureSize, Docs, FunctionKind, Handle, Resolve, SizeAlign, Type, TypeDefKind, + TypeId, +}; /// FunctionBindgen generates the C# code for calling functions defined in wit pub(crate) struct FunctionBindgen<'a, 'b> { @@ -397,22 +400,22 @@ impl Bindgen for FunctionBindgen<'_, '_> { })), Instruction::I32Load { offset } | Instruction::PointerLoad { offset } - | Instruction::LengthLoad { offset } => results.push(format!("BitConverter.ToInt32(new Span((void*)({} + {offset}), 4))",operands[0])), - Instruction::I32Load8U { offset } => results.push(format!("new Span((void*)({} + {offset}), 1)[0]",operands[0])), - Instruction::I32Load8S { offset } => results.push(format!("(sbyte)new Span((void*)({} + {offset}), 1)[0]",operands[0])), - Instruction::I32Load16U { offset } => results.push(format!("BitConverter.ToUInt16(new Span((void*)({} + {offset}), 2))",operands[0])), - Instruction::I32Load16S { offset } => results.push(format!("BitConverter.ToInt16(new Span((void*)({} + {offset}), 2))",operands[0])), - Instruction::I64Load { offset } => results.push(format!("BitConverter.ToInt64(new Span((void*)({} + {offset}), 8))",operands[0])), - Instruction::F32Load { offset } => results.push(format!("BitConverter.ToSingle(new Span((void*)({} + {offset}), 4))",operands[0])), - Instruction::F64Load { offset } => results.push(format!("BitConverter.ToDouble(new Span((void*)({} + {offset}), 8))",operands[0])), + | Instruction::LengthLoad { offset } => results.push(format!("BitConverter.ToInt32(new Span((void*)({} + {offset}), 4))",operands[0],offset = offset.size_wasm32())), + Instruction::I32Load8U { offset } => results.push(format!("new Span((void*)({} + {offset}), 1)[0]",operands[0],offset = offset.size_wasm32())), + Instruction::I32Load8S { offset } => results.push(format!("(sbyte)new Span((void*)({} + {offset}), 1)[0]",operands[0],offset = offset.size_wasm32())), + Instruction::I32Load16U { offset } => results.push(format!("BitConverter.ToUInt16(new Span((void*)({} + {offset}), 2))",operands[0],offset = offset.size_wasm32())), + Instruction::I32Load16S { offset } => results.push(format!("BitConverter.ToInt16(new Span((void*)({} + {offset}), 2))",operands[0],offset = offset.size_wasm32())), + Instruction::I64Load { offset } => results.push(format!("BitConverter.ToInt64(new Span((void*)({} + {offset}), 8))",operands[0],offset = offset.size_wasm32())), + Instruction::F32Load { offset } => results.push(format!("BitConverter.ToSingle(new Span((void*)({} + {offset}), 4))",operands[0],offset = offset.size_wasm32())), + Instruction::F64Load { offset } => results.push(format!("BitConverter.ToDouble(new Span((void*)({} + {offset}), 8))",operands[0],offset = offset.size_wasm32())), Instruction::I32Store { offset } | Instruction::PointerStore { offset } - | Instruction::LengthStore { offset } => uwriteln!(self.src, "BitConverter.TryWriteBytes(new Span((void*)({} + {offset}), 4), {});", operands[1], operands[0]), - Instruction::I32Store8 { offset } => uwriteln!(self.src, "*(byte*)({} + {offset}) = (byte){};", operands[1], operands[0]), - Instruction::I32Store16 { offset } => uwriteln!(self.src, "BitConverter.TryWriteBytes(new Span((void*)({} + {offset}), 2), (short){});", operands[1], operands[0]), - Instruction::I64Store { offset } => uwriteln!(self.src, "BitConverter.TryWriteBytes(new Span((void*)({} + {offset}), 8), unchecked((long){}));", operands[1], operands[0]), - Instruction::F32Store { offset } => uwriteln!(self.src, "BitConverter.TryWriteBytes(new Span((void*)({} + {offset}), 4), unchecked((float){}));", operands[1], operands[0]), - Instruction::F64Store { offset } => uwriteln!(self.src, "BitConverter.TryWriteBytes(new Span((void*)({} + {offset}), 8), unchecked((double){}));", operands[1], operands[0]), + | Instruction::LengthStore { offset } => uwriteln!(self.src, "BitConverter.TryWriteBytes(new Span((void*)({} + {offset}), 4), {});", operands[1], operands[0],offset = offset.size_wasm32()), + Instruction::I32Store8 { offset } => uwriteln!(self.src, "*(byte*)({} + {offset}) = (byte){};", operands[1], operands[0],offset = offset.size_wasm32()), + Instruction::I32Store16 { offset } => uwriteln!(self.src, "BitConverter.TryWriteBytes(new Span((void*)({} + {offset}), 2), (short){});", operands[1], operands[0],offset = offset.size_wasm32()), + Instruction::I64Store { offset } => uwriteln!(self.src, "BitConverter.TryWriteBytes(new Span((void*)({} + {offset}), 8), unchecked((long){}));", operands[1], operands[0],offset = offset.size_wasm32()), + Instruction::F32Store { offset } => uwriteln!(self.src, "BitConverter.TryWriteBytes(new Span((void*)({} + {offset}), 4), unchecked((float){}));", operands[1], operands[0],offset = offset.size_wasm32()), + Instruction::F64Store { offset } => uwriteln!(self.src, "BitConverter.TryWriteBytes(new Span((void*)({} + {offset}), 8), unchecked((double){}));", operands[1], operands[0],offset = offset.size_wasm32()), Instruction::I64FromU64 => results.push(format!("unchecked((long)({}))", operands[0])), Instruction::I32FromChar => results.push(format!("((int){})", operands[0])), @@ -1206,15 +1209,16 @@ impl Bindgen for FunctionBindgen<'_, '_> { } } - fn return_pointer(&mut self, size: usize, align: usize) -> String { + fn return_pointer(&mut self, size: ArchitectureSize, align: Alignment) -> String { let ptr = self.locals.tmp("ptr"); match self.interface_gen.direction { Direction::Import => { self.import_return_pointer_area_size = - self.import_return_pointer_area_size.max(size); - self.import_return_pointer_area_align = - self.import_return_pointer_area_align.max(align); + self.import_return_pointer_area_size.max(size.size_wasm32()); + self.import_return_pointer_area_align = self + .import_return_pointer_area_align + .max(align.align_wasm32()); let (array_size, element_type) = crate::world_generator::dotnet_aligned_array( self.import_return_pointer_area_size, self.import_return_pointer_area_align, @@ -1230,16 +1234,23 @@ impl Bindgen for FunctionBindgen<'_, '_> { " var {ret_area} = stackalloc {element_type}[{array_size}+1]; var {ptr} = ((int){ret_area}) + ({align} - 1) & -{align}; - " + ", + align = align.align_wasm32() ); format!("{ptr}") } Direction::Export => { // exports need their return area to be live until the post-return call. - self.interface_gen.csharp_gen.return_area_size = - self.interface_gen.csharp_gen.return_area_size.max(size); - self.interface_gen.csharp_gen.return_area_align = - self.interface_gen.csharp_gen.return_area_align.max(align); + self.interface_gen.csharp_gen.return_area_size = self + .interface_gen + .csharp_gen + .return_area_size + .max(size.size_wasm32()); + self.interface_gen.csharp_gen.return_area_align = self + .interface_gen + .csharp_gen + .return_area_align + .max(align.align_wasm32()); uwrite!( self.src, diff --git a/crates/moonbit/src/lib.rs b/crates/moonbit/src/lib.rs index 5f64e6fd9..95dc64301 100644 --- a/crates/moonbit/src/lib.rs +++ b/crates/moonbit/src/lib.rs @@ -6,9 +6,9 @@ use wit_bindgen_core::{ abi::{self, AbiVariant, Bindgen, Bitcast, Instruction, LiftLower, WasmType}, dealias, uwrite, uwriteln, wit_parser::{ - Docs, Enum, Flags, FlagsRepr, Function, FunctionKind, Handle, Int, InterfaceId, Record, - Resolve, Result_, SizeAlign, Tuple, Type, TypeDef, TypeDefKind, TypeId, TypeOwner, Variant, - WorldId, WorldKey, + Alignment, ArchitectureSize, Docs, Enum, Flags, FlagsRepr, Function, FunctionKind, Handle, + Int, InterfaceId, Record, Resolve, Result_, SizeAlign, Tuple, Type, TypeDef, TypeDefKind, + TypeId, TypeOwner, Variant, WorldId, WorldKey, }, Direction, Files, InterfaceGenerator as _, Ns, Source, WorldGenerator, }; @@ -280,8 +280,8 @@ pub struct MoonBit { export: HashMap, export_ns: Ns, // return area allocation - return_area_size: usize, - return_area_align: usize, + return_area_size: ArchitectureSize, + return_area_align: Alignment, } impl MoonBit { @@ -615,13 +615,13 @@ impl WorldGenerator for MoonBit { }} " ); - if self.return_area_size != 0 { + if !self.return_area_size.is_empty() { uwriteln!( &mut body, " let return_area : Int = {ffi_qualifier}malloc({}) ", - self.return_area_size, + self.return_area_size.size_wasm32(), ); } files.push( @@ -2499,49 +2499,57 @@ impl Bindgen for FunctionBindgen<'_, '_> { | Instruction::LengthLoad { offset } => results.push(format!( "{}load32(({}) + {offset})", self.gen.qualify_package(FFI_DIR), - operands[0] + operands[0], + offset = offset.size_wasm32() )), Instruction::I32Load8U { offset } => results.push(format!( "{}load8_u(({}) + {offset})", self.gen.qualify_package(FFI_DIR), - operands[0] + operands[0], + offset = offset.size_wasm32() )), Instruction::I32Load8S { offset } => results.push(format!( "{}load8(({}) + {offset})", self.gen.qualify_package(FFI_DIR), - operands[0] + operands[0], + offset = offset.size_wasm32() )), Instruction::I32Load16U { offset } => results.push(format!( "{}load16_u(({}) + {offset})", self.gen.qualify_package(FFI_DIR), - operands[0] + operands[0], + offset = offset.size_wasm32() )), Instruction::I32Load16S { offset } => results.push(format!( "{}load16(({}) + {offset})", self.gen.qualify_package(FFI_DIR), - operands[0] + operands[0], + offset = offset.size_wasm32() )), Instruction::I64Load { offset } => results.push(format!( "{}load64(({}) + {offset})", self.gen.qualify_package(FFI_DIR), - operands[0] + operands[0], + offset = offset.size_wasm32() )), Instruction::F32Load { offset } => results.push(format!( "{}loadf32(({}) + {offset})", self.gen.qualify_package(FFI_DIR), - operands[0] + operands[0], + offset = offset.size_wasm32() )), Instruction::F64Load { offset } => results.push(format!( "{}loadf64(({}) + {offset})", self.gen.qualify_package(FFI_DIR), - operands[0] + operands[0], + offset = offset.size_wasm32() )), Instruction::I32Store { offset } @@ -2551,7 +2559,8 @@ impl Bindgen for FunctionBindgen<'_, '_> { "{}store32(({}) + {offset}, {})", self.gen.qualify_package(FFI_DIR), operands[1], - operands[0] + operands[0], + offset = offset.size_wasm32() ), Instruction::I32Store8 { offset } => uwriteln!( @@ -2559,7 +2568,8 @@ impl Bindgen for FunctionBindgen<'_, '_> { "{}store8(({}) + {offset}, {})", self.gen.qualify_package(FFI_DIR), operands[1], - operands[0] + operands[0], + offset = offset.size_wasm32() ), Instruction::I32Store16 { offset } => uwriteln!( @@ -2567,7 +2577,8 @@ impl Bindgen for FunctionBindgen<'_, '_> { "{}store16(({}) + {offset}, {})", self.gen.qualify_package(FFI_DIR), operands[1], - operands[0] + operands[0], + offset = offset.size_wasm32() ), Instruction::I64Store { offset } => uwriteln!( @@ -2575,7 +2586,8 @@ impl Bindgen for FunctionBindgen<'_, '_> { "{}store64(({}) + {offset}, {})", self.gen.qualify_package(FFI_DIR), operands[1], - operands[0] + operands[0], + offset = offset.size_wasm32() ), Instruction::F32Store { offset } => uwriteln!( @@ -2583,7 +2595,8 @@ impl Bindgen for FunctionBindgen<'_, '_> { "{}storef32(({}) + {offset}, {})", self.gen.qualify_package(FFI_DIR), operands[1], - operands[0] + operands[0], + offset = offset.size_wasm32() ), Instruction::F64Store { offset } => uwriteln!( @@ -2591,7 +2604,8 @@ impl Bindgen for FunctionBindgen<'_, '_> { "{}storef64(({}) + {offset}, {})", self.gen.qualify_package(FFI_DIR), operands[1], - operands[0] + operands[0], + offset = offset.size_wasm32() ), // TODO: see what we can do with align Instruction::Malloc { size, .. } => { @@ -2599,7 +2613,7 @@ impl Bindgen for FunctionBindgen<'_, '_> { self.src, "{}malloc({})", self.gen.qualify_package(FFI_DIR), - size + size.size_wasm32() ) } @@ -2707,15 +2721,19 @@ impl Bindgen for FunctionBindgen<'_, '_> { } } - fn return_pointer(&mut self, size: usize, align: usize) -> String { + fn return_pointer(&mut self, size: ArchitectureSize, align: Alignment) -> String { if self.gen.direction == Direction::Import { let ffi_qualifier = self.gen.qualify_package(FFI_DIR); let address = self.locals.tmp("return_area"); - uwriteln!(self.src, "let {address} = {ffi_qualifier}malloc({})", size,); + uwriteln!( + self.src, + "let {address} = {ffi_qualifier}malloc({})", + size.size_wasm32(), + ); self.cleanup.push(Cleanup::Memory { address: address.clone(), - size: size.to_string(), - align, + size: size.size_wasm32().to_string(), + align: align.align_wasm32(), }); address } else { diff --git a/crates/rust/src/bindgen.rs b/crates/rust/src/bindgen.rs index a0f47889a..0a6bc8333 100644 --- a/crates/rust/src/bindgen.rs +++ b/crates/rust/src/bindgen.rs @@ -16,14 +16,16 @@ pub(super) struct FunctionBindgen<'a, 'b> { tmp: usize, pub needs_cleanup_list: bool, cleanup: Vec<(String, String)>, - pub import_return_pointer_area_size: usize, - pub import_return_pointer_area_align: usize, + pub import_return_pointer_area_size: ArchitectureSize, + pub import_return_pointer_area_align: Alignment, pub handle_decls: Vec, always_owned: bool, pub async_result_name: Option, emitted_cleanup: bool, } +pub const POINTER_SIZE_EXPRESSION: &str = "core::mem::size_of::<*const u8>()"; + impl<'a, 'b> FunctionBindgen<'a, 'b> { pub(super) fn new( gen: &'b mut InterfaceGenerator<'a>, @@ -43,8 +45,8 @@ impl<'a, 'b> FunctionBindgen<'a, 'b> { tmp: 0, needs_cleanup_list: false, cleanup: Vec::new(), - import_return_pointer_area_size: 0, - import_return_pointer_area_align: 0, + import_return_pointer_area_size: Default::default(), + import_return_pointer_area_align: Default::default(), handle_decls: Vec::new(), always_owned, async_result_name: None, @@ -271,7 +273,7 @@ impl Bindgen for FunctionBindgen<'_, '_> { } } - fn return_pointer(&mut self, size: usize, align: usize) -> String { + fn return_pointer(&mut self, size: ArchitectureSize, align: Alignment) -> String { let tmp = self.tmp(); // Imports get a per-function return area to facilitate using the @@ -793,10 +795,11 @@ impl Bindgen for FunctionBindgen<'_, '_> { operand0 = operands[0] )); self.push_str(&format!("let {len} = {vec}.len();\n")); - let size = self.gen.sizes.size(element).size_wasm32(); - let align = self.gen.sizes.align(element).align_wasm32(); + let size = self.gen.sizes.size(element); + let align = self.gen.sizes.align(element); self.push_str(&format!( - "let {layout} = {alloc}::Layout::from_size_align_unchecked({vec}.len() * {size}, {align});\n", + "let {layout} = {alloc}::Layout::from_size_align_unchecked({vec}.len() * {}, {});\n", + size.format(POINTER_SIZE_EXPRESSION), align.format(POINTER_SIZE_EXPRESSION), )); self.push_str(&format!("let {result} = if {layout}.size() != 0 {{\n")); self.push_str(&format!( @@ -807,7 +810,10 @@ impl Bindgen for FunctionBindgen<'_, '_> { )); self.push_str("else {\n::core::ptr::null_mut()\n};\n"); self.push_str(&format!("for (i, e) in {vec}.into_iter().enumerate() {{\n",)); - self.push_str(&format!("let base = {result}.add(i * {size});\n",)); + self.push_str(&format!( + "let base = {result}.add(i * {});\n", + size.format(POINTER_SIZE_EXPRESSION) + )); self.push_str(&body); self.push_str("\n}\n"); results.push(format!("{result}")); @@ -824,8 +830,8 @@ impl Bindgen for FunctionBindgen<'_, '_> { Instruction::ListLift { element, .. } => { let body = self.blocks.pop().unwrap(); let tmp = self.tmp(); - let size = self.gen.sizes.size(element).size_wasm32(); - let align = self.gen.sizes.align(element).align_wasm32(); + let size = self.gen.sizes.size(element); + let align = self.gen.sizes.align(element); let len = format!("len{tmp}"); let base = format!("base{tmp}"); let result = format!("result{tmp}"); @@ -843,13 +849,21 @@ impl Bindgen for FunctionBindgen<'_, '_> { )); uwriteln!(self.src, "for i in 0..{len} {{"); - uwriteln!(self.src, "let base = {base}.add(i * {size});"); + uwriteln!( + self.src, + "let base = {base}.add(i * {size});", + size = size.format(POINTER_SIZE_EXPRESSION) + ); uwriteln!(self.src, "let e{tmp} = {body};"); uwriteln!(self.src, "{result}.push(e{tmp});"); uwriteln!(self.src, "}}"); results.push(result); let dealloc = self.gen.path_to_cabi_dealloc(); - self.push_str(&format!("{dealloc}({base}, {len} * {size}, {align});\n",)); + self.push_str(&format!( + "{dealloc}({base}, {len} * {size}, {align});\n", + size = size.format(POINTER_SIZE_EXPRESSION), + align = align.format(POINTER_SIZE_EXPRESSION) + )); } Instruction::IterElem { .. } => results.push("e".to_string()), @@ -879,6 +893,8 @@ impl Bindgen for FunctionBindgen<'_, '_> { let alloc = self.gen.path_to_std_alloc_module(); self.push_str(&format!( "let {layout} = {alloc}::Layout::from_size_align_unchecked({size}, {align});\n", + size = size.format(POINTER_SIZE_EXPRESSION), + align = align.format(POINTER_SIZE_EXPRESSION) )); let operands = operands.join(", "); uwriteln!( @@ -956,7 +972,9 @@ impl Bindgen for FunctionBindgen<'_, '_> { uwriteln!( self.src, "let {layout} = {alloc}::Layout::from_size_align_unchecked({size}, {align}); - let {ptr} = {alloc}::alloc({layout});" + let {ptr} = {alloc}::alloc({layout});", + size = size.format(POINTER_SIZE_EXPRESSION), + align = align.format(POINTER_SIZE_EXPRESSION) ); results.push(ptr); } @@ -1048,7 +1066,8 @@ impl Bindgen for FunctionBindgen<'_, '_> { uwriteln!( self.src, "let l{tmp} = *{}.add({offset}).cast::();", - operands[0] + operands[0], + offset = offset.format_term(POINTER_SIZE_EXPRESSION, true) ); results.push(format!("l{tmp}")); } @@ -1057,7 +1076,8 @@ impl Bindgen for FunctionBindgen<'_, '_> { uwriteln!( self.src, "let l{tmp} = i32::from(*{0}.add({offset}).cast::());", - operands[0] + operands[0], + offset = offset.format_term(POINTER_SIZE_EXPRESSION, true) ); results.push(format!("l{tmp}")); } @@ -1066,7 +1086,8 @@ impl Bindgen for FunctionBindgen<'_, '_> { uwriteln!( self.src, "let l{tmp} = i32::from(*{}.add({offset}).cast::());", - operands[0] + operands[0], + offset = offset.format_term(POINTER_SIZE_EXPRESSION, true) ); results.push(format!("l{tmp}")); } @@ -1075,7 +1096,8 @@ impl Bindgen for FunctionBindgen<'_, '_> { uwriteln!( self.src, "let l{tmp} = i32::from(*{}.add({offset}).cast::());", - operands[0] + operands[0], + offset = offset.format_term(POINTER_SIZE_EXPRESSION, true) ); results.push(format!("l{tmp}")); } @@ -1084,7 +1106,8 @@ impl Bindgen for FunctionBindgen<'_, '_> { uwriteln!( self.src, "let l{tmp} = i32::from(*{}.add({offset}).cast::());", - operands[0] + operands[0], + offset = offset.format_term(POINTER_SIZE_EXPRESSION, true) ); results.push(format!("l{tmp}")); } @@ -1093,7 +1116,8 @@ impl Bindgen for FunctionBindgen<'_, '_> { uwriteln!( self.src, "let l{tmp} = *{}.add({offset}).cast::();", - operands[0] + operands[0], + offset = offset.format_term(POINTER_SIZE_EXPRESSION, true) ); results.push(format!("l{tmp}")); } @@ -1102,7 +1126,8 @@ impl Bindgen for FunctionBindgen<'_, '_> { uwriteln!( self.src, "let l{tmp} = *{}.add({offset}).cast::();", - operands[0] + operands[0], + offset = offset.format_term(POINTER_SIZE_EXPRESSION, true) ); results.push(format!("l{tmp}")); } @@ -1111,7 +1136,8 @@ impl Bindgen for FunctionBindgen<'_, '_> { uwriteln!( self.src, "let l{tmp} = *{}.add({offset}).cast::();", - operands[0] + operands[0], + offset = offset.format_term(POINTER_SIZE_EXPRESSION, true) ); results.push(format!("l{tmp}")); } @@ -1121,7 +1147,8 @@ impl Bindgen for FunctionBindgen<'_, '_> { uwriteln!( self.src, "let l{tmp} = *{}.add({offset}).cast::<*mut u8>();", - operands[0] + operands[0], + offset = offset.format_term(POINTER_SIZE_EXPRESSION, true) ); results.push(format!("l{tmp}")); } @@ -1129,8 +1156,9 @@ impl Bindgen for FunctionBindgen<'_, '_> { let tmp = self.tmp(); uwriteln!( self.src, - "let l{tmp} = *{}.add({offset}).cast::();", - operands[0] + "let l{tmp} = *{}.add({}).cast::();", + operands[0], + offset.format_term(POINTER_SIZE_EXPRESSION, true) ); results.push(format!("l{tmp}")); } @@ -1138,50 +1166,66 @@ impl Bindgen for FunctionBindgen<'_, '_> { Instruction::I32Store { offset } => { self.push_str(&format!( "*{}.add({}).cast::() = {};\n", - operands[1], offset, operands[0] + operands[1], + offset.format_term(POINTER_SIZE_EXPRESSION, true), + operands[0] )); } Instruction::I32Store8 { offset } => { self.push_str(&format!( "*{}.add({}).cast::() = ({}) as u8;\n", - operands[1], offset, operands[0] + operands[1], + offset.format_term(POINTER_SIZE_EXPRESSION, true), + operands[0] )); } Instruction::I32Store16 { offset } => { self.push_str(&format!( "*{}.add({}).cast::() = ({}) as u16;\n", - operands[1], offset, operands[0] + operands[1], + offset.format_term(POINTER_SIZE_EXPRESSION, true), + operands[0] )); } Instruction::I64Store { offset } => { self.push_str(&format!( "*{}.add({}).cast::() = {};\n", - operands[1], offset, operands[0] + operands[1], + offset.format_term(POINTER_SIZE_EXPRESSION, true), + operands[0] )); } Instruction::F32Store { offset } => { self.push_str(&format!( "*{}.add({}).cast::() = {};\n", - operands[1], offset, operands[0] + operands[1], + offset.format_term(POINTER_SIZE_EXPRESSION, true), + operands[0] )); } Instruction::F64Store { offset } => { self.push_str(&format!( "*{}.add({}).cast::() = {};\n", - operands[1], offset, operands[0] + operands[1], + offset.format_term(POINTER_SIZE_EXPRESSION, true), + operands[0] )); } Instruction::PointerStore { offset } => { self.push_str(&format!( "*{}.add({}).cast::<*mut u8>() = {};\n", - operands[1], offset, operands[0] + operands[1], + offset.format_term(POINTER_SIZE_EXPRESSION, true), + operands[0] )); } Instruction::LengthStore { offset } => { self.push_str(&format!( "*{}.add({}).cast::() = {};\n", - operands[1], offset, operands[0] + operands[1], + offset.format_term(POINTER_SIZE_EXPRESSION, true), + operands[0] )); } @@ -1191,7 +1235,9 @@ impl Bindgen for FunctionBindgen<'_, '_> { let dealloc = self.gen.path_to_cabi_dealloc(); self.push_str(&format!( "{dealloc}({op}, {size}, {align});\n", - op = operands[0] + op = operands[0], + size = size.format_term(POINTER_SIZE_EXPRESSION, true), + align = align.format(POINTER_SIZE_EXPRESSION) )); } @@ -1226,8 +1272,8 @@ impl Bindgen for FunctionBindgen<'_, '_> { Instruction::GuestDeallocateList { element } => { let body = self.blocks.pop().unwrap(); let tmp = self.tmp(); - let size = self.gen.sizes.size(element).size_wasm32(); - let align = self.gen.sizes.align(element).align_wasm32(); + let size = self.gen.sizes.size(element); + let align = self.gen.sizes.align(element); let len = format!("len{tmp}"); let base = format!("base{tmp}"); self.push_str(&format!( @@ -1246,13 +1292,17 @@ impl Bindgen for FunctionBindgen<'_, '_> { self.push_str("let base = "); self.push_str(&base); self.push_str(".add(i * "); - self.push_str(&size.to_string()); + self.push_str(&size.format(POINTER_SIZE_EXPRESSION)); self.push_str(");\n"); self.push_str(&body); self.push_str("\n}\n"); } let dealloc = self.gen.path_to_cabi_dealloc(); - self.push_str(&format!("{dealloc}({base}, {len} * {size}, {align});\n",)); + self.push_str(&format!( + "{dealloc}({base}, {len} * {size}, {align});\n", + size = size.format(POINTER_SIZE_EXPRESSION), + align = align.format(POINTER_SIZE_EXPRESSION) + )); } } } diff --git a/crates/rust/src/interface.rs b/crates/rust/src/interface.rs index 93af07d98..f10d584f4 100644 --- a/crates/rust/src/interface.rs +++ b/crates/rust/src/interface.rs @@ -1,4 +1,4 @@ -use crate::bindgen::FunctionBindgen; +use crate::bindgen::{FunctionBindgen, POINTER_SIZE_EXPRESSION}; use crate::{ int_repr, to_rust_ident, to_upper_camel_case, wasm_type, AsyncConfig, FnSig, Identifier, InterfaceName, Ownership, RuntimeItem, RustFlagsRepr, RustWasm, @@ -21,8 +21,8 @@ pub struct InterfaceGenerator<'a> { pub(super) gen: &'a mut RustWasm, pub wasm_import_module: &'a str, pub resolve: &'a Resolve, - pub return_pointer_area_size: usize, - pub return_pointer_area_align: usize, + pub return_pointer_area_size: ArchitectureSize, + pub return_pointer_area_align: Alignment, pub(super) needs_runtime_module: bool, } @@ -381,17 +381,29 @@ macro_rules! {macro_name} {{ } } + pub fn align_area(&mut self, alignment: Alignment) { + match alignment { + Alignment::Pointer => uwriteln!( + self.src, + "#[cfg_attr(target_pointer_width=\"64\", repr(align(8)))] + #[cfg_attr(target_pointer_width=\"32\", repr(align(4)))]" + ), + Alignment::Bytes(bytes) => { + uwriteln!(self.src, "#[repr(align({align}))]", align = bytes.get()) + } + } + } + pub fn finish(&mut self) -> String { - if self.return_pointer_area_align > 0 { + if !self.return_pointer_area_size.is_empty() { + uwriteln!(self.src,); + self.align_area(self.return_pointer_area_align); uwrite!( self.src, - "\ - #[repr(align({align}))] - struct _RetArea([::core::mem::MaybeUninit::; {size}]); + "struct _RetArea([::core::mem::MaybeUninit::; {size}]); static mut _RET_AREA: _RetArea = _RetArea([::core::mem::MaybeUninit::uninit(); {size}]); ", - align = self.return_pointer_area_align, - size = self.return_pointer_area_size, + size = self.return_pointer_area_size.format_term(POINTER_SIZE_EXPRESSION, true), ); } @@ -1041,14 +1053,14 @@ pub mod vtable{ordinal} {{ uwriteln!(self.src, "let mut cleanup_list = {vec}::new();"); } assert!(handle_decls.is_empty()); - if import_return_pointer_area_size > 0 { + if !import_return_pointer_area_size.is_empty() { + uwriteln!(self.src,); + self.align_area(import_return_pointer_area_align); uwrite!( self.src, - "\ - #[repr(align({import_return_pointer_area_align}))] - struct RetArea([::core::mem::MaybeUninit::; {import_return_pointer_area_size}]); + "struct RetArea([::core::mem::MaybeUninit::; {import_return_pointer_area_size}]); let mut ret_area = RetArea([::core::mem::MaybeUninit::uninit(); {import_return_pointer_area_size}]); -", +", import_return_pointer_area_size = import_return_pointer_area_size.format_term(POINTER_SIZE_EXPRESSION, true) ); } self.src.push_str(&String::from(src)); diff --git a/crates/rust/src/lib.rs b/crates/rust/src/lib.rs index 0137974ec..ff185e8b5 100644 --- a/crates/rust/src/lib.rs +++ b/crates/rust/src/lib.rs @@ -330,8 +330,8 @@ impl RustWasm { gen: self, sizes, resolve, - return_pointer_area_size: 0, - return_pointer_area_align: 0, + return_pointer_area_size: Default::default(), + return_pointer_area_align: Default::default(), needs_runtime_module: false, } } diff --git a/crates/teavm-java/src/lib.rs b/crates/teavm-java/src/lib.rs index 53d498fad..4552292ed 100644 --- a/crates/teavm-java/src/lib.rs +++ b/crates/teavm-java/src/lib.rs @@ -10,9 +10,9 @@ use wit_bindgen_core::{ abi::{self, AbiVariant, Bindgen, Bitcast, Instruction, LiftLower, WasmType}, uwrite, uwriteln, wit_parser::{ - Docs, Enum, Flags, FlagsRepr, Function, FunctionKind, Int, InterfaceId, Record, Resolve, - Result_, SizeAlign, Tuple, Type, TypeDef, TypeDefKind, TypeId, TypeOwner, Variant, WorldId, - WorldKey, + Alignment, ArchitectureSize, Docs, Enum, Flags, FlagsRepr, Function, FunctionKind, Int, + InterfaceId, Record, Resolve, Result_, SizeAlign, Tuple, Type, TypeDef, TypeDefKind, + TypeId, TypeOwner, Variant, WorldId, WorldKey, }, Direction, Files, InterfaceGenerator as _, Ns, Source, WorldGenerator, }; @@ -53,8 +53,8 @@ struct InterfaceFragment { pub struct TeaVmJava { opts: Opts, name: String, - return_area_size: usize, - return_area_align: usize, + return_area_size: ArchitectureSize, + return_area_align: Alignment, tuple_counts: HashSet, needs_cleanup: bool, needs_result: bool, @@ -345,9 +345,9 @@ impl WorldGenerator for TeaVmJava { ); } - if self.return_area_align > 0 { - let size = self.return_area_size; - let align = self.return_area_align; + if !self.return_area_size.is_empty() { + let size = self.return_area_size.size_wasm32(); + let align = self.return_area_align.align_wasm32(); uwriteln!( src, @@ -1684,8 +1684,8 @@ impl Bindgen for FunctionBindgen<'_, '_> { assert!(block_results.is_empty()); let op = &operands[0]; - let size = self.gen.gen.sizes.size(element).size_wasm32(); - let align = self.gen.gen.sizes.align(element).align_wasm32(); + let size = self.gen.gen.sizes.size(element); + let align = self.gen.gen.sizes.align(element); let address = self.locals.tmp("address"); let ty = self.gen.type_name(element); let index = self.locals.tmp("index"); @@ -1699,14 +1699,16 @@ impl Bindgen for FunctionBindgen<'_, '_> { int {base} = {address} + ({index} * {size}); {body} }} - " + ", + align = align.align_wasm32(), + size = size.size_wasm32() ); if realloc.is_none() { self.cleanup.push(Cleanup { address: address.clone(), - size: format!("({op}).size() * {size}"), - align, + size: format!("({op}).size() * {size}", size = size.size_wasm32()), + align: align.align_wasm32(), }); } @@ -1882,42 +1884,50 @@ impl Bindgen for FunctionBindgen<'_, '_> { | Instruction::PointerLoad { offset } | Instruction::LengthLoad { offset } => results.push(format!( "org.teavm.interop.Address.fromInt(({}) + {offset}).getInt()", - operands[0] + operands[0], + offset = offset.size_wasm32() )), Instruction::I32Load8U { offset } => results.push(format!( "(((int) org.teavm.interop.Address.fromInt(({}) + {offset}).getByte()) & 0xFF)", - operands[0] + operands[0], + offset = offset.size_wasm32() )), Instruction::I32Load8S { offset } => results.push(format!( "((int) org.teavm.interop.Address.fromInt(({}) + {offset}).getByte())", - operands[0] + operands[0], + offset = offset.size_wasm32() )), Instruction::I32Load16U { offset } => results.push(format!( "(((int) org.teavm.interop.Address.fromInt(({}) + {offset}).getShort()) & 0xFFFF)", - operands[0] + operands[0], + offset = offset.size_wasm32() )), Instruction::I32Load16S { offset } => results.push(format!( "((int) org.teavm.interop.Address.fromInt(({}) + {offset}).getShort())", - operands[0] + operands[0], + offset = offset.size_wasm32() )), Instruction::I64Load { offset } => results.push(format!( "org.teavm.interop.Address.fromInt(({}) + {offset}).getLong()", - operands[0] + operands[0], + offset = offset.size_wasm32() )), Instruction::F32Load { offset } => results.push(format!( "org.teavm.interop.Address.fromInt(({}) + {offset}).getFloat()", - operands[0] + operands[0], + offset = offset.size_wasm32() )), Instruction::F64Load { offset } => results.push(format!( "org.teavm.interop.Address.fromInt(({}) + {offset}).getDouble()", - operands[0] + operands[0], + offset = offset.size_wasm32() )), Instruction::I32Store { offset } @@ -1926,42 +1936,48 @@ impl Bindgen for FunctionBindgen<'_, '_> { self.src, "org.teavm.interop.Address.fromInt(({}) + {offset}).putInt({});", operands[1], - operands[0] + operands[0], + offset = offset.size_wasm32() ), Instruction::I32Store8 { offset } => uwriteln!( self.src, "org.teavm.interop.Address.fromInt(({}) + {offset}).putByte((byte) ({}));", operands[1], - operands[0] + operands[0], + offset = offset.size_wasm32() ), Instruction::I32Store16 { offset } => uwriteln!( self.src, "org.teavm.interop.Address.fromInt(({}) + {offset}).putShort((short) ({}));", operands[1], - operands[0] + operands[0], + offset = offset.size_wasm32() ), Instruction::I64Store { offset } => uwriteln!( self.src, "org.teavm.interop.Address.fromInt(({}) + {offset}).putLong({});", operands[1], - operands[0] + operands[0], + offset = offset.size_wasm32() ), Instruction::F32Store { offset } => uwriteln!( self.src, "org.teavm.interop.Address.fromInt(({}) + {offset}).putFloat({});", operands[1], - operands[0] + operands[0], + offset = offset.size_wasm32() ), Instruction::F64Store { offset } => uwriteln!( self.src, "org.teavm.interop.Address.fromInt(({}) + {offset}).putDouble({});", operands[1], - operands[0] + operands[0], + offset = offset.size_wasm32() ), Instruction::Malloc { .. } => unimplemented!(), @@ -1970,7 +1986,9 @@ impl Bindgen for FunctionBindgen<'_, '_> { uwriteln!( self.src, "Memory.free(org.teavm.interop.Address.fromInt({}), {size}, {align});", - operands[0] + operands[0], + size = size.size_wasm32(), + align = align.align_wasm32() ) } @@ -2063,7 +2081,7 @@ impl Bindgen for FunctionBindgen<'_, '_> { } } - fn return_pointer(&mut self, size: usize, align: usize) -> String { + fn return_pointer(&mut self, size: ArchitectureSize, align: Alignment) -> String { self.gen.gen.return_area_size = self.gen.gen.return_area_size.max(size); self.gen.gen.return_area_align = self.gen.gen.return_area_align.max(align); format!("{}RETURN_AREA", self.gen.gen.qualifier()) From 669e2f784213797cd78606779363c71aa6e7e6fd Mon Sep 17 00:00:00 2001 From: Christof Petig Date: Tue, 11 Feb 2025 17:52:12 +0100 Subject: [PATCH 2/3] prefer absolute path for core crate --- crates/rust/src/bindgen.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crates/rust/src/bindgen.rs b/crates/rust/src/bindgen.rs index 0a6bc8333..67a471199 100644 --- a/crates/rust/src/bindgen.rs +++ b/crates/rust/src/bindgen.rs @@ -24,7 +24,7 @@ pub(super) struct FunctionBindgen<'a, 'b> { emitted_cleanup: bool, } -pub const POINTER_SIZE_EXPRESSION: &str = "core::mem::size_of::<*const u8>()"; +pub const POINTER_SIZE_EXPRESSION: &str = "::core::mem::size_of::<*const u8>()"; impl<'a, 'b> FunctionBindgen<'a, 'b> { pub(super) fn new( From fd9c9832bf8b938ae609ba7ca50f35832af58d83 Mon Sep 17 00:00:00 2001 From: Christof Petig Date: Tue, 11 Feb 2025 18:06:11 +0100 Subject: [PATCH 3/3] fix rustfmt mistake created by merge tool --- crates/core/src/abi.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crates/core/src/abi.rs b/crates/core/src/abi.rs index a4fa35029..2c8883663 100644 --- a/crates/core/src/abi.rs +++ b/crates/core/src/abi.rs @@ -1068,7 +1068,7 @@ impl<'a, B: Bindgen> Generator<'a, B> { offset += self_.bindgen.sizes().size(ty); } }; - + if !sig.indirect_params { // If parameters are not passed indirectly then we lift each // argument in succession from the component wasm types that