From a939252a90195df6faa6a7e219af3c5b563ec697 Mon Sep 17 00:00:00 2001 From: Dan Gohman Date: Tue, 13 Feb 2024 10:20:41 -0800 Subject: [PATCH] Use the new `Pointer` and `Length` types. --- crates/c/src/lib.rs | 10 ++++- crates/core/src/abi.rs | 19 +++++++++- crates/csharp/src/lib.rs | 6 +++ crates/guest-rust/src/lib.rs | 4 +- crates/rust/src/bindgen.rs | 73 +++++++++++++++++++----------------- crates/rust/src/interface.rs | 7 +++- crates/rust/src/lib.rs | 7 ++++ crates/teavm-java/src/lib.rs | 10 +++++ 8 files changed, 93 insertions(+), 43 deletions(-) diff --git a/crates/c/src/lib.rs b/crates/c/src/lib.rs index e25b77748..03174d66e 100644 --- a/crates/c/src/lib.rs +++ b/crates/c/src/lib.rs @@ -2205,12 +2205,15 @@ impl Bindgen for FunctionBindgen<'_, '_> { op )); } - Bitcast::I32ToI64 => { + Bitcast::I32ToI64 | Bitcast::PToP64 => { results.push(format!("(int64_t) {}", op)); } - Bitcast::I64ToI32 => { + Bitcast::I64ToI32 | Bitcast::P64ToP => { results.push(format!("(int32_t) {}", op)); } + Bitcast::I64ToP64 | Bitcast::P64ToI64 => { + results.push(format!("{}", op)); + } Bitcast::None => results.push(op.to_string()), } } @@ -3015,6 +3018,9 @@ fn wasm_type(ty: WasmType) -> &'static str { WasmType::I64 => "int64_t", WasmType::F32 => "float", WasmType::F64 => "double", + WasmType::Pointer => "uintptr_t", + WasmType::Pointer64 => "int64_t", + WasmType::Length => "size_t", } } diff --git a/crates/core/src/abi.rs b/crates/core/src/abi.rs index 83fe4d39d..a90a7e6db 100644 --- a/crates/core/src/abi.rs +++ b/crates/core/src/abi.rs @@ -526,6 +526,12 @@ pub enum Bitcast { I64ToI32, I64ToF32, + // Pointers + P64ToI64, + I64ToP64, + P64ToP, + PToP64, + None, } @@ -1862,7 +1868,7 @@ fn cast(from: WasmType, to: WasmType) -> Bitcast { use WasmType::*; match (from, to) { - (I32, I32) | (I64, I64) | (F32, F32) | (F64, F64) => Bitcast::None, + (I32, I32) | (I64, I64) | (F32, F32) | (F64, F64) | (Pointer, Pointer) | (Length, Length) => Bitcast::None, (I32, I64) => Bitcast::I32ToI64, (F32, I32) => Bitcast::F32ToI32, @@ -1875,7 +1881,16 @@ fn cast(from: WasmType, to: WasmType) -> Bitcast { (F32, I64) => Bitcast::F32ToI64, (I64, F32) => Bitcast::I64ToF32, - (F32, F64) | (F64, F32) | (F64, I32) | (I32, F64) => unreachable!(), + (I64, Pointer64) => Bitcast::I64ToP64, + (Pointer64, I64) => Bitcast::P64ToI64, + (Pointer, Pointer64) => Bitcast::PToP64, + (Pointer64, Pointer) => Bitcast::P64ToP, + + (Pointer | Pointer64 | Length, _) | + (_, Pointer | Pointer64 | Length) | + (F32, F64) | (F64, F32) | (F64, I32) | (I32, F64) => { + unreachable!() + } } } diff --git a/crates/csharp/src/lib.rs b/crates/csharp/src/lib.rs index efc51f522..8401ef647 100644 --- a/crates/csharp/src/lib.rs +++ b/crates/csharp/src/lib.rs @@ -1696,6 +1696,9 @@ impl Bindgen for FunctionBindgen<'_, '_> { WasmType::I64 => "0L", WasmType::F32 => "0.0F", WasmType::F64 => "0.0D", + WasmType::Pointer => "0", + WasmType::Pointer64 => "0L", + WasmType::Length => "0", } .to_owned() })), @@ -2223,6 +2226,9 @@ fn wasm_type(ty: WasmType) -> &'static str { WasmType::I64 => "long", WasmType::F32 => "float", WasmType::F64 => "double", + WasmType::Pointer => "int", + WasmType::Pointer64 => "long", + WasmType::Length => "int", } } diff --git a/crates/guest-rust/src/lib.rs b/crates/guest-rust/src/lib.rs index 8ceceb2c0..b43996a1d 100644 --- a/crates/guest-rust/src/lib.rs +++ b/crates/guest-rust/src/lib.rs @@ -92,12 +92,12 @@ pub mod rt { return ptr; } - pub unsafe fn dealloc(ptr: i32, size: usize, align: usize) { + pub unsafe fn dealloc(ptr: *mut core::ffi::c_void, size: usize, align: usize) { if size == 0 { return; } let layout = Layout::from_size_align_unchecked(size, align); - alloc::dealloc(ptr as *mut u8, layout); + alloc::dealloc(ptr.cast::(), layout); } macro_rules! as_traits { diff --git a/crates/rust/src/bindgen.rs b/crates/rust/src/bindgen.rs index 4f83d60b8..38e899aff 100644 --- a/crates/rust/src/bindgen.rs +++ b/crates/rust/src/bindgen.rs @@ -266,11 +266,11 @@ impl Bindgen for FunctionBindgen<'_, '_> { 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); - uwrite!(self.src, "let ptr{tmp} = ret_area.as_mut_ptr() as i32;"); + uwrite!(self.src, "let ptr{tmp} = ret_area.as_mut_ptr().cast::();"); } else { self.gen.return_pointer_area_size = self.gen.return_pointer_area_size.max(size); self.gen.return_pointer_area_align = self.gen.return_pointer_area_align.max(align); - uwriteln!(self.src, "let ptr{tmp} = _RET_AREA.0.as_mut_ptr() as i32;"); + uwriteln!(self.src, "let ptr{tmp} = _RET_AREA.0.as_mut_ptr().cast::();"); } format!("ptr{}", tmp) } @@ -313,6 +313,9 @@ impl Bindgen for FunctionBindgen<'_, '_> { WasmType::I64 => results.push("0i64".to_string()), WasmType::F32 => results.push("0.0f32".to_string()), WasmType::F64 => results.push("0.0f64".to_string()), + WasmType::Pointer => results.push("core::ptr::null_mut()".to_string()), + WasmType::Pointer64 => results.push("(core::ptr::null_mut(), core::ptr::null_mut())".to_string()), + WasmType::Length => results.push("0usize".to_string()), } } } @@ -655,13 +658,13 @@ impl Bindgen for FunctionBindgen<'_, '_> { let ptr = format!("ptr{}", tmp); let len = format!("len{}", tmp); if realloc.is_none() { - self.push_str(&format!("let {} = {};\n", val, operands[0])); + self.push_str(&format!("let mut {} = {};\n", val, operands[0])); } else { let op0 = operands.pop().unwrap(); - self.push_str(&format!("let {} = ({}).into_boxed_slice();\n", val, op0)); + self.push_str(&format!("let mut {} = ({}).into_boxed_slice();\n", val, op0)); } - self.push_str(&format!("let {} = {}.as_ptr() as i32;\n", ptr, val)); - self.push_str(&format!("let {} = {}.len() as i32;\n", len, val)); + self.push_str(&format!("let {} = {}.as_mut_ptr().cast::();\n", ptr, val)); + self.push_str(&format!("let {} = {}.len();\n", len, val)); if realloc.is_some() { self.push_str(&format!("::core::mem::forget({});\n", val)); } @@ -672,9 +675,9 @@ impl Bindgen for FunctionBindgen<'_, '_> { Instruction::ListCanonLift { .. } => { let tmp = self.tmp(); let len = format!("len{}", tmp); - self.push_str(&format!("let {} = {} as usize;\n", len, operands[1])); + self.push_str(&format!("let {} = {};\n", len, operands[1])); let result = format!( - "Vec::from_raw_parts({} as *mut _, {1}, {1})", + "Vec::from_raw_parts({}.cast(), {1}, {1})", operands[0], len ); results.push(result); @@ -686,13 +689,13 @@ impl Bindgen for FunctionBindgen<'_, '_> { let ptr = format!("ptr{}", tmp); let len = format!("len{}", tmp); if realloc.is_none() { - self.push_str(&format!("let {} = {};\n", val, operands[0])); + self.push_str(&format!("let mut {} = {};\n", val, operands[0])); } else { let op0 = format!("{}.into_bytes()", operands[0]); - self.push_str(&format!("let {} = ({}).into_boxed_slice();\n", val, op0)); + self.push_str(&format!("let mut {} = ({}).into_boxed_slice();\n", val, op0)); } - self.push_str(&format!("let {} = {}.as_ptr() as i32;\n", ptr, val)); - self.push_str(&format!("let {} = {}.len() as i32;\n", len, val)); + self.push_str(&format!("let {} = {}.as_mut_ptr().cast::();\n", ptr, val)); + self.push_str(&format!("let {} = {}.len();\n", len, val)); if realloc.is_some() { self.push_str(&format!("::core::mem::forget({});\n", val)); } @@ -703,10 +706,10 @@ impl Bindgen for FunctionBindgen<'_, '_> { Instruction::StringLift => { let tmp = self.tmp(); let len = format!("len{}", tmp); - uwriteln!(self.src, "let {len} = {} as usize;", operands[1]); + uwriteln!(self.src, "let {len} = {};", operands[1]); uwriteln!( self.src, - "let bytes{tmp} = Vec::from_raw_parts({} as *mut _, {len}, {len});", + "let bytes{tmp} = Vec::from_raw_parts({}.cast(), {len}, {len});", operands[0], ); if self.gen.gen.opts.raw_strings { @@ -730,7 +733,7 @@ impl Bindgen for FunctionBindgen<'_, '_> { "let {vec} = {operand0};\n", operand0 = operands[0] )); - self.push_str(&format!("let {len} = {vec}.len() as i32;\n")); + self.push_str(&format!("let {len} = {vec}.len();\n")); let size = self.gen.sizes.size(element); let align = self.gen.sizes.align(element); self.push_str(&format!( @@ -745,11 +748,11 @@ 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} as i32 + (i as i32) * {size};\n", + "let base = {result}.byte_add(i * {size});\n", )); self.push_str(&body); self.push_str("\n}\n"); - results.push(format!("{result} as i32")); + results.push(format!("{result}")); results.push(len); if realloc.is_none() { @@ -777,7 +780,7 @@ impl Bindgen for FunctionBindgen<'_, '_> { operand1 = operands[1] )); self.push_str(&format!( - "let mut {result} = Vec::with_capacity({len} as usize);\n", + "let mut {result} = Vec::with_capacity({len});\n", )); uwriteln!(self.src, "for i in 0..{len} {{"); @@ -787,7 +790,7 @@ impl Bindgen for FunctionBindgen<'_, '_> { uwriteln!(self.src, "}}"); results.push(result); self.push_str(&format!( - "{rt}::dealloc({base}, ({len} as usize) * {size}, {align});\n", + "{rt}::dealloc({base}, {len} * {size}, {align});\n", rt = self.gen.gen.runtime_path(), )); } @@ -876,7 +879,7 @@ impl Bindgen for FunctionBindgen<'_, '_> { let tmp = self.tmp(); uwriteln!( self.src, - "let l{tmp} = *(({} + {offset}) as *const i32);", + "let l{tmp} = *{}.byte_add({offset}).cast::();", operands[0] ); results.push(format!("l{tmp}")); @@ -885,7 +888,7 @@ impl Bindgen for FunctionBindgen<'_, '_> { let tmp = self.tmp(); uwriteln!( self.src, - "let l{tmp} = i32::from(*(({} + {offset}) as *const u8));", + "let l{tmp} = i32::from(*{}.byte_add({offset}).cast::());", operands[0] ); results.push(format!("l{tmp}")); @@ -894,7 +897,7 @@ impl Bindgen for FunctionBindgen<'_, '_> { let tmp = self.tmp(); uwriteln!( self.src, - "let l{tmp} = i32::from(*(({} + {offset}) as *const i8));", + "let l{tmp} = i32::from(*{}.byte_add({offset}).cast::());", operands[0] ); results.push(format!("l{tmp}")); @@ -903,7 +906,7 @@ impl Bindgen for FunctionBindgen<'_, '_> { let tmp = self.tmp(); uwriteln!( self.src, - "let l{tmp} = i32::from(*(({} + {offset}) as *const u16));", + "let l{tmp} = i32::from(*{}.byte_add({offset}).cast::());", operands[0] ); results.push(format!("l{tmp}")); @@ -912,7 +915,7 @@ impl Bindgen for FunctionBindgen<'_, '_> { let tmp = self.tmp(); uwriteln!( self.src, - "let l{tmp} = i32::from(*(({} + {offset}) as *const i16));", + "let l{tmp} = i32::from(*{}.byte_add({offset}).cast::());", operands[0] ); results.push(format!("l{tmp}")); @@ -921,7 +924,7 @@ impl Bindgen for FunctionBindgen<'_, '_> { let tmp = self.tmp(); uwriteln!( self.src, - "let l{tmp} = *(({} + {offset}) as *const i64);", + "let l{tmp} = *{}.byte_add({offset}).cast::();", operands[0] ); results.push(format!("l{tmp}")); @@ -930,7 +933,7 @@ impl Bindgen for FunctionBindgen<'_, '_> { let tmp = self.tmp(); uwriteln!( self.src, - "let l{tmp} = *(({} + {offset}) as *const f32);", + "let l{tmp} = *{}.byte_add({offset}).cast::();", operands[0] ); results.push(format!("l{tmp}")); @@ -939,44 +942,44 @@ impl Bindgen for FunctionBindgen<'_, '_> { let tmp = self.tmp(); uwriteln!( self.src, - "let l{tmp} = *(({} + {offset}) as *const f64);", + "let l{tmp} = *{}.byte_add({offset}).cast::();", operands[0] ); results.push(format!("l{tmp}")); } Instruction::I32Store { offset } => { self.push_str(&format!( - "*(({} + {}) as *mut i32) = {};\n", + "*{}.byte_add({}).cast::() = {};\n", operands[1], offset, operands[0] )); } Instruction::I32Store8 { offset } => { self.push_str(&format!( - "*(({} + {}) as *mut u8) = ({}) as u8;\n", + "*{}.byte_add({}).cast::() = ({}) as u8;\n", operands[1], offset, operands[0] )); } Instruction::I32Store16 { offset } => { self.push_str(&format!( - "*(({} + {}) as *mut u16) = ({}) as u16;\n", + "*{}.byte_add({}).cast::() = ({}) as u16;\n", operands[1], offset, operands[0] )); } Instruction::I64Store { offset } => { self.push_str(&format!( - "*(({} + {}) as *mut i64) = {};\n", + "*{}.byte_add({}).cast::() = {};\n", operands[1], offset, operands[0] )); } Instruction::F32Store { offset } => { self.push_str(&format!( - "*(({} + {}) as *mut f32) = {};\n", + "*{}.byte_add({}).cast::() = {};\n", operands[1], offset, operands[0] )); } Instruction::F64Store { offset } => { self.push_str(&format!( - "*(({} + {}) as *mut f64) = {};\n", + "*{}.byte_add({}).cast::() = {};\n", operands[1], offset, operands[0] )); } @@ -993,7 +996,7 @@ impl Bindgen for FunctionBindgen<'_, '_> { Instruction::GuestDeallocateString => { self.push_str(&format!( - "{rt}::dealloc({op0}, ({op1}) as usize, 1);\n", + "{rt}::dealloc({op0}, {op1}, 1);\n", rt = self.gen.gen.runtime_path(), op0 = operands[0], op1 = operands[1], @@ -1048,7 +1051,7 @@ impl Bindgen for FunctionBindgen<'_, '_> { self.push_str("\n}\n"); } self.push_str(&format!( - "{rt}::dealloc({base}, ({len} as usize) * {size}, {align});\n", + "{rt}::dealloc({base}, {len} * {size}, {align});\n", rt = self.gen.gen.runtime_path(), )); } diff --git a/crates/rust/src/interface.rs b/crates/rust/src/interface.rs index 54579b886..67fda4961 100644 --- a/crates/rust/src/interface.rs +++ b/crates/rust/src/interface.rs @@ -168,10 +168,13 @@ impl InterfaceGenerator<'_> { " #[allow(unused_imports)] use {rt}::{{alloc, vec::Vec, string::String}}; + use core::ffi::c_void; + use core::mem::size_of; + const LEN = ({size} + (sizeof::<*mut c_void>() - 1)) / sizeof::<*mut c_void>(); #[repr(align({align}))] - struct _RetArea([u8; {size}]); - static mut _RET_AREA: _RetArea = _RetArea([0; {size}]); + struct _RetArea([*mut c_void; LEN]); + static mut _RET_AREA: _RetArea = _RetArea([0; LEN]); ", rt = self.gen.runtime_path(), align = self.return_pointer_area_align, diff --git a/crates/rust/src/lib.rs b/crates/rust/src/lib.rs index 4f05c8230..12d54146e 100644 --- a/crates/rust/src/lib.rs +++ b/crates/rust/src/lib.rs @@ -788,6 +788,9 @@ fn wasm_type(ty: WasmType) -> &'static str { WasmType::I64 => "i64", WasmType::F32 => "f32", WasmType::F64 => "f64", + WasmType::Pointer => "*mut core::ffi::c_void", + WasmType::Pointer64 => "(*mut core::ffi::c_void, *mut core::ffi::c_void)", + WasmType::Length => "usize", } } @@ -812,6 +815,10 @@ fn bitcast(casts: &[Bitcast], operands: &[String], results: &mut Vec) { Bitcast::I64ToF64 => format!("f64::from_bits({} as u64)", operand), Bitcast::F32ToI64 => format!("i64::from(({}).to_bits())", operand), Bitcast::I64ToF32 => format!("f32::from_bits({} as u32)", operand), + Bitcast::I64ToP64 => format!("({} as *mut core::ffi::c_void, core::ptr::null_mut())", operand), + Bitcast::P64ToI64 => format!("{}.0 as i64", operand), + Bitcast::PToP64 => format!("({} as *mut core::ffi::c_void, core::ptr::null_mut())", operand), + Bitcast::P64ToP => format!("{}.0 as i64", operand), }); } } diff --git a/crates/teavm-java/src/lib.rs b/crates/teavm-java/src/lib.rs index 3b51547bc..4a05df548 100644 --- a/crates/teavm-java/src/lib.rs +++ b/crates/teavm-java/src/lib.rs @@ -1294,6 +1294,9 @@ impl Bindgen for FunctionBindgen<'_, '_> { WasmType::I64 => "0L", WasmType::F32 => "0.0F", WasmType::F64 => "0.0D", + WasmType::Pointer => "0", + WasmType::Pointer64 => "0L", + WasmType::Length => "0", } .to_owned() })), @@ -1336,6 +1339,10 @@ impl Bindgen for FunctionBindgen<'_, '_> { Bitcast::F64ToI64 => format!("Double.doubleToLongBits({op})"), Bitcast::I32ToI64 => format!("(long) ({op})"), Bitcast::I64ToI32 => format!("(int) ({op})"), + Bitcast::I64ToP64 => format!("{op}"), + Bitcast::P64ToI64 => format!("{op}"), + Bitcast::PToP64 => format!("(long) ({op})"), + Bitcast::P64ToP => format!("(int) ({op})"), Bitcast::None => op.to_owned(), })) } @@ -2103,6 +2110,9 @@ fn wasm_type(ty: WasmType) -> &'static str { WasmType::I64 => "long", WasmType::F32 => "float", WasmType::F64 => "double", + WasmType::Pointer => "int", + WasmType::Pointer64 => "long", + WasmType::Length => "int", } }