diff --git a/wasi-common-cbindgen/src/lib.rs b/wasi-common-cbindgen/src/lib.rs index 2fa082a3e0..52cdd7999b 100644 --- a/wasi-common-cbindgen/src/lib.rs +++ b/wasi-common-cbindgen/src/lib.rs @@ -2,7 +2,7 @@ extern crate proc_macro; use proc_macro::TokenStream; use quote::quote; -use syn::{FnArg, ArgCaptured, Pat, PatIdent}; +use syn::{FnArg, ArgCaptured, Pat, PatIdent, TypeReference, Type, Token}; use std::collections::HashMap; #[proc_macro_attribute] @@ -10,8 +10,52 @@ pub fn wasi_common_cbindgen(attr: TokenStream, function: TokenStream) -> TokenSt assert!(attr.is_empty()); let function = syn::parse_macro_input!(function as syn::ItemFn); + + // generate C fn name prefixed with __wasi_ + let ident = &function.ident; + let concatenated = format!("__wasi_{}", ident); + let c_fn_ident = syn::Ident::new(&concatenated, ident.span()); + + // capture signature + let mut arg_ident = Vec::new(); + let mut arg_type = Vec::new(); + for input in &function.decl.inputs { + match input { + FnArg::Captured(ArgCaptured { + pat: Pat::Ident(pat @ PatIdent { .. }), + colon_token: _, + ty, + }) => { + // parse arg identifier + let ident = &pat.ident; + arg_ident.push(quote!(#ident)); + // parse arg type + if let Type::Reference(ty @ TypeReference { .. }) = &ty { + // if we're here, then we found a &-ref + // so substitute it for *mut since we're exporting to C + let elem = &ty.elem; + arg_type.push(quote!(*mut #elem)); + } else { + arg_type.push(quote!(#ty)); + } + } + _ => {} + } + } + + println!("{:#?}", arg_ident); + println!("{:#?}", arg_type); + let result = quote! { #function + + pub unsafe extern "C" fn #c_fn_ident( + #( + #arg_ident: #arg_type, + )* + ) { + + } }; result.into()