2020-05-30 01:55:39 +03:00
|
|
|
/*
|
|
|
|
* Copyright 2020 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.
|
|
|
|
*/
|
|
|
|
|
2020-06-02 17:20:00 +03:00
|
|
|
use super::wit_prelude::*;
|
|
|
|
use super::{IType, IValue, WValue};
|
|
|
|
|
2020-06-04 19:06:23 +03:00
|
|
|
use fce_wit_interfaces::extract_fce_wit;
|
|
|
|
use fce_wit_interfaces::FCEWITInterfaces;
|
2020-06-02 17:20:00 +03:00
|
|
|
use wasmer_wit::interpreter::Interpreter;
|
2020-05-30 01:55:39 +03:00
|
|
|
use wasmer_runtime::{compile, ImportObject};
|
2020-06-02 17:20:00 +03:00
|
|
|
use wasmer_core::Instance as WasmerInstance;
|
|
|
|
use wasmer_core::import::Namespace;
|
2020-05-30 01:55:39 +03:00
|
|
|
|
|
|
|
use std::collections::HashMap;
|
|
|
|
use std::convert::TryInto;
|
2020-06-01 02:45:04 +03:00
|
|
|
use std::mem::MaybeUninit;
|
|
|
|
use std::sync::Arc;
|
2020-05-30 01:55:39 +03:00
|
|
|
|
2020-06-01 02:45:04 +03:00
|
|
|
type WITInterpreter =
|
|
|
|
Interpreter<WITInstance, WITExport, WITFunction, WITMemory, WITMemoryView<'static>>;
|
2020-06-04 19:06:23 +03:00
|
|
|
|
|
|
|
struct WITModuleFunc {
|
|
|
|
interpreter: WITInterpreter,
|
|
|
|
inputs: Vec<IType>,
|
|
|
|
outputs: Vec<IType>,
|
|
|
|
}
|
2020-05-30 01:55:39 +03:00
|
|
|
|
2020-06-02 17:20:00 +03:00
|
|
|
pub struct FCEModule {
|
|
|
|
// it is needed because of WITInstance contains dynamic functions
|
|
|
|
// that internally keep pointer to Wasmer instance.
|
2020-06-02 00:12:23 +03:00
|
|
|
#[allow(unused)]
|
2020-06-02 17:20:00 +03:00
|
|
|
wamser_instance: WasmerInstance,
|
2020-06-01 02:45:04 +03:00
|
|
|
wit_instance: Arc<WITInstance>,
|
2020-06-02 17:20:00 +03:00
|
|
|
exports_funcs: HashMap<String, WITModuleFunc>,
|
2020-05-30 01:55:39 +03:00
|
|
|
}
|
|
|
|
|
2020-06-02 17:20:00 +03:00
|
|
|
impl FCEModule {
|
2020-06-01 02:45:04 +03:00
|
|
|
pub fn new(
|
|
|
|
wasm_bytes: &[u8],
|
|
|
|
imports: ImportObject,
|
2020-06-02 17:20:00 +03:00
|
|
|
modules: &HashMap<String, Arc<FCEModule>>,
|
2020-06-02 19:16:15 +03:00
|
|
|
) -> Result<Self, FCEError> {
|
2020-06-02 17:20:00 +03:00
|
|
|
let wasmer_module = compile(&wasm_bytes)?;
|
2020-06-04 19:06:23 +03:00
|
|
|
let wit = extract_fce_wit(&wasmer_module)?;
|
2020-06-02 17:20:00 +03:00
|
|
|
let wit_exports = Self::instantiate_wit_exports(&wit)?;
|
2020-05-30 01:55:39 +03:00
|
|
|
|
2020-06-01 02:45:04 +03:00
|
|
|
let mut wit_instance = Arc::new_uninit();
|
2020-06-04 19:06:23 +03:00
|
|
|
let mut import_object = Self::adjust_wit_imports(&wit, wit_instance.clone())?;
|
2020-06-01 02:45:04 +03:00
|
|
|
import_object.extend(imports);
|
2020-05-30 01:55:39 +03:00
|
|
|
|
2020-06-02 17:20:00 +03:00
|
|
|
let wasmer_instance = wasmer_module.instantiate(&import_object)?;
|
2020-05-30 01:55:39 +03:00
|
|
|
|
2020-06-01 02:45:04 +03:00
|
|
|
let wit_instance = unsafe {
|
2020-06-02 00:12:23 +03:00
|
|
|
// get_mut_unchecked here is safe because currently only this modules have reference to
|
|
|
|
// it and the environment is single-threaded
|
2020-06-01 02:45:04 +03:00
|
|
|
*Arc::get_mut_unchecked(&mut wit_instance) =
|
2020-06-02 17:20:00 +03:00
|
|
|
MaybeUninit::new(WITInstance::new(&wasmer_instance, &wit, modules)?);
|
2020-06-01 02:45:04 +03:00
|
|
|
std::mem::transmute::<_, Arc<WITInstance>>(wit_instance)
|
|
|
|
};
|
2020-05-30 01:55:39 +03:00
|
|
|
|
|
|
|
Ok(Self {
|
2020-06-02 17:20:00 +03:00
|
|
|
wamser_instance: wasmer_instance,
|
2020-05-30 01:55:39 +03:00
|
|
|
wit_instance,
|
2020-06-02 17:20:00 +03:00
|
|
|
exports_funcs: wit_exports,
|
2020-05-30 01:55:39 +03:00
|
|
|
})
|
|
|
|
}
|
|
|
|
|
2020-06-03 23:08:18 +03:00
|
|
|
pub fn call(&mut self, function_name: &str, args: &[IValue]) -> Result<Vec<IValue>, FCEError> {
|
2020-06-02 17:20:00 +03:00
|
|
|
use wasmer_wit::interpreter::stack::Stackable;
|
|
|
|
|
|
|
|
match self.exports_funcs.get(function_name) {
|
2020-05-30 01:55:39 +03:00
|
|
|
Some(func) => {
|
2020-06-02 00:12:23 +03:00
|
|
|
let result = func
|
2020-06-04 19:06:23 +03:00
|
|
|
.interpreter
|
2020-06-02 00:12:23 +03:00
|
|
|
.run(args, Arc::make_mut(&mut self.wit_instance))?
|
|
|
|
.as_slice()
|
|
|
|
.to_owned();
|
2020-05-30 01:55:39 +03:00
|
|
|
Ok(result)
|
|
|
|
}
|
2020-06-02 19:16:15 +03:00
|
|
|
None => Err(FCEError::NoSuchFunction(format!(
|
2020-06-02 00:12:23 +03:00
|
|
|
"{} hasn't been found while calling",
|
|
|
|
function_name
|
|
|
|
))),
|
2020-06-01 02:45:04 +03:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn get_func_signature(
|
|
|
|
&self,
|
|
|
|
function_name: &str,
|
2020-06-02 19:16:15 +03:00
|
|
|
) -> Result<(&Vec<IType>, &Vec<IType>), FCEError> {
|
2020-06-02 17:20:00 +03:00
|
|
|
match self.exports_funcs.get(function_name) {
|
2020-06-04 19:06:23 +03:00
|
|
|
Some(func) => Ok((&func.inputs, &func.outputs)),
|
2020-06-02 19:16:15 +03:00
|
|
|
None => Err(FCEError::NoSuchFunction(format!(
|
2020-06-01 02:45:04 +03:00
|
|
|
"{} has't been found during its signature looking up",
|
|
|
|
function_name
|
|
|
|
))),
|
2020-05-30 01:55:39 +03:00
|
|
|
}
|
|
|
|
}
|
2020-06-01 02:45:04 +03:00
|
|
|
|
2020-06-05 23:12:02 +03:00
|
|
|
pub fn get_exports_signatures(
|
|
|
|
&self,
|
|
|
|
) -> impl Iterator<Item = (&String, &Vec<IType>, &Vec<IType>)> {
|
|
|
|
self.exports_funcs
|
|
|
|
.iter()
|
|
|
|
.map(|(func_name, func)| (func_name, &func.inputs, &func.outputs))
|
|
|
|
}
|
|
|
|
|
2020-06-02 17:20:00 +03:00
|
|
|
fn instantiate_wit_exports(
|
2020-06-04 19:06:23 +03:00
|
|
|
wit: &FCEWITInterfaces<'_>,
|
2020-06-02 19:16:15 +03:00
|
|
|
) -> Result<HashMap<String, WITModuleFunc>, FCEError> {
|
2020-06-04 19:06:23 +03:00
|
|
|
use fce_wit_interfaces::WITAstType;
|
|
|
|
|
2020-06-04 19:54:23 +03:00
|
|
|
wit.implementations()
|
|
|
|
.filter_map(|(adapter_function_type, core_function_type)| {
|
2020-06-04 19:06:23 +03:00
|
|
|
match wit.export_by_type(*core_function_type) {
|
2020-06-04 19:54:23 +03:00
|
|
|
Some(export_function_name) => {
|
|
|
|
Some((adapter_function_type, *export_function_name))
|
|
|
|
}
|
2020-06-04 19:06:23 +03:00
|
|
|
// pass functions that aren't export
|
2020-06-04 19:54:23 +03:00
|
|
|
None => None,
|
2020-06-04 19:06:23 +03:00
|
|
|
}
|
2020-06-04 19:54:23 +03:00
|
|
|
})
|
2020-06-04 19:06:23 +03:00
|
|
|
.map(|(adapter_function_type, export_function_name)| {
|
2020-06-04 19:54:23 +03:00
|
|
|
let adapter_instructions = wit.adapter_by_type_r(*adapter_function_type)?;
|
|
|
|
let wit_type = wit.type_by_idx_r(*adapter_function_type)?;
|
2020-06-04 19:06:23 +03:00
|
|
|
|
|
|
|
match wit_type {
|
2020-06-04 19:54:23 +03:00
|
|
|
WITAstType::Function {
|
|
|
|
inputs, outputs, ..
|
|
|
|
} => {
|
|
|
|
let interpreter: WITInterpreter = adapter_instructions.try_into()?;
|
2020-06-04 19:06:23 +03:00
|
|
|
|
|
|
|
Ok((
|
|
|
|
export_function_name.to_string(),
|
|
|
|
WITModuleFunc {
|
|
|
|
interpreter,
|
|
|
|
inputs: inputs.clone(),
|
|
|
|
outputs: outputs.clone(),
|
2020-06-04 19:54:23 +03:00
|
|
|
},
|
2020-06-04 19:06:23 +03:00
|
|
|
))
|
2020-06-04 19:54:23 +03:00
|
|
|
}
|
2020-06-04 19:06:23 +03:00
|
|
|
_ => Err(FCEError::IncorrectWIT(format!(
|
|
|
|
"type with idx = {} isn't a function type",
|
|
|
|
adapter_function_type
|
2020-06-04 19:54:23 +03:00
|
|
|
))),
|
2020-06-01 12:14:12 +03:00
|
|
|
}
|
2020-06-04 19:06:23 +03:00
|
|
|
})
|
|
|
|
.collect::<Result<HashMap<String, WITModuleFunc>, FCEError>>()
|
2020-06-01 02:45:04 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
// this function deals only with import functions that have an adaptor implementation
|
2020-06-04 19:06:23 +03:00
|
|
|
fn adjust_wit_imports(
|
|
|
|
wit: &FCEWITInterfaces<'_>,
|
2020-06-01 02:45:04 +03:00
|
|
|
wit_instance: Arc<MaybeUninit<WITInstance>>,
|
2020-06-02 19:16:15 +03:00
|
|
|
) -> Result<ImportObject, FCEError> {
|
2020-06-04 19:06:23 +03:00
|
|
|
use fce_wit_interfaces::WITAstType;
|
2020-06-02 17:20:00 +03:00
|
|
|
use wasmer_core::typed_func::DynamicFunc;
|
|
|
|
use wasmer_core::vm::Ctx;
|
2020-06-01 02:45:04 +03:00
|
|
|
|
|
|
|
// returns function that will be called from imports of Wasmer module
|
2020-06-04 19:54:23 +03:00
|
|
|
fn dyn_func_from_raw_import(
|
2020-06-04 19:06:23 +03:00
|
|
|
inputs: Vec<IType>,
|
|
|
|
func: Box<dyn Fn(&mut Ctx, &[WValue]) -> Vec<WValue> + 'static>,
|
|
|
|
) -> DynamicFunc<'static> {
|
2020-06-04 19:54:23 +03:00
|
|
|
use wasmer_core::types::FuncSig;
|
|
|
|
use super::type_converters::itype_to_wtype;
|
|
|
|
|
2020-06-01 02:45:04 +03:00
|
|
|
let signature = inputs.iter().map(itype_to_wtype).collect::<Vec<_>>();
|
|
|
|
DynamicFunc::new(Arc::new(FuncSig::new(signature, vec![])), func)
|
|
|
|
}
|
|
|
|
|
2020-06-04 19:54:23 +03:00
|
|
|
// creates a closure that is represent a WIT module import
|
2020-06-04 19:06:23 +03:00
|
|
|
fn create_raw_import(
|
|
|
|
wit_instance: Arc<MaybeUninit<WITInstance>>,
|
|
|
|
interpreter: WITInterpreter,
|
|
|
|
) -> Box<dyn for<'a, 'b> Fn(&'a mut Ctx, &'b [WValue]) -> Vec<WValue> + 'static> {
|
|
|
|
Box::new(move |_: &mut Ctx, inputs: &[WValue]| -> Vec<WValue> {
|
2020-06-04 19:54:23 +03:00
|
|
|
use super::type_converters::wval_to_ival;
|
|
|
|
|
2020-06-04 19:06:23 +03:00
|
|
|
// 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()),
|
|
|
|
);
|
|
|
|
}
|
2020-06-01 02:45:04 +03:00
|
|
|
|
2020-06-04 19:06:23 +03:00
|
|
|
// wit import functions should only change the stack state -
|
|
|
|
// the result will be returned by an export function
|
|
|
|
vec![]
|
2020-06-01 02:45:04 +03:00
|
|
|
})
|
|
|
|
}
|
|
|
|
|
2020-06-04 19:06:23 +03:00
|
|
|
let namespaces = wit
|
|
|
|
.implementations()
|
2020-06-04 19:54:23 +03:00
|
|
|
.filter_map(|(adapter_function_type, core_function_type)| {
|
2020-06-04 19:06:23 +03:00
|
|
|
match wit.import_by_type(*core_function_type) {
|
|
|
|
Some(import) => Some((adapter_function_type, *import)),
|
2020-06-04 19:54:23 +03:00
|
|
|
// skip functions that aren't export
|
|
|
|
None => None,
|
2020-06-04 19:06:23 +03:00
|
|
|
}
|
2020-06-04 19:54:23 +03:00
|
|
|
})
|
2020-06-04 19:06:23 +03:00
|
|
|
.map(|(adapter_function_type, (import_namespace, import_name))| {
|
2020-06-04 19:54:23 +03:00
|
|
|
let adapter_instructions = wit.adapter_by_type_r(*adapter_function_type)?;
|
|
|
|
let wit_type = wit.type_by_idx_r(*adapter_function_type)?;
|
2020-06-04 19:06:23 +03:00
|
|
|
|
|
|
|
match wit_type {
|
|
|
|
WITAstType::Function { inputs, .. } => {
|
2020-06-04 19:54:23 +03:00
|
|
|
let interpreter: WITInterpreter = adapter_instructions.try_into()?;
|
2020-06-04 19:06:23 +03:00
|
|
|
let inner_import = create_raw_import(wit_instance.clone(), interpreter);
|
2020-06-04 19:54:23 +03:00
|
|
|
let wit_import = dyn_func_from_raw_import(inputs.clone(), inner_import);
|
|
|
|
|
2020-06-04 19:06:23 +03:00
|
|
|
let mut namespace = Namespace::new();
|
|
|
|
namespace.insert(import_name, wit_import);
|
|
|
|
|
2020-06-04 19:54:23 +03:00
|
|
|
Ok((import_namespace.to_string(), namespace))
|
|
|
|
}
|
2020-06-04 19:06:23 +03:00
|
|
|
_ => Err(FCEError::IncorrectWIT(format!(
|
|
|
|
"type with idx = {} isn't a function type",
|
|
|
|
adapter_function_type
|
2020-06-04 19:54:23 +03:00
|
|
|
))),
|
2020-06-04 19:06:23 +03:00
|
|
|
}
|
2020-06-04 19:54:23 +03:00
|
|
|
})
|
|
|
|
.collect::<Result<HashMap<String, Namespace>, FCEError>>()?;
|
2020-06-04 19:06:23 +03:00
|
|
|
|
2020-06-01 02:45:04 +03:00
|
|
|
let mut import_object = ImportObject::new();
|
|
|
|
|
2020-06-04 19:06:23 +03:00
|
|
|
for (namespace_name, namespace) in namespaces {
|
2020-06-01 02:45:04 +03:00
|
|
|
import_object.register(namespace_name, namespace);
|
|
|
|
}
|
|
|
|
|
|
|
|
Ok(import_object)
|
|
|
|
}
|
2020-05-30 01:55:39 +03:00
|
|
|
}
|