745 lines
32 KiB
Rust
Raw Normal View History

2017-06-13 12:01:59 +03:00
use std::collections::HashMap;
2017-05-04 19:50:48 +03:00
use std::iter::repeat;
2017-04-21 14:35:12 +03:00
use std::sync::{Arc, Weak};
2017-06-16 12:23:49 +03:00
use std::fmt;
2017-06-26 11:54:17 +03:00
use elements::{Module, InitExpr, Opcode, Type, FunctionType, Internal, External, BlockType, ResizableLimits, Local, ValueType};
2017-08-01 16:15:08 +03:00
use interpreter::{Error, UserError};
2017-06-26 11:54:17 +03:00
use interpreter::env_native::UserFunctionDescriptor;
2017-04-21 14:35:12 +03:00
use interpreter::imports::ModuleImports;
use interpreter::memory::MemoryInstance;
use interpreter::program::ProgramInstanceEssence;
2017-06-19 11:01:59 +03:00
use interpreter::runner::{Interpreter, FunctionContext, prepare_function_args};
2017-04-28 13:34:58 +03:00
use interpreter::stack::StackWithLimit;
2017-04-21 14:35:12 +03:00
use interpreter::table::TableInstance;
2017-06-07 14:48:02 +03:00
use interpreter::validator::{Validator, FunctionValidationContext};
2017-05-31 18:43:09 +02:00
use interpreter::value::{RuntimeValue, TryInto};
2017-04-26 15:41:22 +03:00
use interpreter::variable::{VariableInstance, VariableType};
2017-04-21 14:35:12 +03:00
2017-06-07 14:48:02 +03:00
/// Maximum number of entries in value stack.
const DEFAULT_VALUE_STACK_LIMIT: usize = 16384;
/// Maximum number of entries in frame stack.
2017-06-16 12:23:49 +03:00
const DEFAULT_FRAME_STACK_LIMIT: usize = 1024;
2017-06-07 14:48:02 +03:00
2017-05-18 15:08:55 +03:00
/// Execution context.
#[derive(Clone)]
2017-08-01 16:15:08 +03:00
pub struct ExecutionParams<'a, E: UserError> {
2017-05-18 15:08:55 +03:00
/// Arguments.
pub args: Vec<RuntimeValue>,
/// Execution-local external modules.
pub externals: HashMap<String, Arc<ModuleInstanceInterface<E> + 'a>>,
2017-05-18 15:08:55 +03:00
}
2017-06-13 12:01:59 +03:00
/// Export type.
#[derive(Debug, Clone)]
2017-06-26 11:54:17 +03:00
pub enum ExportEntryType<'a> {
2017-06-13 12:01:59 +03:00
/// Any type.
Any,
/// Type of function.
2017-06-26 11:54:17 +03:00
Function(FunctionSignature<'a>),
2017-06-13 12:01:59 +03:00
/// Type of global.
Global(VariableType),
}
2017-06-26 11:54:17 +03:00
/// Function signature.
#[derive(Debug, Clone)]
pub enum FunctionSignature<'a> {
/// Module function reference.
Module(&'a FunctionType),
/// Native user function refrence.
User(&'a UserFunctionDescriptor),
}
2017-05-04 11:25:25 +03:00
/// Module instance API.
2017-08-01 16:15:08 +03:00
pub trait ModuleInstanceInterface<E: UserError> {
2017-05-04 11:25:25 +03:00
/// Execute function with the given index.
2017-08-01 14:44:33 +03:00
fn execute_index(&self, index: u32, params: ExecutionParams<E>) -> Result<Option<RuntimeValue>, Error<E>>;
2017-05-04 19:09:43 +03:00
/// Execute function with the given export name.
2017-08-01 14:44:33 +03:00
fn execute_export(&self, name: &str, params: ExecutionParams<E>) -> Result<Option<RuntimeValue>, Error<E>>;
2017-05-18 15:08:55 +03:00
/// Get export entry.
2017-08-01 14:44:33 +03:00
fn export_entry<'a>(&self, name: &str, required_type: &ExportEntryType) -> Result<Internal, Error<E>>;
2017-05-04 11:25:25 +03:00
/// Get table reference.
2017-08-01 14:44:33 +03:00
fn table(&self, index: ItemIndex) -> Result<Arc<TableInstance<E>>, Error<E>>;
2017-05-04 11:25:25 +03:00
/// Get memory reference.
2017-08-01 14:44:33 +03:00
fn memory(&self, index: ItemIndex) -> Result<Arc<MemoryInstance<E>>, Error<E>>;
2017-05-04 11:25:25 +03:00
/// Get global reference.
2017-08-01 14:44:33 +03:00
fn global<'a>(&self, index: ItemIndex, variable_type: Option<VariableType>, externals: Option<&'a HashMap<String, Arc<ModuleInstanceInterface<E> + 'a>>>) -> Result<Arc<VariableInstance<E>>, Error<E>>;
2017-06-19 12:04:16 +03:00
/// Get function type for given function index.
2017-08-01 14:44:33 +03:00
fn function_type(&self, function_index: ItemIndex) -> Result<FunctionSignature, Error<E>>;
2017-06-19 12:04:16 +03:00
/// Get function type for given function index.
2017-08-01 14:44:33 +03:00
fn function_type_by_index(&self, type_index: u32) -> Result<FunctionSignature, Error<E>>;
2017-06-16 12:23:49 +03:00
/// Get function reference.
2017-08-01 14:44:33 +03:00
fn function_reference<'a>(&self, index: ItemIndex, externals: Option<&'a HashMap<String, Arc<ModuleInstanceInterface<E> + 'a>>>) -> Result<InternalFunctionReference<'a, E>, Error<E>>;
2017-06-16 12:23:49 +03:00
/// Get function indirect reference.
2017-08-01 14:44:33 +03:00
fn function_reference_indirect<'a>(&self, table_idx: u32, type_idx: u32, func_idx: u32, externals: Option<&'a HashMap<String, Arc<ModuleInstanceInterface<E> + 'a>>>) -> Result<InternalFunctionReference<'a, E>, Error<E>>;
2017-06-16 12:23:49 +03:00
/// Get internal function for interpretation.
2017-08-01 14:44:33 +03:00
fn function_body<'a>(&'a self, internal_index: u32) -> Result<Option<InternalFunction<'a>>, Error<E>>;
2017-06-19 12:04:16 +03:00
/// Call function with given internal index.
2017-08-01 14:44:33 +03:00
fn call_internal_function(&self, outer: CallerContext<E>, index: u32) -> Result<Option<RuntimeValue>, Error<E>>;
2017-05-04 11:25:25 +03:00
}
2017-04-21 14:35:12 +03:00
/// Item index in items index space.
#[derive(Debug, Clone, Copy)]
pub enum ItemIndex {
/// Index in index space.
IndexSpace(u32),
/// Internal item index (i.e. index of item in items section).
Internal(u32),
2017-05-18 15:08:55 +03:00
/// External module item index (i.e. index of item in the import section).
2017-04-21 14:35:12 +03:00
External(u32),
}
/// Module instance.
2017-08-01 16:15:08 +03:00
pub struct ModuleInstance<E: UserError> {
2017-06-13 12:01:59 +03:00
/// Module name.
name: String,
2017-04-21 14:35:12 +03:00
/// Module.
module: Module,
2017-06-22 17:52:05 +03:00
/// Function labels.
functions_labels: HashMap<u32, HashMap<usize, usize>>,
2017-04-21 14:35:12 +03:00
/// Module imports.
imports: ModuleImports<E>,
2017-06-28 11:03:01 +03:00
/// Module exports.
exports: HashMap<String, Vec<Internal>>,
2017-04-21 14:35:12 +03:00
/// Tables.
2017-08-01 14:44:33 +03:00
tables: Vec<Arc<TableInstance<E>>>,
2017-04-21 14:35:12 +03:00
/// Linear memory regions.
2017-08-01 14:44:33 +03:00
memory: Vec<Arc<MemoryInstance<E>>>,
2017-04-21 14:35:12 +03:00
/// Globals.
2017-08-01 14:44:33 +03:00
globals: Vec<Arc<VariableInstance<E>>>,
2017-04-21 14:35:12 +03:00
}
2017-04-28 13:34:58 +03:00
/// Caller context.
2017-08-01 16:15:08 +03:00
pub struct CallerContext<'a, E: 'a + UserError> {
2017-05-15 15:40:08 +03:00
/// Value stack limit
2017-04-28 13:34:58 +03:00
pub value_stack_limit: usize,
2017-05-15 15:40:08 +03:00
/// Frame stack limit
2017-04-28 13:34:58 +03:00
pub frame_stack_limit: usize,
2017-05-15 15:40:08 +03:00
/// Stack of the input parameters
2017-08-01 14:44:33 +03:00
pub value_stack: &'a mut StackWithLimit<RuntimeValue, E>,
2017-05-18 15:08:55 +03:00
/// Execution-local external modules.
pub externals: &'a HashMap<String, Arc<ModuleInstanceInterface<E> + 'a>>,
2017-05-18 15:08:55 +03:00
}
2017-06-16 12:23:49 +03:00
/// Internal function reference.
#[derive(Clone)]
2017-08-01 16:15:08 +03:00
pub struct InternalFunctionReference<'a, E: UserError> {
2017-06-16 12:23:49 +03:00
/// Module reference.
pub module: Arc<ModuleInstanceInterface<E> + 'a>,
2017-06-16 12:23:49 +03:00
/// Internal function index.
pub internal_index: u32,
}
2017-08-01 16:15:08 +03:00
impl<'a, E> fmt::Debug for InternalFunctionReference<'a, E> where E: UserError {
2017-06-16 12:23:49 +03:00
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "InternalFunctionReference")
}
}
/// Internal function ready for interpretation.
pub struct InternalFunction<'a> {
/// Function locals.
pub locals: &'a [Local],
/// Function body.
pub body: &'a [Opcode],
2017-06-22 17:52:05 +03:00
/// Function labels.
pub labels: &'a HashMap<usize, usize>,
2017-06-16 12:23:49 +03:00
}
2017-08-01 16:15:08 +03:00
impl<'a, E> ExecutionParams<'a, E> where E: UserError {
2017-05-18 15:08:55 +03:00
/// Create new execution params with given externa; module override.
pub fn with_external(name: String, module: Arc<ModuleInstanceInterface<E> + 'a>) -> Self {
2017-05-18 15:08:55 +03:00
let mut externals = HashMap::new();
externals.insert(name, module);
ExecutionParams {
args: Vec::new(),
externals: externals,
}
}
2017-05-19 09:36:50 +03:00
/// Add argument.
pub fn add_argument(mut self, arg: RuntimeValue) -> Self {
self.args.push(arg);
self
}
2017-05-18 15:08:55 +03:00
}
2017-08-01 16:15:08 +03:00
impl<'a, E> Default for ExecutionParams<'a, E> where E: UserError {
fn default() -> Self {
ExecutionParams {
args: Vec::default(),
externals: HashMap::default(),
}
}
}
2017-08-01 16:15:08 +03:00
impl<'a, E> From<Vec<RuntimeValue>> for ExecutionParams<'a, E> where E: UserError {
fn from(args: Vec<RuntimeValue>) -> ExecutionParams<'a, E> {
2017-05-18 15:08:55 +03:00
ExecutionParams {
args: args,
externals: HashMap::new(),
}
}
2017-04-28 13:34:58 +03:00
}
2017-08-01 16:15:08 +03:00
impl<E> ModuleInstance<E> where E: UserError {
2017-04-21 14:35:12 +03:00
/// Instantiate given module within program context.
2017-08-01 14:44:33 +03:00
pub fn new<'a>(program: Weak<ProgramInstanceEssence<E>>, name: String, module: Module) -> Result<Self, Error<E>> {
2017-04-21 14:35:12 +03:00
// load entries from import section
let imports = ModuleImports::new(program, module.import_section());
// instantiate linear memory regions, if any
2017-05-04 10:58:16 +03:00
let memory = match module.memory_section() {
2017-04-21 14:35:12 +03:00
Some(memory_section) => memory_section.entries()
2017-06-21 11:35:09 +03:00
.iter()
.map(MemoryInstance::new)
.collect::<Result<Vec<_>, _>>()?,
2017-04-21 14:35:12 +03:00
None => Vec::new(),
};
// instantiate tables, if any
2017-05-04 10:58:16 +03:00
let tables = match module.table_section() {
2017-04-21 14:35:12 +03:00
Some(table_section) => table_section.entries()
2017-06-21 11:35:09 +03:00
.iter()
.map(|tt| TableInstance::new(tt))
.collect::<Result<Vec<_>, _>>()?,
2017-04-21 14:35:12 +03:00
None => Vec::new(),
};
// instantiate globals, if any
let globals = match module.global_section() {
Some(global_section) => global_section.entries()
2017-06-21 11:35:09 +03:00
.iter()
.map(|g| {
get_initializer(g.init_expr(), &module, &imports, g.global_type().content_type().into())
.map_err(|e| Error::Initialization(e.into()))
.and_then(|v| VariableInstance::new_global(g.global_type(), v).map(Arc::new))
})
.collect::<Result<Vec<_>, _>>()?,
2017-04-21 14:35:12 +03:00
None => Vec::new(),
};
2017-06-13 12:01:59 +03:00
Ok(ModuleInstance {
name: name,
2017-04-21 14:35:12 +03:00
module: module,
imports: imports,
2017-06-28 11:03:01 +03:00
exports: HashMap::new(),
2017-06-22 17:52:05 +03:00
functions_labels: HashMap::new(),
2017-04-21 14:35:12 +03:00
memory: memory,
tables: tables,
globals: globals,
2017-06-13 12:01:59 +03:00
})
}
/// Run instantiation-time procedures (validation). Module is not completely validated until this call.
2017-08-01 14:44:33 +03:00
pub fn instantiate<'a>(&mut self, externals: Option<&'a HashMap<String, Arc<ModuleInstanceInterface<E> + 'a>>>) -> Result<(), Error<E>> {
2017-06-08 10:49:32 +03:00
// validate start section
if let Some(start_function) = self.module.start_section() {
2017-06-09 12:13:35 +03:00
let func_type_index = self.require_function(ItemIndex::IndexSpace(start_function))?;
let func_type = self.function_type_by_index(func_type_index)?;
if func_type.return_type() != None || func_type.params().len() != 0 {
return Err(Error::Validation("start function expected to have type [] -> []".into()));
2017-06-09 12:13:35 +03:00
}
2017-06-08 10:49:32 +03:00
}
// validate export section
2017-07-25 15:26:31 +03:00
if let Some(export_section) = self.module.export_section() {
for export in export_section.entries() {
match export.internal() {
&Internal::Function(function_index) => {
self.require_function(ItemIndex::IndexSpace(function_index)).map(|_| ())?;
self.exports.entry(export.field().into()).or_insert_with(Default::default).push(Internal::Function(function_index));
},
&Internal::Global(global_index) => {
2017-07-31 11:58:24 +03:00
self.global(ItemIndex::IndexSpace(global_index), None, externals)
.and_then(|g| if g.is_mutable() {
2017-07-25 15:26:31 +03:00
Err(Error::Validation(format!("trying to export mutable global {}", export.field())))
} else {
Ok(())
})?;
self.exports.entry(export.field().into()).or_insert_with(Default::default).push(Internal::Global(global_index));
},
&Internal::Memory(memory_index) => {
self.memory(ItemIndex::IndexSpace(memory_index)).map(|_| ())?;
self.exports.entry(export.field().into()).or_insert_with(Default::default).push(Internal::Memory(memory_index));
},
&Internal::Table(table_index) => {
self.table(ItemIndex::IndexSpace(table_index)).map(|_| ())?;
self.exports.entry(export.field().into()).or_insert_with(Default::default).push(Internal::Table(table_index));
},
2017-06-08 10:49:32 +03:00
}
}
}
// validate import section
if let Some(import_section) = self.module.import_section() {
for import in import_section.entries() {
match import.external() {
2017-06-13 12:01:59 +03:00
// for functions we need to check if function type matches in both modules
&External::Function(ref function_type_index) => {
// External::Function points to function type in type section in this module
2017-06-19 11:01:59 +03:00
let import_function_type = self.function_type_by_index(*function_type_index)?;
2017-06-13 12:01:59 +03:00
// get export entry in external module
let external_module = self.imports.module(externals, import.module())?;
2017-06-19 12:35:17 +03:00
let export_entry = external_module.export_entry(import.field(), &ExportEntryType::Function(import_function_type.clone()))?;
2017-06-13 12:01:59 +03:00
// export entry points to function in function index space
// and Internal::Function points to type in type section
match export_entry {
Internal::Function(function_index) => {
external_module.function_type(ItemIndex::IndexSpace(function_index))?
}
_ => {
return Err(Error::Validation(format!(
"Export with name {} from module {} is not a function",
import.field(),
import.module()
)))
2017-06-26 11:54:17 +03:00
}
};
2017-08-21 17:49:36 +03:00
},
2017-06-08 10:49:32 +03:00
&External::Global(ref global_type) => if global_type.is_mutable() {
2017-06-13 12:01:59 +03:00
return Err(Error::Validation(format!("trying to import mutable global {}", import.field())));
} else {
self.imports.global(externals, import, Some(global_type.content_type().into()))?;
},
&External::Memory(ref memory_type) => {
let import_limits = memory_type.limits();
check_limits(import_limits)?;
let memory = self.imports.memory(externals, import)?;
let memory_limits = memory.limits();
// a linear-memory import's minimum length is required to be at most the imported linear memory's minimum length.
if import_limits.initial() > memory_limits.initial() {
return Err(Error::Validation(format!("trying to import memory with initial={} and import.initial={}", memory_limits.initial(), import_limits.initial())));
}
2017-09-04 12:25:23 +03:00
// not working because of wabt tests:
// a linear-memory import is required to have a maximum length if the imported linear memory has a maximum length.
2017-09-04 12:25:23 +03:00
// if present, a linear-memory import's maximum length is required to be at least the imported linear memory's maximum length.
match (memory_limits.maximum(), import_limits.maximum()) {
(Some(ml), Some(il)) if il < ml =>
return Err(Error::Validation(format!("trying to import memory with maximum={} and import.maximum={}", ml, il))),
_ => (),
}
2017-06-13 12:01:59 +03:00
},
&External::Table(ref table_type) => {
let import_limits = table_type.limits();
check_limits(import_limits)?;
let table = self.imports.table(externals, import)?;
let table_limits = table.limits();
// a table import's minimum length is required to be at most the imported table's minimum length.
if import_limits.initial() > table_limits.initial() {
return Err(Error::Validation(format!("trying to import table with initial={} and import.initial={}", table_limits.initial(), import_limits.initial())));
}
2017-09-04 12:25:23 +03:00
// not working because of wabt tests:
// a table import is required to have a maximum length if the imported table has a maximum length.
2017-09-04 12:25:23 +03:00
// if present, a table import's maximum length is required to be at least the imported table's maximum length.
match (table_limits.maximum(), import_limits.maximum()) {
(Some(ml), Some(il)) if il < ml =>
return Err(Error::Validation(format!("trying to import table with maximum={} and import.maximum={}", ml, il))),
_ => (),
}
2017-06-08 10:49:32 +03:00
},
}
}
}
// there must be no greater than 1 table in tables index space
if self.imports.tables_len() + self.tables.len() > 1 {
return Err(Error::Validation(format!("too many tables in index space: {}", self.imports.tables_len() + self.tables.len())));
}
// there must be no greater than 1 memory region in memory regions index space
if self.imports.memory_regions_len() + self.memory.len() > 1 {
return Err(Error::Validation(format!("too many memory regions in index space: {}", self.imports.memory_regions_len() + self.memory.len())));
}
// for every function section entry there must be corresponding entry in code section and type && vice versa
let function_section_len = self.module.function_section().map(|s| s.entries().len()).unwrap_or(0);
let code_section_len = self.module.code_section().map(|s| s.bodies().len()).unwrap_or(0);
if function_section_len != code_section_len {
return Err(Error::Validation(format!("length of function section is {}, while len of code section is {}", function_section_len, code_section_len)));
}
// validate every function body in user modules
if function_section_len != 0 { // tests use invalid code
2017-06-08 10:49:32 +03:00
let function_section = self.module.function_section().expect("function_section_len != 0; qed");
let code_section = self.module.code_section().expect("function_section_len != 0; function_section_len == code_section_len; qed");
// check every function body
for (index, function) in function_section.entries().iter().enumerate() {
let function_labels = {
2017-06-26 11:54:17 +03:00
let function_type = self.function_type_by_index(function.type_ref())?;
let function_body = code_section.bodies().get(index as usize).ok_or(Error::Validation(format!("Missing body for function {}", index)))?;
let mut locals = function_type.params().to_vec();
locals.extend(function_body.locals().iter().flat_map(|l| repeat(l.value_type()).take(l.count() as usize)));
let mut context = FunctionValidationContext::new(
self,
2017-07-31 11:58:24 +03:00
externals,
2017-08-21 17:49:36 +03:00
&locals,
DEFAULT_VALUE_STACK_LIMIT,
DEFAULT_FRAME_STACK_LIMIT,
2017-06-26 11:54:17 +03:00
function_type.clone());
let block_type = function_type.return_type().map(BlockType::Value).unwrap_or(BlockType::NoResult);
Validator::validate_function(&mut context, block_type, function_body.code().elements())
2017-08-21 17:49:36 +03:00
.map_err(|e| {
if let Error::Validation(msg) = e {
Error::Validation(format!("Function #{} validation error: {}", index, msg))
} else {
e
}
})?;
context.function_labels()
};
self.functions_labels.insert(index as u32, function_labels);
2017-06-07 14:48:02 +03:00
}
}
2017-05-04 11:25:25 +03:00
// use data section to initialize linear memory regions
if let Some(data_section) = self.module.data_section() {
for (data_segment_index, data_segment) in data_section.entries().iter().enumerate() {
2017-06-13 12:01:59 +03:00
let offset: u32 = get_initializer(data_segment.offset(), &self.module, &self.imports, VariableType::I32)?.try_into()?;
2017-05-04 11:25:25 +03:00
self.memory(ItemIndex::IndexSpace(data_segment.index()))
.map_err(|e| Error::Initialization(format!("DataSegment {} initializes non-existant MemoryInstance {}: {:?}", data_segment_index, data_segment.index(), e)))
.and_then(|m| m.set(offset, data_segment.value()))
.map_err(|e| Error::Initialization(e.into()))?;
}
}
// use element section to fill tables
if let Some(element_section) = self.module.elements_section() {
for (element_segment_index, element_segment) in element_section.entries().iter().enumerate() {
2017-06-13 12:01:59 +03:00
let offset: u32 = get_initializer(element_segment.offset(), &self.module, &self.imports, VariableType::I32)?.try_into()?;
2017-06-08 10:49:32 +03:00
for function_index in element_segment.members() {
self.require_function(ItemIndex::IndexSpace(*function_index))?;
}
2017-05-04 11:25:25 +03:00
self.table(ItemIndex::IndexSpace(element_segment.index()))
.map_err(|e| Error::Initialization(format!("ElementSegment {} initializes non-existant Table {}: {:?}", element_segment_index, element_segment.index(), e)))
2017-06-13 12:01:59 +03:00
.and_then(|m| m.set_raw(offset, self.name.clone(), element_segment.members()))
2017-05-04 11:25:25 +03:00
.map_err(|e| Error::Initialization(e.into()))?;
}
}
2017-06-22 17:52:05 +03:00
Ok(())
}
/// Run start function [if any].
2017-08-01 14:44:33 +03:00
pub fn run_start_function(&self) -> Result<(), Error<E>> {
2017-06-09 12:13:35 +03:00
// execute start function (if any)
if let Some(start_function) = self.module.start_section() {
self.execute_index(start_function, ExecutionParams::default())?;
}
2017-05-04 11:25:25 +03:00
Ok(())
}
2017-06-08 10:49:32 +03:00
2017-08-01 14:44:33 +03:00
fn self_ref<'a>(&self, externals: Option<&'a HashMap<String, Arc<ModuleInstanceInterface<E> + 'a>>>) -> Result<Arc<ModuleInstanceInterface<E> + 'a>, Error<E>> {
2017-06-23 14:11:09 +03:00
self.imports.module(externals, &self.name)
2017-06-22 17:52:05 +03:00
}
2017-08-01 14:44:33 +03:00
fn require_function(&self, index: ItemIndex) -> Result<u32, Error<E>> {
2017-06-22 17:52:05 +03:00
match self.imports.parse_function_index(index) {
ItemIndex::IndexSpace(_) => unreachable!("parse_function_index resolves IndexSpace option"),
ItemIndex::Internal(index) => self.module.function_section()
.ok_or(Error::Function(format!("missing internal function {}", index)))
.and_then(|s| s.entries().get(index as usize)
.ok_or(Error::Function(format!("missing internal function {}", index))))
.map(|f| f.type_ref()),
ItemIndex::External(index) => self.module.import_section()
.ok_or(Error::Function(format!("missing external function {}", index)))
.and_then(|s| s.entries().get(index as usize)
.ok_or(Error::Function(format!("missing external function {}", index))))
.and_then(|import| match import.external() {
&External::Function(type_idx) => Ok(type_idx),
_ => Err(Error::Function(format!("external function {} is pointing to non-function import", index))),
}),
}
}
}
2017-08-01 16:15:08 +03:00
impl<E> ModuleInstanceInterface<E> for ModuleInstance<E> where E: UserError {
2017-08-01 14:44:33 +03:00
fn execute_index(&self, index: u32, params: ExecutionParams<E>) -> Result<Option<RuntimeValue>, Error<E>> {
2017-06-16 12:23:49 +03:00
let ExecutionParams { args, externals } = params;
let mut args = StackWithLimit::with_data(args, DEFAULT_VALUE_STACK_LIMIT);
let function_reference = self.function_reference(ItemIndex::IndexSpace(index), Some(&externals))?;
let function_context = CallerContext::topmost(&mut args, &externals);
2017-06-19 12:04:16 +03:00
function_reference.module.call_internal_function(function_context, function_reference.internal_index)
2017-04-27 14:44:03 +03:00
}
2017-08-01 14:44:33 +03:00
fn execute_export(&self, name: &str, params: ExecutionParams<E>) -> Result<Option<RuntimeValue>, Error<E>> {
2017-06-28 11:03:01 +03:00
let index = self.exports.get(name)
2017-07-31 11:58:24 +03:00
.ok_or(Error::Function(format!("missing executable export with name {}", name)))
2017-06-28 11:03:01 +03:00
.and_then(|l| l.iter()
.find(|i| match i {
&&Internal::Function(_) => true,
2017-05-04 19:09:43 +03:00
_ => false,
})
2017-06-28 11:03:01 +03:00
.ok_or(Error::Function(format!("missing exported function with name {}", name)))
.map(|i| match i {
2017-05-04 19:09:43 +03:00
&Internal::Function(index) => index,
_ => unreachable!(), // checked couple of lines above
})
)?;
2017-05-18 15:08:55 +03:00
self.execute_index(index, params)
2017-05-04 19:09:43 +03:00
}
2017-08-01 14:44:33 +03:00
fn export_entry<'a>(&self, name: &str, required_type: &ExportEntryType) -> Result<Internal, Error<E>> {
2017-06-28 11:03:01 +03:00
self.exports.get(name)
2017-07-31 11:58:24 +03:00
.ok_or(Error::Function(format!("missing export entry with name {}", name)))
2017-06-28 11:03:01 +03:00
.and_then(|l| l.iter()
.find(|i| match required_type {
2017-06-13 12:01:59 +03:00
&ExportEntryType::Any => true,
2017-06-28 11:03:01 +03:00
&ExportEntryType::Global(global_type) => match i {
2017-07-31 11:58:24 +03:00
&&Internal::Global(global_index) => self.global(ItemIndex::IndexSpace(global_index), Some(global_type), None).map(|_| true).unwrap_or(false),
2017-06-13 12:01:59 +03:00
_ => false,
},
2017-06-28 11:03:01 +03:00
&ExportEntryType::Function(ref required_type) => match i {
&&Internal::Function(function_index) =>
2017-06-19 12:35:17 +03:00
self.function_type(ItemIndex::IndexSpace(function_index))
2017-06-26 11:54:17 +03:00
.map(|ft| ft == *required_type)
2017-06-13 12:01:59 +03:00
.unwrap_or(false),
_ => false,
},
})
2017-06-28 11:03:01 +03:00
.map(|i| *i)
2017-08-21 17:49:36 +03:00
.ok_or(Error::Program(format!("unresolved export {}", name))))
2017-04-21 14:35:12 +03:00
}
2017-08-01 14:44:33 +03:00
fn table(&self, index: ItemIndex) -> Result<Arc<TableInstance<E>>, Error<E>> {
2017-04-21 14:35:12 +03:00
match self.imports.parse_table_index(index) {
ItemIndex::IndexSpace(_) => unreachable!("parse_table_index resolves IndexSpace option"),
ItemIndex::Internal(index) => self.tables.get(index as usize).cloned()
.ok_or(Error::Table(format!("trying to access table with local index {} when there are only {} local tables", index, self.tables.len()))),
ItemIndex::External(index) => self.module.import_section()
.ok_or(Error::Table(format!("trying to access external table with index {} in module without import section", index)))
.and_then(|s| s.entries().get(index as usize)
.ok_or(Error::Table(format!("trying to access external table with index {} in module with {}-entries import section", index, s.entries().len()))))
2017-05-18 15:08:55 +03:00
.and_then(|e| self.imports.table(None, e)),
2017-04-21 14:35:12 +03:00
}
}
2017-08-01 14:44:33 +03:00
fn memory(&self, index: ItemIndex) -> Result<Arc<MemoryInstance<E>>, Error<E>> {
2017-04-21 14:35:12 +03:00
match self.imports.parse_memory_index(index) {
ItemIndex::IndexSpace(_) => unreachable!("parse_memory_index resolves IndexSpace option"),
ItemIndex::Internal(index) => self.memory.get(index as usize).cloned()
.ok_or(Error::Memory(format!("trying to access memory with local index {} when there are only {} memory regions", index, self.memory.len()))),
ItemIndex::External(index) => self.module.import_section()
.ok_or(Error::Memory(format!("trying to access external memory with index {} in module without import section", index)))
.and_then(|s| s.entries().get(index as usize)
.ok_or(Error::Memory(format!("trying to access external memory with index {} in module with {}-entries import section", index, s.entries().len()))))
2017-05-18 15:08:55 +03:00
.and_then(|e| self.imports.memory(None, e)),
2017-04-21 14:35:12 +03:00
}
}
2017-08-01 14:44:33 +03:00
fn global<'a>(&self, index: ItemIndex, variable_type: Option<VariableType>, externals: Option<&'a HashMap<String, Arc<ModuleInstanceInterface<E> + 'a>>>) -> Result<Arc<VariableInstance<E>>, Error<E>> {
2017-04-21 14:35:12 +03:00
match self.imports.parse_global_index(index) {
ItemIndex::IndexSpace(_) => unreachable!("parse_global_index resolves IndexSpace option"),
ItemIndex::Internal(index) => self.globals.get(index as usize).cloned()
.ok_or(Error::Global(format!("trying to access global with local index {} when there are only {} globals", index, self.globals.len()))),
ItemIndex::External(index) => self.module.import_section()
.ok_or(Error::Global(format!("trying to access external global with index {} in module without import section", index)))
.and_then(|s| s.entries().get(index as usize)
.ok_or(Error::Global(format!("trying to access external global with index {} in module with {}-entries import section", index, s.entries().len()))))
2017-07-31 11:58:24 +03:00
.and_then(|e| self.imports.global(externals, e, variable_type)),
2017-04-21 14:35:12 +03:00
}
}
2017-08-01 14:44:33 +03:00
fn function_type(&self, function_index: ItemIndex) -> Result<FunctionSignature, Error<E>> {
2017-06-19 12:04:16 +03:00
match self.imports.parse_function_index(function_index) {
ItemIndex::IndexSpace(_) => unreachable!("parse_function_index resolves IndexSpace option"),
ItemIndex::Internal(index) => self.require_function(ItemIndex::Internal(index))
.and_then(|ft| self.function_type_by_index(ft)),
ItemIndex::External(index) => self.module.import_section()
.ok_or(Error::Function(format!("trying to access external function with index {} in module without import section", index)))
.and_then(|s| s.entries().get(index as usize)
.ok_or(Error::Function(format!("trying to access external function with index {} in module with {}-entries import section", index, s.entries().len()))))
.and_then(|e| match e.external() {
&External::Function(type_index) => self.function_type_by_index(type_index),
_ => Err(Error::Function(format!("exported function {} is not a function", index))),
}),
}
}
2017-08-01 14:44:33 +03:00
fn function_type_by_index(&self, type_index: u32) -> Result<FunctionSignature, Error<E>> {
2017-06-19 12:04:16 +03:00
self.module.type_section()
.ok_or(Error::Validation(format!("type reference {} exists in module without type section", type_index)))
.and_then(|s| match s.types().get(type_index as usize) {
Some(&Type::Function(ref function_type)) => Ok(function_type),
_ => Err(Error::Validation(format!("missing function type with index {}", type_index))),
})
2017-06-26 11:54:17 +03:00
.map(FunctionSignature::Module)
2017-06-19 12:04:16 +03:00
}
2017-08-01 14:44:33 +03:00
fn function_reference<'a>(&self, index: ItemIndex, externals: Option<&'a HashMap<String, Arc<ModuleInstanceInterface<E> + 'a>>>) -> Result<InternalFunctionReference<'a, E>, Error<E>> {
2017-04-21 14:35:12 +03:00
match self.imports.parse_function_index(index) {
ItemIndex::IndexSpace(_) => unreachable!("parse_function_index resolves IndexSpace option"),
2017-06-16 12:23:49 +03:00
ItemIndex::Internal(index) => Ok(InternalFunctionReference {
module: self.self_ref(externals)?,
internal_index: index,
}),
ItemIndex::External(index) => {
2017-06-19 12:04:16 +03:00
let import_entry = self.module.import_section()
.expect("parse_function_index has returned External(index); it is only returned when import section exists; qed")
.entries().get(index as usize)
.expect("parse_function_index has returned External(index); it is only returned when entry with index exists in import section exists; qed");
2017-06-19 12:35:17 +03:00
let required_function_type = self.function_type(ItemIndex::External(index))?;
2017-06-26 11:54:17 +03:00
let internal_function_index = self.imports.function(externals, import_entry, Some(required_function_type))?;
2017-06-16 12:23:49 +03:00
Ok(InternalFunctionReference {
module: self.imports.module(externals, import_entry.module())?,
2017-06-19 11:01:59 +03:00
internal_index: internal_function_index,
2017-06-16 12:23:49 +03:00
})
},
2017-04-21 14:35:12 +03:00
}
}
2017-04-26 15:41:22 +03:00
2017-08-01 14:44:33 +03:00
fn function_reference_indirect<'a>(&self, table_idx: u32, type_idx: u32, func_idx: u32, externals: Option<&'a HashMap<String, Arc<ModuleInstanceInterface<E> + 'a>>>) -> Result<InternalFunctionReference<'a, E>, Error<E>> {
2017-06-16 12:23:49 +03:00
let table = self.table(ItemIndex::IndexSpace(table_idx))?;
let (module, index) = match table.get(func_idx)? {
2017-06-13 12:01:59 +03:00
RuntimeValue::AnyFunc(module, index) => (module.clone(), index),
2017-06-16 12:23:49 +03:00
_ => return Err(Error::Function(format!("trying to indirect call function {} via non-anyfunc table {:?}", func_idx, table_idx))),
2017-06-13 12:01:59 +03:00
};
2017-06-16 12:23:49 +03:00
let module = self.imports.module(externals, &module)?;
2017-06-19 12:04:16 +03:00
let required_function_type = self.function_type_by_index(type_idx)?;
2017-06-19 12:35:17 +03:00
let actual_function_type = module.function_type(ItemIndex::IndexSpace(index))?;
2017-06-19 12:04:16 +03:00
if required_function_type != actual_function_type {
return Err(Error::Function(format!("expected indirect function with signature ({:?}) -> {:?} when got with ({:?}) -> {:?}",
required_function_type.params(), required_function_type.return_type(),
actual_function_type.params(), actual_function_type.return_type())));
}
2017-06-16 12:23:49 +03:00
module.function_reference(ItemIndex::IndexSpace(index), externals)
2017-04-26 15:41:22 +03:00
}
2017-05-02 08:37:48 +03:00
2017-08-01 14:44:33 +03:00
fn function_body<'a>(&'a self, internal_index: u32) -> Result<Option<InternalFunction<'a>>, Error<E>> {
2017-05-02 08:37:48 +03:00
let function_body = self.module
.code_section()
2017-06-16 12:23:49 +03:00
.ok_or(Error::Function(format!("trying to call function with index {} in module without code section", internal_index)))
2017-05-02 08:37:48 +03:00
.and_then(|s| s.bodies()
2017-06-16 12:23:49 +03:00
.get(internal_index as usize)
.ok_or(Error::Function(format!("trying to call function with index {} in module with {} functions codes", internal_index, s.bodies().len()))))?;
2017-06-22 17:52:05 +03:00
let function_labels = self.functions_labels.get(&internal_index)
.ok_or(Error::Function(format!("trying to call non-validated internal function {}", internal_index)))?;
2017-06-16 12:23:49 +03:00
Ok(Some(InternalFunction {
locals: function_body.locals(),
body: function_body.code().elements(),
2017-06-22 17:52:05 +03:00
labels: function_labels,
2017-06-16 12:23:49 +03:00
}))
}
fn call_internal_function(&self, outer: CallerContext<E>, index: u32) -> Result<Option<RuntimeValue>, Error<E>> {
2017-06-19 12:35:17 +03:00
let function_type = self.function_type(ItemIndex::Internal(index))?;
let args = prepare_function_args(&function_type, outer.value_stack)?;
2017-06-16 12:23:49 +03:00
let function_ref = InternalFunctionReference { module: self.self_ref(Some(outer.externals))?, internal_index: index };
2017-06-26 12:28:21 +03:00
let inner = FunctionContext::new(function_ref, outer.externals, outer.value_stack_limit, outer.frame_stack_limit, &function_type, args);
2017-06-16 12:23:49 +03:00
Interpreter::run_function(inner)
2017-05-02 08:37:48 +03:00
}
2017-04-21 14:35:12 +03:00
}
2017-08-01 16:15:08 +03:00
impl<'a, E> CallerContext<'a, E> where E: UserError {
2017-05-15 15:40:08 +03:00
/// Top most args
2017-08-01 14:44:33 +03:00
pub fn topmost(args: &'a mut StackWithLimit<RuntimeValue, E>, externals: &'a HashMap<String, Arc<ModuleInstanceInterface<E> + 'a>>) -> Self {
2017-04-28 13:34:58 +03:00
CallerContext {
2017-06-07 14:48:02 +03:00
value_stack_limit: DEFAULT_VALUE_STACK_LIMIT,
frame_stack_limit: DEFAULT_FRAME_STACK_LIMIT,
2017-04-28 13:34:58 +03:00
value_stack: args,
2017-05-18 15:08:55 +03:00
externals: externals,
2017-04-28 13:34:58 +03:00
}
}
2017-05-15 15:40:08 +03:00
/// Nested context
pub fn nested(outer: &'a mut FunctionContext<E>) -> Self {
2017-04-28 13:34:58 +03:00
CallerContext {
value_stack_limit: outer.value_stack().limit() - outer.value_stack().len(),
frame_stack_limit: outer.frame_stack().limit() - outer.frame_stack().len(),
2017-05-18 15:08:55 +03:00
value_stack: &mut outer.value_stack,
externals: &outer.externals,
2017-04-28 13:34:58 +03:00
}
}
}
2017-08-01 16:15:08 +03:00
pub fn check_limits<E: UserError>(limits: &ResizableLimits) -> Result<(), Error<E>> {
2017-06-08 10:49:32 +03:00
if let Some(maximum) = limits.maximum() {
if maximum < limits.initial() {
return Err(Error::Validation(format!("maximum limit {} is lesser than minimum {}", maximum, limits.initial())));
}
}
Ok(())
}
2017-08-01 16:15:08 +03:00
fn get_initializer<E: UserError>(expr: &InitExpr, module: &Module, imports: &ModuleImports<E>, expected_type: VariableType) -> Result<RuntimeValue, Error<E>> {
2017-06-09 12:13:35 +03:00
let first_opcode = match expr.code().len() {
1 => &expr.code()[0],
2 if expr.code().len() == 2 && expr.code()[1] == Opcode::End => &expr.code()[0],
_ => return Err(Error::Initialization(format!("expected 1-instruction len initializer. Got {:?}", expr.code()))),
};
2017-04-21 14:35:12 +03:00
match first_opcode {
2017-05-04 19:09:43 +03:00
&Opcode::GetGlobal(index) => {
let index = match imports.parse_global_index(ItemIndex::IndexSpace(index)) {
ItemIndex::External(index) => index,
_ => return Err(Error::Global(format!("trying to initialize with non-external global {}", index))),
};
module.import_section()
.ok_or(Error::Global(format!("trying to initialize with external global with index {} in module without import section", index)))
.and_then(|s| s.entries().get(index as usize)
.ok_or(Error::Global(format!("trying to initialize with external global with index {} in module with {}-entries import section", index, s.entries().len()))))
2017-06-13 12:01:59 +03:00
.and_then(|e| imports.global(None, e, Some(expected_type)))
2017-05-04 19:09:43 +03:00
.map(|g| g.get())
},
2017-04-21 14:35:12 +03:00
&Opcode::I32Const(val) => Ok(RuntimeValue::I32(val)),
&Opcode::I64Const(val) => Ok(RuntimeValue::I64(val)),
2017-05-31 18:43:09 +02:00
&Opcode::F32Const(val) => Ok(RuntimeValue::decode_f32(val)),
&Opcode::F64Const(val) => Ok(RuntimeValue::decode_f64(val)),
2017-04-21 14:35:12 +03:00
_ => Err(Error::Initialization(format!("not-supported {:?} instruction in instantiation-time initializer", first_opcode))),
}
}
2017-06-26 11:54:17 +03:00
impl<'a> FunctionSignature<'a> {
2017-06-28 11:03:01 +03:00
/// Get return type of this function.
2017-06-26 11:54:17 +03:00
pub fn return_type(&self) -> Option<ValueType> {
match self {
&FunctionSignature::Module(ft) => ft.return_type(),
&FunctionSignature::User(fd) => fd.return_type(),
}
}
2017-06-28 11:03:01 +03:00
/// Get parameters of this function.
2017-06-26 11:54:17 +03:00
pub fn params(&self) -> &[ValueType] {
match self {
&FunctionSignature::Module(ft) => ft.params(),
&FunctionSignature::User(fd) => fd.params(),
}
}
}
impl<'a> PartialEq for FunctionSignature<'a> {
fn eq<'b>(&self, other: &FunctionSignature<'b>) -> bool {
match self {
&FunctionSignature::Module(ft1) => match other {
&FunctionSignature::Module(ft2) => ft1 == ft2,
&FunctionSignature::User(ft2) => ft1.params() == ft2.params() && ft1.return_type() == ft2.return_type(),
},
&FunctionSignature::User(ft1) => match other {
&FunctionSignature::User(ft2) => ft1 == ft2,
&FunctionSignature::Module(ft2) => ft1.params() == ft2.params() && ft1.return_type() == ft2.return_type(),
},
}
}
}
impl<'a> From<&'a FunctionType> for FunctionSignature<'a> {
fn from(other: &'a FunctionType) -> Self {
FunctionSignature::Module(other)
}
}