622 lines
17 KiB
Rust
Raw Normal View History

2017-12-13 18:31:40 +01:00
use std::rc::Rc;
use std::cell::RefCell;
2017-12-15 18:23:54 +03:00
use std::fmt;
2017-12-13 18:31:40 +01:00
use std::collections::HashMap;
use std::borrow::Cow;
2017-12-18 16:12:59 +03:00
use elements::{External, FunctionType, GlobalType, InitExpr, Internal, MemoryType, Module, Opcode,
2017-12-18 16:46:04 +03:00
ResizableLimits, TableType, Type};
2017-12-13 18:31:40 +01:00
use interpreter::{Error, MemoryInstance, RuntimeValue, TableInstance};
use interpreter::imports::{ImportResolver, Imports};
2018-01-05 16:22:20 +03:00
use interpreter::global::{GlobalInstance, GlobalRef};
use interpreter::func::{FuncRef, FuncBody, FuncInstance};
use interpreter::table::TableRef;
2017-12-19 20:46:05 +03:00
use interpreter::state::HostState;
2018-01-05 16:22:20 +03:00
use interpreter::memory::MemoryRef;
2017-12-13 18:31:40 +01:00
use validation::validate_module;
use common::{DEFAULT_MEMORY_INDEX, DEFAULT_TABLE_INDEX};
2017-12-19 20:46:05 +03:00
pub enum ExternVal {
2018-01-05 13:10:01 +03:00
Func(FuncRef),
Table(TableRef),
Memory(MemoryRef),
Global(GlobalRef),
2017-12-13 18:31:40 +01:00
}
2017-12-19 20:46:05 +03:00
impl Clone for ExternVal {
2017-12-15 18:23:54 +03:00
fn clone(&self) -> Self {
match *self {
2018-01-05 16:22:20 +03:00
ExternVal::Func(ref func) => ExternVal::Func(func.clone()),
ExternVal::Table(ref table) => ExternVal::Table(table.clone()),
ExternVal::Memory(ref memory) => ExternVal::Memory(memory.clone()),
ExternVal::Global(ref global) => ExternVal::Global(global.clone()),
2017-12-15 18:23:54 +03:00
}
}
}
2017-12-19 20:46:05 +03:00
impl fmt::Debug for ExternVal {
2017-12-15 18:23:54 +03:00
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
2017-12-18 16:12:59 +03:00
write!(
f,
"ExternVal {{ {} }}",
match *self {
ExternVal::Func(_) => "Func",
ExternVal::Table(_) => "Table",
ExternVal::Memory(_) => "Memory",
ExternVal::Global(_) => "Global",
}
)
2017-12-15 18:23:54 +03:00
}
}
2017-12-19 20:46:05 +03:00
impl ExternVal {
2018-01-05 13:10:01 +03:00
pub fn as_func(&self) -> Option<FuncRef> {
2017-12-13 18:31:40 +01:00
match *self {
2018-01-05 16:22:20 +03:00
ExternVal::Func(ref func) => Some(func.clone()),
2017-12-13 18:31:40 +01:00
_ => None,
}
}
2018-01-05 13:10:01 +03:00
pub fn as_table(&self) -> Option<TableRef> {
2017-12-13 18:31:40 +01:00
match *self {
2018-01-05 16:22:20 +03:00
ExternVal::Table(ref table) => Some(table.clone()),
2017-12-13 18:31:40 +01:00
_ => None,
}
}
2018-01-05 13:10:01 +03:00
pub fn as_memory(&self) -> Option<MemoryRef> {
2017-12-13 18:31:40 +01:00
match *self {
2018-01-05 16:22:20 +03:00
ExternVal::Memory(ref memory) => Some(memory.clone()),
2017-12-13 18:31:40 +01:00
_ => None,
}
}
2018-01-05 13:10:01 +03:00
pub fn as_global(&self) -> Option<GlobalRef> {
2017-12-13 18:31:40 +01:00
match *self {
2018-01-05 16:22:20 +03:00
ExternVal::Global(ref global) => Some(global.clone()),
2017-12-13 18:31:40 +01:00
_ => None,
}
}
}
2017-12-18 12:59:59 +03:00
#[derive(Debug)]
2017-12-19 20:46:05 +03:00
pub struct ModuleInstance {
2017-12-13 18:31:40 +01:00
types: RefCell<Vec<Rc<FunctionType>>>,
2018-01-05 13:10:01 +03:00
tables: RefCell<Vec<TableRef>>,
funcs: RefCell<Vec<FuncRef>>,
memories: RefCell<Vec<MemoryRef>>,
globals: RefCell<Vec<GlobalRef>>,
2017-12-19 20:46:05 +03:00
exports: RefCell<HashMap<String, ExternVal>>,
2017-12-13 18:31:40 +01:00
}
2017-12-19 20:46:05 +03:00
impl Default for ModuleInstance {
2017-12-18 12:59:59 +03:00
fn default() -> Self {
2017-12-13 18:31:40 +01:00
ModuleInstance {
2017-12-15 18:23:54 +03:00
types: RefCell::new(Vec::new()),
tables: RefCell::new(Vec::new()),
funcs: RefCell::new(Vec::new()),
memories: RefCell::new(Vec::new()),
globals: RefCell::new(Vec::new()),
exports: RefCell::new(HashMap::new()),
2017-12-13 18:31:40 +01:00
}
}
2017-12-18 12:59:59 +03:00
}
2017-12-13 18:31:40 +01:00
2017-12-19 20:46:05 +03:00
impl ModuleInstance {
pub fn with_exports(exports: HashMap<String, ExternVal>) -> Self {
2017-12-18 12:59:59 +03:00
let mut instance = Self::default();
2017-12-15 18:23:54 +03:00
instance.exports = RefCell::new(exports);
instance
}
2018-01-05 13:10:01 +03:00
pub fn memory_by_index(&self, idx: u32) -> Option<MemoryRef> {
2017-12-13 18:31:40 +01:00
self.memories.borrow().get(idx as usize).cloned()
}
2018-01-05 13:10:01 +03:00
pub fn table_by_index(&self, idx: u32) -> Option<TableRef> {
2017-12-13 18:31:40 +01:00
self.tables.borrow().get(idx as usize).cloned()
}
2018-01-05 13:10:01 +03:00
pub fn global_by_index(&self, idx: u32) -> Option<GlobalRef> {
2017-12-13 18:31:40 +01:00
self.globals.borrow().get(idx as usize).cloned()
}
2018-01-05 13:10:01 +03:00
pub fn func_by_index(&self, idx: u32) -> Option<FuncRef> {
2017-12-13 18:31:40 +01:00
self.funcs.borrow().get(idx as usize).cloned()
}
pub fn type_by_index(&self, idx: u32) -> Option<Rc<FunctionType>> {
self.types.borrow().get(idx as usize).cloned()
}
2017-12-19 20:46:05 +03:00
pub fn export_by_name(&self, name: &str) -> Option<ExternVal> {
2017-12-13 18:31:40 +01:00
self.exports.borrow().get(name).cloned()
}
2018-01-05 13:10:01 +03:00
fn push_func(&self, func: FuncRef) {
2017-12-13 18:31:40 +01:00
self.funcs.borrow_mut().push(func);
}
fn push_type(&self, func_type: Rc<FunctionType>) {
self.types.borrow_mut().push(func_type)
}
2018-01-05 13:10:01 +03:00
fn push_memory(&self, memory: MemoryRef) {
2017-12-13 18:31:40 +01:00
self.memories.borrow_mut().push(memory)
}
2018-01-05 13:10:01 +03:00
fn push_table(&self, table: TableRef) {
2017-12-13 18:31:40 +01:00
self.tables.borrow_mut().push(table)
}
2018-01-05 13:10:01 +03:00
fn push_global(&self, global: GlobalRef) {
2017-12-13 18:31:40 +01:00
self.globals.borrow_mut().push(global)
}
2017-12-19 20:46:05 +03:00
fn insert_export<N: Into<String>>(&self, name: N, extern_val: ExternVal) {
2017-12-13 18:31:40 +01:00
self.exports.borrow_mut().insert(name.into(), extern_val);
}
2017-12-14 15:33:40 +01:00
fn alloc_module(
2017-12-13 18:31:40 +01:00
module: &Module,
2017-12-19 20:46:05 +03:00
extern_vals: &[ExternVal],
instance: &Rc<ModuleInstance>,
2017-12-13 18:31:40 +01:00
) -> Result<(), Error> {
let mut aux_data = validate_module(module)?;
for &Type::Function(ref ty) in module.type_section().map(|ts| ts.types()).unwrap_or(&[]) {
let type_id = alloc_func_type(ty.clone());
instance.push_type(type_id);
}
{
2017-12-18 16:46:04 +03:00
let imports = module.import_section().map(|is| is.entries()).unwrap_or(
&[],
);
2017-12-13 18:31:40 +01:00
if imports.len() != extern_vals.len() {
2017-12-18 20:31:47 +03:00
return Err(Error::Instantiation(format!(
2017-12-13 18:31:40 +01:00
"extern_vals length is not equal to import section entries"
)));
}
2017-12-18 16:46:04 +03:00
for (import, extern_val) in
Iterator::zip(imports.into_iter(), extern_vals.into_iter())
2017-12-13 18:31:40 +01:00
{
match (import.external(), extern_val) {
(&External::Function(fn_type_idx), &ExternVal::Func(ref func)) => {
2017-12-18 16:46:04 +03:00
let expected_fn_type = instance.type_by_index(fn_type_idx).expect(
"Due to validation function type should exists",
);
2017-12-13 18:31:40 +01:00
let actual_fn_type = func.func_type();
if expected_fn_type != actual_fn_type {
2017-12-18 20:31:47 +03:00
return Err(Error::Instantiation(format!(
2017-12-13 18:31:40 +01:00
"Expected function with type {:?}, but actual type is {:?} for entry {}",
expected_fn_type,
actual_fn_type,
import.field(),
)));
}
2018-01-05 16:22:20 +03:00
instance.push_func(func.clone())
2017-12-13 18:31:40 +01:00
}
(&External::Table(ref tt), &ExternVal::Table(ref table)) => {
match_limits(table.limits(), tt.limits())?;
2018-01-05 16:22:20 +03:00
instance.push_table(table.clone());
2017-12-13 18:31:40 +01:00
}
(&External::Memory(ref mt), &ExternVal::Memory(ref memory)) => {
match_limits(memory.limits(), mt.limits())?;
2018-01-05 16:22:20 +03:00
instance.push_memory(memory.clone());
2017-12-13 18:31:40 +01:00
}
2017-12-18 15:34:17 +03:00
(&External::Global(ref gl), &ExternVal::Global(ref global)) => {
if gl.content_type() != global.value_type() {
2017-12-18 20:31:47 +03:00
return Err(Error::Instantiation(format!(
2017-12-18 15:34:17 +03:00
"Expect global with {:?} type, but provided global with {:?} type",
gl.content_type(),
global.value_type(),
)));
}
2018-01-05 16:22:20 +03:00
instance.push_global(global.clone());
2017-12-13 18:31:40 +01:00
}
(expected_import, actual_extern_val) => {
2017-12-18 20:31:47 +03:00
return Err(Error::Instantiation(format!(
2017-12-13 18:31:40 +01:00
"Expected {:?} type, but provided {:?} extern_val",
expected_import,
actual_extern_val
)));
}
}
}
}
{
2017-12-18 16:46:04 +03:00
let funcs = module.function_section().map(|fs| fs.entries()).unwrap_or(
&[],
);
2017-12-13 18:31:40 +01:00
let bodies = module.code_section().map(|cs| cs.bodies()).unwrap_or(&[]);
debug_assert!(
funcs.len() == bodies.len(),
"Due to validation func and body counts must match"
);
for (index, (ty, body)) in
Iterator::zip(funcs.into_iter(), bodies.into_iter()).enumerate()
{
2017-12-18 16:46:04 +03:00
let func_type = instance.type_by_index(ty.type_ref()).expect(
"Due to validation type should exists",
);
2017-12-13 18:31:40 +01:00
let labels = aux_data.labels.remove(&index).expect(
"At func validation time labels are collected; Collected labels are added by index; qed",
);
let func_body = FuncBody {
locals: body.locals().to_vec(),
opcodes: body.code().clone(),
labels: labels,
};
2017-12-18 16:12:59 +03:00
let func_instance =
FuncInstance::alloc_internal(Rc::clone(instance), func_type, func_body);
2017-12-13 18:31:40 +01:00
instance.push_func(func_instance);
}
}
for table_type in module.table_section().map(|ts| ts.entries()).unwrap_or(&[]) {
2018-01-05 16:22:20 +03:00
let table = TableInstance::alloc(table_type)?;
2017-12-13 18:31:40 +01:00
instance.push_table(table);
}
2017-12-18 16:46:04 +03:00
for memory_type in module.memory_section().map(|ms| ms.entries()).unwrap_or(
&[],
)
2017-12-13 18:31:40 +01:00
{
2018-01-05 16:22:20 +03:00
let memory = MemoryInstance::alloc(memory_type)?;
2017-12-13 18:31:40 +01:00
instance.push_memory(memory);
}
2017-12-18 16:46:04 +03:00
for global_entry in module.global_section().map(|gs| gs.entries()).unwrap_or(
&[],
)
2017-12-13 18:31:40 +01:00
{
let init_val = eval_init_expr(global_entry.init_expr(), &*instance);
2018-01-05 16:22:20 +03:00
let global = GlobalInstance::alloc(global_entry.global_type(), init_val);
2017-12-13 18:31:40 +01:00
instance.push_global(global);
}
2017-12-18 16:46:04 +03:00
for export in module.export_section().map(|es| es.entries()).unwrap_or(
&[],
)
2017-12-13 18:31:40 +01:00
{
let field = export.field();
2017-12-19 20:46:05 +03:00
let extern_val: ExternVal = match *export.internal() {
2017-12-13 18:31:40 +01:00
Internal::Function(idx) => {
2017-12-18 16:46:04 +03:00
let func = instance.func_by_index(idx).expect(
"Due to validation func should exists",
);
2017-12-13 18:31:40 +01:00
ExternVal::Func(func)
}
Internal::Global(idx) => {
2017-12-18 16:46:04 +03:00
let global = instance.global_by_index(idx).expect(
"Due to validation global should exists",
);
2017-12-13 18:31:40 +01:00
ExternVal::Global(global)
}
Internal::Memory(idx) => {
2017-12-18 16:46:04 +03:00
let memory = instance.memory_by_index(idx).expect(
"Due to validation memory should exists",
);
2017-12-13 18:31:40 +01:00
ExternVal::Memory(memory)
}
Internal::Table(idx) => {
2017-12-18 16:46:04 +03:00
let table = instance.table_by_index(idx).expect(
"Due to validation table should exists",
);
2017-12-13 18:31:40 +01:00
ExternVal::Table(table)
}
};
instance.insert_export(field, extern_val);
}
Ok(())
}
2017-12-13 19:11:25 +01:00
fn instantiate_with_externvals(
2017-12-13 18:31:40 +01:00
module: &Module,
2017-12-19 20:46:05 +03:00
extern_vals: &[ExternVal],
) -> Result<Rc<ModuleInstance>, Error> {
2017-12-18 12:59:59 +03:00
let instance = Rc::new(ModuleInstance::default());
2017-12-13 18:31:40 +01:00
2017-12-14 15:33:40 +01:00
ModuleInstance::alloc_module(module, extern_vals, &instance)?;
2017-12-13 18:31:40 +01:00
2017-12-18 16:46:04 +03:00
for element_segment in module.elements_section().map(|es| es.entries()).unwrap_or(
&[],
)
2017-12-13 18:31:40 +01:00
{
let offset_val = match eval_init_expr(element_segment.offset(), &instance) {
RuntimeValue::I32(v) => v as u32,
_ => panic!("Due to validation elem segment offset should evaluate to i32"),
};
2017-12-18 16:46:04 +03:00
let table_inst = instance.table_by_index(DEFAULT_TABLE_INDEX).expect(
"Due to validation default table should exists",
);
2017-12-13 18:31:40 +01:00
for (j, func_idx) in element_segment.members().into_iter().enumerate() {
2017-12-18 16:46:04 +03:00
let func = instance.func_by_index(*func_idx).expect(
"Due to validation funcs from element segments should exists",
);
2017-12-13 18:31:40 +01:00
table_inst.set(offset_val + j as u32, func)?;
}
}
for data_segment in module.data_section().map(|ds| ds.entries()).unwrap_or(&[]) {
let offset_val = match eval_init_expr(data_segment.offset(), &instance) {
RuntimeValue::I32(v) => v as u32,
_ => panic!("Due to validation data segment offset should evaluate to i32"),
};
2017-12-18 16:46:04 +03:00
let memory_inst = instance.memory_by_index(DEFAULT_MEMORY_INDEX).expect(
"Due to validation default memory should exists",
);
2017-12-13 18:31:40 +01:00
memory_inst.set(offset_val, data_segment.value())?;
}
Ok(instance)
}
2017-12-13 19:11:25 +01:00
fn instantiate_with_imports(
2017-12-13 18:31:40 +01:00
module: &Module,
2017-12-19 20:46:05 +03:00
imports: &Imports,
) -> Result<Rc<ModuleInstance>, Error> {
2017-12-13 18:31:40 +01:00
let mut extern_vals = Vec::new();
for import_entry in module.import_section().map(|s| s.entries()).unwrap_or(&[]) {
let module_name = import_entry.module();
let field_name = import_entry.field();
let resolver = imports.resolver(module_name).ok_or_else(|| {
2017-12-18 20:31:47 +03:00
Error::Instantiation(format!("Module {} not found", module_name))
2017-12-13 18:31:40 +01:00
})?;
let extern_val = match *import_entry.external() {
External::Function(fn_ty_idx) => {
// Module is not yet validated so we have to check type indexes.
let types = module.type_section().map(|s| s.types()).unwrap_or(&[]);
let &Type::Function(ref func_type) =
types.get(fn_ty_idx as usize).ok_or_else(|| {
Error::Validation(format!("Function type {} not found", fn_ty_idx))
})?;
let func = resolver.resolve_func(field_name, func_type)?;
ExternVal::Func(func)
}
External::Table(ref table_type) => {
let table = resolver.resolve_table(field_name, table_type)?;
ExternVal::Table(table)
}
External::Memory(ref memory_type) => {
let memory = resolver.resolve_memory(field_name, memory_type)?;
ExternVal::Memory(memory)
}
External::Global(ref global_type) => {
let global = resolver.resolve_global(field_name, global_type)?;
ExternVal::Global(global)
}
};
extern_vals.push(extern_val);
}
2017-12-13 19:11:25 +01:00
Self::instantiate_with_externvals(module, &extern_vals)
}
2017-12-19 20:46:05 +03:00
pub fn new<'a>(module: &'a Module) -> InstantiationBuilder<'a> {
2017-12-18 12:59:59 +03:00
InstantiationBuilder::new(module)
2017-12-13 18:31:40 +01:00
}
2017-12-19 20:46:05 +03:00
pub fn invoke_index<'a>(
2017-12-13 18:31:40 +01:00
&self,
func_idx: u32,
args: &[RuntimeValue],
2017-12-19 20:46:05 +03:00
state: &'a mut HostState<'a>,
2017-12-13 18:31:40 +01:00
) -> Result<Option<RuntimeValue>, Error> {
let func_instance = self.func_by_index(func_idx).ok_or_else(|| {
Error::Program(format!(
"Module doesn't contain function at index {}",
func_idx
))
})?;
FuncInstance::invoke(func_instance, Cow::Borrowed(args), state)
2017-12-13 18:31:40 +01:00
}
2017-12-19 20:46:05 +03:00
pub fn invoke_export<'a>(
2017-12-13 18:31:40 +01:00
&self,
func_name: &str,
args: &[RuntimeValue],
2017-12-19 20:46:05 +03:00
state: &'a mut HostState<'a>,
2017-12-13 18:31:40 +01:00
) -> Result<Option<RuntimeValue>, Error> {
let extern_val = self.export_by_name(func_name).ok_or_else(|| {
Error::Program(format!("Module doesn't have export {}", func_name))
})?;
let func_instance = match extern_val {
ExternVal::Func(func_instance) => func_instance,
unexpected => {
return Err(Error::Program(format!(
"Export {} is not a function, but {:?}",
func_name,
unexpected
)));
}
};
2018-01-05 16:22:20 +03:00
FuncInstance::invoke(func_instance.clone(), Cow::Borrowed(args), state)
2017-12-13 18:31:40 +01:00
}
}
2017-12-19 20:46:05 +03:00
pub struct InstantiationBuilder<'a> {
2017-12-13 19:11:25 +01:00
module: &'a Module,
2017-12-19 20:46:05 +03:00
imports: Option<Imports<'a>>,
2017-12-13 19:11:25 +01:00
}
2017-12-19 20:46:05 +03:00
impl<'a> InstantiationBuilder<'a> {
2017-12-13 19:11:25 +01:00
fn new(module: &'a Module) -> Self {
2017-12-18 12:59:59 +03:00
InstantiationBuilder {
2017-12-13 19:11:25 +01:00
module,
imports: None,
}
}
2017-12-19 20:46:05 +03:00
pub fn with_imports(mut self, imports: Imports<'a>) -> Self {
2017-12-13 19:11:25 +01:00
self.imports = Some(imports);
self
}
pub fn with_import<N: Into<String>>(
mut self,
name: N,
2017-12-19 20:46:05 +03:00
import_resolver: &'a ImportResolver,
2017-12-13 19:11:25 +01:00
) -> Self {
self.imports
.get_or_insert_with(|| Imports::default())
.push_resolver(name, import_resolver);
self
}
2017-12-19 20:46:05 +03:00
pub fn run_start<'b>(mut self, state: &'b mut HostState<'b>) -> Result<Rc<ModuleInstance>, Error> {
2017-12-13 19:11:25 +01:00
let imports = self.imports.get_or_insert_with(|| Imports::default());
let instance = ModuleInstance::instantiate_with_imports(self.module, imports)?;
if let Some(start_fn_idx) = self.module.start_section() {
2017-12-18 16:46:04 +03:00
let start_func = instance.func_by_index(start_fn_idx).expect(
"Due to validation start function should exists",
);
FuncInstance::invoke(start_func, Cow::Borrowed(&[]), state)?;
2017-12-13 19:11:25 +01:00
}
Ok(instance)
}
2017-12-19 20:46:05 +03:00
pub fn assert_no_start(mut self) -> Result<Rc<ModuleInstance>, Error> {
2017-12-13 19:11:25 +01:00
assert!(self.module.start_section().is_none());
let imports = self.imports.get_or_insert_with(|| Imports::default());
let instance = ModuleInstance::instantiate_with_imports(self.module, imports)?;
Ok(instance)
}
}
2017-12-19 20:46:05 +03:00
impl ImportResolver for ModuleInstance {
2017-12-13 18:31:40 +01:00
fn resolve_func(
&self,
field_name: &str,
_func_type: &FunctionType,
2018-01-05 13:10:01 +03:00
) -> Result<FuncRef, Error> {
2017-12-13 18:31:40 +01:00
Ok(self.export_by_name(field_name)
.ok_or_else(|| {
Error::Validation(format!("Export {} not found", field_name))
})?
.as_func()
.ok_or_else(|| {
Error::Validation(format!("Export {} is not a function", field_name))
})?)
}
fn resolve_global(
&self,
field_name: &str,
_global_type: &GlobalType,
2018-01-05 13:10:01 +03:00
) -> Result<GlobalRef, Error> {
2017-12-13 18:31:40 +01:00
Ok(self.export_by_name(field_name)
.ok_or_else(|| {
Error::Validation(format!("Export {} not found", field_name))
})?
.as_global()
.ok_or_else(|| {
Error::Validation(format!("Export {} is not a global", field_name))
})?)
}
fn resolve_memory(
&self,
field_name: &str,
_memory_type: &MemoryType,
2018-01-05 13:10:01 +03:00
) -> Result<MemoryRef, Error> {
2017-12-13 18:31:40 +01:00
Ok(self.export_by_name(field_name)
.ok_or_else(|| {
Error::Validation(format!("Export {} not found", field_name))
})?
.as_memory()
.ok_or_else(|| {
Error::Validation(format!("Export {} is not a memory", field_name))
})?)
}
fn resolve_table(
&self,
field_name: &str,
_table_type: &TableType,
2018-01-05 13:10:01 +03:00
) -> Result<TableRef, Error> {
2017-12-13 18:31:40 +01:00
Ok(self.export_by_name(field_name)
.ok_or_else(|| {
Error::Validation(format!("Export {} not found", field_name))
})?
.as_table()
.ok_or_else(|| {
Error::Validation(format!("Export {} is not a table", field_name))
})?)
}
}
fn alloc_func_type(func_type: FunctionType) -> Rc<FunctionType> {
Rc::new(func_type)
}
2017-12-19 20:46:05 +03:00
fn eval_init_expr(init_expr: &InitExpr, module: &ModuleInstance) -> RuntimeValue {
2017-12-13 18:31:40 +01:00
let code = init_expr.code();
debug_assert!(
code.len() == 2,
"Due to validation `code`.len() should be 2"
);
match code[0] {
Opcode::I32Const(v) => v.into(),
Opcode::I64Const(v) => v.into(),
Opcode::F32Const(v) => RuntimeValue::decode_f32(v),
Opcode::F64Const(v) => RuntimeValue::decode_f64(v),
Opcode::GetGlobal(idx) => {
2017-12-18 16:46:04 +03:00
let global = module.global_by_index(idx).expect(
"Due to validation global should exists in module",
);
2017-12-13 18:31:40 +01:00
global.get()
}
_ => panic!("Due to validation init should be a const expr"),
}
}
fn match_limits(l1: &ResizableLimits, l2: &ResizableLimits) -> Result<(), Error> {
if l1.initial() < l2.initial() {
2017-12-18 20:31:47 +03:00
return Err(Error::Instantiation(format!(
2017-12-13 18:31:40 +01:00
"trying to import with limits l1.initial={} and l2.initial={}",
l1.initial(),
l2.initial()
)));
}
match (l1.maximum(), l2.maximum()) {
(_, None) => (),
(Some(m1), Some(m2)) if m1 <= m2 => (),
_ => {
2017-12-18 20:31:47 +03:00
return Err(Error::Instantiation(format!(
2017-12-13 18:31:40 +01:00
"trying to import with limits l1.max={:?} and l2.max={:?}",
l1.maximum(),
l2.maximum()
)))
}
}
Ok(())
2017-04-21 14:35:12 +03:00
}
2017-11-25 22:55:45 +03:00
pub fn check_limits(limits: &ResizableLimits) -> Result<(), Error> {
2017-06-08 10:49:32 +03:00
if let Some(maximum) = limits.maximum() {
if maximum < limits.initial() {
2017-12-18 16:12:59 +03:00
return Err(Error::Validation(format!(
"maximum limit {} is lesser than minimum {}",
maximum,
limits.initial()
)));
2017-06-08 10:49:32 +03:00
}
}
Ok(())
}