mirror of
https://github.com/fluencelabs/parity-wasm
synced 2025-06-18 17:31:42 +00:00
Offline host module builder
This commit is contained in:
@ -3,28 +3,47 @@ use std::sync::Arc;
|
|||||||
use std::marker::PhantomData;
|
use std::marker::PhantomData;
|
||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
use elements::{FunctionType, ValueType, GlobalType, MemoryType, TableType};
|
use elements::{FunctionType, ValueType, GlobalType, MemoryType, TableType};
|
||||||
use interpreter::store::{Store, ExternVal};
|
use interpreter::store::{Store, ExternVal, ModuleId, ModuleInstance};
|
||||||
use interpreter::value::RuntimeValue;
|
use interpreter::value::RuntimeValue;
|
||||||
use interpreter::Error;
|
use interpreter::Error;
|
||||||
|
|
||||||
pub struct HostModuleBuilder<'a, St> {
|
enum HostItem {
|
||||||
store: &'a mut Store,
|
Func {
|
||||||
exports: HashMap<String, ExternVal>,
|
name: String,
|
||||||
|
func_type: FunctionType,
|
||||||
|
host_func: Arc<AnyFunc>,
|
||||||
|
},
|
||||||
|
Global {
|
||||||
|
name: String,
|
||||||
|
global_type: GlobalType,
|
||||||
|
init_val: RuntimeValue,
|
||||||
|
},
|
||||||
|
Memory {
|
||||||
|
name: String,
|
||||||
|
memory_type: MemoryType,
|
||||||
|
},
|
||||||
|
Table {
|
||||||
|
name: String,
|
||||||
|
table_type: TableType,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct HostModuleBuilder<St> {
|
||||||
|
items: Vec<HostItem>,
|
||||||
_marker: PhantomData<St>,
|
_marker: PhantomData<St>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a, St: 'static> HostModuleBuilder<'a, St> {
|
impl<St: 'static> HostModuleBuilder<St> {
|
||||||
pub fn new(store: &'a mut Store) -> Self {
|
pub fn new() -> Self {
|
||||||
HostModuleBuilder {
|
HostModuleBuilder {
|
||||||
store: store,
|
items: Vec::new(),
|
||||||
exports: HashMap::new(),
|
|
||||||
_marker: PhantomData,
|
_marker: PhantomData,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn with_func1<
|
pub fn with_func1<
|
||||||
Cl: Fn(&mut St, P1) -> Result<Option<Ret>, Error> + 'static,
|
Cl: Fn(&mut St, P1) -> Result<Option<Ret>, Error> + 'static,
|
||||||
Ret: AsReturn + 'static,
|
Ret: AsReturnVal + 'static,
|
||||||
P1: FromArg + 'static,
|
P1: FromArg + 'static,
|
||||||
F: Into<Func1<Cl, St, Ret, P1>>,
|
F: Into<Func1<Cl, St, Ret, P1>>,
|
||||||
>(
|
>(
|
||||||
@ -33,29 +52,78 @@ impl<'a, St: 'static> HostModuleBuilder<'a, St> {
|
|||||||
f: F,
|
f: F,
|
||||||
) {
|
) {
|
||||||
let func_type = Func1::<Cl, St, Ret, P1>::derive_func_type();
|
let func_type = Func1::<Cl, St, Ret, P1>::derive_func_type();
|
||||||
let type_id = self.store.alloc_func_type(func_type);
|
let host_func = Arc::new(f.into()) as Arc<AnyFunc>;
|
||||||
|
|
||||||
let anyfunc = Arc::new(f.into()) as Arc<AnyFunc>;
|
self.items.push(HostItem::Func {
|
||||||
|
name: name.to_owned(),
|
||||||
let func_id = self.store.alloc_host_func(type_id, anyfunc);
|
func_type,
|
||||||
self.exports.insert(name.to_owned(), ExternVal::Func(func_id));
|
host_func,
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn with_global(&mut self, name: &str, global_type: GlobalType, val: RuntimeValue) {
|
pub fn with_global(&mut self, name: &str, global_type: GlobalType, init_val: RuntimeValue) {
|
||||||
let global_id = self.store.alloc_global(global_type, val);
|
self.items.push(HostItem::Global {
|
||||||
self.exports.insert(name.to_owned(), ExternVal::Global(global_id));
|
name: name.to_owned(),
|
||||||
|
global_type,
|
||||||
|
init_val,
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn with_memory(&mut self, name: &str, memory_type: &MemoryType) -> Result<(), Error> {
|
pub fn with_memory(&mut self, name: &str, memory_type: MemoryType) {
|
||||||
let memory_id = self.store.alloc_memory(memory_type)?;
|
self.items.push(HostItem::Memory {
|
||||||
self.exports.insert(name.to_owned(), ExternVal::Memory(memory_id));
|
name: name.to_owned(),
|
||||||
Ok(())
|
memory_type,
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn with_table(&mut self, name: &str, table_type: &TableType) -> Result<(), Error> {
|
pub fn with_table(&mut self, name: &str, table_type: TableType) {
|
||||||
let table_id = self.store.alloc_table(table_type)?;
|
self.items.push(HostItem::Table {
|
||||||
self.exports.insert(name.to_owned(), ExternVal::Table(table_id));
|
name: name.to_owned(),
|
||||||
Ok(())
|
table_type,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn build(self) -> HostModule {
|
||||||
|
HostModule {
|
||||||
|
items: self.items
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct HostModule {
|
||||||
|
items: Vec<HostItem>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl HostModule {
|
||||||
|
pub(crate) fn allocate(self, store: &mut Store) -> Result<ModuleId, Error> {
|
||||||
|
let mut exports = HashMap::new();
|
||||||
|
|
||||||
|
for item in self.items {
|
||||||
|
match item {
|
||||||
|
HostItem::Func { name, func_type, host_func } => {
|
||||||
|
let type_id = store.alloc_func_type(func_type);
|
||||||
|
let func_id = store.alloc_host_func(type_id, host_func);
|
||||||
|
exports.insert(name, ExternVal::Func(func_id));
|
||||||
|
},
|
||||||
|
HostItem::Global { name, global_type, init_val } => {
|
||||||
|
let global_id = store.alloc_global(global_type, init_val);
|
||||||
|
exports.insert(name, ExternVal::Global(global_id));
|
||||||
|
},
|
||||||
|
HostItem::Memory { name, memory_type } => {
|
||||||
|
let memory_id = store.alloc_memory(&memory_type)?;
|
||||||
|
exports.insert(name, ExternVal::Memory(memory_id));
|
||||||
|
},
|
||||||
|
HostItem::Table { name, table_type } => {
|
||||||
|
let table_id = store.alloc_table(&table_type)?;
|
||||||
|
exports.insert(name, ExternVal::Table(table_id));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
let host_module_instance = ModuleInstance::with_exports(exports);
|
||||||
|
let module_id = store.add_module_instance(host_module_instance);
|
||||||
|
|
||||||
|
Ok(module_id)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -85,12 +153,12 @@ impl FromArg for i32 {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub trait AsReturn {
|
pub trait AsReturnVal {
|
||||||
fn as_return_val(self) -> Option<RuntimeValue>;
|
fn as_return_val(self) -> Option<RuntimeValue>;
|
||||||
fn value_type() -> Option<ValueType>;
|
fn value_type() -> Option<ValueType>;
|
||||||
}
|
}
|
||||||
|
|
||||||
impl AsReturn for i32 {
|
impl AsReturnVal for i32 {
|
||||||
fn as_return_val(self) -> Option<RuntimeValue> {
|
fn as_return_val(self) -> Option<RuntimeValue> {
|
||||||
Some(self.into())
|
Some(self.into())
|
||||||
}
|
}
|
||||||
@ -100,7 +168,7 @@ impl AsReturn for i32 {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl AsReturn for () {
|
impl AsReturnVal for () {
|
||||||
fn as_return_val(self) -> Option<RuntimeValue> {
|
fn as_return_val(self) -> Option<RuntimeValue> {
|
||||||
None
|
None
|
||||||
}
|
}
|
||||||
@ -110,14 +178,14 @@ impl AsReturn for () {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct Func1<Cl: Fn(&mut St, P1) -> Result<Option<Ret>, Error>, St, Ret: AsReturn, P1: FromArg> {
|
pub struct Func1<Cl: Fn(&mut St, P1) -> Result<Option<Ret>, Error>, St, Ret: AsReturnVal, P1: FromArg> {
|
||||||
closure: Cl,
|
closure: Cl,
|
||||||
_marker: PhantomData<(St, Ret, P1)>,
|
_marker: PhantomData<(St, Ret, P1)>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<
|
impl<
|
||||||
St: 'static,
|
St: 'static,
|
||||||
Ret: AsReturn,
|
Ret: AsReturnVal,
|
||||||
P1: FromArg,
|
P1: FromArg,
|
||||||
Cl: Fn(&mut St, P1) -> Result<Option<Ret>, Error>,
|
Cl: Fn(&mut St, P1) -> Result<Option<Ret>, Error>,
|
||||||
> AnyFunc for Func1<Cl, St, Ret, P1> {
|
> AnyFunc for Func1<Cl, St, Ret, P1> {
|
||||||
@ -133,7 +201,7 @@ impl<
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<St: 'static, Ret: AsReturn, P1: FromArg, Cl: Fn(&mut St, P1) -> Result<Option<Ret>, Error>> From<Cl>
|
impl<St: 'static, Ret: AsReturnVal, P1: FromArg, Cl: Fn(&mut St, P1) -> Result<Option<Ret>, Error>> From<Cl>
|
||||||
for Func1<Cl, St, Ret, P1> {
|
for Func1<Cl, St, Ret, P1> {
|
||||||
fn from(cl: Cl) -> Self {
|
fn from(cl: Cl) -> Self {
|
||||||
Func1 {
|
Func1 {
|
||||||
@ -145,7 +213,7 @@ impl<St: 'static, Ret: AsReturn, P1: FromArg, Cl: Fn(&mut St, P1) -> Result<Opti
|
|||||||
|
|
||||||
impl<
|
impl<
|
||||||
St: 'static,
|
St: 'static,
|
||||||
Ret: AsReturn,
|
Ret: AsReturnVal,
|
||||||
P1: FromArg,
|
P1: FromArg,
|
||||||
Cl: Fn(&mut St, P1) -> Result<Option<Ret>, Error>,
|
Cl: Fn(&mut St, P1) -> Result<Option<Ret>, Error>,
|
||||||
> Func1<Cl, St, Ret, P1> {
|
> Func1<Cl, St, Ret, P1> {
|
||||||
|
@ -150,3 +150,4 @@ pub use self::table::TableInstance;
|
|||||||
pub use self::program::ProgramInstance;
|
pub use self::program::ProgramInstance;
|
||||||
pub use self::value::RuntimeValue;
|
pub use self::value::RuntimeValue;
|
||||||
pub use self::variable::{VariableInstance, VariableType, ExternalVariableValue};
|
pub use self::variable::{VariableInstance, VariableType, ExternalVariableValue};
|
||||||
|
pub use self::host::{HostModule, HostModuleBuilder, Func1, AnyFunc, AsReturnVal, FromArg};
|
||||||
|
@ -3,7 +3,7 @@ use std::collections::HashMap;
|
|||||||
use elements::Module;
|
use elements::Module;
|
||||||
use interpreter::Error;
|
use interpreter::Error;
|
||||||
use interpreter::store::{Store, ModuleId};
|
use interpreter::store::{Store, ModuleId};
|
||||||
use interpreter::host::HostModuleBuilder;
|
use interpreter::host::HostModule;
|
||||||
|
|
||||||
/// Program instance. Program is a set of instantiated modules.
|
/// Program instance. Program is a set of instantiated modules.
|
||||||
pub struct ProgramInstance {
|
pub struct ProgramInstance {
|
||||||
@ -37,13 +37,15 @@ impl ProgramInstance {
|
|||||||
}
|
}
|
||||||
|
|
||||||
let module_id = self.store.instantiate_module(&module, &extern_vals, state)?;
|
let module_id = self.store.instantiate_module(&module, &extern_vals, state)?;
|
||||||
self.modules.insert(name.to_string(), module_id);
|
self.modules.insert(name.to_owned(), module_id);
|
||||||
|
|
||||||
Ok(module_id)
|
Ok(module_id)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn with_host_module<St: 'static>(&mut self, name: &str) -> HostModuleBuilder<St> {
|
pub fn add_host_module(&mut self, name: &str, host_module: HostModule) -> Result<ModuleId, Error> {
|
||||||
HostModuleBuilder::new(&mut self.store)
|
let module_id = host_module.allocate(&mut self.store)?;
|
||||||
|
self.modules.insert(name.to_owned(), module_id);
|
||||||
|
Ok(module_id)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Get one of the modules by name
|
/// Get one of the modules by name
|
||||||
|
@ -181,7 +181,7 @@ pub struct ExportInstance {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Default)]
|
#[derive(Default)]
|
||||||
struct ModuleInstance {
|
pub struct ModuleInstance {
|
||||||
types: Vec<TypeId>,
|
types: Vec<TypeId>,
|
||||||
funcs: Vec<FuncId>,
|
funcs: Vec<FuncId>,
|
||||||
tables: Vec<TableId>,
|
tables: Vec<TableId>,
|
||||||
@ -194,6 +194,12 @@ impl ModuleInstance {
|
|||||||
fn new() -> ModuleInstance {
|
fn new() -> ModuleInstance {
|
||||||
ModuleInstance::default()
|
ModuleInstance::default()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn with_exports(exports: HashMap<String, ExternVal>) -> ModuleInstance {
|
||||||
|
ModuleInstance {
|
||||||
|
exports, ..Default::default()
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Default)]
|
#[derive(Default)]
|
||||||
@ -474,6 +480,12 @@ impl Store {
|
|||||||
Ok(module_id)
|
Ok(module_id)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn add_module_instance(&mut self, instance: ModuleInstance) -> ModuleId {
|
||||||
|
self.modules.push(instance);
|
||||||
|
let module_id = self.modules.len() - 1;
|
||||||
|
ModuleId(module_id as u32)
|
||||||
|
}
|
||||||
|
|
||||||
pub fn invoke<St: 'static>(
|
pub fn invoke<St: 'static>(
|
||||||
&mut self,
|
&mut self,
|
||||||
func: FuncId,
|
func: FuncId,
|
||||||
|
Reference in New Issue
Block a user