From b8feffe6e1c0969087fc3b356c250df611f84a4e Mon Sep 17 00:00:00 2001 From: Pat Hickey Date: Mon, 20 Jan 2020 14:55:06 -0800 Subject: [PATCH] funcs get abi type definitions --- crates/generate/src/funcs.rs | 50 +++++++++++++++++++++++++++++------- crates/generate/src/lib.rs | 9 ++++++- crates/generate/src/names.rs | 16 +++++++++++- src/lib.rs | 1 + 4 files changed, 65 insertions(+), 11 deletions(-) diff --git a/crates/generate/src/funcs.rs b/crates/generate/src/funcs.rs index 6a6430cb80..3f856b863a 100644 --- a/crates/generate/src/funcs.rs +++ b/crates/generate/src/funcs.rs @@ -3,21 +3,53 @@ use quote::quote; use crate::names::Names; +// FIXME need to template what arguments are required to an import function - some context +// struct (e.g. WasiCtx) should be provided at the invocation of the `gen` proc macro. +// Rather than pass in memory as a `&mut [u8]` as today, require a `GuestMemory<'a>` be +// passed in. pub fn define_func(names: &Names, func: &witx::InterfaceFunc) -> TokenStream { let ident = names.func(&func.name); - let mut args = TokenStream::new(); + let mut args = quote!(wasi_ctx: &mut WasiCtx, memory: GuestMemory,); + + let arg_signature = |param: &witx::InterfaceFuncParam| -> TokenStream { + let name = names.func_param(¶m.name); + match param.tref.type_().passed_by() { + witx::TypePassedBy::Value(atom) => { + let atom = names.atom_type(atom); + quote!(#name: #atom,) + } + witx::TypePassedBy::Pointer => { + let atom = names.atom_type(witx::AtomType::I32); + quote!(#name: #atom,) + } + witx::TypePassedBy::PointerLengthPair => { + let atom = names.atom_type(witx::AtomType::I32); + let len_name = names.func_len_param(¶m.name); + quote!(#name: #atom, #len_name, #atom,) + } + } + }; for param in func.params.iter() { - let name = names.func_param(¶m.name); - let type_ = names.type_ref(¶m.tref); - args.extend(quote!(#name: #type_,)); + args.extend(arg_signature(param)); } - let mut rets = TokenStream::new(); - for result in func.results.iter() { - let type_ = names.type_ref(&result.tref); - rets.extend(quote!(#type_,)); + if let Some(arg_results) = func.results.get(1..) { + for result in arg_results { + args.extend(arg_signature(result)) + } } - quote!(pub fn #ident(#args) -> (#rets) { unimplemented!() }) + let ret = if let Some(first_result) = func.results.get(0) { + match first_result.tref.type_().passed_by() { + witx::TypePassedBy::Value(atom) => names.atom_type(atom), + _ => unreachable!("first result should always be passed by value"), + } + } else if func.noreturn { + quote!(!) + } else { + quote!(()) + }; + + quote!(pub fn #ident(#args) -> #ret { unimplemented!() }) } diff --git a/crates/generate/src/lib.rs b/crates/generate/src/lib.rs index 7f9deb9687..acf60e1401 100644 --- a/crates/generate/src/lib.rs +++ b/crates/generate/src/lib.rs @@ -36,7 +36,14 @@ pub fn from_witx(args: TokenStream) -> TokenStream { for func in module.funcs() { fs.extend(define_func(&names, &func)); } - modules.extend(quote!(mod #modname { use super::types::*; #fs })); + modules.extend(quote!( + mod #modname { + use super::*; + use super::types::*; + use memory::*; + #fs + } + )); } TokenStream::from(quote!(mod types { #types } #modules)) diff --git a/crates/generate/src/names.rs b/crates/generate/src/names.rs index a1ca1a0407..ed59e44e3c 100644 --- a/crates/generate/src/names.rs +++ b/crates/generate/src/names.rs @@ -1,7 +1,7 @@ use heck::{CamelCase, SnakeCase}; use proc_macro2::{Ident, TokenStream}; use quote::{format_ident, quote}; -use witx::{BuiltinType, Id, TypeRef}; +use witx::{AtomType, BuiltinType, Id, TypeRef}; #[derive(Debug, Clone)] pub struct Names { @@ -32,6 +32,15 @@ impl Names { BuiltinType::USize => quote!(usize), } } + pub fn atom_type(&self, atom: AtomType) -> TokenStream { + match atom { + AtomType::I32 => quote!(i32), + AtomType::I64 => quote!(i64), + AtomType::F32 => quote!(f32), + AtomType::F64 => quote!(f64), + } + } + pub fn type_ref(&self, tref: &TypeRef) -> TokenStream { match tref { TypeRef::Name(nt) => { @@ -65,4 +74,9 @@ impl Names { pub fn func_param(&self, id: &Id) -> Ident { format_ident!("{}", id.as_str().to_snake_case()) } + + /// For when you need a {name}_len parameter for passing an array: + pub fn func_len_param(&self, id: &Id) -> Ident { + format_ident!("{}_len", id.as_str().to_snake_case()) + } } diff --git a/src/lib.rs b/src/lib.rs index 4c58828ac7..227fdd8126 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,4 +1,5 @@ pub mod test { + pub struct WasiCtx {} // FIXME: parameterize macro on what ctx type is used here generate::from_witx!("test.witx"); } /*