move fce to fce_wit_interfaces

This commit is contained in:
vms
2020-06-04 19:06:23 +03:00
parent f2cafd0770
commit 6a7dbb47c8
10 changed files with 237 additions and 288 deletions

28
Cargo.lock generated
View File

@ -361,6 +361,20 @@ dependencies = [
"synstructure", "synstructure",
] ]
[[package]]
name = "fce"
version = "0.2.0"
dependencies = [
"fce_wit_interfaces",
"multimap",
"parity-wasm",
"pwasm-utils",
"wasmer-interface-types",
"wasmer-runtime",
"wasmer-runtime-core",
"wasmer-wasi",
]
[[package]] [[package]]
name = "fce_wit_interfaces" name = "fce_wit_interfaces"
version = "0.1.0" version = "0.1.0"
@ -369,6 +383,7 @@ dependencies = [
"multimap", "multimap",
"walrus", "walrus",
"wasmer-interface-types", "wasmer-interface-types",
"wasmer-runtime-core",
] ]
[[package]] [[package]]
@ -1209,16 +1224,3 @@ dependencies = [
"failure", "failure",
"fce_wit_interfaces", "fce_wit_interfaces",
] ]
[[package]]
name = "wit_fce"
version = "0.2.0"
dependencies = [
"multimap",
"parity-wasm",
"pwasm-utils",
"wasmer-interface-types",
"wasmer-runtime",
"wasmer-runtime-core",
"wasmer-wasi",
]

View File

@ -10,6 +10,8 @@ path = "src/lib.rs"
[dependencies] [dependencies]
walrus = "0.17.0" walrus = "0.17.0"
wasmer-core = { package = "wasmer-runtime-core", version = "0.17.0", features = ["dynamicfunc-fat-closures"] }
wasmer-wit = { package = "wasmer-interface-types", git = "https://github.com/fluencelabs/interface-types", branch = "master"} wasmer-wit = { package = "wasmer-interface-types", git = "https://github.com/fluencelabs/interface-types", branch = "master"}
multimap = "0.8.1" multimap = "0.8.1"
anyhow = "1.0.31" anyhow = "1.0.31"

View File

