mirror of
https://github.com/fluencelabs/parity-wasm
synced 2025-06-26 21:22:13 +00:00
impl
This commit is contained in:
@ -14,3 +14,4 @@ exclude = [ "res/*", "spec/*" ]
|
|||||||
[dependencies]
|
[dependencies]
|
||||||
log = "0.3"
|
log = "0.3"
|
||||||
byteorder = "1.0"
|
byteorder = "1.0"
|
||||||
|
unsafe-any = "0.4.2"
|
||||||
|
@ -3,7 +3,7 @@
|
|||||||
extern crate parity_wasm;
|
extern crate parity_wasm;
|
||||||
|
|
||||||
use std::env::args;
|
use std::env::args;
|
||||||
use parity_wasm::interpreter::ModuleInstance;
|
use parity_wasm::interpreter::{ModuleInstance, HostState};
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
let args: Vec<_> = args().collect();
|
let args: Vec<_> = args().collect();
|
||||||
@ -23,7 +23,7 @@ fn main() {
|
|||||||
// - "main" module doesn't import native module(s) this is why we don't need to provide external native modules here
|
// - "main" module doesn't import native module(s) this is why we don't need to provide external native modules here
|
||||||
// This test shows how to implement native module https://github.com/NikVolf/parity-wasm/blob/master/src/interpreter/tests/basics.rs#L197
|
// This test shows how to implement native module https://github.com/NikVolf/parity-wasm/blob/master/src/interpreter/tests/basics.rs#L197
|
||||||
let main = ModuleInstance::new(&module)
|
let main = ModuleInstance::new(&module)
|
||||||
.run_start(&mut ())
|
.run_start(&mut HostState::default())
|
||||||
.expect("Failed to initialize module");
|
.expect("Failed to initialize module");
|
||||||
|
|
||||||
// The argument should be parsable as a valid integer
|
// The argument should be parsable as a valid integer
|
||||||
|
@ -4,7 +4,7 @@ use std::env::args;
|
|||||||
|
|
||||||
use parity_wasm::RuntimeValue;
|
use parity_wasm::RuntimeValue;
|
||||||
use parity_wasm::elements::{Internal, External, Type, FunctionType, ValueType};
|
use parity_wasm::elements::{Internal, External, Type, FunctionType, ValueType};
|
||||||
use parity_wasm::interpreter::ModuleInstance;
|
use parity_wasm::interpreter::{ModuleInstance, HostState};
|
||||||
|
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
@ -75,8 +75,8 @@ fn main() {
|
|||||||
// - "main" module doesn't import native module(s) this is why we don't need to provide external native modules here
|
// - "main" module doesn't import native module(s) this is why we don't need to provide external native modules here
|
||||||
// This test shows how to implement native module https://github.com/NikVolf/parity-wasm/blob/master/src/interpreter/tests/basics.rs#L197
|
// This test shows how to implement native module https://github.com/NikVolf/parity-wasm/blob/master/src/interpreter/tests/basics.rs#L197
|
||||||
let main = ModuleInstance::new(&module)
|
let main = ModuleInstance::new(&module)
|
||||||
.run_start(&mut ())
|
.run_start(&mut HostState::default())
|
||||||
.expect("Failed to initialize module");
|
.expect("Failed to initialize module");
|
||||||
|
|
||||||
println!("Result: {:?}", main.invoke_export(func_name, &args, &mut ()).expect(""));
|
println!("Result: {:?}", main.invoke_export(func_name, &args, &mut HostState::default()).expect(""));
|
||||||
}
|
}
|
||||||
|
@ -6,7 +6,7 @@ use std::rc::Rc;
|
|||||||
use parity_wasm::elements::Module;
|
use parity_wasm::elements::Module;
|
||||||
use parity_wasm::interpreter::{
|
use parity_wasm::interpreter::{
|
||||||
Error as InterpreterError, HostModule, HostModuleBuilder,
|
Error as InterpreterError, HostModule, HostModuleBuilder,
|
||||||
ModuleInstance, UserError};
|
ModuleInstance, UserError, HostState, StateKey};
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub enum Error {
|
pub enum Error {
|
||||||
@ -142,32 +142,39 @@ struct Runtime<'a> {
|
|||||||
game: &'a tictactoe::Game,
|
game: &'a tictactoe::Game,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
unsafe impl<'a> StateKey for Runtime<'a> {
|
||||||
|
type Static = Runtime<'static>;
|
||||||
|
}
|
||||||
|
|
||||||
fn instantiate<'a, 'b>(
|
fn instantiate<'a, 'b>(
|
||||||
module: &Module,
|
module: &Module,
|
||||||
env: &HostModule<Runtime<'a>>,
|
env: &HostModule,
|
||||||
runtime: &'b Runtime<'a>,
|
) -> Result<Rc<ModuleInstance>, Error> {
|
||||||
) -> Result<Rc<ModuleInstance<Runtime<'a>>>, Error> {
|
|
||||||
let instance = ModuleInstance::new(module)
|
let instance = ModuleInstance::new(module)
|
||||||
.with_import("env", &*env)
|
.with_import("env", &*env)
|
||||||
.run_start(runtime)?;
|
.run_start(&mut HostState::default())?;
|
||||||
|
|
||||||
Ok(instance)
|
Ok(instance)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn env_host_module<'a>() -> HostModule<Runtime<'a>> {
|
fn env_host_module<'a>() -> HostModule {
|
||||||
HostModuleBuilder::<Runtime>::new()
|
HostModuleBuilder::new()
|
||||||
.with_func1(
|
.with_func1(
|
||||||
"set",
|
"set",
|
||||||
|state: &Runtime, idx: i32| -> Result<(), InterpreterError> {
|
|state: &mut HostState, idx: i32| -> Result<(), InterpreterError> {
|
||||||
state.game.set(idx, state.player)?;
|
state.with_state(|runtime: &mut Runtime| -> Result<(), InterpreterError> {
|
||||||
Ok(())
|
runtime.game.set(idx, runtime.player)?;
|
||||||
|
Ok(())
|
||||||
|
})
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
.with_func1(
|
.with_func1(
|
||||||
"get",
|
"get",
|
||||||
|state: &Runtime, idx: i32| -> Result<i32, InterpreterError> {
|
|state: &mut HostState, idx: i32| -> Result<i32, InterpreterError> {
|
||||||
let val: i32 = tictactoe::Player::into_i32(state.game.get(idx).unwrap());
|
state.with_state(|runtime: &mut Runtime| -> Result<i32, InterpreterError> {
|
||||||
Ok(val)
|
let val: i32 = tictactoe::Player::into_i32(runtime.game.get(idx)?);
|
||||||
|
Ok(val)
|
||||||
|
})
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
.build()
|
.build()
|
||||||
@ -176,24 +183,12 @@ fn env_host_module<'a>() -> HostModule<Runtime<'a>> {
|
|||||||
fn play<'a>(
|
fn play<'a>(
|
||||||
x_module: &Module,
|
x_module: &Module,
|
||||||
o_module: &Module,
|
o_module: &Module,
|
||||||
host_module: &HostModule<Runtime<'a>>,
|
host_module: &HostModule,
|
||||||
game: &'a tictactoe::Game,
|
game: &'a tictactoe::Game,
|
||||||
) -> Result<tictactoe::GameResult, Error> {
|
) -> Result<tictactoe::GameResult, Error> {
|
||||||
// Instantiate modules of X and O players.
|
// Instantiate modules of X and O players.
|
||||||
let x_instance = {
|
let x_instance = instantiate(x_module, host_module)?;
|
||||||
let mut runtime = Runtime {
|
let o_instance = instantiate(o_module, host_module)?;
|
||||||
player: tictactoe::Player::X,
|
|
||||||
game: game,
|
|
||||||
};
|
|
||||||
instantiate(x_module, host_module, &runtime)?
|
|
||||||
};
|
|
||||||
let o_instance = {
|
|
||||||
let mut runtime = Runtime {
|
|
||||||
player: tictactoe::Player::O,
|
|
||||||
game: game,
|
|
||||||
};
|
|
||||||
instantiate(o_module, host_module, &runtime)?
|
|
||||||
};
|
|
||||||
|
|
||||||
let mut turn_of = tictactoe::Player::X;
|
let mut turn_of = tictactoe::Player::X;
|
||||||
let game_result = loop {
|
let game_result = loop {
|
||||||
@ -206,7 +201,9 @@ fn play<'a>(
|
|||||||
player: turn_of,
|
player: turn_of,
|
||||||
game: game,
|
game: game,
|
||||||
};
|
};
|
||||||
let _ = instance.invoke_export("mk_turn", &[], &runtime)?;
|
let mut host_state = HostState::new();
|
||||||
|
host_state.insert::<Runtime>(&mut runtime);
|
||||||
|
let _ = instance.invoke_export("mk_turn", &[], &mut host_state)?;
|
||||||
|
|
||||||
match game.game_result() {
|
match game.game_result() {
|
||||||
Some(game_result) => break game_result,
|
Some(game_result) => break game_result,
|
||||||
|
@ -7,23 +7,24 @@ use interpreter::{Error, ModuleInstance};
|
|||||||
use interpreter::runner::{prepare_function_args, FunctionContext, Interpreter};
|
use interpreter::runner::{prepare_function_args, FunctionContext, Interpreter};
|
||||||
use interpreter::host::HostFunc;
|
use interpreter::host::HostFunc;
|
||||||
use interpreter::value::RuntimeValue;
|
use interpreter::value::RuntimeValue;
|
||||||
|
use interpreter::state::HostState;
|
||||||
use common::stack::StackWithLimit;
|
use common::stack::StackWithLimit;
|
||||||
use common::{DEFAULT_FRAME_STACK_LIMIT, DEFAULT_VALUE_STACK_LIMIT};
|
use common::{DEFAULT_FRAME_STACK_LIMIT, DEFAULT_VALUE_STACK_LIMIT};
|
||||||
|
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
pub enum FuncInstance<St> {
|
pub enum FuncInstance {
|
||||||
Internal {
|
Internal {
|
||||||
func_type: Rc<FunctionType>,
|
func_type: Rc<FunctionType>,
|
||||||
module: Rc<ModuleInstance<St>>,
|
module: Rc<ModuleInstance>,
|
||||||
body: Rc<FuncBody>,
|
body: Rc<FuncBody>,
|
||||||
},
|
},
|
||||||
Host {
|
Host {
|
||||||
func_type: Rc<FunctionType>,
|
func_type: Rc<FunctionType>,
|
||||||
host_func: Rc<HostFunc<St>>,
|
host_func: Rc<HostFunc>,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<St: fmt::Debug> fmt::Debug for FuncInstance<St> {
|
impl fmt::Debug for FuncInstance {
|
||||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||||
match self {
|
match self {
|
||||||
&FuncInstance::Internal {
|
&FuncInstance::Internal {
|
||||||
@ -45,9 +46,9 @@ impl<St: fmt::Debug> fmt::Debug for FuncInstance<St> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<St> FuncInstance<St> {
|
impl FuncInstance {
|
||||||
pub fn alloc_internal(
|
pub fn alloc_internal(
|
||||||
module: Rc<ModuleInstance<St>>,
|
module: Rc<ModuleInstance>,
|
||||||
func_type: Rc<FunctionType>,
|
func_type: Rc<FunctionType>,
|
||||||
body: FuncBody,
|
body: FuncBody,
|
||||||
) -> Rc<Self> {
|
) -> Rc<Self> {
|
||||||
@ -59,7 +60,7 @@ impl<St> FuncInstance<St> {
|
|||||||
Rc::new(func)
|
Rc::new(func)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn alloc_host(func_type: Rc<FunctionType>, host_func: Rc<HostFunc<St>>) -> Rc<Self> {
|
pub fn alloc_host(func_type: Rc<FunctionType>, host_func: Rc<HostFunc>) -> Rc<Self> {
|
||||||
let func = FuncInstance::Host {
|
let func = FuncInstance::Host {
|
||||||
func_type,
|
func_type,
|
||||||
host_func,
|
host_func,
|
||||||
@ -81,14 +82,14 @@ impl<St> FuncInstance<St> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn invoke(
|
pub fn invoke<'a, 'b: 'a>(
|
||||||
func: Rc<FuncInstance<St>>,
|
func: Rc<FuncInstance>,
|
||||||
args: Cow<[RuntimeValue]>,
|
args: Cow<[RuntimeValue]>,
|
||||||
state: &St,
|
state: &'a mut HostState<'b>,
|
||||||
) -> Result<Option<RuntimeValue>, Error> {
|
) -> Result<Option<RuntimeValue>, Error> {
|
||||||
enum InvokeKind<'a, St> {
|
enum InvokeKind<'a> {
|
||||||
Internal(FunctionContext<St>),
|
Internal(FunctionContext),
|
||||||
Host(Rc<HostFunc<St>>, &'a [RuntimeValue]),
|
Host(Rc<HostFunc>, &'a [RuntimeValue]),
|
||||||
}
|
}
|
||||||
|
|
||||||
let result = match *func {
|
let result = match *func {
|
||||||
|
@ -10,15 +10,16 @@ use interpreter::table::TableInstance;
|
|||||||
use interpreter::value::{RuntimeValue, TryInto};
|
use interpreter::value::{RuntimeValue, TryInto};
|
||||||
use interpreter::Error;
|
use interpreter::Error;
|
||||||
use interpreter::ImportResolver;
|
use interpreter::ImportResolver;
|
||||||
|
use interpreter::state::HostState;
|
||||||
|
|
||||||
pub type HostFunc<St> = Fn(&St, &[RuntimeValue])
|
pub type HostFunc = Fn(&mut HostState, &[RuntimeValue])
|
||||||
-> Result<Option<RuntimeValue>, Error>;
|
-> Result<Option<RuntimeValue>, Error>;
|
||||||
|
|
||||||
pub struct HostModuleBuilder<St> {
|
pub struct HostModuleBuilder {
|
||||||
exports: HashMap<String, ExternVal<St>>,
|
exports: HashMap<String, ExternVal>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<St> HostModuleBuilder<St> {
|
impl HostModuleBuilder {
|
||||||
pub fn new() -> Self {
|
pub fn new() -> Self {
|
||||||
HostModuleBuilder {
|
HostModuleBuilder {
|
||||||
exports: HashMap::new(),
|
exports: HashMap::new(),
|
||||||
@ -26,7 +27,7 @@ impl<St> HostModuleBuilder<St> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn insert_func0<
|
pub fn insert_func0<
|
||||||
Cl: Fn(&St) -> Result<Ret, Error> + 'static,
|
Cl: Fn(&mut HostState) -> Result<Ret, Error> + 'static,
|
||||||
Ret: IntoReturnVal + 'static,
|
Ret: IntoReturnVal + 'static,
|
||||||
N: Into<String>,
|
N: Into<String>,
|
||||||
>(
|
>(
|
||||||
@ -36,7 +37,7 @@ impl<St> HostModuleBuilder<St> {
|
|||||||
) {
|
) {
|
||||||
let func_type = FunctionType::new(vec![], Ret::value_type());
|
let func_type = FunctionType::new(vec![], Ret::value_type());
|
||||||
let host_func = Rc::new(
|
let host_func = Rc::new(
|
||||||
move |state: &St, args: &[RuntimeValue]| -> Result<Option<RuntimeValue>, Error> {
|
move |state: &mut HostState, args: &[RuntimeValue]| -> Result<Option<RuntimeValue>, Error> {
|
||||||
assert!(args.len() == 0);
|
assert!(args.len() == 0);
|
||||||
let result = f(state)?.into_return_val();
|
let result = f(state)?.into_return_val();
|
||||||
Ok(result)
|
Ok(result)
|
||||||
@ -48,7 +49,7 @@ impl<St> HostModuleBuilder<St> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn insert_func1<
|
pub fn insert_func1<
|
||||||
Cl: Fn(&St, P1) -> Result<Ret, Error> + 'static,
|
Cl: Fn(&mut HostState, P1) -> Result<Ret, Error> + 'static,
|
||||||
Ret: IntoReturnVal + 'static,
|
Ret: IntoReturnVal + 'static,
|
||||||
P1: FromArg + 'static,
|
P1: FromArg + 'static,
|
||||||
N: Into<String>,
|
N: Into<String>,
|
||||||
@ -59,7 +60,7 @@ impl<St> HostModuleBuilder<St> {
|
|||||||
) {
|
) {
|
||||||
let func_type = FunctionType::new(vec![P1::value_type()], Ret::value_type());
|
let func_type = FunctionType::new(vec![P1::value_type()], Ret::value_type());
|
||||||
let host_func = Rc::new(
|
let host_func = Rc::new(
|
||||||
move |state: &St, args: &[RuntimeValue]| -> Result<Option<RuntimeValue>, Error> {
|
move |state: &mut HostState, args: &[RuntimeValue]| -> Result<Option<RuntimeValue>, Error> {
|
||||||
assert!(args.len() == 1);
|
assert!(args.len() == 1);
|
||||||
let mut args = args.into_iter();
|
let mut args = args.into_iter();
|
||||||
let result = f(
|
let result = f(
|
||||||
@ -75,7 +76,7 @@ impl<St> HostModuleBuilder<St> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn insert_func2<
|
pub fn insert_func2<
|
||||||
Cl: Fn(&St, P1, P2) -> Result<Ret, Error> + 'static,
|
Cl: Fn(&mut HostState, P1, P2) -> Result<Ret, Error> + 'static,
|
||||||
Ret: IntoReturnVal + 'static,
|
Ret: IntoReturnVal + 'static,
|
||||||
P1: FromArg + 'static,
|
P1: FromArg + 'static,
|
||||||
P2: FromArg + 'static,
|
P2: FromArg + 'static,
|
||||||
@ -88,7 +89,7 @@ impl<St> HostModuleBuilder<St> {
|
|||||||
let func_type =
|
let func_type =
|
||||||
FunctionType::new(vec![P1::value_type(), P2::value_type()], Ret::value_type());
|
FunctionType::new(vec![P1::value_type(), P2::value_type()], Ret::value_type());
|
||||||
let host_func = Rc::new(
|
let host_func = Rc::new(
|
||||||
move |state: &St, args: &[RuntimeValue]| -> Result<Option<RuntimeValue>, Error> {
|
move |state: &mut HostState, args: &[RuntimeValue]| -> Result<Option<RuntimeValue>, Error> {
|
||||||
assert!(args.len() == 2);
|
assert!(args.len() == 2);
|
||||||
let mut args = args.into_iter();
|
let mut args = args.into_iter();
|
||||||
let result = f(
|
let result = f(
|
||||||
@ -105,7 +106,7 @@ impl<St> HostModuleBuilder<St> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn insert_func3<
|
pub fn insert_func3<
|
||||||
Cl: Fn(&St, P1, P2, P3) -> Result<Ret, Error> + 'static,
|
Cl: Fn(&mut HostState, P1, P2, P3) -> Result<Ret, Error> + 'static,
|
||||||
Ret: IntoReturnVal + 'static,
|
Ret: IntoReturnVal + 'static,
|
||||||
P1: FromArg + 'static,
|
P1: FromArg + 'static,
|
||||||
P2: FromArg + 'static,
|
P2: FromArg + 'static,
|
||||||
@ -121,7 +122,7 @@ impl<St> HostModuleBuilder<St> {
|
|||||||
Ret::value_type(),
|
Ret::value_type(),
|
||||||
);
|
);
|
||||||
let host_func = Rc::new(
|
let host_func = Rc::new(
|
||||||
move |state: &St, args: &[RuntimeValue]| -> Result<Option<RuntimeValue>, Error> {
|
move |state: &mut HostState, args: &[RuntimeValue]| -> Result<Option<RuntimeValue>, Error> {
|
||||||
assert!(args.len() == 3);
|
assert!(args.len() == 3);
|
||||||
let mut args = args.into_iter();
|
let mut args = args.into_iter();
|
||||||
let result = f(
|
let result = f(
|
||||||
@ -139,7 +140,7 @@ impl<St> HostModuleBuilder<St> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn insert_func4<
|
pub fn insert_func4<
|
||||||
Cl: Fn(&St, P1, P2, P3, P4) -> Result<Ret, Error> + 'static,
|
Cl: Fn(&mut HostState, P1, P2, P3, P4) -> Result<Ret, Error> + 'static,
|
||||||
Ret: IntoReturnVal + 'static,
|
Ret: IntoReturnVal + 'static,
|
||||||
P1: FromArg + 'static,
|
P1: FromArg + 'static,
|
||||||
P2: FromArg + 'static,
|
P2: FromArg + 'static,
|
||||||
@ -161,7 +162,7 @@ impl<St> HostModuleBuilder<St> {
|
|||||||
Ret::value_type(),
|
Ret::value_type(),
|
||||||
);
|
);
|
||||||
let host_func = Rc::new(
|
let host_func = Rc::new(
|
||||||
move |state: &St, args: &[RuntimeValue]| -> Result<Option<RuntimeValue>, Error> {
|
move |state: &mut HostState, args: &[RuntimeValue]| -> Result<Option<RuntimeValue>, Error> {
|
||||||
assert!(args.len() == 4);
|
assert!(args.len() == 4);
|
||||||
let mut args = args.into_iter();
|
let mut args = args.into_iter();
|
||||||
let result = f(
|
let result = f(
|
||||||
@ -180,7 +181,7 @@ impl<St> HostModuleBuilder<St> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn with_func0<
|
pub fn with_func0<
|
||||||
Cl: Fn(&St) -> Result<Ret, Error> + 'static,
|
Cl: Fn(&mut HostState) -> Result<Ret, Error> + 'static,
|
||||||
Ret: IntoReturnVal + 'static,
|
Ret: IntoReturnVal + 'static,
|
||||||
N: Into<String>,
|
N: Into<String>,
|
||||||
>(
|
>(
|
||||||
@ -193,7 +194,7 @@ impl<St> HostModuleBuilder<St> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn with_func1<
|
pub fn with_func1<
|
||||||
Cl: Fn(&St, P1) -> Result<Ret, Error> + 'static,
|
Cl: Fn(&mut HostState, P1) -> Result<Ret, Error> + 'static,
|
||||||
Ret: IntoReturnVal + 'static,
|
Ret: IntoReturnVal + 'static,
|
||||||
P1: FromArg + 'static,
|
P1: FromArg + 'static,
|
||||||
N: Into<String>,
|
N: Into<String>,
|
||||||
@ -207,7 +208,7 @@ impl<St> HostModuleBuilder<St> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn with_func2<
|
pub fn with_func2<
|
||||||
Cl: Fn(&St, P1, P2) -> Result<Ret, Error> + 'static,
|
Cl: Fn(&mut HostState, P1, P2) -> Result<Ret, Error> + 'static,
|
||||||
Ret: IntoReturnVal + 'static,
|
Ret: IntoReturnVal + 'static,
|
||||||
P1: FromArg + 'static,
|
P1: FromArg + 'static,
|
||||||
P2: FromArg + 'static,
|
P2: FromArg + 'static,
|
||||||
@ -221,7 +222,7 @@ impl<St> HostModuleBuilder<St> {
|
|||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn insert_func<N: Into<String>>(&mut self, name: N, func: Rc<FuncInstance<St>>) {
|
pub fn insert_func<N: Into<String>>(&mut self, name: N, func: Rc<FuncInstance>) {
|
||||||
self.insert(name, ExternVal::Func(func));
|
self.insert(name, ExternVal::Func(func));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -233,7 +234,7 @@ impl<St> HostModuleBuilder<St> {
|
|||||||
self.insert(name, ExternVal::Memory(memory));
|
self.insert(name, ExternVal::Memory(memory));
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn insert_table<N: Into<String>>(&mut self, name: N, table: Rc<TableInstance<St>>) {
|
pub fn insert_table<N: Into<String>>(&mut self, name: N, table: Rc<TableInstance>) {
|
||||||
self.insert(name, ExternVal::Table(table));
|
self.insert(name, ExternVal::Table(table));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -247,40 +248,40 @@ impl<St> HostModuleBuilder<St> {
|
|||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn with_table<N: Into<String>>(mut self, name: N, table: Rc<TableInstance<St>>) -> Self {
|
pub fn with_table<N: Into<String>>(mut self, name: N, table: Rc<TableInstance>) -> Self {
|
||||||
self.insert_table(name, table);
|
self.insert_table(name, table);
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
fn insert<N: Into<String>>(&mut self, name: N, extern_val: ExternVal<St>) {
|
fn insert<N: Into<String>>(&mut self, name: N, extern_val: ExternVal) {
|
||||||
match self.exports.entry(name.into()) {
|
match self.exports.entry(name.into()) {
|
||||||
Entry::Vacant(v) => v.insert(extern_val),
|
Entry::Vacant(v) => v.insert(extern_val),
|
||||||
Entry::Occupied(o) => panic!("Duplicate export name {}", o.key()),
|
Entry::Occupied(o) => panic!("Duplicate export name {}", o.key()),
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn build(self) -> HostModule<St> {
|
pub fn build(self) -> HostModule {
|
||||||
let internal_instance = Rc::new(ModuleInstance::with_exports(self.exports));
|
let internal_instance = Rc::new(ModuleInstance::with_exports(self.exports));
|
||||||
HostModule { internal_instance }
|
HostModule { internal_instance }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct HostModule<St> {
|
pub struct HostModule {
|
||||||
internal_instance: Rc<ModuleInstance<St>>,
|
internal_instance: Rc<ModuleInstance>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<St> HostModule<St> {
|
impl HostModule {
|
||||||
pub fn export_by_name(&self, name: &str) -> Option<ExternVal<St>> {
|
pub fn export_by_name(&self, name: &str) -> Option<ExternVal> {
|
||||||
self.internal_instance.export_by_name(name)
|
self.internal_instance.export_by_name(name)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<St> ImportResolver<St> for HostModule<St> {
|
impl ImportResolver for HostModule {
|
||||||
fn resolve_func(
|
fn resolve_func(
|
||||||
&self,
|
&self,
|
||||||
field_name: &str,
|
field_name: &str,
|
||||||
func_type: &FunctionType,
|
func_type: &FunctionType,
|
||||||
) -> Result<Rc<FuncInstance<St>>, Error> {
|
) -> Result<Rc<FuncInstance>, Error> {
|
||||||
self.internal_instance.resolve_func(field_name, func_type)
|
self.internal_instance.resolve_func(field_name, func_type)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -306,7 +307,7 @@ impl<St> ImportResolver<St> for HostModule<St> {
|
|||||||
&self,
|
&self,
|
||||||
field_name: &str,
|
field_name: &str,
|
||||||
table_type: &TableType,
|
table_type: &TableType,
|
||||||
) -> Result<Rc<TableInstance<St>>, Error> {
|
) -> Result<Rc<TableInstance>, Error> {
|
||||||
self.internal_instance.resolve_table(field_name, table_type)
|
self.internal_instance.resolve_table(field_name, table_type)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -7,45 +7,45 @@ use interpreter::memory::MemoryInstance;
|
|||||||
use interpreter::table::TableInstance;
|
use interpreter::table::TableInstance;
|
||||||
use interpreter::Error;
|
use interpreter::Error;
|
||||||
|
|
||||||
pub struct Imports<'a, St: 'a> {
|
pub struct Imports<'a> {
|
||||||
modules: HashMap<String, &'a ImportResolver<St>>,
|
modules: HashMap<String, &'a ImportResolver>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a, St: 'a> Default for Imports<'a, St> {
|
impl<'a> Default for Imports<'a> {
|
||||||
fn default() -> Self {
|
fn default() -> Self {
|
||||||
Self::new()
|
Self::new()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a, St: 'a> Imports<'a, St> {
|
impl<'a> Imports<'a> {
|
||||||
pub fn new() -> Imports<'a, St> {
|
pub fn new() -> Imports<'a> {
|
||||||
Imports { modules: HashMap::new() }
|
Imports { modules: HashMap::new() }
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn with_resolver<N: Into<String>>(
|
pub fn with_resolver<N: Into<String>>(
|
||||||
mut self,
|
mut self,
|
||||||
name: N,
|
name: N,
|
||||||
resolver: &'a ImportResolver<St>,
|
resolver: &'a ImportResolver,
|
||||||
) -> Self {
|
) -> Self {
|
||||||
self.modules.insert(name.into(), resolver);
|
self.modules.insert(name.into(), resolver);
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn push_resolver<N: Into<String>>(&mut self, name: N, resolver: &'a ImportResolver<St>) {
|
pub fn push_resolver<N: Into<String>>(&mut self, name: N, resolver: &'a ImportResolver) {
|
||||||
self.modules.insert(name.into(), resolver);
|
self.modules.insert(name.into(), resolver);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn resolver(&self, name: &str) -> Option<&ImportResolver<St>> {
|
pub fn resolver(&self, name: &str) -> Option<&ImportResolver> {
|
||||||
self.modules.get(name).cloned()
|
self.modules.get(name).cloned()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub trait ImportResolver<St> {
|
pub trait ImportResolver {
|
||||||
fn resolve_func(
|
fn resolve_func(
|
||||||
&self,
|
&self,
|
||||||
field_name: &str,
|
field_name: &str,
|
||||||
func_type: &FunctionType,
|
func_type: &FunctionType,
|
||||||
) -> Result<Rc<FuncInstance<St>>, Error>;
|
) -> Result<Rc<FuncInstance>, Error>;
|
||||||
|
|
||||||
fn resolve_global(
|
fn resolve_global(
|
||||||
&self,
|
&self,
|
||||||
@ -63,5 +63,5 @@ pub trait ImportResolver<St> {
|
|||||||
&self,
|
&self,
|
||||||
field_name: &str,
|
field_name: &str,
|
||||||
table_type: &TableType,
|
table_type: &TableType,
|
||||||
) -> Result<Rc<TableInstance<St>>, Error>;
|
) -> Result<Rc<TableInstance>, Error>;
|
||||||
}
|
}
|
||||||
|
@ -146,6 +146,7 @@ mod host;
|
|||||||
mod imports;
|
mod imports;
|
||||||
mod global;
|
mod global;
|
||||||
mod func;
|
mod func;
|
||||||
|
mod state;
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests;
|
mod tests;
|
||||||
@ -159,3 +160,4 @@ pub use self::imports::{ImportResolver, Imports};
|
|||||||
pub use self::module::ModuleInstance;
|
pub use self::module::ModuleInstance;
|
||||||
pub use self::global::GlobalInstance;
|
pub use self::global::GlobalInstance;
|
||||||
pub use self::func::FuncInstance;
|
pub use self::func::FuncInstance;
|
||||||
|
pub use self::state::{HostState, StateKey};
|
||||||
|
@ -9,17 +9,18 @@ use interpreter::{Error, MemoryInstance, RuntimeValue, TableInstance};
|
|||||||
use interpreter::imports::{ImportResolver, Imports};
|
use interpreter::imports::{ImportResolver, Imports};
|
||||||
use interpreter::global::GlobalInstance;
|
use interpreter::global::GlobalInstance;
|
||||||
use interpreter::func::{FuncBody, FuncInstance};
|
use interpreter::func::{FuncBody, FuncInstance};
|
||||||
|
use interpreter::state::HostState;
|
||||||
use validation::validate_module;
|
use validation::validate_module;
|
||||||
use common::{DEFAULT_MEMORY_INDEX, DEFAULT_TABLE_INDEX};
|
use common::{DEFAULT_MEMORY_INDEX, DEFAULT_TABLE_INDEX};
|
||||||
|
|
||||||
pub enum ExternVal<St> {
|
pub enum ExternVal {
|
||||||
Func(Rc<FuncInstance<St>>),
|
Func(Rc<FuncInstance>),
|
||||||
Table(Rc<TableInstance<St>>),
|
Table(Rc<TableInstance>),
|
||||||
Memory(Rc<MemoryInstance>),
|
Memory(Rc<MemoryInstance>),
|
||||||
Global(Rc<GlobalInstance>),
|
Global(Rc<GlobalInstance>),
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<St> Clone for ExternVal<St> {
|
impl Clone for ExternVal {
|
||||||
fn clone(&self) -> Self {
|
fn clone(&self) -> Self {
|
||||||
match *self {
|
match *self {
|
||||||
ExternVal::Func(ref func) => ExternVal::Func(Rc::clone(func)),
|
ExternVal::Func(ref func) => ExternVal::Func(Rc::clone(func)),
|
||||||
@ -30,7 +31,7 @@ impl<St> Clone for ExternVal<St> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<St> fmt::Debug for ExternVal<St> {
|
impl fmt::Debug for ExternVal {
|
||||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||||
write!(
|
write!(
|
||||||
f,
|
f,
|
||||||
@ -45,15 +46,15 @@ impl<St> fmt::Debug for ExternVal<St> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<St> ExternVal<St> {
|
impl ExternVal {
|
||||||
pub fn as_func(&self) -> Option<Rc<FuncInstance<St>>> {
|
pub fn as_func(&self) -> Option<Rc<FuncInstance>> {
|
||||||
match *self {
|
match *self {
|
||||||
ExternVal::Func(ref func) => Some(Rc::clone(func)),
|
ExternVal::Func(ref func) => Some(Rc::clone(func)),
|
||||||
_ => None,
|
_ => None,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn as_table(&self) -> Option<Rc<TableInstance<St>>> {
|
pub fn as_table(&self) -> Option<Rc<TableInstance>> {
|
||||||
match *self {
|
match *self {
|
||||||
ExternVal::Table(ref table) => Some(Rc::clone(table)),
|
ExternVal::Table(ref table) => Some(Rc::clone(table)),
|
||||||
_ => None,
|
_ => None,
|
||||||
@ -76,16 +77,16 @@ impl<St> ExternVal<St> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct ModuleInstance<St> {
|
pub struct ModuleInstance {
|
||||||
types: RefCell<Vec<Rc<FunctionType>>>,
|
types: RefCell<Vec<Rc<FunctionType>>>,
|
||||||
tables: RefCell<Vec<Rc<TableInstance<St>>>>,
|
tables: RefCell<Vec<Rc<TableInstance>>>,
|
||||||
funcs: RefCell<Vec<Rc<FuncInstance<St>>>>,
|
funcs: RefCell<Vec<Rc<FuncInstance>>>,
|
||||||
memories: RefCell<Vec<Rc<MemoryInstance>>>,
|
memories: RefCell<Vec<Rc<MemoryInstance>>>,
|
||||||
globals: RefCell<Vec<Rc<GlobalInstance>>>,
|
globals: RefCell<Vec<Rc<GlobalInstance>>>,
|
||||||
exports: RefCell<HashMap<String, ExternVal<St>>>,
|
exports: RefCell<HashMap<String, ExternVal>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<St> Default for ModuleInstance<St> {
|
impl Default for ModuleInstance {
|
||||||
fn default() -> Self {
|
fn default() -> Self {
|
||||||
ModuleInstance {
|
ModuleInstance {
|
||||||
types: RefCell::new(Vec::new()),
|
types: RefCell::new(Vec::new()),
|
||||||
@ -98,8 +99,8 @@ impl<St> Default for ModuleInstance<St> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<St> ModuleInstance<St> {
|
impl ModuleInstance {
|
||||||
pub fn with_exports(exports: HashMap<String, ExternVal<St>>) -> Self {
|
pub fn with_exports(exports: HashMap<String, ExternVal>) -> Self {
|
||||||
let mut instance = Self::default();
|
let mut instance = Self::default();
|
||||||
instance.exports = RefCell::new(exports);
|
instance.exports = RefCell::new(exports);
|
||||||
instance
|
instance
|
||||||
@ -109,7 +110,7 @@ impl<St> ModuleInstance<St> {
|
|||||||
self.memories.borrow().get(idx as usize).cloned()
|
self.memories.borrow().get(idx as usize).cloned()
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn table_by_index(&self, idx: u32) -> Option<Rc<TableInstance<St>>> {
|
pub fn table_by_index(&self, idx: u32) -> Option<Rc<TableInstance>> {
|
||||||
self.tables.borrow().get(idx as usize).cloned()
|
self.tables.borrow().get(idx as usize).cloned()
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -117,7 +118,7 @@ impl<St> ModuleInstance<St> {
|
|||||||
self.globals.borrow().get(idx as usize).cloned()
|
self.globals.borrow().get(idx as usize).cloned()
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn func_by_index(&self, idx: u32) -> Option<Rc<FuncInstance<St>>> {
|
pub fn func_by_index(&self, idx: u32) -> Option<Rc<FuncInstance>> {
|
||||||
self.funcs.borrow().get(idx as usize).cloned()
|
self.funcs.borrow().get(idx as usize).cloned()
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -125,11 +126,11 @@ impl<St> ModuleInstance<St> {
|
|||||||
self.types.borrow().get(idx as usize).cloned()
|
self.types.borrow().get(idx as usize).cloned()
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn export_by_name(&self, name: &str) -> Option<ExternVal<St>> {
|
pub fn export_by_name(&self, name: &str) -> Option<ExternVal> {
|
||||||
self.exports.borrow().get(name).cloned()
|
self.exports.borrow().get(name).cloned()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn push_func(&self, func: Rc<FuncInstance<St>>) {
|
fn push_func(&self, func: Rc<FuncInstance>) {
|
||||||
self.funcs.borrow_mut().push(func);
|
self.funcs.borrow_mut().push(func);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -141,7 +142,7 @@ impl<St> ModuleInstance<St> {
|
|||||||
self.memories.borrow_mut().push(memory)
|
self.memories.borrow_mut().push(memory)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn push_table(&self, table: Rc<TableInstance<St>>) {
|
fn push_table(&self, table: Rc<TableInstance>) {
|
||||||
self.tables.borrow_mut().push(table)
|
self.tables.borrow_mut().push(table)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -149,14 +150,14 @@ impl<St> ModuleInstance<St> {
|
|||||||
self.globals.borrow_mut().push(global)
|
self.globals.borrow_mut().push(global)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn insert_export<N: Into<String>>(&self, name: N, extern_val: ExternVal<St>) {
|
fn insert_export<N: Into<String>>(&self, name: N, extern_val: ExternVal) {
|
||||||
self.exports.borrow_mut().insert(name.into(), extern_val);
|
self.exports.borrow_mut().insert(name.into(), extern_val);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn alloc_module(
|
fn alloc_module(
|
||||||
module: &Module,
|
module: &Module,
|
||||||
extern_vals: &[ExternVal<St>],
|
extern_vals: &[ExternVal],
|
||||||
instance: &Rc<ModuleInstance<St>>,
|
instance: &Rc<ModuleInstance>,
|
||||||
) -> Result<(), Error> {
|
) -> Result<(), Error> {
|
||||||
let mut aux_data = validate_module(module)?;
|
let mut aux_data = validate_module(module)?;
|
||||||
|
|
||||||
@ -280,7 +281,7 @@ impl<St> ModuleInstance<St> {
|
|||||||
)
|
)
|
||||||
{
|
{
|
||||||
let field = export.field();
|
let field = export.field();
|
||||||
let extern_val: ExternVal<St> = match *export.internal() {
|
let extern_val: ExternVal = match *export.internal() {
|
||||||
Internal::Function(idx) => {
|
Internal::Function(idx) => {
|
||||||
let func = instance.func_by_index(idx).expect(
|
let func = instance.func_by_index(idx).expect(
|
||||||
"Due to validation func should exists",
|
"Due to validation func should exists",
|
||||||
@ -314,8 +315,8 @@ impl<St> ModuleInstance<St> {
|
|||||||
|
|
||||||
fn instantiate_with_externvals(
|
fn instantiate_with_externvals(
|
||||||
module: &Module,
|
module: &Module,
|
||||||
extern_vals: &[ExternVal<St>],
|
extern_vals: &[ExternVal],
|
||||||
) -> Result<Rc<ModuleInstance<St>>, Error> {
|
) -> Result<Rc<ModuleInstance>, Error> {
|
||||||
let instance = Rc::new(ModuleInstance::default());
|
let instance = Rc::new(ModuleInstance::default());
|
||||||
|
|
||||||
ModuleInstance::alloc_module(module, extern_vals, &instance)?;
|
ModuleInstance::alloc_module(module, extern_vals, &instance)?;
|
||||||
@ -358,8 +359,8 @@ impl<St> ModuleInstance<St> {
|
|||||||
|
|
||||||
fn instantiate_with_imports(
|
fn instantiate_with_imports(
|
||||||
module: &Module,
|
module: &Module,
|
||||||
imports: &Imports<St>,
|
imports: &Imports,
|
||||||
) -> Result<Rc<ModuleInstance<St>>, Error> {
|
) -> Result<Rc<ModuleInstance>, Error> {
|
||||||
let mut extern_vals = Vec::new();
|
let mut extern_vals = Vec::new();
|
||||||
for import_entry in module.import_section().map(|s| s.entries()).unwrap_or(&[]) {
|
for import_entry in module.import_section().map(|s| s.entries()).unwrap_or(&[]) {
|
||||||
let module_name = import_entry.module();
|
let module_name = import_entry.module();
|
||||||
@ -398,15 +399,15 @@ impl<St> ModuleInstance<St> {
|
|||||||
Self::instantiate_with_externvals(module, &extern_vals)
|
Self::instantiate_with_externvals(module, &extern_vals)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn new<'a>(module: &'a Module) -> InstantiationBuilder<'a, St> {
|
pub fn new<'a>(module: &'a Module) -> InstantiationBuilder<'a> {
|
||||||
InstantiationBuilder::new(module)
|
InstantiationBuilder::new(module)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn invoke_index(
|
pub fn invoke_index<'a>(
|
||||||
&self,
|
&self,
|
||||||
func_idx: u32,
|
func_idx: u32,
|
||||||
args: &[RuntimeValue],
|
args: &[RuntimeValue],
|
||||||
state: &St,
|
state: &'a mut HostState<'a>,
|
||||||
) -> Result<Option<RuntimeValue>, Error> {
|
) -> Result<Option<RuntimeValue>, Error> {
|
||||||
let func_instance = self.func_by_index(func_idx).ok_or_else(|| {
|
let func_instance = self.func_by_index(func_idx).ok_or_else(|| {
|
||||||
Error::Program(format!(
|
Error::Program(format!(
|
||||||
@ -417,11 +418,11 @@ impl<St> ModuleInstance<St> {
|
|||||||
FuncInstance::invoke(func_instance, Cow::Borrowed(args), state)
|
FuncInstance::invoke(func_instance, Cow::Borrowed(args), state)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn invoke_export(
|
pub fn invoke_export<'a>(
|
||||||
&self,
|
&self,
|
||||||
func_name: &str,
|
func_name: &str,
|
||||||
args: &[RuntimeValue],
|
args: &[RuntimeValue],
|
||||||
state: &St,
|
state: &'a mut HostState<'a>,
|
||||||
) -> Result<Option<RuntimeValue>, Error> {
|
) -> Result<Option<RuntimeValue>, Error> {
|
||||||
let extern_val = self.export_by_name(func_name).ok_or_else(|| {
|
let extern_val = self.export_by_name(func_name).ok_or_else(|| {
|
||||||
Error::Program(format!("Module doesn't have export {}", func_name))
|
Error::Program(format!("Module doesn't have export {}", func_name))
|
||||||
@ -442,12 +443,12 @@ impl<St> ModuleInstance<St> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct InstantiationBuilder<'a, St: 'a> {
|
pub struct InstantiationBuilder<'a> {
|
||||||
module: &'a Module,
|
module: &'a Module,
|
||||||
imports: Option<Imports<'a, St>>,
|
imports: Option<Imports<'a>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a, St: 'a> InstantiationBuilder<'a, St> {
|
impl<'a> InstantiationBuilder<'a> {
|
||||||
fn new(module: &'a Module) -> Self {
|
fn new(module: &'a Module) -> Self {
|
||||||
InstantiationBuilder {
|
InstantiationBuilder {
|
||||||
module,
|
module,
|
||||||
@ -455,7 +456,7 @@ impl<'a, St: 'a> InstantiationBuilder<'a, St> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn with_imports(mut self, imports: Imports<'a, St>) -> Self {
|
pub fn with_imports(mut self, imports: Imports<'a>) -> Self {
|
||||||
self.imports = Some(imports);
|
self.imports = Some(imports);
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
@ -463,7 +464,7 @@ impl<'a, St: 'a> InstantiationBuilder<'a, St> {
|
|||||||
pub fn with_import<N: Into<String>>(
|
pub fn with_import<N: Into<String>>(
|
||||||
mut self,
|
mut self,
|
||||||
name: N,
|
name: N,
|
||||||
import_resolver: &'a ImportResolver<St>,
|
import_resolver: &'a ImportResolver,
|
||||||
) -> Self {
|
) -> Self {
|
||||||
self.imports
|
self.imports
|
||||||
.get_or_insert_with(|| Imports::default())
|
.get_or_insert_with(|| Imports::default())
|
||||||
@ -471,7 +472,7 @@ impl<'a, St: 'a> InstantiationBuilder<'a, St> {
|
|||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn run_start(mut self, state: &St) -> Result<Rc<ModuleInstance<St>>, Error> {
|
pub fn run_start<'b>(mut self, state: &'b mut HostState<'b>) -> Result<Rc<ModuleInstance>, Error> {
|
||||||
let imports = self.imports.get_or_insert_with(|| Imports::default());
|
let imports = self.imports.get_or_insert_with(|| Imports::default());
|
||||||
let instance = ModuleInstance::instantiate_with_imports(self.module, imports)?;
|
let instance = ModuleInstance::instantiate_with_imports(self.module, imports)?;
|
||||||
|
|
||||||
@ -484,7 +485,7 @@ impl<'a, St: 'a> InstantiationBuilder<'a, St> {
|
|||||||
Ok(instance)
|
Ok(instance)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn assert_no_start(mut self) -> Result<Rc<ModuleInstance<St>>, Error> {
|
pub fn assert_no_start(mut self) -> Result<Rc<ModuleInstance>, Error> {
|
||||||
assert!(self.module.start_section().is_none());
|
assert!(self.module.start_section().is_none());
|
||||||
let imports = self.imports.get_or_insert_with(|| Imports::default());
|
let imports = self.imports.get_or_insert_with(|| Imports::default());
|
||||||
let instance = ModuleInstance::instantiate_with_imports(self.module, imports)?;
|
let instance = ModuleInstance::instantiate_with_imports(self.module, imports)?;
|
||||||
@ -492,12 +493,12 @@ impl<'a, St: 'a> InstantiationBuilder<'a, St> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<St> ImportResolver<St> for ModuleInstance<St> {
|
impl ImportResolver for ModuleInstance {
|
||||||
fn resolve_func(
|
fn resolve_func(
|
||||||
&self,
|
&self,
|
||||||
field_name: &str,
|
field_name: &str,
|
||||||
_func_type: &FunctionType,
|
_func_type: &FunctionType,
|
||||||
) -> Result<Rc<FuncInstance<St>>, Error> {
|
) -> Result<Rc<FuncInstance>, Error> {
|
||||||
Ok(self.export_by_name(field_name)
|
Ok(self.export_by_name(field_name)
|
||||||
.ok_or_else(|| {
|
.ok_or_else(|| {
|
||||||
Error::Validation(format!("Export {} not found", field_name))
|
Error::Validation(format!("Export {} not found", field_name))
|
||||||
@ -542,7 +543,7 @@ impl<St> ImportResolver<St> for ModuleInstance<St> {
|
|||||||
&self,
|
&self,
|
||||||
field_name: &str,
|
field_name: &str,
|
||||||
_table_type: &TableType,
|
_table_type: &TableType,
|
||||||
) -> Result<Rc<TableInstance<St>>, Error> {
|
) -> Result<Rc<TableInstance>, Error> {
|
||||||
Ok(self.export_by_name(field_name)
|
Ok(self.export_by_name(field_name)
|
||||||
.ok_or_else(|| {
|
.ok_or_else(|| {
|
||||||
Error::Validation(format!("Export {} not found", field_name))
|
Error::Validation(format!("Export {} not found", field_name))
|
||||||
@ -558,7 +559,7 @@ fn alloc_func_type(func_type: FunctionType) -> Rc<FunctionType> {
|
|||||||
Rc::new(func_type)
|
Rc::new(func_type)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn alloc_table<St>(table_type: &TableType) -> Result<Rc<TableInstance<St>>, Error> {
|
fn alloc_table(table_type: &TableType) -> Result<Rc<TableInstance>, Error> {
|
||||||
let table = TableInstance::new(table_type)?;
|
let table = TableInstance::new(table_type)?;
|
||||||
Ok(Rc::new(table))
|
Ok(Rc::new(table))
|
||||||
}
|
}
|
||||||
@ -573,7 +574,7 @@ fn alloc_global(global_type: GlobalType, val: RuntimeValue) -> Rc<GlobalInstance
|
|||||||
Rc::new(global)
|
Rc::new(global)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn eval_init_expr<T>(init_expr: &InitExpr, module: &ModuleInstance<T>) -> RuntimeValue {
|
fn eval_init_expr(init_expr: &InitExpr, module: &ModuleInstance) -> RuntimeValue {
|
||||||
let code = init_expr.code();
|
let code = init_expr.code();
|
||||||
debug_assert!(
|
debug_assert!(
|
||||||
code.len() == 2,
|
code.len() == 2,
|
||||||
|
@ -8,17 +8,18 @@ use interpreter::func::FuncInstance;
|
|||||||
use interpreter::host::HostModule;
|
use interpreter::host::HostModule;
|
||||||
use interpreter::value::RuntimeValue;
|
use interpreter::value::RuntimeValue;
|
||||||
use interpreter::imports::{Imports, ImportResolver};
|
use interpreter::imports::{Imports, ImportResolver};
|
||||||
|
use interpreter::state::HostState;
|
||||||
|
|
||||||
/// Program instance. Program is a set of instantiated modules.
|
/// Program instance. Program is a set of instantiated modules.
|
||||||
#[deprecated]
|
#[deprecated]
|
||||||
pub struct ProgramInstance<St=()> {
|
pub struct ProgramInstance {
|
||||||
modules: HashMap<String, Rc<ModuleInstance<St>>>,
|
modules: HashMap<String, Rc<ModuleInstance>>,
|
||||||
resolvers: HashMap<String, Box<ImportResolver<St>>>,
|
resolvers: HashMap<String, Box<ImportResolver>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<St> ProgramInstance<St> {
|
impl ProgramInstance {
|
||||||
/// Create new program instance.
|
/// Create new program instance.
|
||||||
pub fn new() -> ProgramInstance<St> {
|
pub fn new() -> ProgramInstance {
|
||||||
ProgramInstance {
|
ProgramInstance {
|
||||||
modules: HashMap::new(),
|
modules: HashMap::new(),
|
||||||
resolvers: HashMap::new(),
|
resolvers: HashMap::new(),
|
||||||
@ -26,12 +27,12 @@ impl<St> ProgramInstance<St> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Instantiate module with validation.
|
/// Instantiate module with validation.
|
||||||
pub fn add_module(
|
pub fn add_module<'a>(
|
||||||
&mut self,
|
&mut self,
|
||||||
name: &str,
|
name: &str,
|
||||||
module: Module,
|
module: Module,
|
||||||
state: &St,
|
state: &'a mut HostState<'a>,
|
||||||
) -> Result<Rc<ModuleInstance<St>>, Error> {
|
) -> Result<Rc<ModuleInstance>, Error> {
|
||||||
let module_instance = {
|
let module_instance = {
|
||||||
let mut imports = Imports::new();
|
let mut imports = Imports::new();
|
||||||
for (module_name, module_instance) in self.modules.iter() {
|
for (module_name, module_instance) in self.modules.iter() {
|
||||||
@ -52,7 +53,7 @@ impl<St> ProgramInstance<St> {
|
|||||||
pub fn add_import_resolver(
|
pub fn add_import_resolver(
|
||||||
&mut self,
|
&mut self,
|
||||||
name: &str,
|
name: &str,
|
||||||
import_resolver: Box<ImportResolver<St>>,
|
import_resolver: Box<ImportResolver>,
|
||||||
) {
|
) {
|
||||||
self.resolvers.insert(name.to_owned(), import_resolver);
|
self.resolvers.insert(name.to_owned(), import_resolver);
|
||||||
}
|
}
|
||||||
@ -60,21 +61,21 @@ impl<St> ProgramInstance<St> {
|
|||||||
pub fn add_host_module(
|
pub fn add_host_module(
|
||||||
&mut self,
|
&mut self,
|
||||||
name: &str,
|
name: &str,
|
||||||
host_module: HostModule<St>,
|
host_module: HostModule,
|
||||||
) where St: 'static {
|
) {
|
||||||
self.resolvers.insert(name.to_owned(), Box::new(host_module) as Box<ImportResolver<St>>);
|
self.resolvers.insert(name.to_owned(), Box::new(host_module) as Box<ImportResolver>);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn insert_loaded_module(&mut self, name: &str, module: Rc<ModuleInstance<St>>) {
|
pub fn insert_loaded_module(&mut self, name: &str, module: Rc<ModuleInstance>) {
|
||||||
self.modules.insert(name.to_owned(), module);
|
self.modules.insert(name.to_owned(), module);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn invoke_export(
|
pub fn invoke_export<'a>(
|
||||||
&mut self,
|
&mut self,
|
||||||
module_name: &str,
|
module_name: &str,
|
||||||
func_name: &str,
|
func_name: &str,
|
||||||
args: &[RuntimeValue],
|
args: &[RuntimeValue],
|
||||||
state: &St,
|
state: &'a mut HostState<'a>,
|
||||||
) -> Result<Option<RuntimeValue>, Error> {
|
) -> Result<Option<RuntimeValue>, Error> {
|
||||||
let module_instance = self.modules.get(module_name).ok_or_else(|| {
|
let module_instance = self.modules.get(module_name).ok_or_else(|| {
|
||||||
Error::Program(format!("Module {} not found", module_name))
|
Error::Program(format!("Module {} not found", module_name))
|
||||||
@ -82,12 +83,12 @@ impl<St> ProgramInstance<St> {
|
|||||||
module_instance.invoke_export(func_name, args, state)
|
module_instance.invoke_export(func_name, args, state)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn invoke_index(
|
pub fn invoke_index<'a>(
|
||||||
&mut self,
|
&mut self,
|
||||||
module_name: &str,
|
module_name: &str,
|
||||||
func_idx: u32,
|
func_idx: u32,
|
||||||
args: &[RuntimeValue],
|
args: &[RuntimeValue],
|
||||||
state: &St,
|
state: &'a mut HostState<'a>,
|
||||||
) -> Result<Option<RuntimeValue>, Error> {
|
) -> Result<Option<RuntimeValue>, Error> {
|
||||||
let module_instance = self.modules.get(module_name).cloned().ok_or_else(|| {
|
let module_instance = self.modules.get(module_name).cloned().ok_or_else(|| {
|
||||||
Error::Program(format!("Module {} not found", module_name))
|
Error::Program(format!("Module {} not found", module_name))
|
||||||
@ -95,23 +96,23 @@ impl<St> ProgramInstance<St> {
|
|||||||
module_instance.invoke_index(func_idx, args, state)
|
module_instance.invoke_index(func_idx, args, state)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn invoke_func(
|
pub fn invoke_func<'a>(
|
||||||
&mut self,
|
&mut self,
|
||||||
func_instance: Rc<FuncInstance<St>>,
|
func_instance: Rc<FuncInstance>,
|
||||||
args: &[RuntimeValue],
|
args: &[RuntimeValue],
|
||||||
state: &St,
|
state: &'a mut HostState<'a>,
|
||||||
) -> Result<Option<RuntimeValue>, Error> {
|
) -> Result<Option<RuntimeValue>, Error> {
|
||||||
FuncInstance::invoke(Rc::clone(&func_instance), Cow::Borrowed(args), state)
|
FuncInstance::invoke(Rc::clone(&func_instance), Cow::Borrowed(args), state)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn resolver(&self, name: &str) -> Option<&ImportResolver<St>> {
|
pub fn resolver(&self, name: &str) -> Option<&ImportResolver> {
|
||||||
self.modules
|
self.modules
|
||||||
.get(name)
|
.get(name)
|
||||||
.map(|x| &**x as &ImportResolver<St>)
|
.map(|x| &**x as &ImportResolver)
|
||||||
.or_else(|| self.resolvers.get(name).map(|x| &**x))
|
.or_else(|| self.resolvers.get(name).map(|x| &**x))
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn module(&self, name: &str) -> Option<Rc<ModuleInstance<St>>> {
|
pub fn module(&self, name: &str) -> Option<Rc<ModuleInstance>> {
|
||||||
self.modules.get(name).cloned()
|
self.modules.get(name).cloned()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -15,19 +15,20 @@ use interpreter::value::{
|
|||||||
};
|
};
|
||||||
use common::{DEFAULT_MEMORY_INDEX, DEFAULT_TABLE_INDEX, BlockFrame, BlockFrameType};
|
use common::{DEFAULT_MEMORY_INDEX, DEFAULT_TABLE_INDEX, BlockFrame, BlockFrameType};
|
||||||
use common::stack::StackWithLimit;
|
use common::stack::StackWithLimit;
|
||||||
|
use interpreter::state::HostState;
|
||||||
|
|
||||||
/// Function interpreter.
|
/// Function interpreter.
|
||||||
pub struct Interpreter<'a, St: 'a> {
|
pub struct Interpreter<'a, 'b: 'a> {
|
||||||
state: &'a St,
|
state: &'a mut HostState<'b>,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Function execution context.
|
/// Function execution context.
|
||||||
pub struct FunctionContext<St> {
|
pub struct FunctionContext {
|
||||||
/// Is context initialized.
|
/// Is context initialized.
|
||||||
pub is_initialized: bool,
|
pub is_initialized: bool,
|
||||||
/// Internal function reference.
|
/// Internal function reference.
|
||||||
pub function: Rc<FuncInstance<St>>,
|
pub function: Rc<FuncInstance>,
|
||||||
pub module: Rc<ModuleInstance<St>>,
|
pub module: Rc<ModuleInstance>,
|
||||||
/// Function return type.
|
/// Function return type.
|
||||||
pub return_type: BlockType,
|
pub return_type: BlockType,
|
||||||
/// Local variables.
|
/// Local variables.
|
||||||
@ -41,13 +42,13 @@ pub struct FunctionContext<St> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Interpreter action to execute after executing instruction.
|
/// Interpreter action to execute after executing instruction.
|
||||||
pub enum InstructionOutcome<St> {
|
pub enum InstructionOutcome {
|
||||||
/// Continue with next instruction.
|
/// Continue with next instruction.
|
||||||
RunNextInstruction,
|
RunNextInstruction,
|
||||||
/// Branch to given frame.
|
/// Branch to given frame.
|
||||||
Branch(usize),
|
Branch(usize),
|
||||||
/// Execute function call.
|
/// Execute function call.
|
||||||
ExecuteCall(Rc<FuncInstance<St>>),
|
ExecuteCall(Rc<FuncInstance>),
|
||||||
/// End current frame.
|
/// End current frame.
|
||||||
End,
|
End,
|
||||||
/// Return from current function block.
|
/// Return from current function block.
|
||||||
@ -55,21 +56,21 @@ pub enum InstructionOutcome<St> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Function run result.
|
/// Function run result.
|
||||||
enum RunResult<St> {
|
enum RunResult {
|
||||||
/// Function has returned (optional) value.
|
/// Function has returned (optional) value.
|
||||||
Return(Option<RuntimeValue>),
|
Return(Option<RuntimeValue>),
|
||||||
/// Function is calling other function.
|
/// Function is calling other function.
|
||||||
NestedCall(Rc<FuncInstance<St>>),
|
NestedCall(Rc<FuncInstance>),
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a, St: 'a> Interpreter<'a, St> {
|
impl<'a, 'b: 'a> Interpreter<'a, 'b> {
|
||||||
pub fn new(state: &'a St) -> Interpreter<'a, St> {
|
pub fn new(state: &'a mut HostState<'b>) -> Interpreter<'a, 'b> {
|
||||||
Interpreter {
|
Interpreter {
|
||||||
state
|
state: state,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn run_function(&mut self, function_context: FunctionContext<St>) -> Result<Option<RuntimeValue>, Error> {
|
pub fn run_function(&mut self, function_context: FunctionContext) -> Result<Option<RuntimeValue>, Error> {
|
||||||
let mut function_stack = VecDeque::new();
|
let mut function_stack = VecDeque::new();
|
||||||
function_stack.push_back(function_context);
|
function_stack.push_back(function_context);
|
||||||
|
|
||||||
@ -115,7 +116,7 @@ impl<'a, St: 'a> Interpreter<'a, St> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn do_run_function(&mut self, function_context: &mut FunctionContext<St>, function_body: &[Opcode], function_labels: &HashMap<usize, usize>) -> Result<RunResult<St>, Error> {
|
fn do_run_function(&mut self, function_context: &mut FunctionContext, function_body: &[Opcode], function_labels: &HashMap<usize, usize>) -> Result<RunResult, Error> {
|
||||||
loop {
|
loop {
|
||||||
let instruction = &function_body[function_context.position];
|
let instruction = &function_body[function_context.position];
|
||||||
|
|
||||||
@ -153,7 +154,7 @@ impl<'a, St: 'a> Interpreter<'a, St> {
|
|||||||
}))
|
}))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn run_instruction(&mut self, context: &mut FunctionContext<St>, labels: &HashMap<usize, usize>, opcode: &Opcode) -> Result<InstructionOutcome<St>, Error> {
|
fn run_instruction(&mut self, context: &mut FunctionContext, labels: &HashMap<usize, usize>, opcode: &Opcode) -> Result<InstructionOutcome, Error> {
|
||||||
match opcode {
|
match opcode {
|
||||||
&Opcode::Unreachable => self.run_unreachable(context),
|
&Opcode::Unreachable => self.run_unreachable(context),
|
||||||
&Opcode::Nop => self.run_nop(context),
|
&Opcode::Nop => self.run_nop(context),
|
||||||
@ -347,25 +348,25 @@ impl<'a, St: 'a> Interpreter<'a, St> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn run_unreachable(&mut self, _context: &mut FunctionContext<St>) -> Result<InstructionOutcome<St>, Error> {
|
fn run_unreachable(&mut self, _context: &mut FunctionContext) -> Result<InstructionOutcome, Error> {
|
||||||
Err(Error::Trap("programmatic".into()))
|
Err(Error::Trap("programmatic".into()))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn run_nop(&mut self, _context: &mut FunctionContext<St>) -> Result<InstructionOutcome<St>, Error> {
|
fn run_nop(&mut self, _context: &mut FunctionContext) -> Result<InstructionOutcome, Error> {
|
||||||
Ok(InstructionOutcome::RunNextInstruction)
|
Ok(InstructionOutcome::RunNextInstruction)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn run_block(&mut self, context: &mut FunctionContext<St>, labels: &HashMap<usize, usize>, block_type: BlockType) -> Result<InstructionOutcome<St>, Error> {
|
fn run_block(&mut self, context: &mut FunctionContext, labels: &HashMap<usize, usize>, block_type: BlockType) -> Result<InstructionOutcome, Error> {
|
||||||
context.push_frame(labels, BlockFrameType::Block, block_type)?;
|
context.push_frame(labels, BlockFrameType::Block, block_type)?;
|
||||||
Ok(InstructionOutcome::RunNextInstruction)
|
Ok(InstructionOutcome::RunNextInstruction)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn run_loop(&mut self, context: &mut FunctionContext<St>, labels: &HashMap<usize, usize>, block_type: BlockType) -> Result<InstructionOutcome<St>, Error> {
|
fn run_loop(&mut self, context: &mut FunctionContext, labels: &HashMap<usize, usize>, block_type: BlockType) -> Result<InstructionOutcome, Error> {
|
||||||
context.push_frame(labels, BlockFrameType::Loop, block_type)?;
|
context.push_frame(labels, BlockFrameType::Loop, block_type)?;
|
||||||
Ok(InstructionOutcome::RunNextInstruction)
|
Ok(InstructionOutcome::RunNextInstruction)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn run_if(&mut self, context: &mut FunctionContext<St>, labels: &HashMap<usize, usize>, block_type: BlockType) -> Result<InstructionOutcome<St>, Error> {
|
fn run_if(&mut self, context: &mut FunctionContext, labels: &HashMap<usize, usize>, block_type: BlockType) -> Result<InstructionOutcome, Error> {
|
||||||
let branch = context.value_stack_mut().pop_as()?;
|
let branch = context.value_stack_mut().pop_as()?;
|
||||||
let block_frame_type = if branch { BlockFrameType::IfTrue } else {
|
let block_frame_type = if branch { BlockFrameType::IfTrue } else {
|
||||||
let else_pos = labels[&context.position];
|
let else_pos = labels[&context.position];
|
||||||
@ -380,23 +381,23 @@ impl<'a, St: 'a> Interpreter<'a, St> {
|
|||||||
context.push_frame(labels, block_frame_type, block_type).map(|_| InstructionOutcome::RunNextInstruction)
|
context.push_frame(labels, block_frame_type, block_type).map(|_| InstructionOutcome::RunNextInstruction)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn run_else(&mut self, context: &mut FunctionContext<St>, labels: &HashMap<usize, usize>) -> Result<InstructionOutcome<St>, Error> {
|
fn run_else(&mut self, context: &mut FunctionContext, labels: &HashMap<usize, usize>) -> Result<InstructionOutcome, Error> {
|
||||||
let end_pos = labels[&context.position];
|
let end_pos = labels[&context.position];
|
||||||
context.pop_frame(false)?;
|
context.pop_frame(false)?;
|
||||||
context.position = end_pos;
|
context.position = end_pos;
|
||||||
Ok(InstructionOutcome::RunNextInstruction)
|
Ok(InstructionOutcome::RunNextInstruction)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn run_end(&mut self, context: &mut FunctionContext<St>) -> Result<InstructionOutcome<St>, Error> {
|
fn run_end(&mut self, context: &mut FunctionContext) -> Result<InstructionOutcome, Error> {
|
||||||
context.pop_frame(false)?;
|
context.pop_frame(false)?;
|
||||||
Ok(InstructionOutcome::End)
|
Ok(InstructionOutcome::End)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn run_br(&mut self, _context: &mut FunctionContext<St>, label_idx: u32) -> Result<InstructionOutcome<St>, Error> {
|
fn run_br(&mut self, _context: &mut FunctionContext, label_idx: u32) -> Result<InstructionOutcome, Error> {
|
||||||
Ok(InstructionOutcome::Branch(label_idx as usize))
|
Ok(InstructionOutcome::Branch(label_idx as usize))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn run_br_if(&mut self, context: &mut FunctionContext<St>, label_idx: u32) -> Result<InstructionOutcome<St>, Error> {
|
fn run_br_if(&mut self, context: &mut FunctionContext, label_idx: u32) -> Result<InstructionOutcome, Error> {
|
||||||
if context.value_stack_mut().pop_as()? {
|
if context.value_stack_mut().pop_as()? {
|
||||||
Ok(InstructionOutcome::Branch(label_idx as usize))
|
Ok(InstructionOutcome::Branch(label_idx as usize))
|
||||||
} else {
|
} else {
|
||||||
@ -404,20 +405,20 @@ impl<'a, St: 'a> Interpreter<'a, St> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn run_br_table(&mut self, context: &mut FunctionContext<St>, table: &Vec<u32>, default: u32) -> Result<InstructionOutcome<St>, Error> {
|
fn run_br_table(&mut self, context: &mut FunctionContext, table: &Vec<u32>, default: u32) -> Result<InstructionOutcome, Error> {
|
||||||
let index: u32 = context.value_stack_mut().pop_as()?;
|
let index: u32 = context.value_stack_mut().pop_as()?;
|
||||||
Ok(InstructionOutcome::Branch(table.get(index as usize).cloned().unwrap_or(default) as usize))
|
Ok(InstructionOutcome::Branch(table.get(index as usize).cloned().unwrap_or(default) as usize))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn run_return(&mut self, _context: &mut FunctionContext<St>) -> Result<InstructionOutcome<St>, Error> {
|
fn run_return(&mut self, _context: &mut FunctionContext) -> Result<InstructionOutcome, Error> {
|
||||||
Ok(InstructionOutcome::Return)
|
Ok(InstructionOutcome::Return)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn run_call(
|
fn run_call(
|
||||||
&mut self,
|
&mut self,
|
||||||
context: &mut FunctionContext<St>,
|
context: &mut FunctionContext,
|
||||||
func_idx: u32,
|
func_idx: u32,
|
||||||
) -> Result<InstructionOutcome<St>, Error> {
|
) -> Result<InstructionOutcome, Error> {
|
||||||
let func = context
|
let func = context
|
||||||
.module()
|
.module()
|
||||||
.func_by_index(func_idx)
|
.func_by_index(func_idx)
|
||||||
@ -427,9 +428,9 @@ impl<'a, St: 'a> Interpreter<'a, St> {
|
|||||||
|
|
||||||
fn run_call_indirect(
|
fn run_call_indirect(
|
||||||
&mut self,
|
&mut self,
|
||||||
context: &mut FunctionContext<St>,
|
context: &mut FunctionContext,
|
||||||
type_idx: u32,
|
type_idx: u32,
|
||||||
) -> Result<InstructionOutcome<St>, Error> {
|
) -> Result<InstructionOutcome, Error> {
|
||||||
let table_func_idx: u32 = context.value_stack_mut().pop_as()?;
|
let table_func_idx: u32 = context.value_stack_mut().pop_as()?;
|
||||||
let table = context
|
let table = context
|
||||||
.module()
|
.module()
|
||||||
@ -456,7 +457,7 @@ impl<'a, St: 'a> Interpreter<'a, St> {
|
|||||||
Ok(InstructionOutcome::ExecuteCall(func_ref))
|
Ok(InstructionOutcome::ExecuteCall(func_ref))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn run_drop(&mut self, context: &mut FunctionContext<St>) -> Result<InstructionOutcome<St>, Error> {
|
fn run_drop(&mut self, context: &mut FunctionContext) -> Result<InstructionOutcome, Error> {
|
||||||
context
|
context
|
||||||
.value_stack_mut()
|
.value_stack_mut()
|
||||||
.pop()
|
.pop()
|
||||||
@ -464,7 +465,7 @@ impl<'a, St: 'a> Interpreter<'a, St> {
|
|||||||
.map(|_| InstructionOutcome::RunNextInstruction)
|
.map(|_| InstructionOutcome::RunNextInstruction)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn run_select(&mut self, context: &mut FunctionContext<St>) -> Result<InstructionOutcome<St>, Error> {
|
fn run_select(&mut self, context: &mut FunctionContext) -> Result<InstructionOutcome, Error> {
|
||||||
context
|
context
|
||||||
.value_stack_mut()
|
.value_stack_mut()
|
||||||
.pop_triple()
|
.pop_triple()
|
||||||
@ -480,19 +481,19 @@ impl<'a, St: 'a> Interpreter<'a, St> {
|
|||||||
.map(|_| InstructionOutcome::RunNextInstruction)
|
.map(|_| InstructionOutcome::RunNextInstruction)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn run_get_local(&mut self, context: &mut FunctionContext<St>, index: u32) -> Result<InstructionOutcome<St>, Error> {
|
fn run_get_local(&mut self, context: &mut FunctionContext, index: u32) -> Result<InstructionOutcome, Error> {
|
||||||
context.get_local(index as usize)
|
context.get_local(index as usize)
|
||||||
.map(|value| context.value_stack_mut().push(value))
|
.map(|value| context.value_stack_mut().push(value))
|
||||||
.map(|_| InstructionOutcome::RunNextInstruction)
|
.map(|_| InstructionOutcome::RunNextInstruction)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn run_set_local(&mut self, context: &mut FunctionContext<St>, index: u32) -> Result<InstructionOutcome<St>, Error> {
|
fn run_set_local(&mut self, context: &mut FunctionContext, index: u32) -> Result<InstructionOutcome, Error> {
|
||||||
let arg = context.value_stack_mut().pop()?;
|
let arg = context.value_stack_mut().pop()?;
|
||||||
context.set_local(index as usize, arg)
|
context.set_local(index as usize, arg)
|
||||||
.map(|_| InstructionOutcome::RunNextInstruction)
|
.map(|_| InstructionOutcome::RunNextInstruction)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn run_tee_local(&mut self, context: &mut FunctionContext<St>, index: u32) -> Result<InstructionOutcome<St>, Error> {
|
fn run_tee_local(&mut self, context: &mut FunctionContext, index: u32) -> Result<InstructionOutcome, Error> {
|
||||||
let arg = context.value_stack().top()?.clone();
|
let arg = context.value_stack().top()?.clone();
|
||||||
context.set_local(index as usize, arg)
|
context.set_local(index as usize, arg)
|
||||||
.map(|_| InstructionOutcome::RunNextInstruction)
|
.map(|_| InstructionOutcome::RunNextInstruction)
|
||||||
@ -500,9 +501,9 @@ impl<'a, St: 'a> Interpreter<'a, St> {
|
|||||||
|
|
||||||
fn run_get_global(
|
fn run_get_global(
|
||||||
&mut self,
|
&mut self,
|
||||||
context: &mut FunctionContext<St>,
|
context: &mut FunctionContext,
|
||||||
index: u32,
|
index: u32,
|
||||||
) -> Result<InstructionOutcome<St>, Error> {
|
) -> Result<InstructionOutcome, Error> {
|
||||||
let global = context
|
let global = context
|
||||||
.module()
|
.module()
|
||||||
.global_by_index(index)
|
.global_by_index(index)
|
||||||
@ -514,9 +515,9 @@ impl<'a, St: 'a> Interpreter<'a, St> {
|
|||||||
|
|
||||||
fn run_set_global(
|
fn run_set_global(
|
||||||
&mut self,
|
&mut self,
|
||||||
context: &mut FunctionContext<St>,
|
context: &mut FunctionContext,
|
||||||
index: u32,
|
index: u32,
|
||||||
) -> Result<InstructionOutcome<St>, Error> {
|
) -> Result<InstructionOutcome, Error> {
|
||||||
let val = context.value_stack_mut().pop()?;
|
let val = context.value_stack_mut().pop()?;
|
||||||
|
|
||||||
let global = context
|
let global = context
|
||||||
@ -527,7 +528,7 @@ impl<'a, St: 'a> Interpreter<'a, St> {
|
|||||||
Ok(InstructionOutcome::RunNextInstruction)
|
Ok(InstructionOutcome::RunNextInstruction)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn run_load<T>(&mut self, context: &mut FunctionContext<St>, _align: u32, offset: u32) -> Result<InstructionOutcome<St>, Error>
|
fn run_load<T>(&mut self, context: &mut FunctionContext, _align: u32, offset: u32) -> Result<InstructionOutcome, Error>
|
||||||
where RuntimeValue: From<T>, T: LittleEndianConvert {
|
where RuntimeValue: From<T>, T: LittleEndianConvert {
|
||||||
let address = effective_address(offset, context.value_stack_mut().pop_as()?)?;
|
let address = effective_address(offset, context.value_stack_mut().pop_as()?)?;
|
||||||
let m = context.module()
|
let m = context.module()
|
||||||
@ -539,7 +540,7 @@ impl<'a, St: 'a> Interpreter<'a, St> {
|
|||||||
Ok(InstructionOutcome::RunNextInstruction)
|
Ok(InstructionOutcome::RunNextInstruction)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn run_load_extend<T, U>(&mut self, context: &mut FunctionContext<St>, _align: u32, offset: u32) -> Result<InstructionOutcome<St>, Error>
|
fn run_load_extend<T, U>(&mut self, context: &mut FunctionContext, _align: u32, offset: u32) -> Result<InstructionOutcome, Error>
|
||||||
where T: ExtendInto<U>, RuntimeValue: From<U>, T: LittleEndianConvert {
|
where T: ExtendInto<U>, RuntimeValue: From<U>, T: LittleEndianConvert {
|
||||||
let address = effective_address(offset, context.value_stack_mut().pop_as()?)?;
|
let address = effective_address(offset, context.value_stack_mut().pop_as()?)?;
|
||||||
let m = context.module()
|
let m = context.module()
|
||||||
@ -555,7 +556,7 @@ impl<'a, St: 'a> Interpreter<'a, St> {
|
|||||||
.map(|_| InstructionOutcome::RunNextInstruction)
|
.map(|_| InstructionOutcome::RunNextInstruction)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn run_store<T>(&mut self, context: &mut FunctionContext<St>, _align: u32, offset: u32) -> Result<InstructionOutcome<St>, Error>
|
fn run_store<T>(&mut self, context: &mut FunctionContext, _align: u32, offset: u32) -> Result<InstructionOutcome, Error>
|
||||||
where RuntimeValue: TryInto<T, Error>, T: LittleEndianConvert {
|
where RuntimeValue: TryInto<T, Error>, T: LittleEndianConvert {
|
||||||
let stack_value = context
|
let stack_value = context
|
||||||
.value_stack_mut()
|
.value_stack_mut()
|
||||||
@ -572,10 +573,10 @@ impl<'a, St: 'a> Interpreter<'a, St> {
|
|||||||
|
|
||||||
fn run_store_wrap<T, U>(
|
fn run_store_wrap<T, U>(
|
||||||
&mut self,
|
&mut self,
|
||||||
context: &mut FunctionContext<St>,
|
context: &mut FunctionContext,
|
||||||
_align: u32,
|
_align: u32,
|
||||||
offset: u32,
|
offset: u32,
|
||||||
) -> Result<InstructionOutcome<St>, Error>
|
) -> Result<InstructionOutcome, Error>
|
||||||
where
|
where
|
||||||
RuntimeValue: TryInto<T, Error>,
|
RuntimeValue: TryInto<T, Error>,
|
||||||
T: WrapInto<U>,
|
T: WrapInto<U>,
|
||||||
@ -595,7 +596,7 @@ impl<'a, St: 'a> Interpreter<'a, St> {
|
|||||||
Ok(InstructionOutcome::RunNextInstruction)
|
Ok(InstructionOutcome::RunNextInstruction)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn run_current_memory(&mut self, context: &mut FunctionContext<St>) -> Result<InstructionOutcome<St>, Error> {
|
fn run_current_memory(&mut self, context: &mut FunctionContext) -> Result<InstructionOutcome, Error> {
|
||||||
let m = context.module()
|
let m = context.module()
|
||||||
.memory_by_index(DEFAULT_MEMORY_INDEX)
|
.memory_by_index(DEFAULT_MEMORY_INDEX)
|
||||||
.expect("Due to validation memory should exists");
|
.expect("Due to validation memory should exists");
|
||||||
@ -606,7 +607,7 @@ impl<'a, St: 'a> Interpreter<'a, St> {
|
|||||||
Ok(InstructionOutcome::RunNextInstruction)
|
Ok(InstructionOutcome::RunNextInstruction)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn run_grow_memory(&mut self, context: &mut FunctionContext<St>) -> Result<InstructionOutcome<St>, Error> {
|
fn run_grow_memory(&mut self, context: &mut FunctionContext) -> Result<InstructionOutcome, Error> {
|
||||||
let pages: u32 = context.value_stack_mut().pop_as()?;
|
let pages: u32 = context.value_stack_mut().pop_as()?;
|
||||||
let m = context.module()
|
let m = context.module()
|
||||||
.memory_by_index(DEFAULT_MEMORY_INDEX)
|
.memory_by_index(DEFAULT_MEMORY_INDEX)
|
||||||
@ -618,7 +619,7 @@ impl<'a, St: 'a> Interpreter<'a, St> {
|
|||||||
Ok(InstructionOutcome::RunNextInstruction)
|
Ok(InstructionOutcome::RunNextInstruction)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn run_const(&mut self, context: &mut FunctionContext<St>, val: RuntimeValue) -> Result<InstructionOutcome<St>, Error> {
|
fn run_const(&mut self, context: &mut FunctionContext, val: RuntimeValue) -> Result<InstructionOutcome, Error> {
|
||||||
context
|
context
|
||||||
.value_stack_mut()
|
.value_stack_mut()
|
||||||
.push(val)
|
.push(val)
|
||||||
@ -626,7 +627,7 @@ impl<'a, St: 'a> Interpreter<'a, St> {
|
|||||||
.map(|_| InstructionOutcome::RunNextInstruction)
|
.map(|_| InstructionOutcome::RunNextInstruction)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn run_eqz<T>(&mut self, context: &mut FunctionContext<St>) -> Result<InstructionOutcome<St>, Error>
|
fn run_eqz<T>(&mut self, context: &mut FunctionContext) -> Result<InstructionOutcome, Error>
|
||||||
where RuntimeValue: TryInto<T, Error>, T: PartialEq<T> + Default {
|
where RuntimeValue: TryInto<T, Error>, T: PartialEq<T> + Default {
|
||||||
context
|
context
|
||||||
.value_stack_mut()
|
.value_stack_mut()
|
||||||
@ -636,7 +637,7 @@ impl<'a, St: 'a> Interpreter<'a, St> {
|
|||||||
.map(|_| InstructionOutcome::RunNextInstruction)
|
.map(|_| InstructionOutcome::RunNextInstruction)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn run_eq<T>(&mut self, context: &mut FunctionContext<St>) -> Result<InstructionOutcome<St>, Error>
|
fn run_eq<T>(&mut self, context: &mut FunctionContext) -> Result<InstructionOutcome, Error>
|
||||||
where RuntimeValue: TryInto<T, Error>, T: PartialEq<T> {
|
where RuntimeValue: TryInto<T, Error>, T: PartialEq<T> {
|
||||||
context
|
context
|
||||||
.value_stack_mut()
|
.value_stack_mut()
|
||||||
@ -646,7 +647,7 @@ impl<'a, St: 'a> Interpreter<'a, St> {
|
|||||||
.map(|_| InstructionOutcome::RunNextInstruction)
|
.map(|_| InstructionOutcome::RunNextInstruction)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn run_ne<T>(&mut self, context: &mut FunctionContext<St>) -> Result<InstructionOutcome<St>, Error>
|
fn run_ne<T>(&mut self, context: &mut FunctionContext) -> Result<InstructionOutcome, Error>
|
||||||
where RuntimeValue: TryInto<T, Error>, T: PartialEq<T> {
|
where RuntimeValue: TryInto<T, Error>, T: PartialEq<T> {
|
||||||
context
|
context
|
||||||
.value_stack_mut()
|
.value_stack_mut()
|
||||||
@ -656,7 +657,7 @@ impl<'a, St: 'a> Interpreter<'a, St> {
|
|||||||
.map(|_| InstructionOutcome::RunNextInstruction)
|
.map(|_| InstructionOutcome::RunNextInstruction)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn run_lt<T>(&mut self, context: &mut FunctionContext<St>) -> Result<InstructionOutcome<St>, Error>
|
fn run_lt<T>(&mut self, context: &mut FunctionContext) -> Result<InstructionOutcome, Error>
|
||||||
where RuntimeValue: TryInto<T, Error>, T: PartialOrd<T> + Display {
|
where RuntimeValue: TryInto<T, Error>, T: PartialOrd<T> + Display {
|
||||||
context
|
context
|
||||||
.value_stack_mut()
|
.value_stack_mut()
|
||||||
@ -666,7 +667,7 @@ impl<'a, St: 'a> Interpreter<'a, St> {
|
|||||||
.map(|_| InstructionOutcome::RunNextInstruction)
|
.map(|_| InstructionOutcome::RunNextInstruction)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn run_gt<T>(&mut self, context: &mut FunctionContext<St>) -> Result<InstructionOutcome<St>, Error>
|
fn run_gt<T>(&mut self, context: &mut FunctionContext) -> Result<InstructionOutcome, Error>
|
||||||
where RuntimeValue: TryInto<T, Error>, T: PartialOrd<T> {
|
where RuntimeValue: TryInto<T, Error>, T: PartialOrd<T> {
|
||||||
context
|
context
|
||||||
.value_stack_mut()
|
.value_stack_mut()
|
||||||
@ -676,7 +677,7 @@ impl<'a, St: 'a> Interpreter<'a, St> {
|
|||||||
.map(|_| InstructionOutcome::RunNextInstruction)
|
.map(|_| InstructionOutcome::RunNextInstruction)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn run_lte<T>(&mut self, context: &mut FunctionContext<St>) -> Result<InstructionOutcome<St>, Error>
|
fn run_lte<T>(&mut self, context: &mut FunctionContext) -> Result<InstructionOutcome, Error>
|
||||||
where RuntimeValue: TryInto<T, Error>, T: PartialOrd<T> {
|
where RuntimeValue: TryInto<T, Error>, T: PartialOrd<T> {
|
||||||
context
|
context
|
||||||
.value_stack_mut()
|
.value_stack_mut()
|
||||||
@ -686,7 +687,7 @@ impl<'a, St: 'a> Interpreter<'a, St> {
|
|||||||
.map(|_| InstructionOutcome::RunNextInstruction)
|
.map(|_| InstructionOutcome::RunNextInstruction)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn run_gte<T>(&mut self, context: &mut FunctionContext<St>) -> Result<InstructionOutcome<St>, Error>
|
fn run_gte<T>(&mut self, context: &mut FunctionContext) -> Result<InstructionOutcome, Error>
|
||||||
where RuntimeValue: TryInto<T, Error>, T: PartialOrd<T> {
|
where RuntimeValue: TryInto<T, Error>, T: PartialOrd<T> {
|
||||||
context
|
context
|
||||||
.value_stack_mut()
|
.value_stack_mut()
|
||||||
@ -696,7 +697,7 @@ impl<'a, St: 'a> Interpreter<'a, St> {
|
|||||||
.map(|_| InstructionOutcome::RunNextInstruction)
|
.map(|_| InstructionOutcome::RunNextInstruction)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn run_clz<T>(&mut self, context: &mut FunctionContext<St>) -> Result<InstructionOutcome<St>, Error>
|
fn run_clz<T>(&mut self, context: &mut FunctionContext) -> Result<InstructionOutcome, Error>
|
||||||
where RuntimeValue: From<T> + TryInto<T, Error>, T: Integer<T> {
|
where RuntimeValue: From<T> + TryInto<T, Error>, T: Integer<T> {
|
||||||
context
|
context
|
||||||
.value_stack_mut()
|
.value_stack_mut()
|
||||||
@ -706,7 +707,7 @@ impl<'a, St: 'a> Interpreter<'a, St> {
|
|||||||
.map(|_| InstructionOutcome::RunNextInstruction)
|
.map(|_| InstructionOutcome::RunNextInstruction)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn run_ctz<T>(&mut self, context: &mut FunctionContext<St>) -> Result<InstructionOutcome<St>, Error>
|
fn run_ctz<T>(&mut self, context: &mut FunctionContext) -> Result<InstructionOutcome, Error>
|
||||||
where RuntimeValue: From<T> + TryInto<T, Error>, T: Integer<T> {
|
where RuntimeValue: From<T> + TryInto<T, Error>, T: Integer<T> {
|
||||||
context
|
context
|
||||||
.value_stack_mut()
|
.value_stack_mut()
|
||||||
@ -716,7 +717,7 @@ impl<'a, St: 'a> Interpreter<'a, St> {
|
|||||||
.map(|_| InstructionOutcome::RunNextInstruction)
|
.map(|_| InstructionOutcome::RunNextInstruction)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn run_popcnt<T>(&mut self, context: &mut FunctionContext<St>) -> Result<InstructionOutcome<St>, Error>
|
fn run_popcnt<T>(&mut self, context: &mut FunctionContext) -> Result<InstructionOutcome, Error>
|
||||||
where RuntimeValue: From<T> + TryInto<T, Error>, T: Integer<T> {
|
where RuntimeValue: From<T> + TryInto<T, Error>, T: Integer<T> {
|
||||||
context
|
context
|
||||||
.value_stack_mut()
|
.value_stack_mut()
|
||||||
@ -726,7 +727,7 @@ impl<'a, St: 'a> Interpreter<'a, St> {
|
|||||||
.map(|_| InstructionOutcome::RunNextInstruction)
|
.map(|_| InstructionOutcome::RunNextInstruction)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn run_add<T>(&mut self, context: &mut FunctionContext<St>) -> Result<InstructionOutcome<St>, Error>
|
fn run_add<T>(&mut self, context: &mut FunctionContext) -> Result<InstructionOutcome, Error>
|
||||||
where RuntimeValue: From<T> + TryInto<T, Error>, T: ArithmeticOps<T> {
|
where RuntimeValue: From<T> + TryInto<T, Error>, T: ArithmeticOps<T> {
|
||||||
context
|
context
|
||||||
.value_stack_mut()
|
.value_stack_mut()
|
||||||
@ -736,7 +737,7 @@ impl<'a, St: 'a> Interpreter<'a, St> {
|
|||||||
.map(|_| InstructionOutcome::RunNextInstruction)
|
.map(|_| InstructionOutcome::RunNextInstruction)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn run_sub<T>(&mut self, context: &mut FunctionContext<St>) -> Result<InstructionOutcome<St>, Error>
|
fn run_sub<T>(&mut self, context: &mut FunctionContext) -> Result<InstructionOutcome, Error>
|
||||||
where RuntimeValue: From<T> + TryInto<T, Error>, T: ArithmeticOps<T> {
|
where RuntimeValue: From<T> + TryInto<T, Error>, T: ArithmeticOps<T> {
|
||||||
context
|
context
|
||||||
.value_stack_mut()
|
.value_stack_mut()
|
||||||
@ -746,7 +747,7 @@ impl<'a, St: 'a> Interpreter<'a, St> {
|
|||||||
.map(|_| InstructionOutcome::RunNextInstruction)
|
.map(|_| InstructionOutcome::RunNextInstruction)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn run_mul<T>(&mut self, context: &mut FunctionContext<St>) -> Result<InstructionOutcome<St>, Error>
|
fn run_mul<T>(&mut self, context: &mut FunctionContext) -> Result<InstructionOutcome, Error>
|
||||||
where RuntimeValue: From<T> + TryInto<T, Error>, T: ArithmeticOps<T> {
|
where RuntimeValue: From<T> + TryInto<T, Error>, T: ArithmeticOps<T> {
|
||||||
context
|
context
|
||||||
.value_stack_mut()
|
.value_stack_mut()
|
||||||
@ -756,7 +757,7 @@ impl<'a, St: 'a> Interpreter<'a, St> {
|
|||||||
.map(|_| InstructionOutcome::RunNextInstruction)
|
.map(|_| InstructionOutcome::RunNextInstruction)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn run_div<T, U>(&mut self, context: &mut FunctionContext<St>) -> Result<InstructionOutcome<St>, Error>
|
fn run_div<T, U>(&mut self, context: &mut FunctionContext) -> Result<InstructionOutcome, Error>
|
||||||
where RuntimeValue: From<T> + TryInto<T, Error>, T: TransmuteInto<U> + Display, U: ArithmeticOps<U> + TransmuteInto<T> {
|
where RuntimeValue: From<T> + TryInto<T, Error>, T: TransmuteInto<U> + Display, U: ArithmeticOps<U> + TransmuteInto<T> {
|
||||||
context
|
context
|
||||||
.value_stack_mut()
|
.value_stack_mut()
|
||||||
@ -768,7 +769,7 @@ impl<'a, St: 'a> Interpreter<'a, St> {
|
|||||||
.map(|_| InstructionOutcome::RunNextInstruction)
|
.map(|_| InstructionOutcome::RunNextInstruction)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn run_rem<T, U>(&mut self, context: &mut FunctionContext<St>) -> Result<InstructionOutcome<St>, Error>
|
fn run_rem<T, U>(&mut self, context: &mut FunctionContext) -> Result<InstructionOutcome, Error>
|
||||||
where RuntimeValue: From<T> + TryInto<T, Error>, T: TransmuteInto<U>, U: Integer<U> + TransmuteInto<T> {
|
where RuntimeValue: From<T> + TryInto<T, Error>, T: TransmuteInto<U>, U: Integer<U> + TransmuteInto<T> {
|
||||||
context
|
context
|
||||||
.value_stack_mut()
|
.value_stack_mut()
|
||||||
@ -780,7 +781,7 @@ impl<'a, St: 'a> Interpreter<'a, St> {
|
|||||||
.map(|_| InstructionOutcome::RunNextInstruction)
|
.map(|_| InstructionOutcome::RunNextInstruction)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn run_and<T>(&mut self, context: &mut FunctionContext<St>) -> Result<InstructionOutcome<St>, Error>
|
fn run_and<T>(&mut self, context: &mut FunctionContext) -> Result<InstructionOutcome, Error>
|
||||||
where RuntimeValue: From<<T as ops::BitAnd>::Output> + TryInto<T, Error>, T: ops::BitAnd<T> {
|
where RuntimeValue: From<<T as ops::BitAnd>::Output> + TryInto<T, Error>, T: ops::BitAnd<T> {
|
||||||
context
|
context
|
||||||
.value_stack_mut()
|
.value_stack_mut()
|
||||||
@ -790,7 +791,7 @@ impl<'a, St: 'a> Interpreter<'a, St> {
|
|||||||
.map(|_| InstructionOutcome::RunNextInstruction)
|
.map(|_| InstructionOutcome::RunNextInstruction)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn run_or<T>(&mut self, context: &mut FunctionContext<St>) -> Result<InstructionOutcome<St>, Error>
|
fn run_or<T>(&mut self, context: &mut FunctionContext) -> Result<InstructionOutcome, Error>
|
||||||
where RuntimeValue: From<<T as ops::BitOr>::Output> + TryInto<T, Error>, T: ops::BitOr<T> {
|
where RuntimeValue: From<<T as ops::BitOr>::Output> + TryInto<T, Error>, T: ops::BitOr<T> {
|
||||||
context
|
context
|
||||||
.value_stack_mut()
|
.value_stack_mut()
|
||||||
@ -800,7 +801,7 @@ impl<'a, St: 'a> Interpreter<'a, St> {
|
|||||||
.map(|_| InstructionOutcome::RunNextInstruction)
|
.map(|_| InstructionOutcome::RunNextInstruction)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn run_xor<T>(&mut self, context: &mut FunctionContext<St>) -> Result<InstructionOutcome<St>, Error>
|
fn run_xor<T>(&mut self, context: &mut FunctionContext) -> Result<InstructionOutcome, Error>
|
||||||
where RuntimeValue: From<<T as ops::BitXor>::Output> + TryInto<T, Error>, T: ops::BitXor<T> {
|
where RuntimeValue: From<<T as ops::BitXor>::Output> + TryInto<T, Error>, T: ops::BitXor<T> {
|
||||||
context
|
context
|
||||||
.value_stack_mut()
|
.value_stack_mut()
|
||||||
@ -810,7 +811,7 @@ impl<'a, St: 'a> Interpreter<'a, St> {
|
|||||||
.map(|_| InstructionOutcome::RunNextInstruction)
|
.map(|_| InstructionOutcome::RunNextInstruction)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn run_shl<T>(&mut self, context: &mut FunctionContext<St>, mask: T) -> Result<InstructionOutcome<St>, Error>
|
fn run_shl<T>(&mut self, context: &mut FunctionContext, mask: T) -> Result<InstructionOutcome, Error>
|
||||||
where RuntimeValue: From<<T as ops::Shl<T>>::Output> + TryInto<T, Error>, T: ops::Shl<T> + ops::BitAnd<T, Output=T> {
|
where RuntimeValue: From<<T as ops::Shl<T>>::Output> + TryInto<T, Error>, T: ops::Shl<T> + ops::BitAnd<T, Output=T> {
|
||||||
context
|
context
|
||||||
.value_stack_mut()
|
.value_stack_mut()
|
||||||
@ -820,7 +821,7 @@ impl<'a, St: 'a> Interpreter<'a, St> {
|
|||||||
.map(|_| InstructionOutcome::RunNextInstruction)
|
.map(|_| InstructionOutcome::RunNextInstruction)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn run_shr<T, U>(&mut self, context: &mut FunctionContext<St>, mask: U) -> Result<InstructionOutcome<St>, Error>
|
fn run_shr<T, U>(&mut self, context: &mut FunctionContext, mask: U) -> Result<InstructionOutcome, Error>
|
||||||
where RuntimeValue: From<T> + TryInto<T, Error>, T: TransmuteInto<U>, U: ops::Shr<U> + ops::BitAnd<U, Output=U>, <U as ops::Shr<U>>::Output: TransmuteInto<T> {
|
where RuntimeValue: From<T> + TryInto<T, Error>, T: TransmuteInto<U>, U: ops::Shr<U> + ops::BitAnd<U, Output=U>, <U as ops::Shr<U>>::Output: TransmuteInto<T> {
|
||||||
context
|
context
|
||||||
.value_stack_mut()
|
.value_stack_mut()
|
||||||
@ -832,7 +833,7 @@ impl<'a, St: 'a> Interpreter<'a, St> {
|
|||||||
.map(|_| InstructionOutcome::RunNextInstruction)
|
.map(|_| InstructionOutcome::RunNextInstruction)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn run_rotl<T>(&mut self, context: &mut FunctionContext<St>) -> Result<InstructionOutcome<St>, Error>
|
fn run_rotl<T>(&mut self, context: &mut FunctionContext) -> Result<InstructionOutcome, Error>
|
||||||
where RuntimeValue: From<T> + TryInto<T, Error>, T: Integer<T> {
|
where RuntimeValue: From<T> + TryInto<T, Error>, T: Integer<T> {
|
||||||
context
|
context
|
||||||
.value_stack_mut()
|
.value_stack_mut()
|
||||||
@ -842,7 +843,7 @@ impl<'a, St: 'a> Interpreter<'a, St> {
|
|||||||
.map(|_| InstructionOutcome::RunNextInstruction)
|
.map(|_| InstructionOutcome::RunNextInstruction)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn run_rotr<T>(&mut self, context: &mut FunctionContext<St>) -> Result<InstructionOutcome<St>, Error>
|
fn run_rotr<T>(&mut self, context: &mut FunctionContext) -> Result<InstructionOutcome, Error>
|
||||||
where RuntimeValue: From<T> + TryInto<T, Error>, T: Integer<T> {
|
where RuntimeValue: From<T> + TryInto<T, Error>, T: Integer<T> {
|
||||||
context
|
context
|
||||||
.value_stack_mut()
|
.value_stack_mut()
|
||||||
@ -852,7 +853,7 @@ impl<'a, St: 'a> Interpreter<'a, St> {
|
|||||||
.map(|_| InstructionOutcome::RunNextInstruction)
|
.map(|_| InstructionOutcome::RunNextInstruction)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn run_abs<T>(&mut self, context: &mut FunctionContext<St>) -> Result<InstructionOutcome<St>, Error>
|
fn run_abs<T>(&mut self, context: &mut FunctionContext) -> Result<InstructionOutcome, Error>
|
||||||
where RuntimeValue: From<T> + TryInto<T, Error>, T: Float<T> {
|
where RuntimeValue: From<T> + TryInto<T, Error>, T: Float<T> {
|
||||||
context
|
context
|
||||||
.value_stack_mut()
|
.value_stack_mut()
|
||||||
@ -862,7 +863,7 @@ impl<'a, St: 'a> Interpreter<'a, St> {
|
|||||||
.map(|_| InstructionOutcome::RunNextInstruction)
|
.map(|_| InstructionOutcome::RunNextInstruction)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn run_neg<T>(&mut self, context: &mut FunctionContext<St>) -> Result<InstructionOutcome<St>, Error>
|
fn run_neg<T>(&mut self, context: &mut FunctionContext) -> Result<InstructionOutcome, Error>
|
||||||
where RuntimeValue: From<<T as ops::Neg>::Output> + TryInto<T, Error>, T: ops::Neg {
|
where RuntimeValue: From<<T as ops::Neg>::Output> + TryInto<T, Error>, T: ops::Neg {
|
||||||
context
|
context
|
||||||
.value_stack_mut()
|
.value_stack_mut()
|
||||||
@ -872,7 +873,7 @@ impl<'a, St: 'a> Interpreter<'a, St> {
|
|||||||
.map(|_| InstructionOutcome::RunNextInstruction)
|
.map(|_| InstructionOutcome::RunNextInstruction)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn run_ceil<T>(&mut self, context: &mut FunctionContext<St>) -> Result<InstructionOutcome<St>, Error>
|
fn run_ceil<T>(&mut self, context: &mut FunctionContext) -> Result<InstructionOutcome, Error>
|
||||||
where RuntimeValue: From<T> + TryInto<T, Error>, T: Float<T> {
|
where RuntimeValue: From<T> + TryInto<T, Error>, T: Float<T> {
|
||||||
context
|
context
|
||||||
.value_stack_mut()
|
.value_stack_mut()
|
||||||
@ -882,7 +883,7 @@ impl<'a, St: 'a> Interpreter<'a, St> {
|
|||||||
.map(|_| InstructionOutcome::RunNextInstruction)
|
.map(|_| InstructionOutcome::RunNextInstruction)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn run_floor<T>(&mut self, context: &mut FunctionContext<St>) -> Result<InstructionOutcome<St>, Error>
|
fn run_floor<T>(&mut self, context: &mut FunctionContext) -> Result<InstructionOutcome, Error>
|
||||||
where RuntimeValue: From<T> + TryInto<T, Error>, T: Float<T> {
|
where RuntimeValue: From<T> + TryInto<T, Error>, T: Float<T> {
|
||||||
context
|
context
|
||||||
.value_stack_mut()
|
.value_stack_mut()
|
||||||
@ -892,7 +893,7 @@ impl<'a, St: 'a> Interpreter<'a, St> {
|
|||||||
.map(|_| InstructionOutcome::RunNextInstruction)
|
.map(|_| InstructionOutcome::RunNextInstruction)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn run_trunc<T>(&mut self, context: &mut FunctionContext<St>) -> Result<InstructionOutcome<St>, Error>
|
fn run_trunc<T>(&mut self, context: &mut FunctionContext) -> Result<InstructionOutcome, Error>
|
||||||
where RuntimeValue: From<T> + TryInto<T, Error>, T: Float<T> {
|
where RuntimeValue: From<T> + TryInto<T, Error>, T: Float<T> {
|
||||||
context
|
context
|
||||||
.value_stack_mut()
|
.value_stack_mut()
|
||||||
@ -902,7 +903,7 @@ impl<'a, St: 'a> Interpreter<'a, St> {
|
|||||||
.map(|_| InstructionOutcome::RunNextInstruction)
|
.map(|_| InstructionOutcome::RunNextInstruction)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn run_nearest<T>(&mut self, context: &mut FunctionContext<St>) -> Result<InstructionOutcome<St>, Error>
|
fn run_nearest<T>(&mut self, context: &mut FunctionContext) -> Result<InstructionOutcome, Error>
|
||||||
where RuntimeValue: From<T> + TryInto<T, Error>, T: Float<T> {
|
where RuntimeValue: From<T> + TryInto<T, Error>, T: Float<T> {
|
||||||
context
|
context
|
||||||
.value_stack_mut()
|
.value_stack_mut()
|
||||||
@ -912,7 +913,7 @@ impl<'a, St: 'a> Interpreter<'a, St> {
|
|||||||
.map(|_| InstructionOutcome::RunNextInstruction)
|
.map(|_| InstructionOutcome::RunNextInstruction)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn run_sqrt<T>(&mut self, context: &mut FunctionContext<St>) -> Result<InstructionOutcome<St>, Error>
|
fn run_sqrt<T>(&mut self, context: &mut FunctionContext) -> Result<InstructionOutcome, Error>
|
||||||
where RuntimeValue: From<T> + TryInto<T, Error>, T: Float<T> {
|
where RuntimeValue: From<T> + TryInto<T, Error>, T: Float<T> {
|
||||||
context
|
context
|
||||||
.value_stack_mut()
|
.value_stack_mut()
|
||||||
@ -922,7 +923,7 @@ impl<'a, St: 'a> Interpreter<'a, St> {
|
|||||||
.map(|_| InstructionOutcome::RunNextInstruction)
|
.map(|_| InstructionOutcome::RunNextInstruction)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn run_min<T>(&mut self, context: &mut FunctionContext<St>) -> Result<InstructionOutcome<St>, Error>
|
fn run_min<T>(&mut self, context: &mut FunctionContext) -> Result<InstructionOutcome, Error>
|
||||||
where RuntimeValue: From<T> + TryInto<T, Error>, T: Float<T> {
|
where RuntimeValue: From<T> + TryInto<T, Error>, T: Float<T> {
|
||||||
context
|
context
|
||||||
.value_stack_mut()
|
.value_stack_mut()
|
||||||
@ -932,7 +933,7 @@ impl<'a, St: 'a> Interpreter<'a, St> {
|
|||||||
.map(|_| InstructionOutcome::RunNextInstruction)
|
.map(|_| InstructionOutcome::RunNextInstruction)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn run_max<T>(&mut self, context: &mut FunctionContext<St>) -> Result<InstructionOutcome<St>, Error>
|
fn run_max<T>(&mut self, context: &mut FunctionContext) -> Result<InstructionOutcome, Error>
|
||||||
where RuntimeValue: From<T> + TryInto<T, Error>, T: Float<T> {
|
where RuntimeValue: From<T> + TryInto<T, Error>, T: Float<T> {
|
||||||
context
|
context
|
||||||
.value_stack_mut()
|
.value_stack_mut()
|
||||||
@ -942,7 +943,7 @@ impl<'a, St: 'a> Interpreter<'a, St> {
|
|||||||
.map(|_| InstructionOutcome::RunNextInstruction)
|
.map(|_| InstructionOutcome::RunNextInstruction)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn run_copysign<T>(&mut self, context: &mut FunctionContext<St>) -> Result<InstructionOutcome<St>, Error>
|
fn run_copysign<T>(&mut self, context: &mut FunctionContext) -> Result<InstructionOutcome, Error>
|
||||||
where RuntimeValue: From<T> + TryInto<T, Error>, T: Float<T> {
|
where RuntimeValue: From<T> + TryInto<T, Error>, T: Float<T> {
|
||||||
context
|
context
|
||||||
.value_stack_mut()
|
.value_stack_mut()
|
||||||
@ -952,7 +953,7 @@ impl<'a, St: 'a> Interpreter<'a, St> {
|
|||||||
.map(|_| InstructionOutcome::RunNextInstruction)
|
.map(|_| InstructionOutcome::RunNextInstruction)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn run_wrap<T, U>(&mut self, context: &mut FunctionContext<St>) -> Result<InstructionOutcome<St>, Error>
|
fn run_wrap<T, U>(&mut self, context: &mut FunctionContext) -> Result<InstructionOutcome, Error>
|
||||||
where RuntimeValue: From<U> + TryInto<T, Error>, T: WrapInto<U> {
|
where RuntimeValue: From<U> + TryInto<T, Error>, T: WrapInto<U> {
|
||||||
context
|
context
|
||||||
.value_stack_mut()
|
.value_stack_mut()
|
||||||
@ -962,7 +963,7 @@ impl<'a, St: 'a> Interpreter<'a, St> {
|
|||||||
.map(|_| InstructionOutcome::RunNextInstruction)
|
.map(|_| InstructionOutcome::RunNextInstruction)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn run_trunc_to_int<T, U, V>(&mut self, context: &mut FunctionContext<St>) -> Result<InstructionOutcome<St>, Error>
|
fn run_trunc_to_int<T, U, V>(&mut self, context: &mut FunctionContext) -> Result<InstructionOutcome, Error>
|
||||||
where RuntimeValue: From<V> + TryInto<T, Error>, T: TryTruncateInto<U, Error>, U: TransmuteInto<V>, {
|
where RuntimeValue: From<V> + TryInto<T, Error>, T: TryTruncateInto<U, Error>, U: TransmuteInto<V>, {
|
||||||
context
|
context
|
||||||
.value_stack_mut()
|
.value_stack_mut()
|
||||||
@ -973,7 +974,7 @@ impl<'a, St: 'a> Interpreter<'a, St> {
|
|||||||
.map(|_| InstructionOutcome::RunNextInstruction)
|
.map(|_| InstructionOutcome::RunNextInstruction)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn run_extend<T, U, V>(&mut self, context: &mut FunctionContext<St>) -> Result<InstructionOutcome<St>, Error>
|
fn run_extend<T, U, V>(&mut self, context: &mut FunctionContext) -> Result<InstructionOutcome, Error>
|
||||||
where RuntimeValue: From<V> + TryInto<T, Error>, T: ExtendInto<U>, U: TransmuteInto<V> {
|
where RuntimeValue: From<V> + TryInto<T, Error>, T: ExtendInto<U>, U: TransmuteInto<V> {
|
||||||
context
|
context
|
||||||
.value_stack_mut()
|
.value_stack_mut()
|
||||||
@ -985,7 +986,7 @@ impl<'a, St: 'a> Interpreter<'a, St> {
|
|||||||
.map(|_| InstructionOutcome::RunNextInstruction)
|
.map(|_| InstructionOutcome::RunNextInstruction)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn run_reinterpret<T, U>(&mut self, context: &mut FunctionContext<St>) -> Result<InstructionOutcome<St>, Error>
|
fn run_reinterpret<T, U>(&mut self, context: &mut FunctionContext) -> Result<InstructionOutcome, Error>
|
||||||
where RuntimeValue: From<U>, RuntimeValue: TryInto<T, Error>, T: TransmuteInto<U> {
|
where RuntimeValue: From<U>, RuntimeValue: TryInto<T, Error>, T: TransmuteInto<U> {
|
||||||
context
|
context
|
||||||
.value_stack_mut()
|
.value_stack_mut()
|
||||||
@ -996,8 +997,8 @@ impl<'a, St: 'a> Interpreter<'a, St> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<St> FunctionContext<St> {
|
impl FunctionContext {
|
||||||
pub fn new<'store>(function: Rc<FuncInstance<St>>, value_stack_limit: usize, frame_stack_limit: usize, function_type: &FunctionType, args: Vec<RuntimeValue>) -> Self {
|
pub fn new<'store>(function: Rc<FuncInstance>, value_stack_limit: usize, frame_stack_limit: usize, function_type: &FunctionType, args: Vec<RuntimeValue>) -> Self {
|
||||||
let module = match *function {
|
let module = match *function {
|
||||||
FuncInstance::Internal { ref module, .. } => Rc::clone(module),
|
FuncInstance::Internal { ref module, .. } => Rc::clone(module),
|
||||||
FuncInstance::Host { .. } => panic!("Host functions can't be called as internally defined functions; Thus FunctionContext can be created only with internally defined functions; qed"),
|
FuncInstance::Host { .. } => panic!("Host functions can't be called as internally defined functions; Thus FunctionContext can be created only with internally defined functions; qed"),
|
||||||
@ -1014,7 +1015,7 @@ impl<St> FunctionContext<St> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn nested(&mut self, function: Rc<FuncInstance<St>>) -> Result<Self, Error> {
|
pub fn nested(&mut self, function: Rc<FuncInstance>) -> Result<Self, Error> {
|
||||||
let (function_locals, module, function_return_type) = {
|
let (function_locals, module, function_return_type) = {
|
||||||
let module = match *function {
|
let module = match *function {
|
||||||
FuncInstance::Internal { ref module, .. } => Rc::clone(module),
|
FuncInstance::Internal { ref module, .. } => Rc::clone(module),
|
||||||
@ -1053,11 +1054,11 @@ impl<St> FunctionContext<St> {
|
|||||||
self.locals.extend(locals);
|
self.locals.extend(locals);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn module(&self) -> Rc<ModuleInstance<St>> {
|
pub fn module(&self) -> Rc<ModuleInstance> {
|
||||||
Rc::clone(&self.module)
|
Rc::clone(&self.module)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn set_local(&mut self, index: usize, value: RuntimeValue) -> Result<InstructionOutcome<St>, Error> {
|
pub fn set_local(&mut self, index: usize, value: RuntimeValue) -> Result<InstructionOutcome, Error> {
|
||||||
let l = self.locals.get_mut(index)
|
let l = self.locals.get_mut(index)
|
||||||
.ok_or(Error::Local(format!("expected to have local with index {}", index)))?;
|
.ok_or(Error::Local(format!("expected to have local with index {}", index)))?;
|
||||||
|
|
||||||
@ -1135,7 +1136,7 @@ impl<St> FunctionContext<St> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<St> fmt::Debug for FunctionContext<St> {
|
impl fmt::Debug for FunctionContext {
|
||||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||||
write!(f, "FunctionContext")
|
write!(f, "FunctionContext")
|
||||||
}
|
}
|
||||||
|
82
src/interpreter/state.rs
Normal file
82
src/interpreter/state.rs
Normal file
@ -0,0 +1,82 @@
|
|||||||
|
|
||||||
|
use std::any::{TypeId, Any};
|
||||||
|
use std::collections::HashMap;
|
||||||
|
|
||||||
|
pub unsafe trait StateKey {
|
||||||
|
type Static: ?Sized + 'static;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Returns the `TypeId` for `T::Static`
|
||||||
|
pub fn type_id<T>() -> TypeId
|
||||||
|
where T: StateKey, T::Static: Any
|
||||||
|
{
|
||||||
|
TypeId::of::<T::Static>()
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Default)]
|
||||||
|
pub struct HostState<'a> {
|
||||||
|
data: HashMap<TypeId, *mut ()>,
|
||||||
|
_marker: ::std::marker::PhantomData<&'a ()>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a> HostState<'a> {
|
||||||
|
pub fn new() -> Self {
|
||||||
|
HostState {
|
||||||
|
data: HashMap::default(),
|
||||||
|
_marker: ::std::marker::PhantomData,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn insert<V: StateKey>(&mut self, val: &'a mut V) {
|
||||||
|
let ty_id = type_id::<V>();
|
||||||
|
let ptr = val as *mut V as *mut ();
|
||||||
|
let existing = self.data.insert(ty_id, ptr);
|
||||||
|
assert!(existing.is_none());
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn with_state<V: StateKey, R, F: FnOnce(&mut V) -> R>(&mut self, f: F) -> R {
|
||||||
|
let ty_id = type_id::<V>();
|
||||||
|
let ptr = self.data.get_mut(&ty_id).unwrap();
|
||||||
|
unsafe {
|
||||||
|
let val_ref = &mut * { *ptr as *mut V };
|
||||||
|
f(val_ref)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
mod tests {
|
||||||
|
use super::*;
|
||||||
|
|
||||||
|
struct MyState<'a>(&'a mut i32);
|
||||||
|
impl<'a> MyState<'a> {
|
||||||
|
fn inc(&mut self) {
|
||||||
|
*self.0 += 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
fn get(&self) -> i32 {
|
||||||
|
*self.0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
unsafe impl<'a> StateKey for MyState<'a> {
|
||||||
|
type Static = MyState<'static>;
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn it_works() {
|
||||||
|
let mut counter = 33i32;
|
||||||
|
|
||||||
|
let new_value = {
|
||||||
|
let mut my_state = MyState(&mut counter);
|
||||||
|
let mut host_state = HostState::new();
|
||||||
|
host_state.insert::<MyState>(&mut my_state);
|
||||||
|
host_state.with_state(|my_state: &mut MyState| {
|
||||||
|
my_state.inc();
|
||||||
|
my_state.get()
|
||||||
|
})
|
||||||
|
};
|
||||||
|
|
||||||
|
assert_eq!(new_value, counter);
|
||||||
|
}
|
||||||
|
}
|
@ -8,14 +8,14 @@ use interpreter::module::check_limits;
|
|||||||
use interpreter::func::FuncInstance;
|
use interpreter::func::FuncInstance;
|
||||||
|
|
||||||
/// Table instance.
|
/// Table instance.
|
||||||
pub struct TableInstance<St> {
|
pub struct TableInstance {
|
||||||
/// Table limits.
|
/// Table limits.
|
||||||
limits: ResizableLimits,
|
limits: ResizableLimits,
|
||||||
/// Table memory buffer.
|
/// Table memory buffer.
|
||||||
buffer: RefCell<Vec<Option<Rc<FuncInstance<St>>>>>,
|
buffer: RefCell<Vec<Option<Rc<FuncInstance>>>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<St> fmt::Debug for TableInstance<St> {
|
impl fmt::Debug for TableInstance {
|
||||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||||
f.debug_struct("TableInstance")
|
f.debug_struct("TableInstance")
|
||||||
.field("limits", &self.limits)
|
.field("limits", &self.limits)
|
||||||
@ -24,7 +24,7 @@ impl<St> fmt::Debug for TableInstance<St> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<St> TableInstance<St> {
|
impl TableInstance {
|
||||||
/// New instance of the table
|
/// New instance of the table
|
||||||
pub fn new(table_type: &TableType) -> Result<Self, Error> {
|
pub fn new(table_type: &TableType) -> Result<Self, Error> {
|
||||||
check_limits(table_type.limits())?;
|
check_limits(table_type.limits())?;
|
||||||
@ -40,7 +40,7 @@ impl<St> TableInstance<St> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Get the specific value in the table
|
/// Get the specific value in the table
|
||||||
pub fn get(&self, offset: u32) -> Result<Rc<FuncInstance<St>>, Error> {
|
pub fn get(&self, offset: u32) -> Result<Rc<FuncInstance>, Error> {
|
||||||
let buffer = self.buffer.borrow();
|
let buffer = self.buffer.borrow();
|
||||||
let buffer_len = buffer.len();
|
let buffer_len = buffer.len();
|
||||||
let table_elem = buffer.get(offset as usize).cloned().ok_or(
|
let table_elem = buffer.get(offset as usize).cloned().ok_or(
|
||||||
@ -57,7 +57,7 @@ impl<St> TableInstance<St> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Set the table element to the specified function.
|
/// Set the table element to the specified function.
|
||||||
pub fn set(&self, offset: u32, value: Rc<FuncInstance<St>>) -> Result<(), Error> {
|
pub fn set(&self, offset: u32, value: Rc<FuncInstance>) -> Result<(), Error> {
|
||||||
let mut buffer = self.buffer.borrow_mut();
|
let mut buffer = self.buffer.borrow_mut();
|
||||||
let buffer_len = buffer.len();
|
let buffer_len = buffer.len();
|
||||||
let table_elem = buffer.get_mut(offset as usize).ok_or(Error::Table(format!(
|
let table_elem = buffer.get_mut(offset as usize).ok_or(Error::Table(format!(
|
||||||
|
@ -1,23 +1,23 @@
|
|||||||
mod basics;
|
// mod basics;
|
||||||
mod wabt;
|
// mod wabt;
|
||||||
mod wasm;
|
// mod wasm;
|
||||||
|
|
||||||
mod utils {
|
// mod utils {
|
||||||
use elements::{MemoryType, TableType};
|
// use elements::{MemoryType, TableType};
|
||||||
use interpreter::{ProgramInstance, HostModuleBuilder, MemoryInstance, TableInstance, GlobalInstance, RuntimeValue};
|
// use interpreter::{ProgramInstance, HostModuleBuilder, MemoryInstance, TableInstance, GlobalInstance, RuntimeValue};
|
||||||
use std::rc::Rc;
|
// use std::rc::Rc;
|
||||||
|
|
||||||
pub fn program_with_default_env<St: 'static>() -> ProgramInstance<St> {
|
// pub fn program_with_default_env<St: 'static>() -> ProgramInstance<St> {
|
||||||
let mut program = ProgramInstance::<St>::new();
|
// let mut program = ProgramInstance::<St>::new();
|
||||||
|
|
||||||
let mut builder = HostModuleBuilder::<St>::new();
|
// let mut builder = HostModuleBuilder::<St>::new();
|
||||||
builder.insert_memory("memory", Rc::new(MemoryInstance::new(&MemoryType::new(256, None)).unwrap()));
|
// builder.insert_memory("memory", Rc::new(MemoryInstance::new(&MemoryType::new(256, None)).unwrap()));
|
||||||
builder.insert_table("table", Rc::new(TableInstance::new(&TableType::new(64, None)).unwrap()));
|
// builder.insert_table("table", Rc::new(TableInstance::new(&TableType::new(64, None)).unwrap()));
|
||||||
builder.insert_global("tableBase", Rc::new(GlobalInstance::new(RuntimeValue::I32(0), false)));
|
// builder.insert_global("tableBase", Rc::new(GlobalInstance::new(RuntimeValue::I32(0), false)));
|
||||||
builder.insert_global("memoryBase", Rc::new(GlobalInstance::new(RuntimeValue::I32(0), false)));
|
// builder.insert_global("memoryBase", Rc::new(GlobalInstance::new(RuntimeValue::I32(0), false)));
|
||||||
let env_host_module = builder.build();
|
// let env_host_module = builder.build();
|
||||||
|
|
||||||
program.add_host_module("env", env_host_module);
|
// program.add_host_module("env", env_host_module);
|
||||||
program
|
// program
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
|
@ -5,6 +5,7 @@
|
|||||||
#[macro_use]
|
#[macro_use]
|
||||||
extern crate log;
|
extern crate log;
|
||||||
extern crate byteorder;
|
extern crate byteorder;
|
||||||
|
extern crate unsafe_any;
|
||||||
|
|
||||||
pub mod elements;
|
pub mod elements;
|
||||||
pub mod builder;
|
pub mod builder;
|
||||||
|
Reference in New Issue
Block a user