This commit is contained in:
vms 2020-11-07 23:16:03 +03:00
parent 2ef43ee778
commit ee93b8788b
17 changed files with 382 additions and 431 deletions

52
Cargo.lock generated
View File

@ -690,6 +690,7 @@ version = "0.1.10"
dependencies = [
"fce-wit-parser",
"fluence-sdk-wit 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)",
"itertools",
"once_cell",
"serde",
"serde_json",
@ -729,15 +730,6 @@ dependencies = [
"serde_json",
]
[[package]]
name = "fluence"
version = "0.2.8"
source = "git+https://github.com/fluencelabs/rust-sdk#a6c587db0b6f22c3d3af81f10b187f148f8e9d30"
dependencies = [
"fluence-sdk-macro 0.2.8 (git+https://github.com/fluencelabs/rust-sdk)",
"fluence-sdk-main 0.2.8 (git+https://github.com/fluencelabs/rust-sdk)",
]
[[package]]
name = "fluence"
version = "0.2.8"
@ -748,6 +740,15 @@ dependencies = [
"fluence-sdk-main 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "fluence"
version = "0.2.8"
source = "git+https://github.com/fluencelabs/rust-sdk#a6c587db0b6f22c3d3af81f10b187f148f8e9d30"
dependencies = [
"fluence-sdk-macro 0.2.8 (git+https://github.com/fluencelabs/rust-sdk)",
"fluence-sdk-main 0.2.8 (git+https://github.com/fluencelabs/rust-sdk)",
]
[[package]]
name = "fluence-app-service"
version = "0.1.11"
@ -786,14 +787,6 @@ dependencies = [
"wasmer-wasi-fl",
]
[[package]]
name = "fluence-sdk-macro"
version = "0.2.8"
source = "git+https://github.com/fluencelabs/rust-sdk#a6c587db0b6f22c3d3af81f10b187f148f8e9d30"
dependencies = [
"fluence-sdk-wit 0.2.8 (git+https://github.com/fluencelabs/rust-sdk)",
]
[[package]]
name = "fluence-sdk-macro"
version = "0.2.8"
@ -804,13 +797,11 @@ dependencies = [
]
[[package]]
name = "fluence-sdk-main"
name = "fluence-sdk-macro"
version = "0.2.8"
source = "git+https://github.com/fluencelabs/rust-sdk#a6c587db0b6f22c3d3af81f10b187f148f8e9d30"
dependencies = [
"fluence-sdk-macro 0.2.8 (git+https://github.com/fluencelabs/rust-sdk)",
"log",
"serde",
"fluence-sdk-wit 0.2.8 (git+https://github.com/fluencelabs/rust-sdk)",
]
[[package]]
@ -825,9 +816,20 @@ dependencies = [
]
[[package]]
name = "fluence-sdk-wit"
name = "fluence-sdk-main"
version = "0.2.8"
source = "git+https://github.com/fluencelabs/rust-sdk#a6c587db0b6f22c3d3af81f10b187f148f8e9d30"
dependencies = [
"fluence-sdk-macro 0.2.8 (git+https://github.com/fluencelabs/rust-sdk)",
"log",
"serde",
]
[[package]]
name = "fluence-sdk-wit"
version = "0.2.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "560baf91197ded38a99a5c94ff366a3dd971ebf33f5d987ecce31d3dedf86d17"
dependencies = [
"proc-macro2",
"quote",
@ -840,8 +842,7 @@ dependencies = [
[[package]]
name = "fluence-sdk-wit"
version = "0.2.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "560baf91197ded38a99a5c94ff366a3dd971ebf33f5d987ecce31d3dedf86d17"
source = "git+https://github.com/fluencelabs/rust-sdk#a6c587db0b6f22c3d3af81f10b187f148f8e9d30"
dependencies = [
"proc-macro2",
"quote",
@ -2809,8 +2810,7 @@ dependencies = [
[[package]]
name = "wasmer-interface-types-fl"
version = "0.17.15"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "88cf928132b7cc391adc52c47ae48aaebff01a85649b815b3e0142f8111c5529"
source = "git+https://github.com/fluencelabs/interface-types?branch=impl_refactoring#4d1d48bbbf9fdd40677474e9ee8d123803534d60"
dependencies = [
"log",
"nom",

View File

@ -15,7 +15,8 @@ fce-wit-parser = { path = "../wit-parser", version = "0.1.9"}
fluence-sdk-wit = "0.2.8"
walrus = "0.17.0"
wasmer-wit = { package = "wasmer-interface-types-fl", version = "=0.17.15" }
wasmer-wit = { package = "wasmer-interface-types-fl", git = "https://github.com/fluencelabs/interface-types", branch = "impl_refactoring" }
itertools = "0.9.0"
once_cell = "1.4.0"
serde = { version = "1.0.110", features = ["derive"] }
serde_json = "1.0.56"

View File

@ -14,12 +14,10 @@
* limitations under the License.
*/
use wasmer_wit::ast::Interfaces;
use wasmer_wit::types::InterfaceType as IType;
use wasmer_wit::ast::FunctionArg as IFunctionArg;
use once_cell::sync::Lazy;
use crate::IType;
use crate::IFunctionArg;
use std::rc::Rc;
use once_cell::sync::Lazy;
pub(crate) struct ApiExportFuncDescriptor {
pub(crate) name: &'static str,
@ -28,22 +26,6 @@ pub(crate) struct ApiExportFuncDescriptor {
pub(crate) output_types: Vec<IType>,
}
impl ApiExportFuncDescriptor {
pub fn update_interfaces(&self, interfaces: &mut Interfaces<'_>) {
let func_type = wasmer_wit::ast::Type::Function {
arguments: Rc::new(self.arguments.clone()),
output_types: Rc::new(self.output_types.clone()),
};
interfaces.types.push(func_type);
let export = wasmer_wit::ast::Export {
name: self.name,
function_type: self.id,
};
interfaces.exports.push(export);
}
}
pub(crate) static ALLOCATE_FUNC: Lazy<ApiExportFuncDescriptor> =
Lazy::new(|| ApiExportFuncDescriptor {
name: "allocate",
@ -76,7 +58,7 @@ pub(crate) static GET_RESULT_SIZE_FUNC: Lazy<ApiExportFuncDescriptor> =
Lazy::new(|| ApiExportFuncDescriptor {
name: "get_result_size",
id: 2,
arguments: vec![],
arguments: Vec::<IFunctionArg>::new(),
output_types: vec![IType::I32],
});
@ -84,7 +66,7 @@ pub(crate) static GET_RESULT_PTR_FUNC: Lazy<ApiExportFuncDescriptor> =
Lazy::new(|| ApiExportFuncDescriptor {
name: "get_result_ptr",
id: 3,
arguments: vec![],
arguments: Vec::<IFunctionArg>::new(),
output_types: vec![IType::I32],
});

View File

@ -19,24 +19,25 @@ mod foreign_mod_instructions;
mod record_instructions;
mod utils;
use crate::Result;
pub(crate) use utils::add_function_type;
use wasmer_wit::types::InterfaceType as IType;
use wasmer_wit::ast::Interfaces;
use wasmer_wit::types::RecordType;
use crate::*;
use crate::default_export_api_config::ApiExportFuncDescriptor;
use std::rc::Rc;
use std::collections::HashMap;
#[derive(PartialEq, Debug, Default)]
pub(crate) struct WITResolver<'a> {
types: std::collections::HashMap<String, usize>,
pub(crate) interfaces: Interfaces<'a>,
not_resolved_types_count: usize,
record_types: HashMap<String, usize>,
unresolved_types_count: usize,
function_types: HashMap<IFunctionType, u32>,
interfaces: Interfaces<'a>,
}
impl<'a> WITResolver<'a> {
pub(crate) fn get_record_type_id(&self, record_name: &str) -> Result<usize> {
match self.types.get(record_name) {
match self.record_types.get(record_name) {
Some(type_index) => Ok(*type_index),
None => Err(crate::errors::WITGeneratorError::CorruptedRecord(format!(
"Can't find record with name='{}', don't you forget to wrap it with #[fce]",
@ -47,27 +48,22 @@ impl<'a> WITResolver<'a> {
// adds a stub for type with such a name if it wasn't found
pub(crate) fn get_record_type_id_unchecked(&mut self, record_name: &str) -> usize {
use wasmer_wit::ast::Type;
match self.types.get(record_name) {
match self.record_types.get(record_name) {
Some(type_index) => *type_index,
None => {
self.types
self.record_types
.insert(record_name.to_string(), self.interfaces.types.len());
self.interfaces
.types
.push(Type::Record(Rc::new(RecordType::default())));
.push(AstType::Record(Rc::new(IRecordType::default())));
self.not_resolved_types_count += 1;
self.unresolved_types_count += 1;
self.interfaces.types.len()
}
}
}
pub(crate) fn get_record_type(
&self,
record_type_id: u64,
) -> Result<&wasmer_wit::types::RecordType> {
pub(crate) fn get_record_type(&self, record_type_id: u64) -> Result<&IRecordType> {
if record_type_id >= self.interfaces.types.len() as u64 {
return Err(crate::errors::WITGeneratorError::CorruptedRecord(format!(
"Can't find record with id {}, don't you forget to wrap it with #[fce]",
@ -76,35 +72,158 @@ impl<'a> WITResolver<'a> {
}
match &self.interfaces.types[record_type_id as usize] {
wasmer_wit::ast::Type::Function { .. } => {
AstType::Function { .. } => {
panic!("internal error inside WITResolver: interfaces AST type should be record not record")
}
wasmer_wit::ast::Type::Record(record_type) => Ok(record_type),
AstType::Record(record_type) => Ok(record_type),
}
}
pub(crate) fn insert_record_type(&mut self, record: RecordType) {
use wasmer_wit::ast::Type;
match self.types.get(&record.name) {
pub(crate) fn insert_record_type(&mut self, record: IRecordType) {
match self.record_types.get(&record.name) {
Some(pos) => {
self.interfaces.types[*pos] = Type::Record(Rc::new(record));
self.not_resolved_types_count -= 1;
self.interfaces.types[*pos] = AstType::Record(Rc::new(record));
self.unresolved_types_count -= 1;
}
None => {
self.types
self.record_types
.insert(record.name.clone(), self.interfaces.types.len());
self.interfaces.types.push(Type::Record(Rc::new(record)));
self.interfaces.types.push(AstType::Record(Rc::new(record)));
}
}
}
pub(crate) fn unresolved_types_count(&self) -> usize {
self.not_resolved_types_count
pub(crate) fn validate_records(&self) -> Result<()> {
use crate::errors::WITGeneratorError::CorruptedRecord;
const TYPE_RESOLVE_RECURSION_LIMIT: u32 = 1024;
fn validate_record_type(
record_type: &IRecordType,
recursion_level: u32,
wit_resolver: &WITResolver<'_>,
) -> Result<()> {
if recursion_level >= TYPE_RESOLVE_RECURSION_LIMIT {
return Err(CorruptedRecord(String::from(
"too many inner structures level",
)));
}
for field in record_type.fields.iter() {
match &field.ty {
wasmer_wit::types::InterfaceType::Record(record_type_id) => {
let inner_record_type = wit_resolver.get_record_type(*record_type_id)?;
validate_record_type(
&inner_record_type,
recursion_level + 1,
wit_resolver,
)?;
}
_ => continue,
}
}
Ok(())
}
if self.unresolved_types_count != 0 {
return Err(CorruptedRecord(format!(
"{} types unresolved",
self.unresolved_types_count
)));
}
for ty in self.interfaces.types.iter() {
let record_type = match ty {
wasmer_wit::ast::Type::Record(ty) => ty,
_ => continue,
};
validate_record_type(record_type, 0, self)?;
}
Ok(())
}
pub(crate) fn insert_default_api(&mut self, function_descriptor: &ApiExportFuncDescriptor) {
let function_type = IFunctionType {
arguments: function_descriptor.arguments.clone(),
output_types: function_descriptor.output_types.clone(),
};
self.interfaces
.types
.push(AstType::Function(Rc::new(function_type)));
let export = AstExport {
name: function_descriptor.name,
function_type: function_descriptor.id,
};
self.interfaces.exports.push(export);
}
/// Insert a new function type if there is no one already,
/// return already inserted otherwise.
pub(crate) fn insert_function_type(&mut self, function_type: IFunctionType) -> u32 {
use std::collections::hash_map::Entry::*;
let next_id = (self.interfaces.types.len() + self.function_types.len()) as u32;
match self.function_types.entry(function_type) {
Occupied(entry) => *entry.get(),
Vacant(entry) => {
entry.insert(next_id);
next_id
}
}
}
/// Insert a new adapter, returns its id.
pub(crate) fn insert_adapter(&mut self, adapter: AstAdapter) -> u32 {
self.interfaces.adapters.push(adapter);
(self.interfaces.adapters.len() - 1) as u32
}
/// Insert a new implementation.
pub(crate) fn insert_implementation(&mut self, implementation: AstImplementation) -> u32 {
self.interfaces.implementations.push(implementation);
(self.interfaces.implementations.len() - 1) as u32
}
/// Insert a new export type and returns its id, that uniquely identifies its
/// and could be used in a call-core instruction.
pub(crate) fn insert_export_type(&mut self, export: AstExport<'a>) -> u32 {
let interfaces = &mut self.interfaces;
interfaces.exports.push(export);
(interfaces.exports.len() - 1) as u32
}
/// Insert a new import type and returns its id, that uniquely identifies its
/// and could be used in a call-core instruction.
pub(crate) fn insert_import_type(&mut self, import: AstImport<'a>) -> u32 {
let interfaces = &mut self.interfaces;
interfaces.imports.push(import);
(interfaces.imports.len() + interfaces.exports.len() - 1) as u32
}
/// Prepares types by insert collected function types and return resulted Interfaces.
pub(crate) fn finalize(mut self) -> Interfaces<'a> {
use itertools::Itertools;
let function_types: Vec<_> = self
.function_types
.into_iter()
.sorted_by(|(_, v1), (_, v2)| v1.cmp(&v2))
.map(|(function_type, _)| AstType::Function(Rc::new(function_type)))
.collect();
self.interfaces.types.extend(function_types);
self.interfaces
}
}
pub(crate) trait WITGenerator {
fn generate_wit<'a>(&'a self, wit_resolver: &mut WITResolver<'a>) -> Result<()>;
fn generate_wit<'ast_type, 'resolver>(&'ast_type self, wit_resolver: &'resolver mut WITResolver<'ast_type>) -> Result<()>;
}

View File

@ -14,107 +14,82 @@
* limitations under the License.
*/
use super::add_function_type;
use super::WITGenerator;
use super::WITResolver;
use super::utils::ptype_to_itype_checked;
use crate::default_export_api_config::*;
use crate::AstExport;
use crate::Result;
use fluence_sdk_wit::AstFunctionItem;
use fluence_sdk_wit::ParsedType;
use wasmer_wit::interpreter::Instruction;
use wasmer_wit::ast::FunctionArg as IFunctionArg;
use std::rc::Rc;
impl WITGenerator for AstFunctionItem {
fn generate_wit<'a>(&'a self, wit_resolver: &mut WITResolver<'a>) -> Result<()> {
use wasmer_wit::ast::Type;
use wasmer_wit::ast::Adapter;
fn generate_wit<'ast_type, 'resolver>(&'ast_type self, wit_resolver: &'resolver mut WITResolver<'ast_type>) -> Result<()> {
let arguments = &self.signature.arguments;
let output_type = &self.signature.output_type;
let arguments = self
.signature
.arguments
.iter()
.map(|(arg_name, arg_type)| -> Result<IFunctionArg> {
Ok(IFunctionArg {
name: arg_name.clone(),
ty: ptype_to_itype_checked(arg_type, wit_resolver)?,
})
})
.collect::<Result<Vec<_>>>()?;
let arguments = Rc::new(arguments);
let output_types = match self.signature.output_type {
Some(ref output_type) => vec![ptype_to_itype_checked(output_type, wit_resolver)?],
None => vec![],
};
let output_types = Rc::new(output_types);
let interfaces = &mut wit_resolver.interfaces;
interfaces.types.push(Type::Function {
arguments: arguments.clone(),
output_types: output_types.clone(),
});
// TODO: replace with Wasm types
interfaces.types.push(Type::Function {
arguments,
output_types,
});
let adapter_idx = (interfaces.types.len() - 2) as u32;
let export_idx = (interfaces.types.len() - 1) as u32;
interfaces.exports.push(wasmer_wit::ast::Export {
let function_type_id = add_function_type(arguments, output_type, wit_resolver)?;
let export_type = AstExport {
name: &self.signature.name,
function_type: export_idx,
});
let mut instructions = self
.signature
.arguments
.iter()
.enumerate()
.try_fold::<_, _, Result<_>>(
Vec::new(),
|mut instructions, (arg_id, (_, input_type))| {
let mut new_instructions = input_type
.generate_instructions_for_input_type(arg_id as _, wit_resolver)?;
instructions.append(&mut new_instructions);
Ok(instructions)
},
)?;
let export_function_index = (wit_resolver.interfaces.exports.len() - 1) as u32;
instructions.push(Instruction::CallCore {
function_index: export_function_index,
});
instructions.extend(match &self.signature.output_type {
Some(output_type) => output_type.generate_instructions_for_output_type(wit_resolver)?,
None => vec![],
});
let adapter = Adapter {
function_type: adapter_idx,
instructions,
function_type: function_type_id,
};
let export_function_id = wit_resolver.insert_export_type(export_type);
wit_resolver.interfaces.adapters.push(adapter);
let adapter_instructions = generate_export_adapter_instructions(
arguments,
output_type,
wit_resolver,
export_function_id,
)?;
let implementation = wasmer_wit::ast::Implementation {
core_function_type: export_idx,
adapter_function_type: adapter_idx,
let adapter = crate::AstAdapter {
function_type: function_type_id,
instructions: adapter_instructions,
};
wit_resolver.interfaces.implementations.push(implementation);
let adapter_id = wit_resolver.insert_adapter(adapter);
let implementation = crate::AstImplementation {
core_function_id: export_function_id,
adapter_function_id: adapter_id,
};
wit_resolver.insert_implementation(implementation);
Ok(())
}
}
fn generate_export_adapter_instructions(
arguments: &[(String, ParsedType)],
output_type: &Option<ParsedType>,
wit_resolver: &mut WITResolver<'_>,
export_function_id: u32,
) -> Result<Vec<Instruction>> {
let mut instructions = arguments.iter().enumerate().try_fold::<_, _, Result<_>>(
Vec::with_capacity(arguments.len()),
|mut instructions, (arg_id, (_, input_type))| {
let mut new_instructions =
input_type.generate_instructions_for_input_type(arg_id as _, wit_resolver)?;
instructions.append(&mut new_instructions);
Ok(instructions)
},
)?;
instructions.push(Instruction::CallCore {
function_index: export_function_id,
});
instructions.extend(match output_type {
Some(output_type) => output_type.generate_instructions_for_output_type(wit_resolver)?,
None => vec![],
});
Ok(instructions)
}
/// Generate WIT instructions for a function.
trait FnInstructionGenerator {
fn generate_instructions_for_input_type<'a>(

View File

@ -14,25 +14,22 @@
* limitations under the License.
*/
use super::add_function_type;
use super::WITGenerator;
use super::WITResolver;
use super::utils::ptype_to_itype_checked;
use crate::*;
use crate::default_export_api_config::*;
use crate::Result;
use fluence_sdk_wit::AstExternModItem;
use fluence_sdk_wit::AstExternFnItem;
use fluence_sdk_wit::ParsedType;
use wasmer_wit::ast::FunctionArg as IFunctionArg;
use wasmer_wit::interpreter::Instruction;
use crate::instructions_generator::utils::wtype_to_itype;
use std::rc::Rc;
const HOST_NAMESPACE_NAME: &str = "host";
impl WITGenerator for AstExternModItem {
fn generate_wit<'a>(&'a self, wit_resolver: &mut WITResolver<'a>) -> Result<()> {
fn generate_wit<'ast_type, 'resolver>(&'ast_type self, wit_resolver: &'resolver mut WITResolver<'ast_type>) -> Result<()> {
// host imports should be left as is
if self.namespace == HOST_NAMESPACE_NAME {
return Ok(());
@ -51,86 +48,51 @@ fn generate_wit_for_import<'a>(
namespace: &'a str,
wit_resolver: &mut WITResolver<'a>,
) -> Result<()> {
use wasmer_wit::ast::Type;
use wasmer_wit::ast::Adapter;
let arguments = &import.signature.arguments;
let output_type = &import.signature.output_type;
let arguments = import
.signature
.arguments
.iter()
.map(|(arg_name, arg_type)| -> Result<IFunctionArg> {
Ok(IFunctionArg {
name: arg_name.clone(),
ty: ptype_to_itype_checked(arg_type, wit_resolver)?,
})
})
.collect::<Result<Vec<_>>>()?;
let arguments = Rc::new(arguments);
let output_types = match import.signature.output_type {
Some(ref output_type) => vec![ptype_to_itype_checked(output_type, wit_resolver)?],
None => vec![],
};
let output_types = Rc::new(output_types);
let interfaces = &mut wit_resolver.interfaces;
interfaces.types.push(Type::Function {
arguments,
output_types,
});
let raw_inputs = import
.signature
.arguments
.iter()
.map(to_raw_input_types)
.flatten()
.collect::<Vec<_>>();
let raw_inputs = Rc::new(raw_inputs);
let raw_outputs = match import.signature.output_type {
Some(ref output_type) => to_raw_output_type(output_type)
.iter()
.map(wtype_to_itype)
.collect(),
None => vec![],
};
let raw_outputs = Rc::new(raw_outputs);
interfaces.types.push(Type::Function {
arguments: raw_inputs.clone(),
output_types: raw_outputs.clone(),
});
interfaces.types.push(Type::Function {
arguments: raw_inputs,
output_types: raw_outputs,
});
let adapter_idx = (interfaces.types.len() - 2) as u32;
let import_idx = (interfaces.types.len() - 3) as u32;
let raw_import_idx = (interfaces.types.len() - 1) as u32;
let function_type_id = add_function_type(arguments, output_type, wit_resolver)?;
let link_name = match &import.link_name {
Some(link_name) => link_name,
None => &import.signature.name,
};
interfaces.imports.push(wasmer_wit::ast::Import {
namespace: &namespace,
let import_type = AstImport {
name: link_name,
function_type: import_idx,
});
namespace,
function_type: function_type_id,
};
let import_function_id = wit_resolver.insert_import_type(import_type);
interfaces.imports.push(wasmer_wit::ast::Import {
namespace: &namespace,
name: link_name,
function_type: raw_import_idx,
});
let adapter_instructions = generate_import_adapter_instructions(
arguments,
output_type,
wit_resolver,
import_function_id,
)?;
let mut instructions = import
.signature
.arguments
let adapter = crate::AstAdapter {
function_type: function_type_id,
instructions: adapter_instructions,
};
let adapter_id = wit_resolver.insert_adapter(adapter);
let implementation = crate::AstImplementation {
core_function_id: import_function_id,
adapter_function_id: adapter_id,
};
wit_resolver.insert_implementation(implementation);
Ok(())
}
fn generate_import_adapter_instructions(
arguments: &[(String, ParsedType)],
output_type: &Option<ParsedType>,
wit_resolver: &mut WITResolver<'_>,
import_function_id: u32,
) -> Result<Vec<Instruction>> {
let mut instructions = arguments
.iter()
.try_fold::<_, _, Result<_>>(
(0, Vec::new()),
@ -144,32 +106,16 @@ fn generate_wit_for_import<'a>(
)?
.1;
// TODO: refactor
let import_function_index = (wit_resolver.interfaces.exports.len()
+ wit_resolver.interfaces.imports.len() / 2
- 1) as u32;
instructions.push(Instruction::CallCore {
function_index: import_function_index,
function_index: import_function_id,
});
instructions.extend(match &import.signature.output_type {
instructions.extend(match output_type {
Some(output_type) => output_type.generate_instructions_for_output_type(wit_resolver)?,
None => vec![],
});
let adapter = Adapter {
function_type: adapter_idx,
instructions,
};
wit_resolver.interfaces.adapters.push(adapter);
let implementation = wasmer_wit::ast::Implementation {
core_function_type: raw_import_idx,
adapter_function_type: adapter_idx,
};
wit_resolver.interfaces.implementations.push(implementation);
Ok(())
Ok(instructions)
}
/// Generate WIT instructions for a foreign mod.
@ -277,60 +223,3 @@ impl ForeignModInstructionGenerator for ParsedType {
Ok(instructions)
}
}
use fluence_sdk_wit::RustType;
use wasmer_wit::types::InterfaceType as IType;
pub fn to_raw_input_types(arg: &(String, ParsedType)) -> Vec<IFunctionArg> {
match arg.1 {
ParsedType::Boolean
| ParsedType::I8
| ParsedType::I16
| ParsedType::I32
| ParsedType::U8
| ParsedType::U16
| ParsedType::U32
| ParsedType::Record(_) => vec![IFunctionArg {
name: arg.0.clone(),
ty: IType::I32,
}],
ParsedType::I64 | ParsedType::U64 => vec![IFunctionArg {
name: arg.0.clone(),
ty: IType::I64,
}],
ParsedType::F32 => vec![IFunctionArg {
name: arg.0.clone(),
ty: IType::F32,
}],
ParsedType::F64 => vec![IFunctionArg {
name: arg.0.clone(),
ty: IType::F64,
}],
ParsedType::Utf8String | ParsedType::Vector(_) => vec![
IFunctionArg {
name: format!("{}_ptr", arg.0),
ty: IType::I32,
},
IFunctionArg {
name: format!("{}_ptr", arg.0),
ty: IType::I32,
},
],
}
}
pub fn to_raw_output_type(ty: &ParsedType) -> Vec<RustType> {
match ty {
ParsedType::Boolean
| ParsedType::I8
| ParsedType::I16
| ParsedType::I32
| ParsedType::U8
| ParsedType::U16
| ParsedType::U32 => vec![RustType::I32],
ParsedType::I64 | ParsedType::U64 => vec![RustType::I64],
ParsedType::F32 => vec![RustType::F32],
ParsedType::F64 => vec![RustType::F64],
ParsedType::Utf8String | ParsedType::Vector(_) | ParsedType::Record(_) => vec![],
}
}

View File

@ -25,13 +25,15 @@ use wasmer_wit::types::RecordType;
use wasmer_wit::vec1::Vec1;
impl WITGenerator for AstRecordItem {
fn generate_wit<'a>(&'a self, wit_resolver: &mut WITResolver<'a>) -> Result<()> {
fn generate_wit<'ast_type, 'resolver>(&'ast_type self, wit_resolver: &'resolver mut WITResolver<'ast_type>) -> Result<()> {
use super::utils::ptype_to_itype_unchecked;
let fields = self
.fields
.iter()
.map(|field| IRecordFieldType {
name: field.name.clone().unwrap_or_default(),
ty: super::utils::ptype_to_itype_unchecked(&field.ty, wit_resolver),
ty: ptype_to_itype_unchecked(&field.ty, wit_resolver),
})
.collect::<Vec<_>>();

View File

@ -14,12 +14,13 @@
* limitations under the License.
*/
use super::IType;
use crate::IType;
use crate::IFunctionArg;
use crate::IFunctionType;
use crate::instructions_generator::WITResolver;
use crate::Result;
use fluence_sdk_wit::ParsedType;
use fluence_sdk_wit::RustType;
// return error if there is no record with such name
pub(crate) fn ptype_to_itype_checked(
@ -78,17 +79,30 @@ pub(crate) fn ptype_to_itype_unchecked(
}
}
pub(crate) fn wtype_to_itype(pty: &RustType) -> IType {
match pty {
RustType::I8 => IType::S8,
RustType::I16 => IType::S16,
RustType::I32 => IType::S32,
RustType::I64 => IType::S64,
RustType::U8 => IType::U8,
RustType::U16 => IType::U16,
RustType::U32 => IType::U32,
RustType::U64 => IType::U64,
RustType::F32 => IType::F32,
RustType::F64 => IType::F64,
}
pub(crate) fn add_function_type(
arguments: &Vec<(String, ParsedType)>,
output_type: &Option<ParsedType>,
wit_resolver: &mut WITResolver<'_>,
) -> Result<u32> {
let arguments = arguments
.iter()
.map(|(arg_name, arg_type)| -> Result<IFunctionArg> {
Ok(IFunctionArg {
name: arg_name.clone(),
ty: ptype_to_itype_checked(&arg_type, wit_resolver)?,
})
})
.collect::<Result<Vec<_>>>()?;
let output_types = match output_type {
Some(output_type) => vec![ptype_to_itype_checked(output_type, wit_resolver)?],
None => vec![],
};
let function_type = IFunctionType {
arguments,
output_types,
};
Ok(wit_resolver.insert_function_type(function_type))
}

View File

@ -20,9 +20,6 @@ use crate::instructions_generator::WITGenerator;
use crate::instructions_generator::WITResolver;
use crate::Result;
pub use fluence_sdk_wit::FCEAst;
use wasmer_wit::ast::Interfaces;
/// Parse generated by rust-sdk AST types, generate instructions and embed them to Wasm file.
pub fn embed_wit(path: std::path::PathBuf) -> Result<()> {
let wasm_module = walrus::ModuleConfig::new()
@ -30,9 +27,12 @@ pub fn embed_wit(path: std::path::PathBuf) -> Result<()> {
.map_err(|e| WITGeneratorError::IOError(format!("{:?} can't be parsed: {:?}", path, e)))?;
let module_ast = wasm_ast_extractor(&wasm_module)?;
let interfaces = generate_interfaces(&module_ast)?;
let mut wit_resolver = WITResolver::default();
generate_interfaces(&module_ast, &mut wit_resolver)?;
let wasm_module = fce_wit_parser::delete_wit_section(wasm_module);
let interfaces = wit_resolver.finalize();
let mut wasm_module = fce_wit_parser::embed_wit(wasm_module, &interfaces);
wasm_module.emit_wasm_file(path).map_err(|e| {
@ -55,13 +55,15 @@ fn wasm_ast_extractor(wasm_module: &walrus::Module) -> Result<ModuleAST> {
let mut extern_mods: Vec<AstExternModItem> = Vec::new();
// consider only sections name of that starts with GENERATED_SECTION_PREFIX
for custom_module in wasm_module.customs.iter().filter(|(_, section)| {
let custom_sections = wasm_module.customs.iter().filter(|(_, section)| {
section
.name()
.starts_with(fluence_sdk_wit::GENERATED_SECTION_PREFIX)
}) {
});
for custom_section in custom_sections {
let default_ids = walrus::IdsToIndices::default();
let raw_data = custom_module.1.data(&default_ids);
let raw_data = custom_section.1.data(&default_ids);
let decoded_json: FCEAst = serde_json::from_slice(&raw_data)?;
match decoded_json {
FCEAst::Record(record) => records.push(record),
@ -77,77 +79,33 @@ fn wasm_ast_extractor(wasm_module: &walrus::Module) -> Result<ModuleAST> {
})
}
fn generate_interfaces(module_ast: &ModuleAST) -> Result<Interfaces<'_>> {
let mut wit_resolver = WITResolver::default();
generate_default_export_api(&mut wit_resolver.interfaces);
fn generate_interfaces<'ast, 'wit_resolver>(
module_ast: &'ast ModuleAST,
wit_resolver: &'wit_resolver mut WITResolver<'ast>,
) -> Result<()> {
generate_default_export_api(wit_resolver);
for record in &module_ast.records {
record.generate_wit(&mut wit_resolver)?;
record.generate_wit(wit_resolver)?;
}
validate_records(&wit_resolver)?;
wit_resolver.validate_records()?;
for function in &module_ast.functions {
function.generate_wit(&mut wit_resolver)?;
function.generate_wit(wit_resolver)?;
}
for extern_mod in &module_ast.extern_mods {
extern_mod.generate_wit(&mut wit_resolver)?;
}
Ok(wit_resolver.interfaces)
}
fn generate_default_export_api(interfaces: &mut Interfaces<'_>) {
// TODO: the order is matter
ALLOCATE_FUNC.update_interfaces(interfaces);
DEALLOCATE_FUNC.update_interfaces(interfaces);
GET_RESULT_SIZE_FUNC.update_interfaces(interfaces);
GET_RESULT_PTR_FUNC.update_interfaces(interfaces);
SET_RESULT_SIZE_FUNC.update_interfaces(interfaces);
SET_RESULT_PTR_FUNC.update_interfaces(interfaces);
}
fn validate_records(wit_resolver: &WITResolver<'_>) -> Result<()> {
const TYPE_RESOLVE_RECURSION_LIMIT: u32 = 1024;
fn validate_record_type(
record_type: &wasmer_wit::types::RecordType,
recursion_level: u32,
wit_resolver: &WITResolver<'_>,
) -> Result<()> {
if recursion_level >= TYPE_RESOLVE_RECURSION_LIMIT {
return Err(WITGeneratorError::CorruptedRecord(String::from(
"too many inner structures level",
)));
}
for field in record_type.fields.iter() {
match &field.ty {
wasmer_wit::types::InterfaceType::Record(record_type_id) => {
let inner_record_type = wit_resolver.get_record_type(*record_type_id)?;
validate_record_type(&inner_record_type, recursion_level + 1, wit_resolver)?;
}
_ => continue,
}
}
Ok(())
}
if wit_resolver.unresolved_types_count() != 0 {
return Err(WITGeneratorError::CorruptedRecord(format!(
"{} types unresolved",
wit_resolver.unresolved_types_count()
)));
}
for ty in wit_resolver.interfaces.types.iter() {
let record_type = match ty {
wasmer_wit::ast::Type::Record(ty) => ty,
_ => continue,
};
validate_record_type(record_type, 0, wit_resolver)?;
extern_mod.generate_wit(wit_resolver)?;
}
Ok(())
}
fn generate_default_export_api(wit_resolver: &mut WITResolver<'_>) {
// TODO: the order is matter
wit_resolver.insert_default_api(&ALLOCATE_FUNC);
wit_resolver.insert_default_api(&DEALLOCATE_FUNC);
wit_resolver.insert_default_api(&GET_RESULT_SIZE_FUNC);
wit_resolver.insert_default_api(&GET_RESULT_PTR_FUNC);
wit_resolver.insert_default_api(&SET_RESULT_SIZE_FUNC);
wit_resolver.insert_default_api(&SET_RESULT_PTR_FUNC);
}

View File

@ -34,3 +34,14 @@ pub use interface_generator::embed_wit;
pub use errors::WITGeneratorError;
pub(crate) type Result<T> = std::result::Result<T, WITGeneratorError>;
pub(crate) use wasmer_wit::ast::Interfaces;
pub(crate) use wasmer_wit::ast::Adapter as AstAdapter;
pub(crate) use wasmer_wit::ast::Type as AstType;
pub(crate) use wasmer_wit::ast::Export as AstExport;
pub(crate) use wasmer_wit::ast::Import as AstImport;
pub(crate) use wasmer_wit::ast::Implementation as AstImplementation;
pub(crate) use wasmer_wit::types::InterfaceType as IType;
pub(crate) use wasmer_wit::types::RecordType as IRecordType;
pub(crate) use wasmer_wit::types::FunctionArg as IFunctionArg;
pub(crate) use wasmer_wit::types::FunctionType as IFunctionType;

View File

@ -11,5 +11,5 @@ name = "fce_wit_interfaces"
path = "src/lib.rs"
[dependencies]
wasmer-wit = { package = "wasmer-interface-types-fl", version = "=0.17.15" }
wasmer-wit = { package = "wasmer-interface-types-fl", git = "https://github.com/fluencelabs/interface-types", branch = "impl_refactoring" }
multimap = "0.8.1"

View File

@ -77,8 +77,8 @@ impl<'a> FCEWITInterfaces<'a> {
.iter()
.map(|implementation| {
(
implementation.adapter_function_type,
implementation.core_function_type,
implementation.adapter_function_id,
implementation.core_function_id,
)
})
.collect::<MultiMap<_, _>>();
@ -88,8 +88,8 @@ impl<'a> FCEWITInterfaces<'a> {
.iter()
.map(|implementation| {
(
implementation.core_function_type,
implementation.adapter_function_type,
implementation.core_function_id,
implementation.adapter_function_id,
)
})
.collect::<MultiMap<_, _>>();
@ -189,15 +189,15 @@ impl<'a> FCEWITInterfaces<'a> {
pub fn adapter_types_by_core_type(
&self,
core_function_type: CoreFunctionType,
core_function_id: CoreFunctionType,
) -> Option<&Vec<AdapterFunctionType>> {
self.core_type_to_adapter.get_vec(&core_function_type)
self.core_type_to_adapter.get_vec(&core_function_id)
}
pub fn core_types_by_adapter_type(
&self,
adapter_function_type: AdapterFunctionType,
adapter_function_id: AdapterFunctionType,
) -> Option<&Vec<CoreFunctionType>> {
self.adapter_type_to_core.get_vec(&adapter_function_type)
self.adapter_type_to_core.get_vec(&adapter_function_id)
}
}

View File

@ -16,4 +16,4 @@ fce-wit-interfaces = { path = "../wit-interfaces", version = "0.1.7" }
anyhow = "1.0.31"
walrus = "0.17.0"
wasmer-core = { package = "wasmer-runtime-core-fl", version = "0.17.0"}
wasmer-wit = { package = "wasmer-interface-types-fl", version = "=0.17.15" }
wasmer-wit = { package = "wasmer-interface-types-fl", git = "https://github.com/fluencelabs/interface-types", branch = "impl_refactoring" }

View File

@ -18,7 +18,7 @@ fce-utils = { path = "../crates/utils", version = "0.1.0" }
wasmer-runtime = { package = "wasmer-runtime-fl", version = "0.17.0" }
# dynamicfunc-fat-closures allows using state inside DynamicFunc
wasmer-core = { package = "wasmer-runtime-core-fl", version = "0.17.0", features = ["dynamicfunc-fat-closures"] }
wasmer-wit = { package = "wasmer-interface-types-fl", version = "=0.17.15" }
wasmer-wit = { package = "wasmer-interface-types-fl", git = "https://github.com/fluencelabs/interface-types", branch = "impl_refactoring" }
wasmer-wasi = { package = "wasmer-wasi-fl", version = "0.17.0" }
multimap = "0.8.1"

View File

@ -249,24 +249,24 @@ impl FCEModule {
use fce_wit_interfaces::WITAstType;
wit.implementations()
.filter_map(|(adapter_function_type, core_function_type)| {
match wit.exports_by_type(*core_function_type) {
.filter_map(|(adapter_function_id, core_function_id)| {
match wit.exports_by_type(*core_function_id) {
Some(export_function_name) => {
Some((adapter_function_type, export_function_name))
Some((adapter_function_id, export_function_name))
}
// pass functions that aren't export
None => None,
}
})
.map(|(adapter_function_type, export_function_names)| {
.map(|(adapter_function_id, export_function_names)| {
export_function_names
.iter()
.map(move |export_function_name| (*adapter_function_type, export_function_name))
.map(move |export_function_name| (*adapter_function_id, export_function_name))
})
.flatten()
.map(|(adapter_function_type, export_function_name)| {
let adapter_instructions = wit.adapter_by_type_r(adapter_function_type)?;
let wit_type = wit.type_by_idx_r(adapter_function_type)?;
.map(|(adapter_function_id, export_function_name)| {
let adapter_instructions = wit.adapter_by_type_r(adapter_function_id)?;
let wit_type = wit.type_by_idx_r(adapter_function_id)?;
match wit_type {
WITAstType::Function {
@ -291,7 +291,7 @@ impl FCEModule {
}
_ => Err(FCEError::IncorrectWIT(format!(
"type with idx = {} isn't a function type",
adapter_function_type
adapter_function_id
))),
}
})
@ -373,22 +373,22 @@ impl FCEModule {
let wit_import_funcs = wit
.implementations()
.filter_map(|(adapter_function_type, core_function_type)| {
match wit.imports_by_type(*core_function_type) {
Some(import) => Some((adapter_function_type, import)),
.filter_map(|(adapter_function_id, core_function_id)| {
match wit.imports_by_type(*core_function_id) {
Some(import) => Some((adapter_function_id, import)),
// skip functions that aren't import
None => None,
}
})
.map(|(adapter_function_type, import_function_names)| {
.map(|(adapter_function_id, import_function_names)| {
import_function_names
.iter()
.map(move |import_function_name| (*adapter_function_type, import_function_name))
.map(move |import_function_name| (*adapter_function_id, import_function_name))
})
.flatten()
.map(|(adapter_function_type, (import_namespace, import_name))| {
let adapter_instructions = wit.adapter_by_type_r(adapter_function_type)?;
let wit_type = wit.type_by_idx_r(adapter_function_type)?;
.map(|(adapter_function_id, (import_namespace, import_name))| {
let adapter_instructions = wit.adapter_by_type_r(adapter_function_id)?;
let wit_type = wit.type_by_idx_r(adapter_function_id)?;
match wit_type {
WITAstType::Function {
@ -415,7 +415,7 @@ impl FCEModule {
}
_ => Err(FCEError::IncorrectWIT(format!(
"type with idx = {} isn't a function type",
adapter_function_type
adapter_function_id
))),
}
})

View File

@ -79,7 +79,7 @@ impl WITInstance {
let export_func = module_exports.get(export.name)?;
unsafe {
// TODO: refactor this with new Wasmer API when it is ready
// here it is safe because dyn func is never lives WITInstance
// here it is safe because dyn func is never leaves WITInstance
let export_func =
std::mem::transmute::<DynFunc<'_>, DynFunc<'static>>(export_func);
Ok((

View File

@ -15,7 +15,7 @@ wasmer-runtime = { package = "wasmer-runtime-fl", version = "0.17.0" }
# dynamicfunc-fat-closures allows using state inside DynamicFunc
wasmer-core = { package = "wasmer-runtime-core-fl", version = "0.17.0", features = ["dynamicfunc-fat-closures"] }
wasmer-wasi = { package = "wasmer-wasi-fl", version = "0.17.0" }
wasmer-wit = { package = "wasmer-interface-types-fl", version = "=0.17.15" }
wasmer-wit = { package = "wasmer-interface-types-fl", git = "https://github.com/fluencelabs/interface-types", branch = "impl_refactoring" }
toml = "0.5.6"
serde = { version = "1.0.111", features = ["derive"] }