@ -23,39 +23,35 @@ use std::collections::HashMap;
pub type CoreFunctionType = u32; pub type CoreFunctionType = u32;
pub type AdapterFunctionType = u32; pub type AdapterFunctionType = u32;
pub type ExportName = String; pub type ExportName<'a> = &'a str;
pub type ImportName = String; pub type ImportName<'a> = &'a str;
pub type ImportNamespace = String; pub type ImportNamespace<'a> = &'a str;
pub type WITAstType = Type;
pub struct FCEWITInterfaces { pub struct FCEWITInterfaces<'a> {
/// All the types. /// All the types.
types: Vec<Type>, types: Vec<WITAstType>,
/// All the imported functions. /// All the imported functions.
imports: HashMap<CoreFunctionType, (ImportName, ImportNamespace)>, imports: HashMap<CoreFunctionType, (ImportName<'a>, ImportNamespace<'a>)>,
/// All the adapters. /// All the adapters.
adapters: HashMap<AdapterFunctionType, Vec<Instruction>>, adapters: HashMap<AdapterFunctionType, Vec<Instruction>>,
/// All the exported functions. /// All the exported functions.
exports: HashMap<CoreFunctionType, ExportName>, exports: HashMap<CoreFunctionType, ExportName<'a>>,
/// All the implementations. /// All the implementations.
adapter_type_to_core: MultiMap<AdapterFunctionType, CoreFunctionType>, adapter_type_to_core: MultiMap<AdapterFunctionType, CoreFunctionType>,
core_type_to_adapter: MultiMap<CoreFunctionType, AdapterFunctionType>, core_type_to_adapter: MultiMap<CoreFunctionType, AdapterFunctionType>,
} }
impl FCEWITInterfaces { impl<'a> FCEWITInterfaces<'a> {
pub fn new(interfaces: Interfaces<'_>) -> Self { pub fn new(interfaces: Interfaces<'a>) -> Self {
let imports = interfaces let imports = interfaces
.imports .imports
.into_iter() .into_iter()
.map(|import| { .map(|import| (import.function_type, (import.namespace, import.name)))
(
import.function_type,
(import.namespace.to_owned(), import.name.to_owned()),
)
})
.collect::<HashMap<_, _>>(); .collect::<HashMap<_, _>>();
let adapters = interfaces let adapters = interfaces
@ -67,7 +63,7 @@ impl FCEWITInterfaces {
let exports = interfaces let exports = interfaces
.exports .exports
.into_iter() .into_iter()
.map(|export| (export.function_type, export.name.to_owned())) .map(|export| (export.function_type, export.name))
.collect::<HashMap<_, _>>(); .collect::<HashMap<_, _>>();
let adapter_type_to_core = interfaces let adapter_type_to_core = interfaces
@ -102,8 +98,8 @@ impl FCEWITInterfaces {
} }
} }
pub fn type_by_idx(&self, idx: usize) -> Option<&Type> { pub fn type_by_idx(&self, idx: u32) -> Option<&Type> {
self.types.get(idx) self.types.get(idx as usize)
} }
pub fn types(&self) -> impl Iterator<Item = &Type> { pub fn types(&self) -> impl Iterator<Item = &Type> {
@ -113,13 +109,13 @@ impl FCEWITInterfaces {
pub fn import_by_type( pub fn import_by_type(
&self, &self,
import_type: CoreFunctionType, import_type: CoreFunctionType,
) -> Option<&(ImportName, ImportNamespace)> { ) -> Option<&(ImportName<'a>, ImportNamespace<'a>)> {
self.imports.get(&import_type) self.imports.get(&import_type)
} }
pub fn imports( pub fn imports(
&self, &self,
) -> impl Iterator<Item = (&CoreFunctionType, &(ImportName, ImportNamespace))> { ) -> impl Iterator<Item = (&CoreFunctionType, &(ImportName<'a>, ImportNamespace<'a>))> {
self.imports.iter() self.imports.iter()
} }
@ -127,22 +123,22 @@ impl FCEWITInterfaces {
self.adapters.get(&adapter_type) self.adapters.get(&adapter_type)
} }
pub fn export_by_type(&self, export_type: u32) -> Option<&ExportName> { pub fn export_by_type(&self, export_type: u32) -> Option<&ExportName<'a>> {
self.exports.get(&export_type) self.exports.get(&export_type)
} }
pub fn adapter_func_implementations( pub fn exports(
&self,
) -> impl Iterator<Item = (&CoreFunctionType, &ExportName<'a>)> {
self.exports.iter()
}
pub fn implementations(
&self, &self,
) -> impl Iterator<Item = (&AdapterFunctionType, &CoreFunctionType)> { ) -> impl Iterator<Item = (&AdapterFunctionType, &CoreFunctionType)> {
self.adapter_type_to_core.iter() self.adapter_type_to_core.iter()
} }
pub fn core_func_implementations(
&self,
) -> impl Iterator<Item = (&CoreFunctionType, &AdapterFunctionType)> {
self.core_type_to_adapter.iter()
}
pub fn adapter_types_by_core_type( pub fn adapter_types_by_core_type(
&self, &self,
core_function_type: CoreFunctionType, core_function_type: CoreFunctionType,

View File

@ -20,40 +20,47 @@ use crate::fce_wit_interfaces::FCEWITInterfaces;
use walrus::{IdsToIndices, ModuleConfig}; use walrus::{IdsToIndices, ModuleConfig};
use wasmer_wit::ast::Interfaces; use wasmer_wit::ast::Interfaces;
use wasmer_core::Module as WasmerModule;
use std::path::PathBuf; use std::path::PathBuf;
/// Extracts WIT section of provided Wasm binary and converts it to a string.
pub fn extract_text_wit(wasm_file_path: PathBuf) -> Result<String, WITParserError> { pub fn extract_text_wit(wasm_file_path: PathBuf) -> Result<String, WITParserError> {
let wit_section_bytes = extract_wit_section_bytes(wasm_file_path)?;
extract_wit_with_fn( extract_wit_with_fn(
wasm_file_path, &wit_section_bytes,
|wit: Interfaces<'_>| -> Result<String, WITParserError> { Ok((&wit).to_string()) }, |wit: Interfaces<'_>| -> Result<String, WITParserError> { Ok((&wit).to_string()) },
) )
} }
pub fn extract_fce_wit(wasm_file_path: PathBuf) -> Result<FCEWITInterfaces, WITParserError> { /// Extracts WIT section of provided Wasm binary and converts it to a FCEWITInterfaces.
pub fn extract_fce_wit(
wasmer_module: &WasmerModule,
) -> Result<FCEWITInterfaces<'_>, WITParserError> {
let wit_sections = wasmer_module
.custom_sections(WIT_SECTION_NAME)
.ok_or_else(|| WITParserError::NoWITSection)?;
if wit_sections.len() > 1 {
return Err(WITParserError::MultipleWITSections);
}
extract_wit_with_fn( extract_wit_with_fn(
wasm_file_path, &wit_sections[0],
|wit: Interfaces<'_>| -> Result<FCEWITInterfaces, WITParserError> { |wit: Interfaces<'_>| -> Result<FCEWITInterfaces<'_>, WITParserError> {
Ok(FCEWITInterfaces::new(wit)) Ok(FCEWITInterfaces::new(wit))
}, },
) )
} }
fn extract_wit_with_fn<F, FResultType>( fn extract_wit_with_fn<'a, F, FResultType: 'a>(
wasm_file_path: PathBuf, wit_section_bytes: &'a [u8],
func: F, func: F,
) -> Result<FResultType, WITParserError> ) -> Result<FResultType, WITParserError>
where where
F: FnOnce(Interfaces<'_>) -> Result<FResultType, WITParserError>, F: FnOnce(Interfaces<'a>) -> Result<FResultType, WITParserError>,
{ {
let wit_section_bytes = extract_wit_section_bytes(wasm_file_path)?; let raw_wit = match wasmer_wit::decoders::binary::parse::<()>(&wit_section_bytes) {
let raw_wit = extract_raw_interfaces(&wit_section_bytes)?;
func(raw_wit)
}
fn extract_raw_interfaces(wit_section_bytes: &[u8]) -> Result<Interfaces<'_>, WITParserError> {
let wit = match wasmer_wit::decoders::binary::parse::<()>(&wit_section_bytes) {
Ok((remainder, wit)) if remainder.is_empty() => wit, Ok((remainder, wit)) if remainder.is_empty() => wit,
Ok(_) => { Ok(_) => {
return Err(WITParserError::WITRemainderNotEmpty); return Err(WITParserError::WITRemainderNotEmpty);
@ -63,7 +70,7 @@ fn extract_raw_interfaces(wit_section_bytes: &[u8]) -> Result<Interfaces<'_>, WI
} }
}; };
Ok(wit) func(raw_wit)
} }
fn extract_wit_section_bytes(wasm_file_path: PathBuf) -> Result<Vec<u8>, WITParserError> { fn extract_wit_section_bytes(wasm_file_path: PathBuf) -> Result<Vec<u8>, WITParserError> {

View File

@ -1,6 +1,6 @@
mod custom; mod custom;
mod errors; mod errors;
mod extracter; mod extractor;
mod embedder; mod embedder;
pub use errors::WITParserError; pub use errors::WITParserError;
@ -8,5 +8,5 @@ pub use errors::WITParserError;
pub use embedder::EmbedderConfig; pub use embedder::EmbedderConfig;
pub use embedder::embed_text_wit; pub use embedder::embed_text_wit;
pub use extracter::extract_fce_wit; pub use extractor::extract_fce_wit;
pub use extracter::extract_text_wit; pub use extractor::extract_text_wit;

View File

@ -1,15 +1,18 @@
[package] [package]
name = "wit_fce" name = "fce"
version = "0.2.0" version = "0.2.0"
authors = ["Fluence Labs"] authors = ["Fluence Labs"]
edition = "2018" edition = "2018"
[dependencies] [dependencies]
fce_wit_interfaces = { path = "../crates/fce_wit_interfaces" }
wasmer-runtime = "0.17.0" wasmer-runtime = "0.17.0"
# dynamicfunc-fat-closures allows using state inside DynamicFunc # dynamicfunc-fat-closures allows using state inside DynamicFunc
wasmer-core = { package = "wasmer-runtime-core", version = "0.17.0", features = ["dynamicfunc-fat-closures"] } wasmer-core = { package = "wasmer-runtime-core", version = "0.17.0", features = ["dynamicfunc-fat-closures"] }
wasmer-wit = { package = "wasmer-interface-types", git = "http://github.com/fluencelabs/interface-types" } wasmer-wit = { package = "wasmer-interface-types", git = "http://github.com/fluencelabs/interface-types" }
wasmer-wasi = "0.17.0" wasmer-wasi = "0.17.0"
multimap = "0.8.1" multimap = "0.8.1"
parity-wasm = "0.41.0" parity-wasm = "0.41.0"
pwasm-utils = "0.12.0" pwasm-utils = "0.12.0"

View File

@ -14,6 +14,7 @@
* limitations under the License. * limitations under the License.
*/ */
use fce_wit_interfaces::WITParserError;
use wasmer_wit::errors::InstructionError; use wasmer_wit::errors::InstructionError;
use wasmer_runtime::error::{ use wasmer_runtime::error::{
CallError, CompileError, CreationError, Error as WasmerError, ResolveError, RuntimeError, CallError, CompileError, CreationError, Error as WasmerError, ResolveError, RuntimeError,
@ -47,17 +48,11 @@ pub enum FCEError {
/// Returns when there is no module with such name. /// Returns when there is no module with such name.
NoSuchModule, NoSuchModule,
/// WIT section is absent. /// WIT section parse error.
NoWITSection, WITParseError(WITParserError),
/// Multiple WIT sections. /// Incorrect WIT section.
MultipleWITSections, IncorrectWIT(String),
/// WIT section remainder isn't empty.
WITRemainderNotEmpty,
/// An error occurred while parsing WIT section.
WITParseError,
} }
impl Error for FCEError {} impl Error for FCEError {}
@ -77,19 +72,8 @@ impl std::fmt::Display for FCEError {
write!(f, "FCE doesn't have a function with such a name: {}", msg) write!(f, "FCE doesn't have a function with such a name: {}", msg)
} }
FCEError::NoSuchModule => write!(f, "FCE doesn't have a module with such a name"), FCEError::NoSuchModule => write!(f, "FCE doesn't have a module with such a name"),
FCEError::NoWITSection => write!( FCEError::WITParseError(err) => write!(f, "{}", err),
f, FCEError::IncorrectWIT(err_msg) => write!(f, "{}", err_msg),
"Loaded module doesn't contain WIT section that is neccessary for instantiation"
),
FCEError::MultipleWITSections => write!(
f,
"Loaded module contains multiple WIT sections that is unsupported now"
),
FCEError::WITRemainderNotEmpty => write!(
f,
"WIT section remainder isn't empty - WIT section possibly corrupted"
),
FCEError::WITParseError => write!(f, "WIT section is corrupted"),
} }
} }
} }
@ -144,3 +128,9 @@ impl From<InstructionError> for FCEError {
FCEError::WasmerInvokeError(format!("{}", err)) FCEError::WasmerInvokeError(format!("{}", err))
} }
} }
impl From<WITParserError> for FCEError {
fn from(err: WITParserError) -> Self {
FCEError::WITParseError(err)
}
}

