code cleaning

This commit is contained in:
vms 2020-07-05 22:46:23 +03:00
parent 1b76203c91
commit 68cea490d9
17 changed files with 690 additions and 285 deletions

View File

@ -29,4 +29,5 @@ print_logs = ["fluence-sdk-main/print_logs"]
members = [
"crates/main",
"crates/macro",
"crates/greeting"
]

View File

@ -0,0 +1,8 @@
[package]
name = "greeting"
version = "0.1.0"
authors = ["vms <michail.vms@gmail.com>"]
edition = "2018"
[dependencies]
fluence = { path = "../../", version = "=0.1.11" }

View File

@ -0,0 +1,18 @@
use fluence::fce;
fn main() {
println!("Hello, world!");
}
#[fce]
pub fn greeting(arg: String, arg2: String, arg3: i32) -> i64 {
let res = format!("Hi {} {}", arg, arg2);
ipfs(res, arg2);
arg3 as _
}
#[fce]
#[link(wasm_import_module = "ipfs_node.wasm")]
extern "C" {
pub fn ipfs(cmd: String, aa: String) -> String;
}

View File

@ -20,8 +20,8 @@ use serde::Serialize;
use serde::Deserialize;
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub(crate) struct AstFunctionItem {
pub(crate) rust_name: String,
pub(crate) struct AstFunctionSignature {
pub(crate) name: String,
pub(crate) input_types: Vec<ParsedType>,
// fce supports only one return value now,
// waiting for adding multi-value support in Wasmer.
@ -37,19 +37,29 @@ pub(crate) struct AstRecordItem {
pub(crate) struct AstExternFnItem {
pub(crate) link_name: Option<String>,
// only imports are possible here
pub(crate) function: AstFunctionItem,
pub(crate) signature: AstFunctionSignature,
}
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub(crate) struct AstExternModItem {
pub(crate) namespace: String,
// only imports are possible here
pub(crate) imports: Vec<AstExternFnItem>,
}
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
#[derive(Clone, Serialize, Deserialize)]
pub(crate) struct AstFunctionItem {
pub(crate) signature: AstFunctionSignature,
// Option is needed only for skipping serialization/deserialization of syn::ItemFn
#[serde(skip)]
pub(crate) original: Option<syn::ItemFn>,
}
#[derive(Clone, Serialize, Deserialize)]
pub(crate) enum FCEAst {
Function(AstFunctionItem),
Record(AstRecordItem),
ExternMod(AstExternModItem),
Record(AstRecordItem),
}

View File

@ -23,9 +23,7 @@ use syn::Result;
pub(super) fn fce_impl(tokens: TokenStream) -> Result<TokenStream> {
let item = syn::parse2::<syn::Item>(tokens)?;
let fce_ast_item = item.parse_macro_input()?;
fce_ast_item.generate_token_stream()
let tokens = fce_ast_item.generate_token_stream()?;
/*
*/
Ok(tokens)
}

View File

@ -16,20 +16,25 @@
use super::ParseMacroInput;
use crate::fce_ast_types;
use crate::fce_ast_types::FCEAst;
use crate::fce_ast_types::{FCEAst, AstFunctionItem};
use syn::Result;
impl ParseMacroInput for syn::ItemFn {
fn parse_macro_input(self) -> Result<FCEAst> {
parse_function(self.sig, self.vis).map(|f| FCEAst::Function(f))
parse_function(self.sig.clone(), self.vis.clone()).map(|f| {
FCEAst::Function(AstFunctionItem {
signature: f,
original: Some(self),
})
})
}
}
pub(super) fn parse_function(
function_sig: syn::Signature,
function_vis: syn::Visibility,
) -> Result<fce_ast_types::AstFunctionItem> {
) -> Result<fce_ast_types::AstFunctionSignature> {
use crate::parsed_type::ParsedType;
check_func(&function_sig, function_vis)?;
@ -43,8 +48,8 @@ pub(super) fn parse_function(
let output_type = ParsedType::from_return_type(&output)?;
let ast_function_item = fce_ast_types::AstFunctionItem {
rust_name: function_sig.ident.to_string(),
let ast_function_item = fce_ast_types::AstFunctionSignature {
name: function_sig.ident.to_string(),
input_types,
output_type,
};

View File

@ -68,6 +68,10 @@ impl ParseMacroInput for syn::ItemForeignMod {
.collect();
match wasm_import_module {
Some(namespace) if namespace.is_empty() => Err(Error::new(
self_span,
"import module name should be defined by 'wasm_import_module' directive",
)),
Some(namespace) => {
let extern_mod_item = fce_ast_types::AstExternModItem { namespace, imports };
Ok(FCEAst::ExternMod(extern_mod_item))
@ -102,10 +106,16 @@ fn parse_raw_foreign_item(raw_item: syn::ForeignItem) -> Result<fce_ast_types::A
.map(extract_value)
.collect();
let link_name = match link_name {
Some(name) if name.is_empty() => None,
v @ Some(_) => v,
None => None,
};
let function = super::item_fn::parse_function(function_item.sig, function_item.vis)?;
let ast_extern_fn_item = fce_ast_types::AstExternFnItem {
link_name,
function,
signature: function,
};
Ok(ast_extern_fn_item)

View File

@ -14,9 +14,11 @@
* limitations under the License.
*/
mod glue_code_generator;
mod fn_glue_code_generator;
mod foreign_mod_glue_code_generator;
pub(crate) use glue_code_generator::GlueCodeGenerator;
pub(crate) use fn_glue_code_generator::FnGlueCodeGenerator;
pub(crate) use foreign_mod_glue_code_generator::ForeignModeGlueCodeGenerator;
use serde::Serialize;
use serde::Deserialize;
@ -163,4 +165,25 @@ impl ParsedType {
syn::ReturnType::Default => Ok(ParsedType::Empty),
}
}
pub fn to_text_type(&self) -> String {
match self {
ParsedType::Empty => "",
ParsedType::I8 => "i8",
ParsedType::I16 => "i16",
ParsedType::I32 => "i32",
ParsedType::I64 => "i64",
ParsedType::U8 => "u8",
ParsedType::U16 => "u16",
ParsedType::U32 => "u32",
ParsedType::U64 => "u64",
ParsedType::F32 => "f32",
ParsedType::F64 => "f64",
ParsedType::Boolean => "bool",
ParsedType::Utf8String => "String",
ParsedType::ByteVector => "Vec<u8>",
ParsedType::Record(name) => name,
}
.into()
}
}

View File

@ -0,0 +1,299 @@
/*
* Copyright 2018 Fluence Labs Limited
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
use crate::wasm_type::WasmType;
use super::ParsedType;
use quote::quote;
pub(crate) trait FnGlueCodeGenerator {
fn generate_arguments(&self) -> Vec<WasmType>;
fn generate_return_expression(&self) -> proc_macro2::TokenStream;
fn generate_fn_sig_return_expression(&self) -> proc_macro2::TokenStream;
fn generate_fn_prolog(
&self,
generated_arg_id: usize,
supplied_arg_start_id: usize,
) -> proc_macro2::TokenStream;
fn generate_fn_epilog(&self) -> proc_macro2::TokenStream;
}
impl FnGlueCodeGenerator for ParsedType {
fn generate_arguments(&self) -> Vec<WasmType> {
// TODO: investigate possible issues in conversion between signed and unsigned types
match self {
ParsedType::Empty => vec![],
ParsedType::I8 => vec![WasmType::I32],
ParsedType::I16 => vec![WasmType::I32],
ParsedType::I32 => vec![WasmType::I32],
ParsedType::I64 => vec![WasmType::I64],
ParsedType::U8 => vec![WasmType::I32],
ParsedType::U16 => vec![WasmType::I32],
ParsedType::U32 => vec![WasmType::I32],
ParsedType::U64 => vec![WasmType::I64],
ParsedType::F32 => vec![WasmType::F32],
ParsedType::F64 => vec![WasmType::F64],
ParsedType::Boolean => vec![WasmType::I32],
ParsedType::Utf8String => vec![WasmType::I32, WasmType::I32],
ParsedType::ByteVector => vec![WasmType::I32, WasmType::I32],
ParsedType::Record(_) => vec![WasmType::I32, WasmType::I32],
}
}
fn generate_return_expression(&self) -> proc_macro2::TokenStream {
match self {
ParsedType::Utf8String => quote! {},
ParsedType::ByteVector => quote! {},
ParsedType::Record(_) => quote! {},
_ => quote! {
let result =
},
}
}
fn generate_fn_sig_return_expression(&self) -> proc_macro2::TokenStream {
let ty = match self {
ParsedType::I8 => Some("i32"),
ParsedType::I16 => Some("i32"),
ParsedType::I32 => Some("i32"),
ParsedType::I64 => Some("i64"),
ParsedType::U8 => Some("i32"),
ParsedType::U16 => Some("i32"),
ParsedType::U32 => Some("i32"),
ParsedType::U64 => Some("i64"),
ParsedType::F32 => Some("f32"),
ParsedType::F64 => Some("f64"),
ParsedType::Boolean => Some("i32"),
_ => None,
};
match ty {
Some(ty) => {
let ty = syn::Ident::new(ty, proc_macro2::Span::call_site());
quote! { -> #ty}
}
None => quote! {},
}
}
fn generate_fn_prolog(
&self,
generated_arg_id: usize,
supplied_arg_start_id: usize,
) -> proc_macro2::TokenStream {
let generated_arg_id = syn::Ident::new(
&format!("converted_arg_{}", generated_arg_id),
proc_macro2::Span::call_site(),
);
match self {
ParsedType::Empty => unimplemented!(),
ParsedType::I8 => {
let supplied_arg_start_id = syn::Ident::new(
&format!("arg_{}", supplied_arg_start_id),
proc_macro2::Span::call_site(),
);
quote! {
let #generated_arg_id = #supplied_arg_start_id as i8;
}
}
ParsedType::I16 => {
let supplied_arg_start_id = syn::Ident::new(
&format!("arg_{}", supplied_arg_start_id),
proc_macro2::Span::call_site(),
);
quote! {
let #generated_arg_id = #supplied_arg_start_id as i16;
}
}
ParsedType::I32 => {
let supplied_arg_start_id = syn::Ident::new(
&format!("arg_{}", supplied_arg_start_id),
proc_macro2::Span::call_site(),
);
quote! {
let #generated_arg_id = #supplied_arg_start_id as i32;
}
}
ParsedType::I64 => {
let supplied_arg_start_id = syn::Ident::new(
&format!("arg_{}", supplied_arg_start_id),
proc_macro2::Span::call_site(),
);
quote! {
let #generated_arg_id = #supplied_arg_start_id as i64;
}
}
ParsedType::U8 => {
let supplied_arg_start_id = syn::Ident::new(
&format!("arg_{}", supplied_arg_start_id),
proc_macro2::Span::call_site(),
);
quote! {
let #generated_arg_id = #supplied_arg_start_id as u8;
}
}
ParsedType::U16 => {
let supplied_arg_start_id = syn::Ident::new(
&format!("arg_{}", supplied_arg_start_id),
proc_macro2::Span::call_site(),
);
quote! {
let #generated_arg_id = #supplied_arg_start_id as u16;
}
}
ParsedType::U32 => {
let supplied_arg_start_id = syn::Ident::new(
&format!("arg_{}", supplied_arg_start_id),
proc_macro2::Span::call_site(),
);
quote! {
let #generated_arg_id = #supplied_arg_start_id as u32;
}
}
ParsedType::U64 => {
let supplied_arg_start_id = syn::Ident::new(
&format!("arg_{}", supplied_arg_start_id),
proc_macro2::Span::call_site(),
);
quote! {
let #generated_arg_id = #supplied_arg_start_id as u64;
}
}
ParsedType::F32 => {
let supplied_arg_start_id = syn::Ident::new(
&format!("arg_{}", supplied_arg_start_id),
proc_macro2::Span::call_site(),
);
quote! {
let #generated_arg_id = #supplied_arg_start_id as f32;
}
}
ParsedType::F64 => {
let supplied_arg_start_id = syn::Ident::new(
&format!("arg_{}", supplied_arg_start_id),
proc_macro2::Span::call_site(),
);
quote! {
let #generated_arg_id = #supplied_arg_start_id as f64;
}
}
ParsedType::Boolean => {
let supplied_arg_start_id = syn::Ident::new(
&format!("arg_{}", supplied_arg_start_id),
proc_macro2::Span::call_site(),
);
quote! {
let #generated_arg_id = #supplied_arg_start_id as bool;
}
}
ParsedType::Utf8String => {
let ptr = syn::Ident::new(
&format!("arg_{}", supplied_arg_start_id),
proc_macro2::Span::call_site(),
);
let size = syn::Ident::new(
&format!("arg_{}", supplied_arg_start_id + 1),
proc_macro2::Span::call_site(),
);
quote! {
let #generated_arg_id = String::from_raw_parts(#ptr as _, #size as _ , #size as _);
}
}
ParsedType::ByteVector => {
let ptr = syn::Ident::new(
&format!("arg_{}", supplied_arg_start_id),
proc_macro2::Span::call_site(),
);
let size = syn::Ident::new(
&format!("arg_{}", supplied_arg_start_id + 1),
proc_macro2::Span::call_site(),
);
quote! {
let #generated_arg_id = Vec::from_raw_parts(#ptr as _, #size as _, #size as _);
}
}
ParsedType::Record(record_name) => {
quote! {
let #generated_arg_id = __fce_generated_converter_#record_name(
arg_#supplied_arg_start_id,
arg_#(supplied_arg_start_id+1)
);
}
}
}
}
fn generate_fn_epilog(&self) -> proc_macro2::TokenStream {
match self {
ParsedType::Empty => quote! {},
ParsedType::I8 => quote! {
return result as _;
},
ParsedType::I16 => quote! {
return result as _;
},
ParsedType::I32 => quote! {
return result as _;
},
ParsedType::I64 => quote! {
return result as _;
},
ParsedType::U8 => quote! {
return result as _;
},
ParsedType::U16 => quote! {
return result as _;
},
ParsedType::U32 => quote! {
return result as _;
},
ParsedType::U64 => quote! {
return result as _;
},
ParsedType::F32 => quote! {
return result as _;
},
ParsedType::F64 => quote! {
return result as _;
},
ParsedType::Boolean => quote! {
return result as _;
},
ParsedType::Utf8String => quote! {
fluence::set_result_ptr(result.as_ptr() as _);
fluence::set_result_size(result.len() as _);
std::mem::forget(result);
},
ParsedType::ByteVector => quote! {
fluence::set_result_ptr(result.as_ptr() as _);
fluence::set_result_size(result.len() as _);
std::mem::forget(result);
},
ParsedType::Record(_) => quote! {
fluence::set_result_ptr(result.as_ptr() as _);
fluence::set_result_size(result.len() as _);
std::mem::forget(result);
},
}
}
}

View File

@ -0,0 +1,122 @@
/*
* Copyright 2018 Fluence Labs Limited
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
use super::ParsedType;
use quote::quote;
pub(crate) trait ForeignModeGlueCodeGenerator {
fn generate_wrapper_sign_expression(&self) -> proc_macro2::TokenStream;
fn generate_input_type(&self) -> proc_macro2::TokenStream;
fn generate_raw_args(&self, arg_start_id: usize) -> proc_macro2::TokenStream;
fn generate_wrapper_epilog(&self) -> proc_macro2::TokenStream;
}
impl ForeignModeGlueCodeGenerator for ParsedType {
fn generate_wrapper_sign_expression(&self) -> proc_macro2::TokenStream {
match self {
ParsedType::Empty => quote! {},
ty @ _ => {
let ty = syn::Ident::new(&ty.to_text_type(), proc_macro2::Span::call_site());
quote! { -> #ty }
}
}
}
fn generate_input_type(&self) -> proc_macro2::TokenStream {
use quote::ToTokens;
match self {
ParsedType::Empty => quote! {},
ty @ _ => syn::Ident::new(&ty.to_text_type(), proc_macro2::Span::call_site())
.to_token_stream(),
}
}
fn generate_raw_args(&self, arg_start_id: usize) -> proc_macro2::TokenStream {
let arg = syn::Ident::new(
&format!("arg_{}", arg_start_id),
proc_macro2::Span::call_site(),
);
match self {
ParsedType::Utf8String => quote! { #arg.as_ptr() as _, #arg.len() as _ },
ParsedType::ByteVector => quote! { #arg.as_ptr() as _, #arg.len() as _ },
_ => quote! { arg },
}
}
fn generate_wrapper_epilog(&self) -> proc_macro2::TokenStream {
match self {
ParsedType::Empty => quote! {},
ParsedType::I8 => quote! {
return result as _;
},
ParsedType::I16 => quote! {
return result as _;
},
ParsedType::I32 => quote! {
return result as _;
},
ParsedType::I64 => quote! {
return result as _;
},
ParsedType::U8 => quote! {
return result as _;
},
ParsedType::U16 => quote! {
return result as _;
},
ParsedType::U32 => quote! {
return result as _;
},
ParsedType::U64 => quote! {
return result as _;
},
ParsedType::F32 => quote! {
return result as _;
},
ParsedType::F64 => quote! {
return result as _;
},
ParsedType::Boolean => quote! {
return result as _;
},
ParsedType::Utf8String => quote! {
String::from_raw_parts(
fluence::get_result_ptr() as _,
fluence::get_result_size() as _,
fluence::get_result_size() as _
)
},
ParsedType::ByteVector => quote! {
Vec::from_raw_parts(
fluence::get_result_ptr() as _,
fluence::get_result_size() as _,
fluence::get_result_size() as _
)
},
ParsedType::Record(_) => quote! {
fluence::set_result_ptr(result.as_ptr() as _);
fluence::set_result_size(result.len() as _);
std::mem::forget(result);
},
}
}
}

View File

@ -1,207 +0,0 @@
/*
* Copyright 2018 Fluence Labs Limited
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
use crate::wasm_type::WasmType;
use super::ParsedType;
use quote::quote;
pub(crate) trait GlueCodeGenerator {
fn generate_arguments(&self) -> Vec<WasmType>;
fn generate_return_expression(&self) -> proc_macro2::TokenStream;
// TODO: replace String with Ident
fn generate_return_type(&self) -> String;
fn generate_fn_prolog(
&self,
generated_arg_id: usize,
supplied_arg_start_id: usize,
) -> proc_macro2::TokenStream;
fn generate_fn_epilog(&self) -> proc_macro2::TokenStream;
}
impl GlueCodeGenerator for ParsedType {
fn generate_arguments(&self) -> Vec<WasmType> {
// TODO: investigate possible issues in conversion between signed and unsigned types
match self {
ParsedType::Empty => vec![],
ParsedType::I8 => vec![WasmType::I32],
ParsedType::I16 => vec![WasmType::I32],
ParsedType::I32 => vec![WasmType::I32],
ParsedType::I64 => vec![WasmType::I64],
ParsedType::U8 => vec![WasmType::I32],
ParsedType::U16 => vec![WasmType::I32],
ParsedType::U32 => vec![WasmType::I32],
ParsedType::U64 => vec![WasmType::I64],
ParsedType::F32 => vec![WasmType::F32],
ParsedType::F64 => vec![WasmType::F64],
ParsedType::Boolean => vec![WasmType::I32],
ParsedType::Utf8String => vec![WasmType::I32, WasmType::I32],
ParsedType::ByteVector => vec![WasmType::I32, WasmType::I32],
ParsedType::Record(_) => vec![WasmType::I32, WasmType::I32],
}
}
fn generate_return_expression(&self) -> proc_macro2::TokenStream {
match self {
ParsedType::Empty => quote! {},
ParsedType::Utf8String => quote! {},
ParsedType::ByteVector => quote! {},
ParsedType::Record(_) => quote! {},
_ => quote! {
let result =
},
}
}
fn generate_return_type(&self) -> String {
match self {
ParsedType::I8 => "-> i32",
ParsedType::I16 => "-> i32",
ParsedType::I32 => "-> i32",
ParsedType::I64 => "-> i64",
ParsedType::U8 => "-> i32",
ParsedType::U16 => "-> i32",
ParsedType::U32 => "-> i32",
ParsedType::U64 => "-> i64",
ParsedType::F32 => "-> f32",
ParsedType::F64 => "-> f64",
ParsedType::Boolean => "-> i32",
_ => "",
}
.to_string()
}
fn generate_fn_prolog(
&self,
generated_ard_id: usize,
supplied_arg_start_id: usize,
) -> proc_macro2::TokenStream {
match self {
ParsedType::Empty => unimplemented!(),
ParsedType::I8 => quote! {
let converted_arg_#generated_ard_id = arg_#supplied_arg_start_id as i8;
},
ParsedType::I16 => quote! {
let converted_arg_#generated_ard_id = arg_#supplied_arg_start_id as i16;
},
ParsedType::I32 => quote! {
let converted_arg_#generated_ard_id = arg_#supplied_arg_start_id as i32;
},
ParsedType::I64 => quote! {
let converted_arg_#generated_ard_id = arg_#supplied_arg_start_id as i64;
},
ParsedType::U8 => quote! {
let converted_arg_#generated_ard_id = arg_#supplied_arg_start_id as u8;
},
ParsedType::U16 => quote! {
let converted_arg_#generated_ard_id = arg_#supplied_arg_start_id as u16;
},
ParsedType::U32 => quote! {
let converted_arg_#generated_ard_id = arg_#supplied_arg_start_id as u32;
},
ParsedType::U64 => quote! {
let converted_arg_#generated_ard_id = arg_#supplied_arg_start_id as u64;
},
ParsedType::F32 => quote! {
let converted_arg_#generated_ard_id = arg_#supplied_arg_start_id as f32;
},
ParsedType::F64 => quote! {
let converted_arg_#generated_ard_id = arg_#supplied_arg_start_id as f64;
},
ParsedType::Boolean => quote! {
let converted_arg_#generated_ard_id = arg_#supplied_arg_start_id as bool;
},
ParsedType::Utf8String => quote! {
let converted_arg_#generated_ard_id = String::from_raw_parts(
arg_#supplied_arg_start_id,
arg_#(supplied_arg_start_id+1),
arg_#(supplied_arg_start_id+1)
);
},
ParsedType::ByteVector => quote! {
let converted_arg_#generated_ard_id = Vec::from_raw_parts(
arg_#supplied_arg_start_id,
arg_#(supplied_arg_start_id+1),
arg_#(supplied_arg_start_id+1)
);
},
ParsedType::Record(record_name) => quote! {
let converted_arg_#generated_ard_id = __fce_generated_converter_#record_name(
arg_#supplied_arg_start_id,
arg_#(supplied_arg_start_id+1)
);
},
}
}
fn generate_fn_epilog(&self) -> proc_macro2::TokenStream {
match self {
ParsedType::Empty => quote! {},
ParsedType::I8 => quote! {
return result as _;
},
ParsedType::I16 => quote! {
return result as _;
},
ParsedType::I32 => quote! {
return result as _;
},
ParsedType::I64 => quote! {
return result as _;
},
ParsedType::U8 => quote! {
return result as _;
},
ParsedType::U16 => quote! {
return result as _;
},
ParsedType::U32 => quote! {
return result as _;
},
ParsedType::U64 => quote! {
return result as _;
},
ParsedType::F32 => quote! {
return result as _;
},
ParsedType::F64 => quote! {
return result as _;
},
ParsedType::Boolean => quote! {
return result as _;
},
ParsedType::Utf8String => quote! {
fluence::set_result_ptr(result.as_ptr() as _);
fluence::set_result_size(result.len() as _);
std::mem::forget(result);
},
ParsedType::ByteVector => quote! {
fluence::set_result_ptr(result.as_ptr() as _);
fluence::set_result_size(result.len() as _);
std::mem::forget(result);
},
ParsedType::Record(_) => quote! {
fluence::set_result_ptr(result.as_ptr() as _);
fluence::set_result_size(result.len() as _);
std::mem::forget(result);
},
}
}
}

View File

@ -24,7 +24,7 @@ use proc_macro2::TokenStream;
const GENERATED_FUNCS_PREFIX: &str = "__fce_generated_func_";
const GENERATED_SECTION_NAME: &str = "fce_generated_section";
const GENERATED_SECTION_PREFIX: &str = "__fce_generated_section";
const GENERATED_SECTION_PREFIX: &str = "fce_generated_static_global_";
pub(crate) trait TokenStreamGenerator {
fn generate_token_stream(self) -> syn::Result<TokenStream>;

View File

@ -19,7 +19,7 @@ use super::GENERATED_SECTION_NAME;
use super::GENERATED_SECTION_PREFIX;
use super::TokenStreamGenerator;
use crate::fce_ast_types;
use crate::parsed_type::GlueCodeGenerator;
use crate::parsed_type::FnGlueCodeGenerator;
use proc_macro2::TokenStream;
use quote::quote;
@ -27,51 +27,70 @@ use crate::wasm_type::WasmType;
impl TokenStreamGenerator for fce_ast_types::AstFunctionItem {
fn generate_token_stream(self) -> syn::Result<TokenStream> {
let data = serde_json::to_string(&self).unwrap();
let data = serde_json::to_vec(&self).unwrap();
let data_size = data.len();
let func_name = self.rust_name;
let data = syn::LitByteStr::new(&data, proc_macro2::Span::call_site());
let signature = self.signature;
let func_name =
syn::parse_str::<syn::Ident>(&(GENERATED_FUNCS_PREFIX.to_string() + &signature.name))?;
let original_func_ident = syn::parse_str::<syn::Ident>(&signature.name)?;
let export_func_name = signature.name;
//let func_name = syn::parse_str::<syn::Ident>(&(GENERATED_FUNCS_PREFIX.to_string() + &self.name))?;
let prefix = GENERATED_FUNCS_PREFIX;
let section_name = GENERATED_SECTION_NAME;
let section_prefix = GENERATED_SECTION_PREFIX;
let generated_global_name = uuid::Uuid::new_v4().to_string();
//let section_prefix = syn::parse_str::<syn::Ident>(GENERATED_SECTION_PREFIX)?;
let global_static_name = syn::parse_str::<syn::Ident>(
&(GENERATED_SECTION_PREFIX.to_string() + &export_func_name),
)
.unwrap();
let return_type = self.output_type.generate_return_type();
let return_expression = self.output_type.generate_return_expression();
let epilog = self.output_type.generate_fn_epilog();
let return_type = signature.output_type.generate_fn_sig_return_expression();
let return_expression = signature.output_type.generate_return_expression();
let epilog = signature.output_type.generate_fn_epilog();
let mut prolog = TokenStream::new();
let mut args: Vec<String> = Vec::with_capacity(self.input_types.len());
let mut raw_args: Vec<WasmType> = Vec::with_capacity(self.input_types.len());
let mut args: Vec<syn::Ident> = Vec::with_capacity(signature.input_types.len());
let mut raw_arg_names = Vec::with_capacity(signature.input_types.len());
let mut raw_arg_types: Vec<WasmType> = Vec::with_capacity(signature.input_types.len());
let mut input_type_id = 0;
for input_type in self.input_types {
for input_type in signature.input_types {
let type_prolog = input_type.generate_fn_prolog(input_type_id, input_type_id);
let type_raw_args = input_type.generate_arguments();
args.extend(
type_raw_args
.iter()
.enumerate()
.map(|(id, _)| format!("converted_arg_{}", input_type_id + id)),
args.push(
syn::parse_str::<syn::Ident>(&format!("converted_arg_{}", input_type_id)).unwrap(),
);
raw_arg_names.extend(type_raw_args.iter().enumerate().map(|(id, _)| {
syn::parse_str::<syn::Ident>(&format!("arg_{}", input_type_id + id)).unwrap()
}));
input_type_id += type_raw_args.len();
raw_args.extend(type_raw_args);
raw_arg_types.extend(type_raw_args);
prolog.extend(type_prolog);
}
let embedded_tokens = quote! {
let original_func = self.original;
let glue_code = quote! {
#original_func
#[cfg_attr(
target_arch = "wasm32",
export_name = #func_name
export_name = #export_func_name
)]
#[no_mangle]
#[doc(hidden)]
#[allow(clippy::all)]
pub extern "C" unsafe fn #prefix#func_name(#(#raw_args)*) #return_type {
pub unsafe fn #func_name(#(#raw_arg_names: #raw_arg_types),*) #return_type {
#prolog
// calling the original function with converted args
#return_expression #func_name(#(#args)*);
#return_expression #original_func_ident(#(#args), *);
// return value conversation from Rust type to a Wasm type
#epilog
@ -81,9 +100,9 @@ impl TokenStreamGenerator for fce_ast_types::AstFunctionItem {
#[doc(hidden)]
#[allow(clippy::all)]
#[link_section = #section_name]
pub static #func_name#section_prefix#generated_global_name: [u8; #data_size] = { #data };
pub static #global_static_name: [u8; #data_size] = { *#data };
};
Ok(embedded_tokens)
Ok(glue_code)
}
}

View File

@ -22,55 +22,146 @@ use crate::fce_ast_types;
use proc_macro2::TokenStream;
use quote::quote;
use crate::parsed_type::FnGlueCodeGenerator;
use crate::parsed_type::ForeignModeGlueCodeGenerator;
impl TokenStreamGenerator for fce_ast_types::AstExternModItem {
fn generate_token_stream(self) -> syn::Result<TokenStream> {
let data = serde_json::to_string(&self).unwrap();
let data = serde_json::to_vec(&self).unwrap();
let data_size = data.len();
let data = syn::LitByteStr::new(&data, proc_macro2::Span::call_site());
let global_static_name = syn::Ident::new(
&(GENERATED_SECTION_PREFIX.to_string() + &self.namespace.replace(".", "_")),
proc_macro2::Span::call_site(),
);
let prefix = GENERATED_FUNCS_PREFIX;
let section_name = GENERATED_SECTION_NAME;
let section_prefix = GENERATED_SECTION_PREFIX;
let generated_global_name = uuid::Uuid::new_v4().to_string();
let visibility = "pub";
let wasm_import_module_name = self.namespace;
let wasm_import_module_name = &self.namespace;
let generated_imports = generate_extern_section_items(&self);
let wrapper_functions = generate_wrapper_functions(&self);
let glue_code = quote! {
#[link(wasm_import_module = #wasm_import_module_name)]
#[cfg(target_arch = "wasm32")]
// #[cfg(target_arch = "wasm32")]
extern "C" {
fn #import_name(#(#raw_args),*) #import_ret_type;
#generated_imports
}
#[cfg(target_arch = "wasm32")]
unsafe fn #glue_import_name(#(#args),*) #glue_ret_type {
#prolog
#import_name();
}
#[cfg_attr(target_arch = "wasm32")]
#[doc(hidden)]
#[allow(clippy::all)]
#visibility unsafe fn #prefix#func_name(#(#args)*) #return_type {
// arg conversations from Rust types to Wasm types
#prolog
// calling the original function with converted args
#return_expression #func_name(#(#raw_args)*);
// return value conversation from Wasm type to a Rust type
#epilog
}
#wrapper_functions
#[cfg(target_arch = "wasm32")]
#[doc(hidden)]
#[allow(clippy::all)]
#[link_section = #section_name]
pub static #func_name#section_prefix#generated_global_name: [u8; #data_size] = { #data };
pub static #global_static_name: [u8; #data_size] = { *#data };
};
Ok(glue_code)
}
}
fn generate_extern_section_items(extern_item: &fce_ast_types::AstExternModItem) -> TokenStream {
use crate::wasm_type::WasmType;
let mut token_stream = TokenStream::new();
for import in &extern_item.imports {
let ret_type = import
.signature
.output_type
.generate_fn_sig_return_expression();
let link_name = import
.link_name
.as_ref()
.unwrap_or_else(|| &import.signature.name);
let import_name = generate_import_name(&import.signature.name);
let raw_arg_types: Vec<WasmType> = import
.signature
.input_types
.iter()
.map(|input_type| input_type.generate_arguments())
.flatten()
.collect();
let raw_arg_names: Vec<syn::Ident> = raw_arg_types
.iter()
.enumerate()
.map(|(id, _)| syn::Ident::new(&format!("arg_{}", id), proc_macro2::Span::call_site()))
.collect();
let func = quote! {
#[link_name = #link_name]
pub fn #import_name(#(#raw_arg_names: #raw_arg_types),*) #ret_type;
};
token_stream.extend(func);
}
token_stream
}
fn generate_import_name(import_name: &str) -> syn::Ident {
syn::Ident::new(
&format!("{}_{}", GENERATED_FUNCS_PREFIX, import_name),
proc_macro2::Span::call_site(),
)
}
fn generate_wrapper_functions(extern_item: &fce_ast_types::AstExternModItem) -> TokenStream {
let mut token_stream = TokenStream::new();
for import in &extern_item.imports {
let visibility = syn::Ident::new("pub", proc_macro2::Span::call_site());
let func_name = syn::Ident::new(&import.signature.name, proc_macro2::Span::call_site());
let return_type = import
.signature
.output_type
.generate_fn_sig_return_expression();
let arg_types: Vec<proc_macro2::TokenStream> = import
.signature
.input_types
.iter()
.map(|input_type| input_type.generate_input_type())
.collect();
let arg_names: Vec<syn::Ident> = arg_types
.iter()
.enumerate()
.map(|(id, _)| syn::Ident::new(&format!("arg_{}", id), proc_macro2::Span::call_site()))
.collect();
let return_type = import
.signature
.output_type
.generate_wrapper_sign_expression();
let import_func_name = generate_import_name(&import.signature.name);
let raw_args: Vec<proc_macro2::TokenStream> = import
.signature
.input_types
.iter()
.enumerate()
.map(|(id, input_type)| input_type.generate_raw_args(id))
.collect();
let return_expression = import.signature.output_type.generate_return_expression();
let epilog = import.signature.output_type.generate_wrapper_epilog();
let wrapper_func = quote! {
// #[cfg(target_arch = "wasm32")]
#[doc(hidden)]
#[allow(clippy::all)]
#visibility fn #func_name(#(#arg_names: #arg_types), *) #return_type {
unsafe {
// calling the original function with converted args
#return_expression #import_func_name(#(#raw_args), *);
// return value conversation from Wasm type to a Rust type
#epilog
}
}
};
token_stream.extend(wrapper_func);
}
token_stream
}

View File

@ -10,10 +10,18 @@ pub(crate) enum WasmType {
impl quote::ToTokens for WasmType {
fn to_tokens(&self, tokens: &mut TokenStream) {
match self {
WasmType::I32 => "i32".to_tokens(tokens),
WasmType::I64 => "i64".to_tokens(tokens),
WasmType::F32 => "f32".to_tokens(tokens),
WasmType::F64 => "f64".to_tokens(tokens),
WasmType::I32 => {
syn::Ident::new("i32", proc_macro2::Span::call_site()).to_tokens(tokens)
}
WasmType::I64 => syn::parse_str::<syn::Ident>("i64")
.unwrap()
.to_tokens(tokens),
WasmType::F32 => syn::parse_str::<syn::Ident>("f32")
.unwrap()
.to_tokens(tokens),
WasmType::F64 => syn::parse_str::<syn::Ident>("f64")
.unwrap()
.to_tokens(tokens),
}
}
}

View File

@ -26,7 +26,7 @@ use std::alloc::Layout;
pub unsafe fn allocate(size: usize) -> usize {
let layout = match Layout::from_size_align(size, std::mem::align_of::<u8>()) {
Ok(layout) => layout,
// in this case a err could be only in a case of too long allocated size,
// in this case a err may occur only in a case of too long allocated size,
// so just return 0
Err(_) => return 0,
};
@ -43,7 +43,7 @@ pub unsafe fn allocate(size: usize) -> usize {
pub unsafe fn deallocate(ptr: *mut u8, size: usize) {
let layout = match Layout::from_size_align(size, std::mem::align_of::<u8>()) {
Ok(layout) => layout,
// in this case a err could be only in a case of too long allocated size,
// in this case a err may occur only in a case of too long allocated size,
// so just done nothing
Err(_) => return,
};

View File

@ -37,7 +37,7 @@
extern crate fluence_sdk_macro;
extern crate fluence_sdk_main;
pub use fluence_sdk_macro::faas_export;
pub use fluence_sdk_macro::fce;
pub use fluence_sdk_main::get_result_ptr;
pub use fluence_sdk_main::get_result_size;
pub use fluence_sdk_main::set_result_ptr;