Skip to content

Commit

Permalink
fully functional Rust code generation for symmetric strings example
Browse files Browse the repository at this point in the history
  • Loading branch information
cpetig committed Jul 26, 2024
1 parent 01b4216 commit be953c1
Show file tree
Hide file tree
Showing 5 changed files with 128 additions and 96 deletions.
8 changes: 6 additions & 2 deletions crates/core/src/abi.rs
Original file line number Diff line number Diff line change
Expand Up @@ -741,7 +741,7 @@ pub fn call(
async_: bool,
) {
if matches!(lift_lower, LiftLower::Symmetric) {
let sig = wasm_signature_symmetric(resolve, variant, func);
let sig = wasm_signature_symmetric(resolve, variant, func, true);
Generator::new(resolve, variant, lift_lower, bindgen, async_)
.call_with_signature(func, sig);
} else {
Expand Down Expand Up @@ -2276,9 +2276,13 @@ fn push_flat_symmetric(resolve: &Resolve, ty: &Type, vec: &mut Vec<WasmType>) {
// another hack
pub fn wasm_signature_symmetric(
resolve: &Resolve,
_variant: AbiVariant,
variant: AbiVariant,
func: &Function,
symmetric: bool,
) -> WasmSignature {
if !symmetric {
return resolve.wasm_signature(variant, func);
}
const MAX_FLAT_PARAMS: usize = 16;
const MAX_FLAT_RESULTS: usize = 1;

Expand Down
36 changes: 16 additions & 20 deletions crates/cpp/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -969,26 +969,22 @@ impl CppInterfaceGenerator<'_> {

// local patching of borrows function needs more complex solution
fn patched_wasm_signature(&self, variant: AbiVariant, func: &Function) -> WasmSignature {
if self.gen.opts.symmetric {
abi::wasm_signature_symmetric(self.resolve, variant, func)
} else {
self.resolve.wasm_signature(variant, func)
// if matches!(res.params.get(0), Some(WasmType::I32))
// && matches!(func.kind, FunctionKind::Freestanding)
// {
// if let Some((_, ty)) = func.params.get(0) {
// if let Type::Id(id) = ty {
// if let Some(td) = self.resolve.types.get(*id) {
// if let TypeDefKind::Handle(Handle::Borrow(id2)) = &td.kind {
// if let Some(ty2) = self.resolve.types.get(*id2) {
// dbg!((&self.gen.imported_interfaces, id2, ty2, &func));
// }
// }
// }
// }
// }
// }
}
abi::wasm_signature_symmetric(self.resolve, variant, func, self.gen.opts.symmetric)
// if matches!(res.params.get(0), Some(WasmType::I32))
// && matches!(func.kind, FunctionKind::Freestanding)
// {
// if let Some((_, ty)) = func.params.get(0) {
// if let Type::Id(id) = ty {
// if let Some(td) = self.resolve.types.get(*id) {
// if let TypeDefKind::Handle(Handle::Borrow(id2)) = &td.kind {
// if let Some(ty2) = self.resolve.types.get(*id2) {
// dbg!((&self.gen.imported_interfaces, id2, ty2, &func));
// }
// }
// }
// }
// }
// }
}

// print the signature of the guest export (lowered (wasm) function calling into highlevel)
Expand Down
107 changes: 59 additions & 48 deletions crates/cpp/tests/meshless_strings/rust_comp_a/src/the_world.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
// Generated by `wit-bindgen` 0.27.0. DO NOT EDIT!
// Generated by `wit-bindgen` 0.28.0. DO NOT EDIT!
// Options used:
// * with "foo:foo/strings" = generate
#[allow(dead_code)]
pub mod foo {
#[allow(dead_code)]
Expand All @@ -13,7 +12,7 @@ pub mod foo {
static __FORCE_SECTION_REF: fn() = super::super::super::__link_custom_section_describing_imports;
use super::super::super::_rt;
#[allow(unused_unsafe, clippy::all)]
pub fn a(x: &str,){
pub fn a(x: &str,) -> (){
unsafe {
let vec0 = x;
let ptr0 = vec0.as_ptr().cast::<u8>();
Expand All @@ -30,32 +29,40 @@ pub mod foo {
#[allow(unused_unsafe, clippy::all)]
pub fn b() -> _rt::String{
unsafe {
#[repr(align(8))]
struct RetArea([::core::mem::MaybeUninit::<u8>; 16]);
let mut ret_area = RetArea([::core::mem::MaybeUninit::uninit(); 16]);

#[cfg_attr(target_pointer_width="64", repr(align(8)))]
#[cfg_attr(target_pointer_width="32", repr(align(4)))]
struct RetArea([::core::mem::MaybeUninit::<u8>; (2*core::mem::size_of::<*const u8>())]);
let mut ret_area = RetArea([::core::mem::MaybeUninit::uninit(); (2*core::mem::size_of::<*const u8>())]);
let ptr0 = ret_area.0.as_mut_ptr().cast::<u8>();
#[link(wasm_import_module = "foo:foo/strings")]
extern "C" {
#[cfg_attr(target_arch = "wasm32", link_name = "b")]
fn fooX3AfooX2FstringsX00b(_: *mut u8);
#[cfg_attr(target_arch = "wasm32", link_name = "cabi_post_b")]
fn cabi_post_fooX3AfooX2FstringsX00b(_: *mut u8);
fn fooX3AfooX2FstringsX00b(_: *mut u8, );
}
fooX3AfooX2FstringsX00b(ptr0);
let l1 = *ptr0.add(0).cast::<*mut u8>();
let l2 = *ptr0.add(8).cast::<usize>();
let l2 = *ptr0.add(core::mem::size_of::<*const u8>()).cast::<usize>();
let len3 = l2;
let res = String::from(std::str::from_utf8(std::slice::from_raw_parts(l1, len3)).unwrap());
let string3 = String::from(std::str::from_utf8(std::slice::from_raw_parts(l1, len3)).unwrap());

#[link(wasm_import_module = "cabi_post_foo:foo/strings")]
extern "C" {
#[cfg_attr(target_arch = "wasm32", link_name = "b")]
fn cabi_post_fooX3AfooX2FstringsX00b(_: *mut u8, );
}
cabi_post_fooX3AfooX2FstringsX00b(ptr0);
res
string3
}
}
#[allow(unused_unsafe, clippy::all)]
pub fn c(a: &str,b: &str,) -> _rt::String{
unsafe {
#[repr(align(8))]
struct RetArea([::core::mem::MaybeUninit::<u8>; 16]);
let mut ret_area = RetArea([::core::mem::MaybeUninit::uninit(); 16]);

#[cfg_attr(target_pointer_width="64", repr(align(8)))]
#[cfg_attr(target_pointer_width="32", repr(align(4)))]
struct RetArea([::core::mem::MaybeUninit::<u8>; (2*core::mem::size_of::<*const u8>())]);
let mut ret_area = RetArea([::core::mem::MaybeUninit::uninit(); (2*core::mem::size_of::<*const u8>())]);
let vec0 = a;
let ptr0 = vec0.as_ptr().cast::<u8>();
let len0 = vec0.len();
Expand All @@ -66,17 +73,21 @@ pub mod foo {
#[link(wasm_import_module = "foo:foo/strings")]
extern "C" {
#[cfg_attr(target_arch = "wasm32", link_name = "c")]
fn fooX3AfooX2FstringsX00c(_: *mut u8, _: usize, _: *mut u8, _: usize, _: *mut u8);
#[cfg_attr(target_arch = "wasm32", link_name = "cabi_post_c")]
fn cabi_post_fooX3AfooX2FstringsX00c(_: *mut u8);
fn fooX3AfooX2FstringsX00c(_: *mut u8, _: usize, _: *mut u8, _: usize, _: *mut u8, );
}
fooX3AfooX2FstringsX00c(ptr0.cast_mut(), len0, ptr1.cast_mut(), len1, ptr2);
let l3 = *ptr2.add(0).cast::<*mut u8>();
let l4 = *ptr2.add(8).cast::<usize>();
let l4 = *ptr2.add(core::mem::size_of::<*const u8>()).cast::<usize>();
let len5 = l4;
let res = String::from(std::str::from_utf8(std::slice::from_raw_parts(l3, len5)).unwrap());
let string5 = String::from(std::str::from_utf8(std::slice::from_raw_parts(l3, len5)).unwrap());

#[link(wasm_import_module = "cabi_post_foo:foo/strings")]
extern "C" {
#[cfg_attr(target_arch = "wasm32", link_name = "c")]
fn cabi_post_fooX3AfooX2FstringsX00c(_: *mut u8, );
}
cabi_post_fooX3AfooX2FstringsX00c(ptr2);
res
string5
}
}

Expand All @@ -101,52 +112,51 @@ pub mod exports {
#[allow(non_snake_case)]
pub unsafe fn _export_a_cabi<T: Guest>(arg0: *mut u8,arg1: usize,) {#[cfg(target_arch="wasm32")]
_rt::run_ctors_once();let len0 = arg1;
let s = String::from(std::str::from_utf8(std::slice::from_raw_parts(arg0, len0)).unwrap());
// let bytes0 = _rt::Vec::from_raw_parts(arg0.cast(), len0, len0);
T::a(s);
let string0 = String::from(std::str::from_utf8(std::slice::from_raw_parts(arg0, len0)).unwrap());
T::a(string0);
}
#[doc(hidden)]
#[allow(non_snake_case)]
pub unsafe fn _export_b_cabi<T: Guest>(ptr1: *mut u8) {#[cfg(target_arch="wasm32")]
pub unsafe fn _export_b_cabi<T: Guest>(arg0: *mut u8,) {#[cfg(target_arch="wasm32")]
_rt::run_ctors_once();let result0 = T::b();
let vec2 = (result0.into_bytes()).into_boxed_slice();
let ptr2 = vec2.as_ptr().cast::<u8>();
let len2 = vec2.len();
::core::mem::forget(vec2);
*ptr1.add(8).cast::<usize>() = len2;
*ptr1.add(0).cast::<*mut u8>() = ptr2.cast_mut();
let vec1 = (result0.into_bytes()).into_boxed_slice();
let ptr1 = vec1.as_ptr().cast::<u8>();
let len1 = vec1.len();
::core::mem::forget(vec1);
*arg0.add(core::mem::size_of::<*const u8>()).cast::<usize>() = len1;
*arg0.add(0).cast::<*mut u8>() = ptr1.cast_mut();
}
#[doc(hidden)]
#[allow(non_snake_case)]
pub unsafe fn __post_return_b<T: Guest>(arg0: *mut u8,) {
let l0 = *arg0.add(0).cast::<*mut u8>();
let l1 = *arg0.add(8).cast::<usize>();
let l1 = *arg0.add(core::mem::size_of::<*const u8>()).cast::<usize>();
_rt::cabi_dealloc(l0, l1, 1);
}
#[doc(hidden)]
#[allow(non_snake_case)]
pub unsafe fn _export_c_cabi<T: Guest>(arg0: *mut u8,arg1: usize,arg2: *mut u8,arg3: usize, ptr3: *mut u8) {#[cfg(target_arch="wasm32")]
pub unsafe fn _export_c_cabi<T: Guest>(arg0: *mut u8,arg1: usize,arg2: *mut u8,arg3: usize,arg4: *mut u8,) {#[cfg(target_arch="wasm32")]
_rt::run_ctors_once();let len0 = arg1;
let bytes0 = String::from(std::str::from_utf8(std::slice::from_raw_parts(arg0, len0)).unwrap());
let string0 = String::from(std::str::from_utf8(std::slice::from_raw_parts(arg0, len0)).unwrap());
let len1 = arg3;
let bytes1 = String::from(std::str::from_utf8(std::slice::from_raw_parts(arg2, len1)).unwrap());
let result2 = T::c(bytes0, bytes1);
let vec4 = (result2.into_bytes()).into_boxed_slice();
let ptr4 = vec4.as_ptr().cast::<u8>();
let len4 = vec4.len();
::core::mem::forget(vec4);
*ptr3.add(8).cast::<usize>() = len4;
*ptr3.add(0).cast::<*mut u8>() = ptr4.cast_mut();
let string1 = String::from(std::str::from_utf8(std::slice::from_raw_parts(arg2, len1)).unwrap());
let result2 = T::c(string0, string1);
let vec3 = (result2.into_bytes()).into_boxed_slice();
let ptr3 = vec3.as_ptr().cast::<u8>();
let len3 = vec3.len();
::core::mem::forget(vec3);
*arg4.add(core::mem::size_of::<*const u8>()).cast::<usize>() = len3;
*arg4.add(0).cast::<*mut u8>() = ptr3.cast_mut();
}
#[doc(hidden)]
#[allow(non_snake_case)]
pub unsafe fn __post_return_c<T: Guest>(arg0: *mut u8,) {
let l0 = *arg0.add(0).cast::<*mut u8>();
let l1 = *arg0.add(8).cast::<usize>();
let l1 = *arg0.add(core::mem::size_of::<*const u8>()).cast::<usize>();
_rt::cabi_dealloc(l0, l1, 1);
}
pub trait Guest {
fn a(x: _rt::String,);
fn a(x: _rt::String,) -> ();
fn b() -> _rt::String;
fn c(a: _rt::String,b: _rt::String,) -> _rt::String;
}
Expand Down Expand Up @@ -192,7 +202,8 @@ pub mod exports {
}
mod _rt {
pub use alloc_crate::string::String;

pub use alloc_crate::vec::Vec;

#[cfg(target_arch = "wasm32")]
pub fn run_ctors_once() {
wit_bindgen::rt::run_ctors_once();
Expand All @@ -202,7 +213,7 @@ mod _rt {
return;
}
let layout = alloc::Layout::from_size_align_unchecked(size, align);
alloc::dealloc(ptr as *mut u8, layout);
alloc::dealloc(ptr, layout);
}
extern crate alloc as alloc_crate;
pub use alloc_crate::alloc;
Expand Down Expand Up @@ -237,7 +248,7 @@ macro_rules! __export_the_world_impl {
pub(crate) use __export_the_world_impl as export;

#[cfg(target_arch = "wasm32")]
#[link_section = "component-type:wit-bindgen:0.27.0:the-world:encoded world"]
#[link_section = "component-type:wit-bindgen:0.28.0:the-world:encoded world"]
#[doc(hidden)]
pub static __WIT_BINDGEN_COMPONENT_TYPE: [u8; 286] = *b"\
\0asm\x0d\0\x01\0\0\x19\x16wit-component-encoding\x04\0\x07\x9e\x01\x01A\x02\x01\
Expand All @@ -246,7 +257,7 @@ A\x04\x01B\x06\x01@\x01\x01xs\x01\0\x04\0\x01a\x01\0\x01@\0\0s\x04\0\x01b\x01\x0
B\x06\x01@\x01\x01xs\x01\0\x04\0\x01a\x01\0\x01@\0\0s\x04\0\x01b\x01\x01\x01@\x02\
\x01as\x01bs\0s\x04\0\x01c\x01\x02\x04\x01\x0ffoo:foo/strings\x05\x01\x04\x01\x11\
foo:foo/the-world\x04\0\x0b\x0f\x01\0\x09the-world\x03\0\0\0G\x09producers\x01\x0c\
processed-by\x02\x0dwit-component\x070.212.0\x10wit-bindgen-rust\x060.27.0";
processed-by\x02\x0dwit-component\x070.214.0\x10wit-bindgen-rust\x060.28.0";

#[inline(never)]
#[doc(hidden)]
Expand Down
22 changes: 17 additions & 5 deletions crates/rust/src/bindgen.rs
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,13 @@ impl<'a, 'b> FunctionBindgen<'a, 'b> {
}
}

fn declare_import(&mut self, module_prefix: &str, name: &str, params: &[WasmType], results: &[WasmType]) -> String {
fn declare_import(
&mut self,
module_prefix: &str,
name: &str,
params: &[WasmType],
results: &[WasmType],
) -> String {
// Define the actual function we're calling inline
// let tmp = self.tmp();
let mut sig = "(".to_owned();
Expand All @@ -82,7 +88,8 @@ impl<'a, 'b> FunctionBindgen<'a, 'b> {
sig.push_str(wasm_type(*result));
}
let module_name = self.wasm_import_module;
let export_name = String::from(module_prefix) + &make_external_symbol(module_name, name, AbiVariant::GuestImport);
let export_name = String::from(module_prefix)
+ &make_external_symbol(module_name, name, AbiVariant::GuestImport);
uwrite!(
self.src,
"
Expand Down Expand Up @@ -709,15 +716,15 @@ impl Bindgen for FunctionBindgen<'_, '_> {
let val = format!("vec{}", tmp);
let ptr = format!("ptr{}", tmp);
let len = format!("len{}", tmp);
if realloc.is_none() || self.gen.gen.opts.symmetric {
if realloc.is_none() || (self.gen.in_import && self.gen.gen.opts.symmetric) {
self.push_str(&format!("let {} = {};\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 {} = {}.as_ptr().cast::<u8>();\n", ptr, val));
self.push_str(&format!("let {} = {}.len();\n", len, val));
if realloc.is_some() && !self.gen.gen.opts.symmetric {
if realloc.is_some() && !(self.gen.in_import && self.gen.gen.opts.symmetric) {
self.push_str(&format!("::core::mem::forget({});\n", val));
}
results.push(format!("{ptr}.cast_mut()"));
Expand Down Expand Up @@ -838,7 +845,12 @@ impl Bindgen for FunctionBindgen<'_, '_> {

Instruction::IterBasePointer => results.push("base".to_string()),

Instruction::CallWasm { name, sig, module_prefix, .. } => {
Instruction::CallWasm {
name,
sig,
module_prefix,
..
} => {
let func = self.declare_import(module_prefix, name, &sig.params, &sig.results);

// ... then call the function with all our operands
Expand Down
Loading

0 comments on commit be953c1

Please sign in to comment.