This commit is contained in:
Sergey Pepyakin 2019-01-25 10:43:03 +01:00
parent 4c51136e7c
commit af19c66589
5 changed files with 59 additions and 51 deletions

View File

@ -2,22 +2,21 @@ use crate::model::{ExtDefinition, ExternalFunc};
use proc_macro2::{Ident, Literal, Span, TokenStream}; use proc_macro2::{Ident, Literal, Span, TokenStream};
use quote::{quote, quote_spanned, ToTokens}; use quote::{quote, quote_spanned, ToTokens};
pub fn codegen(ext_def: &ExtDefinition, to: &mut TokenStream) { pub fn codegen(ext_def: &ExtDefinition, to: &mut TokenStream) {
let mut externals = TokenStream::new(); let mut externals = TokenStream::new();
let mut module_resolver = TokenStream::new(); let mut module_resolver = TokenStream::new();
// TODO: Come up with a name. // TODO: Come up with a name.
let mut new_name = "_WASMI_IMPLS_".to_string(); let mut new_name = "_WASMI_IMPLS_".to_string();
new_name.push_str("NAME".to_string().trim_start_matches("r#")); new_name.push_str("NAME".to_string().trim_start_matches("r#"));
let dummy_const = Ident::new(&new_name, Span::call_site()); let dummy_const = Ident::new(&new_name, Span::call_site());
derive_externals(ext_def, &mut externals); derive_externals(ext_def, &mut externals);
derive_module_resolver(ext_def, &mut module_resolver); derive_module_resolver(ext_def, &mut module_resolver);
(quote! { (quote! {
const #dummy_const: () = { const #dummy_const: () = {
extern crate wasmi as _wasmi; extern crate wasmi as _wasmi;
use _wasmi::{ use _wasmi::{
Trap, RuntimeValue, RuntimeArgs, Externals, ValueType, ModuleImportResolver, Trap, RuntimeValue, RuntimeArgs, Externals, ValueType, ModuleImportResolver,
@ -41,7 +40,8 @@ pub fn codegen(ext_def: &ExtDefinition, to: &mut TokenStream) {
#externals #externals
#module_resolver #module_resolver
}; };
}).to_tokens(to); })
.to_tokens(to);
} }
fn emit_dispatch_func_arm(func: &ExternalFunc) -> TokenStream { fn emit_dispatch_func_arm(func: &ExternalFunc) -> TokenStream {
@ -58,7 +58,8 @@ fn emit_dispatch_func_arm(func: &ExternalFunc) -> TokenStream {
args.next() args.next()
.and_then(|rt_val| rt_val.try_into()) .and_then(|rt_val| rt_val.try_into())
.unwrap(); .unwrap();
}).to_tokens(&mut unmarshall_args); })
.to_tokens(&mut unmarshall_args);
} }
let prologue = quote! { let prologue = quote! {
@ -109,7 +110,8 @@ fn derive_externals(ext_def: &ExtDefinition, to: &mut TokenStream) {
// ... // ...
} }
}).to_tokens(to); })
.to_tokens(to);
} }
fn emit_resolve_func_arm(func: &ExternalFunc) -> TokenStream { fn emit_resolve_func_arm(func: &ExternalFunc) -> TokenStream {
@ -129,18 +131,26 @@ fn emit_resolve_func_arm(func: &ExternalFunc) -> TokenStream {
} }
}; };
let init = func.args.iter().map(|param| { let init = func
let ident = &param.ident; .args
quote! { .iter()
let #ident = None; .map(|param| {
} let ident = &param.ident;
}).collect::<Vec<_>>(); quote! {
let #ident = None;
}
})
.collect::<Vec<_>>();
let params_materialized_tys = func.args.iter().map(|param| { let params_materialized_tys = func
let ident = &param.ident; .args
let span = param.ident.span(); .iter()
quote_spanned! {span=> materialize_arg_ty(#ident) } .map(|param| {
}).collect::<Vec<_>>(); let ident = &param.ident;
let span = param.ident.span();
quote_spanned! {span=> materialize_arg_ty(#ident) }
})
.collect::<Vec<_>>();
let materialized_return_ty = quote_spanned! { return_ty_span=> let materialized_return_ty = quote_spanned! { return_ty_span=>
materialize_ret_type(return_val) materialize_ret_type(return_val)
@ -162,8 +172,8 @@ fn emit_resolve_func_arm(func: &ExternalFunc) -> TokenStream {
// at this point types of all variables and return_val are inferred. // at this point types of all variables and return_val are inferred.
if signature.params() != &[#(#params_materialized_tys),*] || signature.return_type() != #materialized_return_ty { if signature.params() != &[#(#params_materialized_tys),*] || signature.return_type() != #materialized_return_ty {
return Err(Error::Instantiation( return Err(Error::Instantiation(
format!("Export {} has different signature {:?}", #string_ident, signature), format!("Export {} has different signature {:?}", #string_ident, signature),
)); ));
} }
return Ok(FuncInstance::alloc_host(signature.clone(), #index)); return Ok(FuncInstance::alloc_host(signature.clone(), #index));

View File

@ -1,10 +1,10 @@
#![recursion_limit="128"] #![recursion_limit = "128"]
extern crate proc_macro; extern crate proc_macro;
mod codegen;
mod model; mod model;
mod parser; mod parser;
mod codegen;
use proc_macro::TokenStream; use proc_macro::TokenStream;

View File

@ -1,6 +1,6 @@
use crate::model::{self, ExtDefinition, ExternalFunc, Param}; use crate::model::{self, ExtDefinition, ExternalFunc, Param};
use syn::{ItemImpl, ImplItem, ImplItemMethod, FnArg, ReturnType, Ident};
use syn::spanned::Spanned; use syn::spanned::Spanned;
use syn::{FnArg, Ident, ImplItem, ImplItemMethod, ItemImpl, ReturnType};
/// Parse an incoming stream of tokens into externalities definition. /// Parse an incoming stream of tokens into externalities definition.
pub fn parse(input: proc_macro2::TokenStream) -> Result<ExtDefinition, ()> { pub fn parse(input: proc_macro2::TokenStream) -> Result<ExtDefinition, ()> {
@ -10,20 +10,22 @@ pub fn parse(input: proc_macro2::TokenStream) -> Result<ExtDefinition, ()> {
for item in item_impl.items { for item in item_impl.items {
match item { match item {
ImplItem::Method(ImplItemMethod { ImplItem::Method(ImplItemMethod { sig, .. }) => {
sig,
..
}) => {
let index = funcs.len() as u32; let index = funcs.len() as u32;
// self TODO: handle this properly // self TODO: handle this properly
let args = sig.decl.inputs.iter().skip(1).enumerate().map(|(idx, input)| { let args = sig
let param_name = format!("arg{}", idx); .decl
let ident = Ident::new(&param_name, input.span()); .inputs
Param { .iter()
ident, .skip(1)
} .enumerate()
}).collect::<Vec<_>>(); .map(|(idx, input)| {
let param_name = format!("arg{}", idx);
let ident = Ident::new(&param_name, input.span());
Param { ident }
})
.collect::<Vec<_>>();
let return_ty = match sig.decl.output { let return_ty = match sig.decl.output {
ReturnType::Default => None, ReturnType::Default => None,
@ -36,8 +38,8 @@ pub fn parse(input: proc_macro2::TokenStream) -> Result<ExtDefinition, ()> {
args, args,
return_ty, return_ty,
}); });
}, }
_ => {}, _ => {}
} }
} }

View File

@ -1,5 +1,5 @@
use {ValueType, RuntimeValue, Trap};
use nan_preserving_float::{F32, F64}; use nan_preserving_float::{F32, F64};
use {RuntimeValue, Trap, ValueType};
/// A trait that represents a value that can be directly coerced to one of /// A trait that represents a value that can be directly coerced to one of
/// wasm base value types. /// wasm base value types.
@ -40,21 +40,17 @@ impl IntoWasmResult for () {
} }
} }
impl<R: IntoWasmValue, E: Into<Trap>> IntoWasmResult for Result<R, E> { impl<R: IntoWasmValue, E: Into<Trap>> IntoWasmResult for Result<R, E> {
const VALUE_TYPE: Option<ValueType> = Some(R::VALUE_TYPE); const VALUE_TYPE: Option<ValueType> = Some(R::VALUE_TYPE);
fn into_wasm_result(self) -> Result<Option<RuntimeValue>, Trap> { fn into_wasm_result(self) -> Result<Option<RuntimeValue>, Trap> {
self self.map(|v| Some(v.into_wasm_value())).map_err(Into::into)
.map(|v| Some(v.into_wasm_value()))
.map_err(Into::into)
} }
} }
impl<E: Into<Trap>> IntoWasmResult for Result<(), E> { impl<E: Into<Trap>> IntoWasmResult for Result<(), E> {
const VALUE_TYPE: Option<ValueType> = None; const VALUE_TYPE: Option<ValueType> = None;
fn into_wasm_result(self) -> Result<Option<RuntimeValue>, Trap> { fn into_wasm_result(self) -> Result<Option<RuntimeValue>, Trap> {
self self.map(|_| None).map_err(Into::into)
.map(|_| None)
.map_err(Into::into)
} }
} }

View File

@ -1,17 +1,17 @@
extern crate wasmi_derive;
extern crate wasmi; extern crate wasmi;
extern crate wasmi_derive;
use wasmi_derive::derive_externals;
use wasmi::HostError;
use std::fmt; use std::fmt;
use wasmi::HostError;
use wasmi_derive::derive_externals;
#[derive(Debug)] #[derive(Debug)]
struct NoInfoError; struct NoInfoError;
impl HostError for NoInfoError {} impl HostError for NoInfoError {}
impl fmt::Display for NoInfoError { impl fmt::Display for NoInfoError {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "NoInfoError") write!(f, "NoInfoError")
} }
} }
struct NonStaticExternals<'a> { struct NonStaticExternals<'a> {