2018-01-05 13:10:01 +03:00
|
|
|
use interpreter::module::GlobalRef;
|
2017-12-13 13:25:24 +01:00
|
|
|
use std::rc::Rc;
|
2017-12-11 16:28:05 +01:00
|
|
|
use std::collections::HashMap;
|
2017-12-14 15:33:40 +01:00
|
|
|
use std::collections::hash_map::Entry;
|
2017-12-18 16:12:59 +03:00
|
|
|
use elements::{FunctionType, GlobalType, MemoryType, TableType, ValueType};
|
2018-01-05 13:10:01 +03:00
|
|
|
use interpreter::module::{ExternVal, ModuleInstance, FuncRef};
|
|
|
|
use interpreter::module::MemoryRef;
|
|
|
|
use interpreter::module::TableRef;
|
2017-12-13 18:28:34 +01:00
|
|
|
use interpreter::func::FuncInstance;
|
2017-12-13 18:19:42 +01:00
|
|
|
use interpreter::global::GlobalInstance;
|
2017-12-13 14:36:06 +01:00
|
|
|
use interpreter::memory::MemoryInstance;
|
|
|
|
use interpreter::table::TableInstance;
|
2017-12-18 15:18:53 +03:00
|
|
|
use interpreter::value::{RuntimeValue, TryInto};
|
2017-12-11 16:28:05 +01:00
|
|
|
use interpreter::Error;
|
2017-12-14 15:33:40 +01:00
|
|
|
use interpreter::ImportResolver;
|
2017-12-19 20:46:05 +03:00
|
|
|
use interpreter::state::HostState;
|
2017-12-11 19:22:45 +01:00
|
|
|
|
2017-12-19 20:46:05 +03:00
|
|
|
pub type HostFunc = Fn(&mut HostState, &[RuntimeValue])
|
2017-12-18 16:12:59 +03:00
|
|
|
-> Result<Option<RuntimeValue>, Error>;
|
2017-12-15 18:23:54 +03:00
|
|
|
|
2017-12-19 20:46:05 +03:00
|
|
|
pub struct HostModuleBuilder {
|
|
|
|
exports: HashMap<String, ExternVal>,
|
2017-12-11 16:28:05 +01:00
|
|
|
}
|
|
|
|
|
2017-12-19 20:46:05 +03:00
|
|
|
impl HostModuleBuilder {
|
2017-12-11 19:22:45 +01:00
|
|
|
pub fn new() -> Self {
|
2017-12-11 16:28:05 +01:00
|
|
|
HostModuleBuilder {
|
2017-12-14 15:33:40 +01:00
|
|
|
exports: HashMap::new(),
|
2017-12-11 16:28:05 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-12-18 16:37:48 +03:00
|
|
|
pub fn insert_func0<
|
2017-12-19 20:46:05 +03:00
|
|
|
Cl: Fn(&mut HostState) -> Result<Ret, Error> + 'static,
|
2017-12-18 15:18:53 +03:00
|
|
|
Ret: IntoReturnVal + 'static,
|
2017-12-16 18:19:35 +03:00
|
|
|
N: Into<String>,
|
|
|
|
>(
|
|
|
|
&mut self,
|
|
|
|
name: N,
|
|
|
|
f: Cl,
|
|
|
|
) {
|
|
|
|
let func_type = FunctionType::new(vec![], Ret::value_type());
|
2017-12-18 16:12:59 +03:00
|
|
|
let host_func = Rc::new(
|
2017-12-19 20:46:05 +03:00
|
|
|
move |state: &mut HostState, args: &[RuntimeValue]| -> Result<Option<RuntimeValue>, Error> {
|
2017-12-18 16:37:48 +03:00
|
|
|
assert!(args.len() == 0);
|
2017-12-18 16:12:59 +03:00
|
|
|
let result = f(state)?.into_return_val();
|
|
|
|
Ok(result)
|
|
|
|
},
|
|
|
|
);
|
2017-12-16 18:19:35 +03:00
|
|
|
|
|
|
|
let func = FuncInstance::alloc_host(Rc::new(func_type), host_func);
|
|
|
|
self.insert_func(name, func);
|
|
|
|
}
|
|
|
|
|
2017-12-18 16:37:48 +03:00
|
|
|
pub fn insert_func1<
|
2017-12-19 20:46:05 +03:00
|
|
|
Cl: Fn(&mut HostState, P1) -> Result<Ret, Error> + 'static,
|
2017-12-18 15:18:53 +03:00
|
|
|
Ret: IntoReturnVal + 'static,
|
2017-12-16 18:19:35 +03:00
|
|
|
P1: FromArg + 'static,
|
|
|
|
N: Into<String>,
|
|
|
|
>(
|
|
|
|
&mut self,
|
|
|
|
name: N,
|
|
|
|
f: Cl,
|
|
|
|
) {
|
|
|
|
let func_type = FunctionType::new(vec![P1::value_type()], Ret::value_type());
|
2017-12-18 16:12:59 +03:00
|
|
|
let host_func = Rc::new(
|
2017-12-19 20:46:05 +03:00
|
|
|
move |state: &mut HostState, args: &[RuntimeValue]| -> Result<Option<RuntimeValue>, Error> {
|
2017-12-18 16:37:48 +03:00
|
|
|
assert!(args.len() == 1);
|
|
|
|
let mut args = args.into_iter();
|
|
|
|
let result = f(
|
|
|
|
state,
|
|
|
|
P1::from_arg(args.next().unwrap())
|
|
|
|
)?.into_return_val();
|
2017-12-18 16:12:59 +03:00
|
|
|
Ok(result)
|
|
|
|
},
|
|
|
|
);
|
2017-12-16 18:19:35 +03:00
|
|
|
|
|
|
|
let func = FuncInstance::alloc_host(Rc::new(func_type), host_func);
|
|
|
|
self.insert_func(name, func);
|
|
|
|
}
|
2017-12-11 16:28:05 +01:00
|
|
|
|
2017-12-18 16:37:48 +03:00
|
|
|
pub fn insert_func2<
|
2017-12-19 20:46:05 +03:00
|
|
|
Cl: Fn(&mut HostState, P1, P2) -> Result<Ret, Error> + 'static,
|
2017-12-18 15:18:53 +03:00
|
|
|
Ret: IntoReturnVal + 'static,
|
2017-12-12 10:32:51 +01:00
|
|
|
P1: FromArg + 'static,
|
|
|
|
P2: FromArg + 'static,
|
2017-12-12 15:18:35 +01:00
|
|
|
N: Into<String>,
|
2017-12-12 10:32:51 +01:00
|
|
|
>(
|
|
|
|
&mut self,
|
2017-12-12 15:18:35 +01:00
|
|
|
name: N,
|
2017-12-15 18:23:54 +03:00
|
|
|
f: Cl,
|
2017-12-12 10:32:51 +01:00
|
|
|
) {
|
2017-12-18 16:12:59 +03:00
|
|
|
let func_type =
|
|
|
|
FunctionType::new(vec![P1::value_type(), P2::value_type()], Ret::value_type());
|
|
|
|
let host_func = Rc::new(
|
2017-12-19 20:46:05 +03:00
|
|
|
move |state: &mut HostState, args: &[RuntimeValue]| -> Result<Option<RuntimeValue>, Error> {
|
2017-12-18 16:37:48 +03:00
|
|
|
assert!(args.len() == 2);
|
|
|
|
let mut args = args.into_iter();
|
|
|
|
let result = f(
|
|
|
|
state,
|
|
|
|
P1::from_arg(args.next().unwrap()),
|
|
|
|
P2::from_arg(args.next().unwrap()),
|
|
|
|
)?.into_return_val();
|
2017-12-18 16:12:59 +03:00
|
|
|
Ok(result)
|
|
|
|
},
|
|
|
|
);
|
2017-12-15 18:23:54 +03:00
|
|
|
|
2017-12-14 15:33:40 +01:00
|
|
|
let func = FuncInstance::alloc_host(Rc::new(func_type), host_func);
|
|
|
|
self.insert_func(name, func);
|
|
|
|
}
|
2017-12-12 10:32:51 +01:00
|
|
|
|
2017-12-18 16:37:48 +03:00
|
|
|
pub fn insert_func3<
|
2017-12-19 20:46:05 +03:00
|
|
|
Cl: Fn(&mut HostState, P1, P2, P3) -> Result<Ret, Error> + 'static,
|
2017-12-18 16:37:48 +03:00
|
|
|
Ret: IntoReturnVal + 'static,
|
|
|
|
P1: FromArg + 'static,
|
|
|
|
P2: FromArg + 'static,
|
|
|
|
P3: FromArg + 'static,
|
|
|
|
N: Into<String>,
|
|
|
|
>(
|
|
|
|
&mut self,
|
|
|
|
name: N,
|
|
|
|
f: Cl,
|
|
|
|
) {
|
|
|
|
let func_type = FunctionType::new(
|
|
|
|
vec![P1::value_type(), P2::value_type(), P3::value_type()],
|
|
|
|
Ret::value_type(),
|
|
|
|
);
|
|
|
|
let host_func = Rc::new(
|
2017-12-19 20:46:05 +03:00
|
|
|
move |state: &mut HostState, args: &[RuntimeValue]| -> Result<Option<RuntimeValue>, Error> {
|
2017-12-18 16:37:48 +03:00
|
|
|
assert!(args.len() == 3);
|
|
|
|
let mut args = args.into_iter();
|
|
|
|
let result = f(
|
|
|
|
state,
|
|
|
|
P1::from_arg(args.next().unwrap()),
|
|
|
|
P2::from_arg(args.next().unwrap()),
|
|
|
|
P3::from_arg(args.next().unwrap()),
|
|
|
|
)?.into_return_val();
|
|
|
|
Ok(result)
|
|
|
|
},
|
|
|
|
);
|
|
|
|
|
|
|
|
let func = FuncInstance::alloc_host(Rc::new(func_type), host_func);
|
|
|
|
self.insert_func(name, func);
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn insert_func4<
|
2017-12-19 20:46:05 +03:00
|
|
|
Cl: Fn(&mut HostState, P1, P2, P3, P4) -> Result<Ret, Error> + 'static,
|
2017-12-18 16:37:48 +03:00
|
|
|
Ret: IntoReturnVal + 'static,
|
|
|
|
P1: FromArg + 'static,
|
|
|
|
P2: FromArg + 'static,
|
|
|
|
P3: FromArg + 'static,
|
|
|
|
P4: FromArg + 'static,
|
|
|
|
N: Into<String>,
|
|
|
|
>(
|
|
|
|
&mut self,
|
|
|
|
name: N,
|
|
|
|
f: Cl,
|
|
|
|
) {
|
|
|
|
let func_type = FunctionType::new(
|
|
|
|
vec![
|
|
|
|
P1::value_type(),
|
|
|
|
P2::value_type(),
|
|
|
|
P3::value_type(),
|
|
|
|
P4::value_type(),
|
|
|
|
],
|
|
|
|
Ret::value_type(),
|
|
|
|
);
|
|
|
|
let host_func = Rc::new(
|
2017-12-19 20:46:05 +03:00
|
|
|
move |state: &mut HostState, args: &[RuntimeValue]| -> Result<Option<RuntimeValue>, Error> {
|
2017-12-18 16:37:48 +03:00
|
|
|
assert!(args.len() == 4);
|
|
|
|
let mut args = args.into_iter();
|
|
|
|
let result = f(
|
|
|
|
state,
|
|
|
|
P1::from_arg(args.next().unwrap()),
|
|
|
|
P2::from_arg(args.next().unwrap()),
|
|
|
|
P3::from_arg(args.next().unwrap()),
|
|
|
|
P4::from_arg(args.next().unwrap()),
|
|
|
|
)?.into_return_val();
|
|
|
|
Ok(result)
|
|
|
|
},
|
|
|
|
);
|
|
|
|
|
|
|
|
let func = FuncInstance::alloc_host(Rc::new(func_type), host_func);
|
|
|
|
self.insert_func(name, func);
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn with_func0<
|
2017-12-19 20:46:05 +03:00
|
|
|
Cl: Fn(&mut HostState) -> Result<Ret, Error> + 'static,
|
2017-12-18 16:37:48 +03:00
|
|
|
Ret: IntoReturnVal + 'static,
|
|
|
|
N: Into<String>,
|
|
|
|
>(
|
|
|
|
mut self,
|
|
|
|
name: N,
|
|
|
|
f: Cl,
|
|
|
|
) -> Self {
|
|
|
|
self.insert_func0(name, f);
|
|
|
|
self
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn with_func1<
|
2017-12-19 20:46:05 +03:00
|
|
|
Cl: Fn(&mut HostState, P1) -> Result<Ret, Error> + 'static,
|
2017-12-18 16:37:48 +03:00
|
|
|
Ret: IntoReturnVal + 'static,
|
|
|
|
P1: FromArg + 'static,
|
|
|
|
N: Into<String>,
|
|
|
|
>(
|
|
|
|
mut self,
|
|
|
|
name: N,
|
|
|
|
f: Cl,
|
|
|
|
) -> Self {
|
|
|
|
self.insert_func1(name, f);
|
|
|
|
self
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn with_func2<
|
2017-12-19 20:46:05 +03:00
|
|
|
Cl: Fn(&mut HostState, P1, P2) -> Result<Ret, Error> + 'static,
|
2017-12-18 16:37:48 +03:00
|
|
|
Ret: IntoReturnVal + 'static,
|
|
|
|
P1: FromArg + 'static,
|
|
|
|
P2: FromArg + 'static,
|
|
|
|
N: Into<String>,
|
|
|
|
>(
|
|
|
|
mut self,
|
|
|
|
name: N,
|
|
|
|
f: Cl,
|
|
|
|
) -> Self {
|
|
|
|
self.insert_func2(name, f);
|
|
|
|
self
|
|
|
|
}
|
|
|
|
|
2018-01-05 13:10:01 +03:00
|
|
|
pub fn insert_func<N: Into<String>>(&mut self, name: N, func: FuncRef) {
|
2017-12-14 15:33:40 +01:00
|
|
|
self.insert(name, ExternVal::Func(func));
|
2017-12-12 10:32:51 +01:00
|
|
|
}
|
|
|
|
|
2018-01-05 13:10:01 +03:00
|
|
|
pub fn insert_global<N: Into<String>>(&mut self, name: N, global: GlobalRef) {
|
2017-12-14 15:33:40 +01:00
|
|
|
self.insert(name, ExternVal::Global(global));
|
2017-12-11 18:38:09 +01:00
|
|
|
}
|
|
|
|
|
2018-01-05 13:10:01 +03:00
|
|
|
pub fn insert_memory<N: Into<String>>(&mut self, name: N, memory: MemoryRef) {
|
2017-12-14 15:33:40 +01:00
|
|
|
self.insert(name, ExternVal::Memory(memory));
|
2017-12-11 18:38:09 +01:00
|
|
|
}
|
|
|
|
|
2018-01-05 13:10:01 +03:00
|
|
|
pub fn insert_table<N: Into<String>>(&mut self, name: N, table: TableRef) {
|
2017-12-14 15:33:40 +01:00
|
|
|
self.insert(name, ExternVal::Table(table));
|
2017-12-11 19:22:45 +01:00
|
|
|
}
|
|
|
|
|
2018-01-05 13:10:01 +03:00
|
|
|
pub fn with_global<N: Into<String>>(mut self, name: N, global: GlobalRef) -> Self {
|
2017-12-14 15:33:40 +01:00
|
|
|
self.insert_global(name, global);
|
|
|
|
self
|
|
|
|
}
|
|
|
|
|
2018-01-05 13:10:01 +03:00
|
|
|
pub fn with_memory<N: Into<String>>(mut self, name: N, memory: MemoryRef) -> Self {
|
2017-12-14 15:33:40 +01:00
|
|
|
self.insert_memory(name, memory);
|
|
|
|
self
|
|
|
|
}
|
|
|
|
|
2018-01-05 13:10:01 +03:00
|
|
|
pub fn with_table<N: Into<String>>(mut self, name: N, table: TableRef) -> Self {
|
2017-12-14 15:33:40 +01:00
|
|
|
self.insert_table(name, table);
|
|
|
|
self
|
|
|
|
}
|
|
|
|
|
2017-12-19 20:46:05 +03:00
|
|
|
fn insert<N: Into<String>>(&mut self, name: N, extern_val: ExternVal) {
|
2017-12-14 15:33:40 +01:00
|
|
|
match self.exports.entry(name.into()) {
|
|
|
|
Entry::Vacant(v) => v.insert(extern_val),
|
|
|
|
Entry::Occupied(o) => panic!("Duplicate export name {}", o.key()),
|
|
|
|
};
|
2017-12-12 15:18:35 +01:00
|
|
|
}
|
|
|
|
|
2017-12-19 20:46:05 +03:00
|
|
|
pub fn build(self) -> HostModule {
|
2017-12-14 15:33:40 +01:00
|
|
|
let internal_instance = Rc::new(ModuleInstance::with_exports(self.exports));
|
2017-12-18 16:12:59 +03:00
|
|
|
HostModule { internal_instance }
|
2017-12-11 18:38:09 +01:00
|
|
|
}
|
2017-12-11 19:22:45 +01:00
|
|
|
}
|
|
|
|
|
2017-12-19 20:46:05 +03:00
|
|
|
pub struct HostModule {
|
|
|
|
internal_instance: Rc<ModuleInstance>,
|
2017-12-11 19:22:45 +01:00
|
|
|
}
|
|
|
|
|
2017-12-19 20:46:05 +03:00
|
|
|
impl HostModule {
|
|
|
|
pub fn export_by_name(&self, name: &str) -> Option<ExternVal> {
|
2017-12-14 15:33:40 +01:00
|
|
|
self.internal_instance.export_by_name(name)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-12-19 20:46:05 +03:00
|
|
|
impl ImportResolver for HostModule {
|
2017-12-14 15:33:40 +01:00
|
|
|
fn resolve_func(
|
|
|
|
&self,
|
|
|
|
field_name: &str,
|
|
|
|
func_type: &FunctionType,
|
2018-01-05 13:10:01 +03:00
|
|
|
) -> Result<FuncRef, Error> {
|
2017-12-14 15:33:40 +01:00
|
|
|
self.internal_instance.resolve_func(field_name, func_type)
|
|
|
|
}
|
|
|
|
|
|
|
|
fn resolve_global(
|
|
|
|
&self,
|
|
|
|
field_name: &str,
|
|
|
|
global_type: &GlobalType,
|
2018-01-05 13:10:01 +03:00
|
|
|
) -> Result<GlobalRef, Error> {
|
2017-12-18 16:12:59 +03:00
|
|
|
self.internal_instance
|
|
|
|
.resolve_global(field_name, global_type)
|
2017-12-14 15:33:40 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
fn resolve_memory(
|
|
|
|
&self,
|
|
|
|
field_name: &str,
|
|
|
|
memory_type: &MemoryType,
|
2018-01-05 13:10:01 +03:00
|
|
|
) -> Result<MemoryRef, Error> {
|
2017-12-18 16:12:59 +03:00
|
|
|
self.internal_instance
|
|
|
|
.resolve_memory(field_name, memory_type)
|
2017-12-14 15:33:40 +01:00
|
|
|
}
|
2017-12-11 19:22:45 +01:00
|
|
|
|
2017-12-14 15:33:40 +01:00
|
|
|
fn resolve_table(
|
|
|
|
&self,
|
|
|
|
field_name: &str,
|
|
|
|
table_type: &TableType,
|
2018-01-05 13:10:01 +03:00
|
|
|
) -> Result<TableRef, Error> {
|
2017-12-14 15:33:40 +01:00
|
|
|
self.internal_instance.resolve_table(field_name, table_type)
|
2017-12-11 16:28:05 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-12-18 16:12:59 +03:00
|
|
|
pub trait FromArg
|
|
|
|
where
|
|
|
|
Self: Sized,
|
|
|
|
{
|
2017-12-11 16:28:05 +01:00
|
|
|
fn from_arg(arg: &RuntimeValue) -> Self;
|
|
|
|
fn value_type() -> ValueType;
|
|
|
|
}
|
|
|
|
|
2017-12-18 15:18:53 +03:00
|
|
|
macro_rules! impl_from_arg {
|
|
|
|
($ty: ident, $val_ty: ident) => {
|
|
|
|
impl FromArg for $ty {
|
|
|
|
fn from_arg(arg: &RuntimeValue) -> Self {
|
|
|
|
arg
|
|
|
|
.try_into()
|
|
|
|
.expect(
|
|
|
|
concat!("Due to validation, arg expected to be ", stringify!($val_ty))
|
|
|
|
)
|
|
|
|
}
|
|
|
|
|
|
|
|
fn value_type() -> ValueType {
|
|
|
|
use self::ValueType::*;
|
|
|
|
$val_ty
|
|
|
|
}
|
2017-12-11 16:28:05 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-12-18 15:18:53 +03:00
|
|
|
impl_from_arg!(i32, I32);
|
|
|
|
impl_from_arg!(u32, I32);
|
|
|
|
impl_from_arg!(i64, I64);
|
|
|
|
impl_from_arg!(u64, I64);
|
|
|
|
impl_from_arg!(f32, F32);
|
|
|
|
impl_from_arg!(f64, F64);
|
|
|
|
|
|
|
|
pub trait IntoReturnVal {
|
|
|
|
fn into_return_val(self) -> Option<RuntimeValue>;
|
2017-12-11 16:28:05 +01:00
|
|
|
fn value_type() -> Option<ValueType>;
|
|
|
|
}
|
|
|
|
|
2017-12-18 15:18:53 +03:00
|
|
|
macro_rules! impl_into_return_val {
|
|
|
|
($ty: ident, $val_ty: ident) => {
|
|
|
|
impl IntoReturnVal for $ty {
|
|
|
|
fn into_return_val(self) -> Option<RuntimeValue> {
|
|
|
|
Some(self.into())
|
|
|
|
}
|
|
|
|
|
|
|
|
fn value_type() -> Option<ValueType> {
|
|
|
|
use self::ValueType::*;
|
|
|
|
Some($val_ty)
|
|
|
|
}
|
|
|
|
}
|
2017-12-11 16:28:05 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-12-18 15:18:53 +03:00
|
|
|
impl_into_return_val!(i32, I32);
|
|
|
|
impl_into_return_val!(u32, I32);
|
|
|
|
impl_into_return_val!(i64, I64);
|
|
|
|
impl_into_return_val!(u64, I64);
|
|
|
|
impl_into_return_val!(f32, F32);
|
|
|
|
impl_into_return_val!(f64, F64);
|
|
|
|
|
|
|
|
impl IntoReturnVal for () {
|
|
|
|
fn into_return_val(self) -> Option<RuntimeValue> {
|
2017-12-11 16:28:05 +01:00
|
|
|
None
|
|
|
|
}
|
|
|
|
|
|
|
|
fn value_type() -> Option<ValueType> {
|
|
|
|
None
|
|
|
|
}
|
|
|
|
}
|
2018-01-05 13:10:01 +03:00
|
|
|
|
|
|
|
trait Externals {
|
|
|
|
fn invoke_index(
|
|
|
|
&mut self,
|
|
|
|
index: u32,
|
|
|
|
args: &[RuntimeValue],
|
|
|
|
) -> Result<Option<RuntimeValue>, Error>;
|
|
|
|
|
|
|
|
// TODO: or check signature?
|
|
|
|
fn signature(&self, index: usize) -> &FunctionType;
|
|
|
|
|
|
|
|
fn memory_by_index(&self, index: usize) -> &MemoryInstance;
|
|
|
|
fn table_by_index(&self, index: usize) -> &TableInstance;
|
|
|
|
fn global_by_index(&self, index: usize) -> &GlobalInstance;
|
|
|
|
}
|
|
|
|
|
|
|
|
|