View File

@ -17,10 +17,10 @@
use super::wit_prelude::*; use super::wit_prelude::*;
use super::{IType, IValue, WValue}; use super::{IType, IValue, WValue};
use wasmer_wit::ast::Interfaces; use fce_wit_interfaces::extract_fce_wit;
use fce_wit_interfaces::FCEWITInterfaces;
use wasmer_wit::interpreter::Interpreter; use wasmer_wit::interpreter::Interpreter;
use wasmer_runtime::{compile, ImportObject}; use wasmer_runtime::{compile, ImportObject};
use wasmer_core::Module as WasmerModule;
use wasmer_core::Instance as WasmerInstance; use wasmer_core::Instance as WasmerInstance;
use wasmer_core::import::Namespace; use wasmer_core::import::Namespace;
@ -29,11 +29,14 @@ use std::convert::TryInto;
use std::mem::MaybeUninit; use std::mem::MaybeUninit;
use std::sync::Arc; use std::sync::Arc;
const WIT_SECTION_NAME: &str = "interface-types";
type WITInterpreter = type WITInterpreter =
Interpreter<WITInstance, WITExport, WITFunction, WITMemory, WITMemoryView<'static>>; Interpreter<WITInstance, WITExport, WITFunction, WITMemory, WITMemoryView<'static>>;
// TODO: introduce new trait instead of type
type WITModuleFunc = (WITInterpreter, Vec<IType>, Vec<IType>); struct WITModuleFunc {
interpreter: WITInterpreter,
inputs: Vec<IType>,
outputs: Vec<IType>,
}
pub struct FCEModule { pub struct FCEModule {
// it is needed because of WITInstance contains dynamic functions // it is needed because of WITInstance contains dynamic functions
@ -51,11 +54,11 @@ impl FCEModule {
modules: &HashMap<String, Arc<FCEModule>>, modules: &HashMap<String, Arc<FCEModule>>,
) -> Result<Self, FCEError> { ) -> Result<Self, FCEError> {
let wasmer_module = compile(&wasm_bytes)?; let wasmer_module = compile(&wasm_bytes)?;
let wit = Self::extract_wit(&wasmer_module)?; let wit = extract_fce_wit(&wasmer_module)?;
let wit_exports = Self::instantiate_wit_exports(&wit)?; let wit_exports = Self::instantiate_wit_exports(&wit)?;
let mut wit_instance = Arc::new_uninit(); let mut wit_instance = Arc::new_uninit();
let mut import_object = Self::adjust_imports(&wit, wit_instance.clone())?; let mut import_object = Self::adjust_wit_imports(&wit, wit_instance.clone())?;
import_object.extend(imports); import_object.extend(imports);
let wasmer_instance = wasmer_module.instantiate(&import_object)?; let wasmer_instance = wasmer_module.instantiate(&import_object)?;
@ -81,7 +84,7 @@ impl FCEModule {
match self.exports_funcs.get(function_name) { match self.exports_funcs.get(function_name) {
Some(func) => { Some(func) => {
let result = func let result = func
.0 .interpreter
.run(args, Arc::make_mut(&mut self.wit_instance))? .run(args, Arc::make_mut(&mut self.wit_instance))?
.as_slice() .as_slice()
.to_owned(); .to_owned();
@ -99,7 +102,7 @@ impl FCEModule {
function_name: &str, function_name: &str,
) -> Result<(&Vec<IType>, &Vec<IType>), FCEError> { ) -> Result<(&Vec<IType>, &Vec<IType>), FCEError> {
match self.exports_funcs.get(function_name) { match self.exports_funcs.get(function_name) {
Some((_, inputs, outputs)) => Ok((inputs, outputs)), Some(func) => Ok((&func.inputs, &func.outputs)),
None => Err(FCEError::NoSuchFunction(format!( None => Err(FCEError::NoSuchFunction(format!(
"{} has't been found during its signature looking up", "{} has't been found during its signature looking up",
function_name function_name
@ -107,189 +110,146 @@ impl FCEModule {
} }
} }
fn extract_wit(wasmer_module: &WasmerModule) -> Result<Interfaces<'_>, FCEError> {
let wit_sections = wasmer_module
.custom_sections(WIT_SECTION_NAME)
.ok_or_else(|| FCEError::NoWITSection)?;
if wit_sections.len() > 1 {
return Err(FCEError::MultipleWITSections);
}
let (remainder, interfaces) = wasmer_wit::decoders::binary::parse::<()>(&wit_sections[0])
.map_err(|_e| FCEError::WITParseError)?;
if remainder.len() > 1 {
return Err(FCEError::WITRemainderNotEmpty);
}
Ok(interfaces)
}
fn instantiate_wit_exports( fn instantiate_wit_exports(
wit: &Interfaces<'_>, wit: &FCEWITInterfaces<'_>,
) -> Result<HashMap<String, WITModuleFunc>, FCEError> { ) -> Result<HashMap<String, WITModuleFunc>, FCEError> {
use super::IAstType; use fce_wit_interfaces::WITAstType;
use multimap::MultiMap;
let exports_type_to_names = wit wit
.exports .implementations()
.iter() .filter_map(|(adapter_function_type, core_function_type)|
.map(|export| (export.function_type, export.name.to_string())) match wit.export_by_type(*core_function_type) {
.collect::<MultiMap<_, _>>(); Some(export_function_name) => Some((adapter_function_type, *export_function_name)),
// pass functions that aren't export
let adapter_type_to_instructions = wit None => None
.adapters
.iter()
.map(|adapter| (adapter.function_type, &adapter.instructions))
.collect::<HashMap<_, _>>();
let mut wit_callable_exports = HashMap::new();
for i in wit.implementations.iter() {
let export_function_names = match exports_type_to_names.get_vec(&i.core_function_type) {
Some(export_function_names) => export_function_names,
None => continue,
};
// * just to remove reference
let adapter_instructions = *adapter_type_to_instructions
.get(&i.adapter_function_type)
.ok_or_else(|| FCEError::NoSuchFunction(
format!("adapter function with idx = {} hasn't been found during extracting exports by implementations", i.adapter_function_type)
))?;
if i.adapter_function_type >= wit.types.len() as u32 {
// TODO: change error type
return Err(FCEError::NoSuchFunction(format!(
"{} function id is bigger than WIT interface types count",
i.adapter_function_type
)));
};
if let IAstType::Function { inputs, outputs } =
&wit.types[i.adapter_function_type as usize]
{
for export_function_name in export_function_names.iter() {
// TODO: handle errors
let interpreter: WITInterpreter = adapter_instructions.try_into().unwrap();
wit_callable_exports.insert(
export_function_name.to_owned(),
(interpreter, inputs.clone(), outputs.clone()),
);
} }
} else { )
return Err(FCEError::NoSuchFunction(format!( .map(|(adapter_function_type, export_function_name)| {
"type with idx = {} isn't a function type", let adapter_instructions = wit.adapter_by_type(*adapter_function_type)
i.adapter_function_type .ok_or_else(|| FCEError::IncorrectWIT(
))); format!("adapter function with idx = {} hasn't been found during extracting exports by implementations", adapter_function_type)
} ))?;
}
Ok(wit_callable_exports) let wit_type = wit.type_by_idx(*adapter_function_type).ok_or_else(
// TODO: change error type
|| FCEError::IncorrectWIT(format!(
"{} function id is bigger than WIT interface types count",
adapter_function_type
)))?;
match wit_type {
WITAstType::Function { inputs, outputs, .. } => {
let interpreter: WITInterpreter = adapter_instructions.try_into().map_err(|_| FCEError::IncorrectWIT(
format!("failed to parse instructions for adapter type {}", adapter_function_type)
))?;
Ok((
export_function_name.to_string(),
WITModuleFunc {
interpreter,
inputs: inputs.clone(),
outputs: outputs.clone(),
}
))
},
_ => Err(FCEError::IncorrectWIT(format!(
"type with idx = {} isn't a function type",
adapter_function_type
)))
}
})
.collect::<Result<HashMap<String, WITModuleFunc>, FCEError>>()
} }
// this function deals only with import functions that have an adaptor implementation // this function deals only with import functions that have an adaptor implementation
fn adjust_imports( fn adjust_wit_imports(
interfaces: &Interfaces<'_>, wit: &FCEWITInterfaces<'_>,
wit_instance: Arc<MaybeUninit<WITInstance>>, wit_instance: Arc<MaybeUninit<WITInstance>>,
) -> Result<ImportObject, FCEError> { ) -> Result<ImportObject, FCEError> {
use super::IAstType; use fce_wit_interfaces::WITAstType;
use super::type_converters::{itype_to_wtype, wval_to_ival}; use super::type_converters::{itype_to_wtype, wval_to_ival};
use wasmer_core::typed_func::DynamicFunc; use wasmer_core::typed_func::DynamicFunc;
use wasmer_core::types::FuncSig; use wasmer_core::types::FuncSig;
use wasmer_core::vm::Ctx; use wasmer_core::vm::Ctx;
// returns function that will be called from imports of Wasmer module // returns function that will be called from imports of Wasmer module
fn dyn_func_from_imports<F>(inputs: Vec<IType>, func: F) -> DynamicFunc<'static> fn dyn_func_from_imports(
where inputs: Vec<IType>,
F: Fn(&mut Ctx, &[WValue]) -> Vec<WValue> + 'static, func: Box<dyn Fn(&mut Ctx, &[WValue]) -> Vec<WValue> + 'static>,
{ ) -> DynamicFunc<'static> {
let signature = inputs.iter().map(itype_to_wtype).collect::<Vec<_>>(); let signature = inputs.iter().map(itype_to_wtype).collect::<Vec<_>>();
DynamicFunc::new(Arc::new(FuncSig::new(signature, vec![])), func) DynamicFunc::new(Arc::new(FuncSig::new(signature, vec![])), func)
} }
// uses to filter out import functions that have an adapter implementation fn create_raw_import(
let adapter_to_core = interfaces wit_instance: Arc<MaybeUninit<WITInstance>>,
.implementations interpreter: WITInterpreter,
.iter() ) -> Box<dyn for<'a, 'b> Fn(&'a mut Ctx, &'b [WValue]) -> Vec<WValue> + 'static> {
.map(|i| (i.adapter_function_type, i.core_function_type)) Box::new(move |_: &mut Ctx, inputs: &[WValue]| -> Vec<WValue> {
.collect::<HashMap<_, _>>(); // copy here because otherwise wit_instance will be consumed by the closure
let wit_instance_callable = wit_instance.clone();
let converted_inputs = inputs.iter().map(wval_to_ival).collect::<Vec<_>>();
unsafe {
// error here will be propagated by the special error instruction
let _ = interpreter.run(
&converted_inputs,
Arc::make_mut(&mut wit_instance_callable.assume_init()),
);
}
// all wit imports // wit import functions should only change the stack state -
let mut export_type_to_name = interfaces // the result will be returned by an export function
.imports vec![]
.iter()
.map(|import| {
(
import.function_type,
(import.namespace.to_string(), import.name.to_string()),
)
}) })
.collect::<HashMap<_, _>>();
let mut import_namespaces: HashMap<String, Namespace> = HashMap::new();
for adapter in interfaces.adapters.iter() {
let core_function_idx = adapter_to_core
.get(&adapter.function_type)
.ok_or_else(|| FCEError::NoSuchFunction(format!("function with idx = {} hasn't been found during adjusting imports in WIT implementation", adapter.function_type)))?;
let (namespace, func_name) = match export_type_to_name.remove(core_function_idx) {
Some(v) => (v.0, v.1),
None => continue,
};
if adapter.function_type >= interfaces.types.len() as u32 {
// TODO: change error type
return Err(FCEError::NoSuchFunction(format!(
"{} function id is bigger than WIT interface types count",
adapter.function_type
)));
}
if let IAstType::Function { inputs, .. } =
&interfaces.types[adapter.function_type as usize]
{
let instructions = &adapter.instructions;
let interpreter: WITInterpreter = instructions.try_into().unwrap();
let wit_instance = wit_instance.clone();
let wit_inner_import =
Box::new(move |_: &mut Ctx, inputs: &[WValue]| -> Vec<WValue> {
// copy here to because otherwise wit_instance will be consumed by the closure
let wit_instance_callable = wit_instance.clone();
let converted_inputs = inputs.iter().map(wval_to_ival).collect::<Vec<_>>();
unsafe {
// error here will be propagated by the special error instruction
let _ = interpreter.run(
&converted_inputs,
Arc::make_mut(&mut wit_instance_callable.assume_init()),
);
}
// wit import functions should only change the stack state -
// the result will be returned by an export function
vec![]
});
let wit_import = dyn_func_from_imports(inputs.clone(), wit_inner_import);
// TODO: refactor this
let mut module_namespace = Namespace::new();
module_namespace.insert(func_name.clone(), wit_import);
import_namespaces.insert(namespace, module_namespace);
} else {
// TODO: change error type
return Err(FCEError::WasmerResolveError(format!(
"WIT type with idx = {} doesn't refer to function",
adapter.function_type
)));
}
} }
let namespaces = wit
.implementations()
.filter_map(|(adapter_function_type, core_function_type)|
match wit.import_by_type(*core_function_type) {
Some(import) => Some((adapter_function_type, *import)),
// pass functions that aren't export
None => None
}
)
.map(|(adapter_function_type, (import_namespace, import_name))| {
let adapter_instructions = wit.adapter_by_type(*adapter_function_type)
.ok_or_else(|| FCEError::IncorrectWIT(
format!("adapter function with idx = {} hasn't been found during extracting adjusting wit imports", adapter_function_type)
))?;
let wit_type = wit.type_by_idx(*adapter_function_type).ok_or_else(
|| FCEError::IncorrectWIT(format!(
"{} function id is bigger than WIT interface types count",
adapter_function_type
)))?;
match wit_type {
WITAstType::Function { inputs, .. } => {
let interpreter: WITInterpreter = adapter_instructions.try_into().map_err(|_| FCEError::IncorrectWIT(
format!("failed to parse instructions for adapter type {}", adapter_function_type)
))?;
let inner_import = create_raw_import(wit_instance.clone(), interpreter);
let wit_import = dyn_func_from_imports(inputs.clone(), inner_import);
let mut namespace = Namespace::new();
namespace.insert(import_name, wit_import);
Ok((
import_namespace.to_string(),
namespace
))
},
_ => Err(FCEError::IncorrectWIT(format!(
"type with idx = {} isn't a function type",
adapter_function_type
)))
}
}).collect::<Result<HashMap<String, Namespace>, FCEError>>()?;
let mut import_object = ImportObject::new(); let mut import_object = ImportObject::new();
for (namespace_name, namespace) in import_namespaces.into_iter() { for (namespace_name, namespace) in namespaces {
import_object.register(namespace_name, namespace); import_object.register(namespace_name, namespace);
} }

View File

@ -25,7 +25,6 @@ pub(crate) use fce_module::FCEModule;
pub use wasmer_wit::types::InterfaceType as IType; pub use wasmer_wit::types::InterfaceType as IType;
pub use wasmer_wit::values::InterfaceValue as IValue; pub use wasmer_wit::values::InterfaceValue as IValue;
pub(self) use wasmer_wit::ast::Type as IAstType;
pub(self) use wasmer_core::types::Type as WType; pub(self) use wasmer_core::types::Type as WType;
pub(self) use wasmer_core::types::Value as WValue; pub(self) use wasmer_core::types::Value as WValue;

View File

@ -17,9 +17,9 @@
use super::wit_prelude::*; use super::wit_prelude::*;
use super::fce_module::FCEModule; use super::fce_module::FCEModule;
use fce_wit_interfaces::FCEWITInterfaces;
use wasmer_wit::interpreter::wasm; use wasmer_wit::interpreter::wasm;
use super::IAstType; use fce_wit_interfaces::WITAstType;
use wasmer_wit::ast::Interfaces;
use wasmer_wit::interpreter::wasm::structures::{LocalImportIndex, TypedIndex}; use wasmer_wit::interpreter::wasm::structures::{LocalImportIndex, TypedIndex};
use wasmer_core::Instance as WasmerInstance; use wasmer_core::Instance as WasmerInstance;
@ -36,11 +36,11 @@ pub(super) struct WITInstance {
impl WITInstance { impl WITInstance {
pub(super) fn new( pub(super) fn new(
wasmer_instance: &WasmerInstance, wasmer_instance: &WasmerInstance,
interfaces: &Interfaces<'_>, wit: &FCEWITInterfaces<'_>,
modules: &HashMap<String, Arc<FCEModule>>, modules: &HashMap<String, Arc<FCEModule>>,
) -> Result<Self, FCEError> { ) -> Result<Self, FCEError> {
let mut exports = Self::extract_raw_exports(&wasmer_instance, interfaces)?; let mut exports = Self::extract_raw_exports(&wasmer_instance, wit)?;
let imports = Self::extract_imports(modules, interfaces, exports.len())?; let imports = Self::extract_imports(modules, wit, exports.len())?;
let memories = Self::extract_memories(&wasmer_instance); let memories = Self::extract_memories(&wasmer_instance);
exports.extend(imports); exports.extend(imports);
@ -51,18 +51,16 @@ impl WITInstance {
fn extract_raw_exports( fn extract_raw_exports(
wasmer_instance: &WasmerInstance, wasmer_instance: &WasmerInstance,
interfaces: &Interfaces<'_>, wit: &FCEWITInterfaces<'_>,
) -> Result<HashMap<usize, WITFunction>, FCEError> { ) -> Result<HashMap<usize, WITFunction>, FCEError> {
use wasmer_core::DynFunc; use wasmer_core::DynFunc;
let module_exports = &wasmer_instance.exports; let module_exports = &wasmer_instance.exports;
interfaces wit.exports()
.exports
.iter()
.enumerate() .enumerate()
.map(|(export_id, export)| { .map(|(export_id, (_, export_name))| {
let export_func = module_exports.get(export.name)?; let export_func = module_exports.get(*export_name)?;
unsafe { unsafe {
// TODO: refactor this with new Wasmer API when it is ready // 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 lives WITInstance
@ -77,34 +75,26 @@ impl WITInstance {
/// Extracts only those imports that don't have implementations. /// Extracts only those imports that don't have implementations.
fn extract_imports( fn extract_imports(
modules: &HashMap<String, Arc<FCEModule>>, modules: &HashMap<String, Arc<FCEModule>>,
interfaces: &Interfaces<'_>, wit: &FCEWITInterfaces<'_>,
start_index: usize, start_index: usize,
) -> Result<HashMap<usize, WITFunction>, FCEError> { ) -> Result<HashMap<usize, WITFunction>, FCEError> {
// uses to filter import functions that have an adapter implementation wit.imports()
let core_to_adapter = interfaces .filter(|(core_function_type, _)| {
.implementations // filter out imports that have implementations
.iter() matches!(wit.adapter_by_type(**core_function_type), None)
.map(|i| (i.core_function_type, i.adapter_function_type)) })
.collect::<HashMap<u32, u32>>(); .enumerate()
.map(|(idx, (_, (import_namespace, import_name)))| {
let mut non_wit_callable_imports = HashMap::new(); match modules.get(*import_namespace) {
Some(module) => {
for import in interfaces.imports.iter() { let func =
if core_to_adapter.get(&import.function_type).is_some() { WITFunction::from_import(module.clone(), import_name.to_string())?;
continue; Ok((start_index + idx as usize, func))
} }
None => Err(FCEError::NoSuchModule),
match modules.get(import.namespace) {
Some(module) => {
let func = WITFunction::from_import(module.clone(), import.name.to_string())?;
non_wit_callable_imports
.insert(start_index + non_wit_callable_imports.len() as usize, func);
} }
None => return Err(FCEError::NoSuchModule), })
} .collect::<Result<HashMap<_, _>, _>>()
}
Ok(non_wit_callable_imports)
} }
fn extract_memories(wasmer_instance: &WasmerInstance) -> Vec<WITMemory> { fn extract_memories(wasmer_instance: &WasmerInstance) -> Vec<WITMemory> {
@ -152,7 +142,7 @@ impl wasm::structures::Instance<WITExport, WITFunction, WITMemory, WITMemoryView
} }
} }
fn wit_type(&self, _index: u32) -> Option<&IAstType> { fn wit_type(&self, _index: u32) -> Option<&WITAstType> {
None None
} }
} }