run 'cargo fmt' again

This commit is contained in:
Andrew Dirksen 2018-11-13 16:51:35 -08:00
parent d5b99afe0b
commit 2824b84381
22 changed files with 307 additions and 1002 deletions

View File

@ -22,9 +22,7 @@ fn main() {
// Export section has an entry with a func_name with an index inside a module // Export section has an entry with a func_name with an index inside a module
let export_section = module.export_section().expect("No export section found"); let export_section = module.export_section().expect("No export section found");
// It's a section with function declarations (which are references to the type section entries) // It's a section with function declarations (which are references to the type section entries)
let function_section = module let function_section = module.function_section().expect("No function section found");
.function_section()
.expect("No function section found");
// Type section stores function types which are referenced by function_section entries // Type section stores function types which are referenced by function_section entries
let type_section = module.type_section().expect("No type section found"); let type_section = module.type_section().expect("No type section found");
@ -59,8 +57,7 @@ fn main() {
let function_index_in_section = function_index - import_section_len; let function_index_in_section = function_index - import_section_len;
// Getting a type reference from a function section entry // Getting a type reference from a function section entry
let func_type_ref: usize = let func_type_ref: usize = function_section.entries()[function_index_in_section].type_ref() as usize;
function_section.entries()[function_index_in_section].type_ref() as usize;
// Use the reference to get an actual function type // Use the reference to get an actual function type
let function_type: &FunctionType = match &type_section.types()[func_type_ref] { let function_type: &FunctionType = match &type_section.types()[func_type_ref] {
@ -112,7 +109,6 @@ fn main() {
println!( println!(
"Result: {:?}", "Result: {:?}",
main.invoke_export(func_name, &args, &mut NopExternals) main.invoke_export(func_name, &args, &mut NopExternals).expect("")
.expect("")
); );
} }

View File

@ -5,9 +5,8 @@ use std::env;
use std::fmt; use std::fmt;
use std::fs::File; use std::fs::File;
use wasmi::{ use wasmi::{
Error as InterpreterError, Externals, FuncInstance, FuncRef, HostError, ImportsBuilder, Error as InterpreterError, Externals, FuncInstance, FuncRef, HostError, ImportsBuilder, ModuleImportResolver,
ModuleImportResolver, ModuleInstance, ModuleRef, RuntimeArgs, RuntimeValue, Signature, Trap, ModuleInstance, ModuleRef, RuntimeArgs, RuntimeValue, Signature, Trap, ValueType,
ValueType,
}; };
#[derive(Debug)] #[derive(Debug)]
@ -140,11 +139,7 @@ const SET_FUNC_INDEX: usize = 0;
const GET_FUNC_INDEX: usize = 1; const GET_FUNC_INDEX: usize = 1;
impl<'a> Externals for Runtime<'a> { impl<'a> Externals for Runtime<'a> {
fn invoke_index( fn invoke_index(&mut self, index: usize, args: RuntimeArgs) -> Result<Option<RuntimeValue>, Trap> {
&mut self,
index: usize,
args: RuntimeArgs,
) -> Result<Option<RuntimeValue>, Trap> {
match index { match index {
SET_FUNC_INDEX => { SET_FUNC_INDEX => {
let idx: i32 = args.nth(0); let idx: i32 = args.nth(0);
@ -164,16 +159,9 @@ impl<'a> Externals for Runtime<'a> {
struct RuntimeModuleImportResolver; struct RuntimeModuleImportResolver;
impl<'a> ModuleImportResolver for RuntimeModuleImportResolver { impl<'a> ModuleImportResolver for RuntimeModuleImportResolver {
fn resolve_func( fn resolve_func(&self, field_name: &str, _signature: &Signature) -> Result<FuncRef, InterpreterError> {
&self,
field_name: &str,
_signature: &Signature,
) -> Result<FuncRef, InterpreterError> {
let func_ref = match field_name { let func_ref = match field_name {
"set" => FuncInstance::alloc_host( "set" => FuncInstance::alloc_host(Signature::new(&[ValueType::I32][..], None), SET_FUNC_INDEX),
Signature::new(&[ValueType::I32][..], None),
SET_FUNC_INDEX,
),
"get" => FuncInstance::alloc_host( "get" => FuncInstance::alloc_host(
Signature::new(&[ValueType::I32][..], Some(ValueType::I32)), Signature::new(&[ValueType::I32][..], Some(ValueType::I32)),
GET_FUNC_INDEX, GET_FUNC_INDEX,

View File

@ -7,9 +7,9 @@ use std::env::args;
use std::fs::File; use std::fs::File;
use wasmi::memory_units::*; use wasmi::memory_units::*;
use wasmi::{ use wasmi::{
Error, FuncInstance, FuncRef, GlobalDescriptor, GlobalInstance, GlobalRef, ImportsBuilder, Error, FuncInstance, FuncRef, GlobalDescriptor, GlobalInstance, GlobalRef, ImportsBuilder, MemoryDescriptor,
MemoryDescriptor, MemoryInstance, MemoryRef, Module, ModuleImportResolver, ModuleInstance, MemoryInstance, MemoryRef, Module, ModuleImportResolver, ModuleInstance, NopExternals, RuntimeValue, Signature,
NopExternals, RuntimeValue, Signature, TableDescriptor, TableInstance, TableRef, TableDescriptor, TableInstance, TableRef,
}; };
fn load_from_file(filename: &str) -> Module { fn load_from_file(filename: &str) -> Module {
@ -27,33 +27,21 @@ impl ModuleImportResolver for ResolveAll {
Ok(FuncInstance::alloc_host(signature.clone(), 0)) Ok(FuncInstance::alloc_host(signature.clone(), 0))
} }
fn resolve_global( fn resolve_global(&self, _field_name: &str, global_type: &GlobalDescriptor) -> Result<GlobalRef, Error> {
&self,
_field_name: &str,
global_type: &GlobalDescriptor,
) -> Result<GlobalRef, Error> {
Ok(GlobalInstance::alloc( Ok(GlobalInstance::alloc(
RuntimeValue::default(global_type.value_type()), RuntimeValue::default(global_type.value_type()),
global_type.is_mutable(), global_type.is_mutable(),
)) ))
} }
fn resolve_memory( fn resolve_memory(&self, _field_name: &str, memory_type: &MemoryDescriptor) -> Result<MemoryRef, Error> {
&self,
_field_name: &str,
memory_type: &MemoryDescriptor,
) -> Result<MemoryRef, Error> {
Ok(MemoryInstance::alloc( Ok(MemoryInstance::alloc(
Pages(memory_type.initial() as usize), Pages(memory_type.initial() as usize),
memory_type.maximum().map(|m| Pages(m as usize)), memory_type.maximum().map(|m| Pages(m as usize)),
).unwrap()) ).unwrap())
} }
fn resolve_table( fn resolve_table(&self, _field_name: &str, table_type: &TableDescriptor) -> Result<TableRef, Error> {
&self,
_field_name: &str,
table_type: &TableDescriptor,
) -> Result<TableRef, Error> {
Ok(TableInstance::alloc(table_type.initial(), table_type.maximum()).unwrap()) Ok(TableInstance::alloc(table_type.initial(), table_type.maximum()).unwrap())
} }
} }

View File

@ -63,9 +63,7 @@ impl fmt::Debug for FuncInstance {
// debug string for function instances and this will lead to infinite loop. // debug string for function instances and this will lead to infinite loop.
write!(f, "Internal {{ signature={:?} }}", signature,) write!(f, "Internal {{ signature={:?} }}", signature,)
} }
&FuncInstanceInternal::Host { ref signature, .. } => { &FuncInstanceInternal::Host { ref signature, .. } => write!(f, "Host {{ signature={:?} }}", signature),
write!(f, "Host {{ signature={:?} }}", signature)
}
} }
} }
} }
@ -103,11 +101,7 @@ impl FuncInstance {
&self.0 &self.0
} }
pub(crate) fn alloc_internal( pub(crate) fn alloc_internal(module: Weak<ModuleInstance>, signature: Rc<Signature>, body: FuncBody) -> FuncRef {
module: Weak<ModuleInstance>,
signature: Rc<Signature>,
body: FuncBody,
) -> FuncRef {
let func = FuncInstanceInternal::Internal { let func = FuncInstanceInternal::Internal {
signature, signature,
module: module, module: module,
@ -144,8 +138,7 @@ impl FuncInstance {
interpreter.start_execution(externals) interpreter.start_execution(externals)
} }
FuncInstanceInternal::Host { FuncInstanceInternal::Host {
ref host_func_index, ref host_func_index, ..
..
} => externals.invoke_index(*host_func_index, args.into()), } => externals.invoke_index(*host_func_index, args.into()),
} }
} }
@ -164,10 +157,7 @@ impl FuncInstance {
/// [`Trap`]: #enum.Trap.html /// [`Trap`]: #enum.Trap.html
/// [`start_execution`]: struct.FuncInvocation.html#method.start_execution /// [`start_execution`]: struct.FuncInvocation.html#method.start_execution
/// [`resume_execution`]: struct.FuncInvocation.html#method.resume_execution /// [`resume_execution`]: struct.FuncInvocation.html#method.resume_execution
pub fn invoke_resumable<'args>( pub fn invoke_resumable<'args>(func: &FuncRef, args: &'args [RuntimeValue]) -> Result<FuncInvocation<'args>, Trap> {
func: &FuncRef,
args: &'args [RuntimeValue],
) -> Result<FuncInvocation<'args>, Trap> {
check_function_args(func.signature(), &args)?; check_function_args(func.signature(), &args)?;
match *func.as_internal() { match *func.as_internal() {
FuncInstanceInternal::Internal { .. } => { FuncInstanceInternal::Internal { .. } => {
@ -177,8 +167,7 @@ impl FuncInstance {
}) })
} }
FuncInstanceInternal::Host { FuncInstanceInternal::Host {
ref host_func_index, ref host_func_index, ..
..
} => Ok(FuncInvocation { } => Ok(FuncInvocation {
kind: FuncInvocationKind::Host { kind: FuncInvocationKind::Host {
args, args,

View File

@ -57,9 +57,7 @@ impl GlobalInstance {
/// type of `val` doesn't match global's type. /// type of `val` doesn't match global's type.
pub fn set(&self, val: RuntimeValue) -> Result<(), Error> { pub fn set(&self, val: RuntimeValue) -> Result<(), Error> {
if !self.mutable { if !self.mutable {
return Err(Error::Global( return Err(Error::Global("Attempt to change an immutable variable".into()));
"Attempt to change an immutable variable".into(),
));
} }
if self.value_type() != val.value_type() { if self.value_type() != val.value_type() {
return Err(Error::Global("Attempt to change variable type".into())); return Err(Error::Global("Attempt to change variable type".into()));

View File

@ -208,11 +208,7 @@ impl HostError {
/// ``` /// ```
pub trait Externals { pub trait Externals {
/// Perform invoke of a host function by specified `index`. /// Perform invoke of a host function by specified `index`.
fn invoke_index( fn invoke_index(&mut self, index: usize, args: RuntimeArgs) -> Result<Option<RuntimeValue>, Trap>;
&mut self,
index: usize,
args: RuntimeArgs,
) -> Result<Option<RuntimeValue>, Trap>;
} }
/// Implementation of [`Externals`] that just traps on [`invoke_index`]. /// Implementation of [`Externals`] that just traps on [`invoke_index`].
@ -222,11 +218,7 @@ pub trait Externals {
pub struct NopExternals; pub struct NopExternals;
impl Externals for NopExternals { impl Externals for NopExternals {
fn invoke_index( fn invoke_index(&mut self, _index: usize, _args: RuntimeArgs) -> Result<Option<RuntimeValue>, Trap> {
&mut self,
_index: usize,
_args: RuntimeArgs,
) -> Result<Option<RuntimeValue>, Trap> {
Err(TrapKind::Unreachable.into()) Err(TrapKind::Unreachable.into())
} }
} }

View File

@ -30,12 +30,7 @@ pub trait ImportResolver {
/// ///
/// Returned function should match given `signature`, i.e. all parameter types and return value should have exact match. /// Returned function should match given `signature`, i.e. all parameter types and return value should have exact match.
/// Otherwise, link-time error will occur. /// Otherwise, link-time error will occur.
fn resolve_func( fn resolve_func(&self, _module_name: &str, field_name: &str, _signature: &Signature) -> Result<FuncRef, Error>;
&self,
_module_name: &str,
field_name: &str,
_signature: &Signature,
) -> Result<FuncRef, Error>;
/// Resolve a global variable. /// Resolve a global variable.
/// ///
@ -124,11 +119,7 @@ impl<'a> ImportsBuilder<'a> {
} }
/// Register an resolver by a name. /// Register an resolver by a name.
pub fn with_resolver<N: Into<String>>( pub fn with_resolver<N: Into<String>>(mut self, name: N, resolver: &'a ModuleImportResolver) -> Self {
mut self,
name: N,
resolver: &'a ModuleImportResolver,
) -> Self {
self.modules.insert(name.into(), resolver); self.modules.insert(name.into(), resolver);
self self
} }
@ -146,12 +137,7 @@ impl<'a> ImportsBuilder<'a> {
} }
impl<'a> ImportResolver for ImportsBuilder<'a> { impl<'a> ImportResolver for ImportsBuilder<'a> {
fn resolve_func( fn resolve_func(&self, module_name: &str, field_name: &str, signature: &Signature) -> Result<FuncRef, Error> {
&self,
module_name: &str,
field_name: &str,
signature: &Signature,
) -> Result<FuncRef, Error> {
self.resolver(module_name) self.resolver(module_name)
.ok_or_else(|| Error::Instantiation(format!("Module {} not found", module_name)))? .ok_or_else(|| Error::Instantiation(format!("Module {} not found", module_name)))?
.resolve_func(field_name, signature) .resolve_func(field_name, signature)
@ -201,10 +187,7 @@ pub trait ModuleImportResolver {
/// ///
/// [`ImportResolver::resolve_func`]: trait.ImportResolver.html#tymethod.resolve_func /// [`ImportResolver::resolve_func`]: trait.ImportResolver.html#tymethod.resolve_func
fn resolve_func(&self, field_name: &str, _signature: &Signature) -> Result<FuncRef, Error> { fn resolve_func(&self, field_name: &str, _signature: &Signature) -> Result<FuncRef, Error> {
Err(Error::Instantiation(format!( Err(Error::Instantiation(format!("Export {} not found", field_name)))
"Export {} not found",
field_name
)))
} }
/// Resolve a global variable. /// Resolve a global variable.
@ -212,15 +195,8 @@ pub trait ModuleImportResolver {
/// See [`ImportResolver::resolve_global`] for details. /// See [`ImportResolver::resolve_global`] for details.
/// ///
/// [`ImportResolver::resolve_global`]: trait.ImportResolver.html#tymethod.resolve_global /// [`ImportResolver::resolve_global`]: trait.ImportResolver.html#tymethod.resolve_global
fn resolve_global( fn resolve_global(&self, field_name: &str, _global_type: &GlobalDescriptor) -> Result<GlobalRef, Error> {
&self, Err(Error::Instantiation(format!("Export {} not found", field_name)))
field_name: &str,
_global_type: &GlobalDescriptor,
) -> Result<GlobalRef, Error> {
Err(Error::Instantiation(format!(
"Export {} not found",
field_name
)))
} }
/// Resolve a memory. /// Resolve a memory.
@ -228,15 +204,8 @@ pub trait ModuleImportResolver {
/// See [`ImportResolver::resolve_memory`] for details. /// See [`ImportResolver::resolve_memory`] for details.
/// ///
/// [`ImportResolver::resolve_memory`]: trait.ImportResolver.html#tymethod.resolve_memory /// [`ImportResolver::resolve_memory`]: trait.ImportResolver.html#tymethod.resolve_memory
fn resolve_memory( fn resolve_memory(&self, field_name: &str, _memory_type: &MemoryDescriptor) -> Result<MemoryRef, Error> {
&self, Err(Error::Instantiation(format!("Export {} not found", field_name)))
field_name: &str,
_memory_type: &MemoryDescriptor,
) -> Result<MemoryRef, Error> {
Err(Error::Instantiation(format!(
"Export {} not found",
field_name
)))
} }
/// Resolve a table. /// Resolve a table.
@ -244,15 +213,8 @@ pub trait ModuleImportResolver {
/// See [`ImportResolver::resolve_table`] for details. /// See [`ImportResolver::resolve_table`] for details.
/// ///
/// [`ImportResolver::resolve_table`]: trait.ImportResolver.html#tymethod.resolve_table /// [`ImportResolver::resolve_table`]: trait.ImportResolver.html#tymethod.resolve_table
fn resolve_table( fn resolve_table(&self, field_name: &str, _table_type: &TableDescriptor) -> Result<TableRef, Error> {
&self, Err(Error::Instantiation(format!("Export {} not found", field_name)))
field_name: &str,
_table_type: &TableDescriptor,
) -> Result<TableRef, Error> {
Err(Error::Instantiation(format!(
"Export {} not found",
field_name
)))
} }
} }
@ -263,46 +225,28 @@ impl ModuleImportResolver for ModuleRef {
.ok_or_else(|| Error::Instantiation(format!("Export {} not found", field_name)))? .ok_or_else(|| Error::Instantiation(format!("Export {} not found", field_name)))?
.as_func() .as_func()
.cloned() .cloned()
.ok_or_else(|| { .ok_or_else(|| Error::Instantiation(format!("Export {} is not a function", field_name)))?)
Error::Instantiation(format!("Export {} is not a function", field_name))
})?)
} }
fn resolve_global( fn resolve_global(&self, field_name: &str, _global_type: &GlobalDescriptor) -> Result<GlobalRef, Error> {
&self,
field_name: &str,
_global_type: &GlobalDescriptor,
) -> Result<GlobalRef, Error> {
Ok(self Ok(self
.export_by_name(field_name) .export_by_name(field_name)
.ok_or_else(|| Error::Instantiation(format!("Export {} not found", field_name)))? .ok_or_else(|| Error::Instantiation(format!("Export {} not found", field_name)))?
.as_global() .as_global()
.cloned() .cloned()
.ok_or_else(|| { .ok_or_else(|| Error::Instantiation(format!("Export {} is not a global", field_name)))?)
Error::Instantiation(format!("Export {} is not a global", field_name))
})?)
} }
fn resolve_memory( fn resolve_memory(&self, field_name: &str, _memory_type: &MemoryDescriptor) -> Result<MemoryRef, Error> {
&self,
field_name: &str,
_memory_type: &MemoryDescriptor,
) -> Result<MemoryRef, Error> {
Ok(self Ok(self
.export_by_name(field_name) .export_by_name(field_name)
.ok_or_else(|| Error::Instantiation(format!("Export {} not found", field_name)))? .ok_or_else(|| Error::Instantiation(format!("Export {} not found", field_name)))?
.as_memory() .as_memory()
.cloned() .cloned()
.ok_or_else(|| { .ok_or_else(|| Error::Instantiation(format!("Export {} is not a memory", field_name)))?)
Error::Instantiation(format!("Export {} is not a memory", field_name))
})?)
} }
fn resolve_table( fn resolve_table(&self, field_name: &str, _table_type: &TableDescriptor) -> Result<TableRef, Error> {
&self,
field_name: &str,
_table_type: &TableDescriptor,
) -> Result<TableRef, Error> {
Ok(self Ok(self
.export_by_name(field_name) .export_by_name(field_name)
.ok_or_else(|| Error::Instantiation(format!("Export {} not found", field_name)))? .ok_or_else(|| Error::Instantiation(format!("Export {} not found", field_name)))?

View File

@ -371,11 +371,9 @@ impl<'a> Iterator for InstructionIter<'a> {
#[inline] #[inline]
fn next(&mut self) -> Option<<Self as Iterator>::Item> { fn next(&mut self) -> Option<<Self as Iterator>::Item> {
self.instructions self.instructions.get(self.position as usize).map(|instruction| {
.get(self.position as usize) self.position += 1;
.map(|instruction| { instruction
self.position += 1; })
instruction
})
} }
} }

View File

@ -174,8 +174,7 @@ impl MemoryInstance {
/// Get value from memory at given offset. /// Get value from memory at given offset.
pub fn get_value<T: LittleEndianConvert>(&self, offset: u32) -> Result<T, Error> { pub fn get_value<T: LittleEndianConvert>(&self, offset: u32) -> Result<T, Error> {
let mut buffer = self.buffer.borrow_mut(); let mut buffer = self.buffer.borrow_mut();
let region = let region = self.checked_region(&mut buffer, offset as usize, ::core::mem::size_of::<T>())?;
self.checked_region(&mut buffer, offset as usize, ::core::mem::size_of::<T>())?;
Ok(T::from_little_endian(&buffer[region.range()]).expect("Slice size is checked")) Ok(T::from_little_endian(&buffer[region.range()]).expect("Slice size is checked"))
} }
@ -209,9 +208,7 @@ impl MemoryInstance {
/// Copy data in the memory at given offset. /// Copy data in the memory at given offset.
pub fn set(&self, offset: u32, value: &[u8]) -> Result<(), Error> { pub fn set(&self, offset: u32, value: &[u8]) -> Result<(), Error> {
let mut buffer = self.buffer.borrow_mut(); let mut buffer = self.buffer.borrow_mut();
let range = self let range = self.checked_region(&mut buffer, offset as usize, value.len())?.range();
.checked_region(&mut buffer, offset as usize, value.len())?
.range();
buffer[range].copy_from_slice(value); buffer[range].copy_from_slice(value);
@ -241,9 +238,7 @@ impl MemoryInstance {
return Ok(size_before_grow); return Ok(size_before_grow);
} }
if additional > Pages(65536) { if additional > Pages(65536) {
return Err(Error::Memory(format!( return Err(Error::Memory(format!("Trying to grow memory by more than 65536 pages")));
"Trying to grow memory by more than 65536 pages"
)));
} }
let new_size: Pages = size_before_grow + additional; let new_size: Pages = size_before_grow + additional;
@ -260,12 +255,7 @@ impl MemoryInstance {
Ok(size_before_grow) Ok(size_before_grow)
} }
fn checked_region<B>( fn checked_region<B>(&self, buffer: &mut B, offset: usize, size: usize) -> Result<CheckedRegion, Error>
&self,
buffer: &mut B,
offset: usize,
size: usize,
) -> Result<CheckedRegion, Error>
where where
B: ::core::ops::DerefMut<Target = Vec<u8>>, B: ::core::ops::DerefMut<Target = Vec<u8>>,
{ {
@ -365,8 +355,7 @@ impl MemoryInstance {
pub fn copy(&self, src_offset: usize, dst_offset: usize, len: usize) -> Result<(), Error> { pub fn copy(&self, src_offset: usize, dst_offset: usize, len: usize) -> Result<(), Error> {
let mut buffer = self.buffer.borrow_mut(); let mut buffer = self.buffer.borrow_mut();
let (read_region, write_region) = let (read_region, write_region) = self.checked_region_pair(&mut buffer, src_offset, len, dst_offset, len)?;
self.checked_region_pair(&mut buffer, src_offset, len, dst_offset, len)?;
unsafe { unsafe {
::core::ptr::copy( ::core::ptr::copy(
@ -390,16 +379,10 @@ impl MemoryInstance {
/// ///
/// - either of specified regions is out of bounds, /// - either of specified regions is out of bounds,
/// - these regions overlaps. /// - these regions overlaps.
pub fn copy_nonoverlapping( pub fn copy_nonoverlapping(&self, src_offset: usize, dst_offset: usize, len: usize) -> Result<(), Error> {
&self,
src_offset: usize,
dst_offset: usize,
len: usize,
) -> Result<(), Error> {
let mut buffer = self.buffer.borrow_mut(); let mut buffer = self.buffer.borrow_mut();
let (read_region, write_region) = let (read_region, write_region) = self.checked_region_pair(&mut buffer, src_offset, len, dst_offset, len)?;
self.checked_region_pair(&mut buffer, src_offset, len, dst_offset, len)?;
if read_region.intersects(&write_region) { if read_region.intersects(&write_region) {
return Err(Error::Memory(format!( return Err(Error::Memory(format!(
@ -439,12 +422,8 @@ impl MemoryInstance {
let mut src_buffer = src.buffer.borrow_mut(); let mut src_buffer = src.buffer.borrow_mut();
let mut dst_buffer = dst.buffer.borrow_mut(); let mut dst_buffer = dst.buffer.borrow_mut();
let src_range = src let src_range = src.checked_region(&mut src_buffer, src_offset, len)?.range();
.checked_region(&mut src_buffer, src_offset, len)? let dst_range = dst.checked_region(&mut dst_buffer, dst_offset, len)?.range();
.range();
let dst_range = dst
.checked_region(&mut dst_buffer, dst_offset, len)?
.range();
dst_buffer[dst_range].copy_from_slice(&src_buffer[src_range]); dst_buffer[dst_range].copy_from_slice(&src_buffer[src_range]);
@ -588,8 +567,7 @@ mod tests {
fn create_memory(initial_content: &[u8]) -> MemoryInstance { fn create_memory(initial_content: &[u8]) -> MemoryInstance {
let mem = MemoryInstance::new(Pages(1), Some(Pages(1))); let mem = MemoryInstance::new(Pages(1), Some(Pages(1)));
mem.set(0, initial_content) mem.set(0, initial_content).expect("Successful initialize the memory");
.expect("Successful initialize the memory");
mem mem
} }
@ -641,17 +619,12 @@ mod tests {
#[test] #[test]
fn transfer_works() { fn transfer_works() {
let src = MemoryRef(Rc::new(create_memory(&[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]))); let src = MemoryRef(Rc::new(create_memory(&[0, 1, 2, 3, 4, 5, 6, 7, 8, 9])));
let dst = MemoryRef(Rc::new(create_memory(&[ let dst = MemoryRef(Rc::new(create_memory(&[10, 11, 12, 13, 14, 15, 16, 17, 18, 19])));
10, 11, 12, 13, 14, 15, 16, 17, 18, 19,
])));
MemoryInstance::transfer(&src, 4, &dst, 0, 3).unwrap(); MemoryInstance::transfer(&src, 4, &dst, 0, 3).unwrap();
assert_eq!(src.get(0, 10).unwrap(), &[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]); assert_eq!(src.get(0, 10).unwrap(), &[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]);
assert_eq!( assert_eq!(dst.get(0, 10).unwrap(), &[4, 5, 6, 13, 14, 15, 16, 17, 18, 19]);
dst.get(0, 10).unwrap(),
&[4, 5, 6, 13, 14, 15, 16, 17, 18, 19]
);
} }
#[test] #[test]
@ -675,25 +648,19 @@ mod tests {
#[test] #[test]
fn transfer_oob_errors() { fn transfer_oob_errors() {
let src = MemoryRef(Rc::new(create_memory(&[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]))); let src = MemoryRef(Rc::new(create_memory(&[0, 1, 2, 3, 4, 5, 6, 7, 8, 9])));
let dst = MemoryRef(Rc::new(create_memory(&[ let dst = MemoryRef(Rc::new(create_memory(&[10, 11, 12, 13, 14, 15, 16, 17, 18, 19])));
10, 11, 12, 13, 14, 15, 16, 17, 18, 19,
])));
assert!(MemoryInstance::transfer(&src, 65535, &dst, 0, 3).is_err()); assert!(MemoryInstance::transfer(&src, 65535, &dst, 0, 3).is_err());
// Check that memories content left untouched // Check that memories content left untouched
assert_eq!(src.get(0, 10).unwrap(), &[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]); assert_eq!(src.get(0, 10).unwrap(), &[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]);
assert_eq!( assert_eq!(dst.get(0, 10).unwrap(), &[10, 11, 12, 13, 14, 15, 16, 17, 18, 19]);
dst.get(0, 10).unwrap(),
&[10, 11, 12, 13, 14, 15, 16, 17, 18, 19]
);
} }
#[test] #[test]
fn clear() { fn clear() {
let mem = create_memory(&[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]); let mem = create_memory(&[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]);
mem.clear(0, 0x4A, 10) mem.clear(0, 0x4A, 10).expect("To successfully clear the memory");
.expect("To successfully clear the memory");
let result = mem.get(0, 10).expect("To successfully retrieve the result"); let result = mem.get(0, 10).expect("To successfully retrieve the result");
assert_eq!(result, &[0x4A; 10]); assert_eq!(result, &[0x4A; 10]);
} }
@ -701,12 +668,10 @@ mod tests {
#[test] #[test]
fn get_into() { fn get_into() {
let mem = MemoryInstance::new(Pages(1), None); let mem = MemoryInstance::new(Pages(1), None);
mem.set(6, &[13, 17, 129]) mem.set(6, &[13, 17, 129]).expect("memory set should not fail");
.expect("memory set should not fail");
let mut data = [0u8; 2]; let mut data = [0u8; 2];
mem.get_into(7, &mut data[..]) mem.get_into(7, &mut data[..]).expect("get_into should not fail");
.expect("get_into should not fail");
assert_eq!(data, [17, 129]); assert_eq!(data, [17, 129]);
} }

View File

@ -298,46 +298,36 @@ impl ModuleInstance {
let code = loaded_module.code(); let code = loaded_module.code();
{ {
let funcs = module let funcs = module.function_section().map(|fs| fs.entries()).unwrap_or(&[]);
.function_section()
.map(|fs| fs.entries())
.unwrap_or(&[]);
let bodies = module.code_section().map(|cs| cs.bodies()).unwrap_or(&[]); let bodies = module.code_section().map(|cs| cs.bodies()).unwrap_or(&[]);
debug_assert!( debug_assert!(
funcs.len() == bodies.len(), funcs.len() == bodies.len(),
"Due to validation func and body counts must match" "Due to validation func and body counts must match"
); );
for (index, (ty, body)) in for (index, (ty, body)) in Iterator::zip(funcs.into_iter(), bodies.into_iter()).enumerate() {
Iterator::zip(funcs.into_iter(), bodies.into_iter()).enumerate()
{
let signature = instance let signature = instance
.signature_by_index(ty.type_ref()) .signature_by_index(ty.type_ref())
.expect("Due to validation type should exists"); .expect("Due to validation type should exists");
let code = code.get(index).expect( let code = code
"At func validation time labels are collected; Collected labels are added by index; qed", .get(index)
).clone(); .expect("At func validation time labels are collected; Collected labels are added by index; qed")
.clone();
let func_body = FuncBody { let func_body = FuncBody {
locals: body.locals().to_vec(), locals: body.locals().to_vec(),
code: code, code: code,
}; };
let func_instance = let func_instance = FuncInstance::alloc_internal(Rc::downgrade(&instance.0), signature, func_body);
FuncInstance::alloc_internal(Rc::downgrade(&instance.0), signature, func_body);
instance.push_func(func_instance); instance.push_func(func_instance);
} }
} }
for table_type in module.table_section().map(|ts| ts.entries()).unwrap_or(&[]) { for table_type in module.table_section().map(|ts| ts.entries()).unwrap_or(&[]) {
let table = let table = TableInstance::alloc(table_type.limits().initial(), table_type.limits().maximum())?;
TableInstance::alloc(table_type.limits().initial(), table_type.limits().maximum())?;
instance.push_table(table); instance.push_table(table);
} }
for memory_type in module for memory_type in module.memory_section().map(|ms| ms.entries()).unwrap_or(&[]) {
.memory_section()
.map(|ms| ms.entries())
.unwrap_or(&[])
{
let initial: Pages = Pages(memory_type.limits().initial() as usize); let initial: Pages = Pages(memory_type.limits().initial() as usize);
let maximum: Option<Pages> = memory_type.limits().maximum().map(|m| Pages(m as usize)); let maximum: Option<Pages> = memory_type.limits().maximum().map(|m| Pages(m as usize));
@ -346,21 +336,13 @@ impl ModuleInstance {
instance.push_memory(memory); instance.push_memory(memory);
} }
for global_entry in module for global_entry in module.global_section().map(|gs| gs.entries()).unwrap_or(&[]) {
.global_section()
.map(|gs| gs.entries())
.unwrap_or(&[])
{
let init_val = eval_init_expr(global_entry.init_expr(), &*instance); let init_val = eval_init_expr(global_entry.init_expr(), &*instance);
let global = GlobalInstance::alloc(init_val, global_entry.global_type().is_mutable()); let global = GlobalInstance::alloc(init_val, global_entry.global_type().is_mutable());
instance.push_global(global); instance.push_global(global);
} }
for export in module for export in module.export_section().map(|es| es.entries()).unwrap_or(&[]) {
.export_section()
.map(|es| es.entries())
.unwrap_or(&[])
{
let field = export.field(); let field = export.field();
let extern_val: ExternVal = match *export.internal() { let extern_val: ExternVal = match *export.internal() {
Internal::Function(idx) => { Internal::Function(idx) => {
@ -408,11 +390,7 @@ impl ModuleInstance {
let module_ref = ModuleInstance::alloc_module(loaded_module, extern_vals)?; let module_ref = ModuleInstance::alloc_module(loaded_module, extern_vals)?;
for element_segment in module for element_segment in module.elements_section().map(|es| es.entries()).unwrap_or(&[]) {
.elements_section()
.map(|es| es.entries())
.unwrap_or(&[])
{
let offset_val = match eval_init_expr(element_segment.offset(), &module_ref) { let offset_val = match eval_init_expr(element_segment.offset(), &module_ref) {
RuntimeValue::I32(v) => v as u32, RuntimeValue::I32(v) => v as u32,
_ => panic!("Due to validation elem segment offset should evaluate to i32"), _ => panic!("Due to validation elem segment offset should evaluate to i32"),
@ -424,12 +402,8 @@ impl ModuleInstance {
// This check is not only for bailing out early, but also to check the case when // This check is not only for bailing out early, but also to check the case when
// segment consist of 0 members. // segment consist of 0 members.
if offset_val as u64 + element_segment.members().len() as u64 if offset_val as u64 + element_segment.members().len() as u64 > table_inst.current_size() as u64 {
> table_inst.current_size() as u64 return Err(Error::Instantiation("elements segment does not fit".to_string()));
{
return Err(Error::Instantiation(
"elements segment does not fit".to_string(),
));
} }
for (j, func_idx) in element_segment.members().into_iter().enumerate() { for (j, func_idx) in element_segment.members().into_iter().enumerate() {
@ -541,20 +515,17 @@ impl ModuleInstance {
} }
External::Table(ref table_type) => { External::Table(ref table_type) => {
let table_descriptor = TableDescriptor::from_elements(table_type); let table_descriptor = TableDescriptor::from_elements(table_type);
let table = let table = imports.resolve_table(module_name, field_name, &table_descriptor)?;
imports.resolve_table(module_name, field_name, &table_descriptor)?;
ExternVal::Table(table) ExternVal::Table(table)
} }
External::Memory(ref memory_type) => { External::Memory(ref memory_type) => {
let memory_descriptor = MemoryDescriptor::from_elements(memory_type); let memory_descriptor = MemoryDescriptor::from_elements(memory_type);
let memory = let memory = imports.resolve_memory(module_name, field_name, &memory_descriptor)?;
imports.resolve_memory(module_name, field_name, &memory_descriptor)?;
ExternVal::Memory(memory) ExternVal::Memory(memory)
} }
External::Global(ref global_type) => { External::Global(ref global_type) => {
let global_descriptor = GlobalDescriptor::from_elements(global_type); let global_descriptor = GlobalDescriptor::from_elements(global_type);
let global = let global = imports.resolve_global(module_name, field_name, &global_descriptor)?;
imports.resolve_global(module_name, field_name, &global_descriptor)?;
ExternVal::Global(global) ExternVal::Global(global)
} }
}; };
@ -711,10 +682,7 @@ impl<'a> NotStartedModuleRef<'a> {
fn eval_init_expr(init_expr: &InitExpr, module: &ModuleInstance) -> 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, "Due to validation `code`.len() should be 2");
code.len() == 2,
"Due to validation `code`.len() should be 2"
);
match code[0] { match code[0] {
Instruction::I32Const(v) => v.into(), Instruction::I32Const(v) => v.into(),
Instruction::I64Const(v) => v.into(), Instruction::I64Const(v) => v.into(),

View File

@ -12,10 +12,7 @@ macro_rules! impl_binop {
type Output = Self; type Output = Self;
fn $func_name(self, other: T) -> Self { fn $func_name(self, other: T) -> Self {
$for( $for($op::$func_name($is::from_bits(self.0), $is::from_bits(other.into().0)).to_bits())
$op::$func_name($is::from_bits(self.0), $is::from_bits(other.into().0))
.to_bits(),
)
} }
} }
}; };
@ -23,12 +20,7 @@ macro_rules! impl_binop {
macro_rules! float { macro_rules! float {
($for:ident, $rep:ident, $is:ident) => { ($for:ident, $rep:ident, $is:ident) => {
float!( float!($for, $rep, $is, 1 << (::core::mem::size_of::<$is>() * 8 - 1));
$for,
$rep,
$is,
1 << (::core::mem::size_of::<$is>() * 8 - 1)
);
}; };
($for:ident, $rep:ident, $is:ident, $sign_bit:expr) => { ($for:ident, $rep:ident, $is:ident, $sign_bit:expr) => {
#[derive(Copy, Clone)] #[derive(Copy, Clone)]

View File

@ -13,8 +13,8 @@ use module::ModuleRef;
use nan_preserving_float::{F32, F64}; use nan_preserving_float::{F32, F64};
use parity_wasm::elements::Local; use parity_wasm::elements::Local;
use value::{ use value::{
ArithmeticOps, ExtendInto, Float, Integer, LittleEndianConvert, RuntimeValue, TransmuteInto, ArithmeticOps, ExtendInto, Float, Integer, LittleEndianConvert, RuntimeValue, TransmuteInto, TryTruncateInto,
TryTruncateInto, WrapInto, WrapInto,
}; };
use {Signature, Trap, TrapKind, ValueType}; use {Signature, Trap, TrapKind, ValueType};
@ -211,9 +211,7 @@ impl Interpreter {
self.state = InterpreterState::Started; self.state = InterpreterState::Started;
self.run_interpreter_loop(externals)?; self.run_interpreter_loop(externals)?;
let opt_return_value = self let opt_return_value = self.return_type.map(|vt| self.value_stack.pop().with_type(vt));
.return_type
.map(|vt| self.value_stack.pop().with_type(vt));
// Ensure that stack is empty after the execution. This is guaranteed by the validation properties. // Ensure that stack is empty after the execution. This is guaranteed by the validation properties.
assert!(self.value_stack.len() == 0); assert!(self.value_stack.len() == 0);
@ -235,16 +233,12 @@ impl Interpreter {
swap(&mut self.state, &mut resumable_state); swap(&mut self.state, &mut resumable_state);
if let Some(return_val) = return_val { if let Some(return_val) = return_val {
self.value_stack self.value_stack.push(return_val.into()).map_err(Trap::new)?;
.push(return_val.into())
.map_err(Trap::new)?;
} }
self.run_interpreter_loop(externals)?; self.run_interpreter_loop(externals)?;
let opt_return_value = self let opt_return_value = self.return_type.map(|vt| self.value_stack.pop().with_type(vt));
.return_type
.map(|vt| self.value_stack.pop().with_type(vt));
// Ensure that stack is empty after the execution. This is guaranteed by the validation properties. // Ensure that stack is empty after the execution. This is guaranteed by the validation properties.
assert!(self.value_stack.len() == 0); assert!(self.value_stack.len() == 0);
@ -252,20 +246,16 @@ impl Interpreter {
Ok(opt_return_value) Ok(opt_return_value)
} }
fn run_interpreter_loop<'a, E: Externals + 'a>( fn run_interpreter_loop<'a, E: Externals + 'a>(&mut self, externals: &'a mut E) -> Result<(), Trap> {
&mut self,
externals: &'a mut E,
) -> Result<(), Trap> {
loop { loop {
let mut function_context = self.call_stack.pop().expect( let mut function_context = self
"on loop entry - not empty; on loop continue - checking for emptiness; qed", .call_stack
); .pop()
.expect("on loop entry - not empty; on loop continue - checking for emptiness; qed");
let function_ref = function_context.function.clone(); let function_ref = function_context.function.clone();
let function_body = function_ref let function_body = function_ref
.body() .body()
.expect( .expect("Host functions checked in function_return below; Internal functions always have a body; qed");
"Host functions checked in function_return below; Internal functions always have a body; qed"
);
if !function_context.is_initialized() { if !function_context.is_initialized() {
// Initialize stack frame for the function call. // Initialize stack frame for the function call.
@ -300,18 +290,15 @@ impl Interpreter {
// We push the function context first. If the VM is not resumable, it does no harm. If it is, we then save the context here. // We push the function context first. If the VM is not resumable, it does no harm. If it is, we then save the context here.
self.call_stack.push(function_context); self.call_stack.push(function_context);
let return_val = let return_val = match FuncInstance::invoke(&nested_func, &args, externals) {
match FuncInstance::invoke(&nested_func, &args, externals) { Ok(val) => val,
Ok(val) => val, Err(trap) => {
Err(trap) => { if trap.kind().is_host() {
if trap.kind().is_host() { self.state = InterpreterState::Resumable(nested_func.signature().return_type());
self.state = InterpreterState::Resumable(
nested_func.signature().return_type(),
);
}
return Err(trap);
} }
}; return Err(trap);
}
};
// Check if `return_val` matches the signature. // Check if `return_val` matches the signature.
let value_ty = return_val.as_ref().map(|val| val.value_type()); let value_ty = return_val.as_ref().map(|val| val.value_type());
@ -321,9 +308,7 @@ impl Interpreter {
} }
if let Some(return_val) = return_val { if let Some(return_val) = return_val {
self.value_stack self.value_stack.push(return_val.into()).map_err(Trap::new)?;
.push(return_val.into())
.map_err(Trap::new)?;
} }
} }
} }
@ -392,52 +377,26 @@ impl Interpreter {
&isa::Instruction::I64Load(offset) => self.run_load::<i64>(context, offset), &isa::Instruction::I64Load(offset) => self.run_load::<i64>(context, offset),
&isa::Instruction::F32Load(offset) => self.run_load::<F32>(context, offset), &isa::Instruction::F32Load(offset) => self.run_load::<F32>(context, offset),
&isa::Instruction::F64Load(offset) => self.run_load::<F64>(context, offset), &isa::Instruction::F64Load(offset) => self.run_load::<F64>(context, offset),
&isa::Instruction::I32Load8S(offset) => { &isa::Instruction::I32Load8S(offset) => self.run_load_extend::<i8, i32>(context, offset),
self.run_load_extend::<i8, i32>(context, offset) &isa::Instruction::I32Load8U(offset) => self.run_load_extend::<u8, i32>(context, offset),
} &isa::Instruction::I32Load16S(offset) => self.run_load_extend::<i16, i32>(context, offset),
&isa::Instruction::I32Load8U(offset) => { &isa::Instruction::I32Load16U(offset) => self.run_load_extend::<u16, i32>(context, offset),
self.run_load_extend::<u8, i32>(context, offset) &isa::Instruction::I64Load8S(offset) => self.run_load_extend::<i8, i64>(context, offset),
} &isa::Instruction::I64Load8U(offset) => self.run_load_extend::<u8, i64>(context, offset),
&isa::Instruction::I32Load16S(offset) => { &isa::Instruction::I64Load16S(offset) => self.run_load_extend::<i16, i64>(context, offset),
self.run_load_extend::<i16, i32>(context, offset) &isa::Instruction::I64Load16U(offset) => self.run_load_extend::<u16, i64>(context, offset),
} &isa::Instruction::I64Load32S(offset) => self.run_load_extend::<i32, i64>(context, offset),
&isa::Instruction::I32Load16U(offset) => { &isa::Instruction::I64Load32U(offset) => self.run_load_extend::<u32, i64>(context, offset),
self.run_load_extend::<u16, i32>(context, offset)
}
&isa::Instruction::I64Load8S(offset) => {
self.run_load_extend::<i8, i64>(context, offset)
}
&isa::Instruction::I64Load8U(offset) => {
self.run_load_extend::<u8, i64>(context, offset)
}
&isa::Instruction::I64Load16S(offset) => {
self.run_load_extend::<i16, i64>(context, offset)
}
&isa::Instruction::I64Load16U(offset) => {
self.run_load_extend::<u16, i64>(context, offset)
}
&isa::Instruction::I64Load32S(offset) => {
self.run_load_extend::<i32, i64>(context, offset)
}
&isa::Instruction::I64Load32U(offset) => {
self.run_load_extend::<u32, i64>(context, offset)
}
&isa::Instruction::I32Store(offset) => self.run_store::<i32>(context, offset), &isa::Instruction::I32Store(offset) => self.run_store::<i32>(context, offset),
&isa::Instruction::I64Store(offset) => self.run_store::<i64>(context, offset), &isa::Instruction::I64Store(offset) => self.run_store::<i64>(context, offset),
&isa::Instruction::F32Store(offset) => self.run_store::<F32>(context, offset), &isa::Instruction::F32Store(offset) => self.run_store::<F32>(context, offset),
&isa::Instruction::F64Store(offset) => self.run_store::<F64>(context, offset), &isa::Instruction::F64Store(offset) => self.run_store::<F64>(context, offset),
&isa::Instruction::I32Store8(offset) => self.run_store_wrap::<i32, i8>(context, offset), &isa::Instruction::I32Store8(offset) => self.run_store_wrap::<i32, i8>(context, offset),
&isa::Instruction::I32Store16(offset) => { &isa::Instruction::I32Store16(offset) => self.run_store_wrap::<i32, i16>(context, offset),
self.run_store_wrap::<i32, i16>(context, offset)
}
&isa::Instruction::I64Store8(offset) => self.run_store_wrap::<i64, i8>(context, offset), &isa::Instruction::I64Store8(offset) => self.run_store_wrap::<i64, i8>(context, offset),
&isa::Instruction::I64Store16(offset) => { &isa::Instruction::I64Store16(offset) => self.run_store_wrap::<i64, i16>(context, offset),
self.run_store_wrap::<i64, i16>(context, offset) &isa::Instruction::I64Store32(offset) => self.run_store_wrap::<i64, i32>(context, offset),
}
&isa::Instruction::I64Store32(offset) => {
self.run_store_wrap::<i64, i32>(context, offset)
}
&isa::Instruction::CurrentMemory => self.run_current_memory(context), &isa::Instruction::CurrentMemory => self.run_current_memory(context),
&isa::Instruction::GrowMemory => self.run_grow_memory(context), &isa::Instruction::GrowMemory => self.run_grow_memory(context),
@ -582,18 +541,11 @@ impl Interpreter {
} }
} }
fn run_unreachable( fn run_unreachable(&mut self, _context: &mut FunctionContext) -> Result<InstructionOutcome, TrapKind> {
&mut self,
_context: &mut FunctionContext,
) -> Result<InstructionOutcome, TrapKind> {
Err(TrapKind::Unreachable) Err(TrapKind::Unreachable)
} }
fn run_br( fn run_br(&mut self, _context: &mut FunctionContext, target: isa::Target) -> Result<InstructionOutcome, TrapKind> {
&mut self,
_context: &mut FunctionContext,
target: isa::Target,
) -> Result<InstructionOutcome, TrapKind> {
Ok(InstructionOutcome::Branch(target)) Ok(InstructionOutcome::Branch(target))
} }
@ -633,11 +585,7 @@ impl Interpreter {
Ok(InstructionOutcome::Return(drop_keep)) Ok(InstructionOutcome::Return(drop_keep))
} }
fn run_call( fn run_call(&mut self, context: &mut FunctionContext, func_idx: u32) -> Result<InstructionOutcome, TrapKind> {
&mut self,
context: &mut FunctionContext,
func_idx: u32,
) -> Result<InstructionOutcome, TrapKind> {
let func = context let func = context
.module() .module()
.func_by_index(func_idx) .func_by_index(func_idx)
@ -707,11 +655,7 @@ impl Interpreter {
Ok(InstructionOutcome::RunNextInstruction) Ok(InstructionOutcome::RunNextInstruction)
} }
fn run_get_global( fn run_get_global(&mut self, context: &mut FunctionContext, index: u32) -> Result<InstructionOutcome, TrapKind> {
&mut self,
context: &mut FunctionContext,
index: u32,
) -> Result<InstructionOutcome, TrapKind> {
let global = context let global = context
.module() .module()
.global_by_index(index) .global_by_index(index)
@ -721,11 +665,7 @@ impl Interpreter {
Ok(InstructionOutcome::RunNextInstruction) Ok(InstructionOutcome::RunNextInstruction)
} }
fn run_set_global( fn run_set_global(&mut self, context: &mut FunctionContext, index: u32) -> Result<InstructionOutcome, TrapKind> {
&mut self,
context: &mut FunctionContext,
index: u32,
) -> Result<InstructionOutcome, TrapKind> {
let val = self.value_stack.pop(); let val = self.value_stack.pop();
let global = context let global = context
.module() .module()
@ -737,23 +677,15 @@ impl Interpreter {
Ok(InstructionOutcome::RunNextInstruction) Ok(InstructionOutcome::RunNextInstruction)
} }
fn run_load<T>( fn run_load<T>(&mut self, context: &mut FunctionContext, offset: u32) -> Result<InstructionOutcome, TrapKind>
&mut self,
context: &mut FunctionContext,
offset: u32,
) -> Result<InstructionOutcome, TrapKind>
where where
RuntimeValueInternal: From<T>, RuntimeValueInternal: From<T>,
T: LittleEndianConvert, T: LittleEndianConvert,
{ {
let raw_address = self.value_stack.pop_as(); let raw_address = self.value_stack.pop_as();
let address = effective_address(offset, raw_address)?; let address = effective_address(offset, raw_address)?;
let m = context let m = context.memory().expect("Due to validation memory should exists");
.memory() let n: T = m.get_value(address).map_err(|_| TrapKind::MemoryAccessOutOfBounds)?;
.expect("Due to validation memory should exists");
let n: T = m
.get_value(address)
.map_err(|_| TrapKind::MemoryAccessOutOfBounds)?;
self.value_stack.push(n.into())?; self.value_stack.push(n.into())?;
Ok(InstructionOutcome::RunNextInstruction) Ok(InstructionOutcome::RunNextInstruction)
} }
@ -770,12 +702,8 @@ impl Interpreter {
{ {
let raw_address = self.value_stack.pop_as(); let raw_address = self.value_stack.pop_as();
let address = effective_address(offset, raw_address)?; let address = effective_address(offset, raw_address)?;
let m = context let m = context.memory().expect("Due to validation memory should exists");
.memory() let v: T = m.get_value(address).map_err(|_| TrapKind::MemoryAccessOutOfBounds)?;
.expect("Due to validation memory should exists");
let v: T = m
.get_value(address)
.map_err(|_| TrapKind::MemoryAccessOutOfBounds)?;
let stack_value: U = v.extend_into(); let stack_value: U = v.extend_into();
self.value_stack self.value_stack
.push(stack_value.into()) .push(stack_value.into())
@ -783,11 +711,7 @@ impl Interpreter {
.map(|_| InstructionOutcome::RunNextInstruction) .map(|_| InstructionOutcome::RunNextInstruction)
} }
fn run_store<T>( fn run_store<T>(&mut self, context: &mut FunctionContext, offset: u32) -> Result<InstructionOutcome, TrapKind>
&mut self,
context: &mut FunctionContext,
offset: u32,
) -> Result<InstructionOutcome, TrapKind>
where where
T: FromRuntimeValueInternal, T: FromRuntimeValueInternal,
T: LittleEndianConvert, T: LittleEndianConvert,
@ -796,9 +720,7 @@ impl Interpreter {
let raw_address = self.value_stack.pop_as::<u32>(); let raw_address = self.value_stack.pop_as::<u32>();
let address = effective_address(offset, raw_address)?; let address = effective_address(offset, raw_address)?;
let m = context let m = context.memory().expect("Due to validation memory should exists");
.memory()
.expect("Due to validation memory should exists");
m.set_value(address, stack_value) m.set_value(address, stack_value)
.map_err(|_| TrapKind::MemoryAccessOutOfBounds)?; .map_err(|_| TrapKind::MemoryAccessOutOfBounds)?;
Ok(InstructionOutcome::RunNextInstruction) Ok(InstructionOutcome::RunNextInstruction)
@ -818,34 +740,22 @@ impl Interpreter {
let stack_value = stack_value.wrap_into(); let stack_value = stack_value.wrap_into();
let raw_address = self.value_stack.pop_as::<u32>(); let raw_address = self.value_stack.pop_as::<u32>();
let address = effective_address(offset, raw_address)?; let address = effective_address(offset, raw_address)?;
let m = context let m = context.memory().expect("Due to validation memory should exists");
.memory()
.expect("Due to validation memory should exists");
m.set_value(address, stack_value) m.set_value(address, stack_value)
.map_err(|_| TrapKind::MemoryAccessOutOfBounds)?; .map_err(|_| TrapKind::MemoryAccessOutOfBounds)?;
Ok(InstructionOutcome::RunNextInstruction) Ok(InstructionOutcome::RunNextInstruction)
} }
fn run_current_memory( fn run_current_memory(&mut self, context: &mut FunctionContext) -> Result<InstructionOutcome, TrapKind> {
&mut self, let m = context.memory().expect("Due to validation memory should exists");
context: &mut FunctionContext,
) -> Result<InstructionOutcome, TrapKind> {
let m = context
.memory()
.expect("Due to validation memory should exists");
let s = m.current_size().0; let s = m.current_size().0;
self.value_stack.push(RuntimeValueInternal(s as _))?; self.value_stack.push(RuntimeValueInternal(s as _))?;
Ok(InstructionOutcome::RunNextInstruction) Ok(InstructionOutcome::RunNextInstruction)
} }
fn run_grow_memory( fn run_grow_memory(&mut self, context: &mut FunctionContext) -> Result<InstructionOutcome, TrapKind> {
&mut self,
context: &mut FunctionContext,
) -> Result<InstructionOutcome, TrapKind> {
let pages: u32 = self.value_stack.pop_as(); let pages: u32 = self.value_stack.pop_as();
let m = context let m = context.memory().expect("Due to validation memory should exists");
.memory()
.expect("Due to validation memory should exists");
let m = match m.grow(Pages(pages as usize)) { let m = match m.grow(Pages(pages as usize)) {
Ok(Pages(new_size)) => new_size as u32, Ok(Pages(new_size)) => new_size as u32,
Err(_) => u32::MAX, // Returns -1 (or 0xFFFFFFFF) in case of error. Err(_) => u32::MAX, // Returns -1 (or 0xFFFFFFFF) in case of error.
@ -1279,11 +1189,7 @@ impl FunctionContext {
self.is_initialized self.is_initialized
} }
pub fn initialize( pub fn initialize(&mut self, locals: &[Local], value_stack: &mut ValueStack) -> Result<(), TrapKind> {
&mut self,
locals: &[Local],
value_stack: &mut ValueStack,
) -> Result<(), TrapKind> {
debug_assert!(!self.is_initialized); debug_assert!(!self.is_initialized);
let num_locals = locals.iter().map(|l| l.count() as usize).sum(); let num_locals = locals.iter().map(|l| l.count() as usize).sum();
@ -1291,9 +1197,7 @@ impl FunctionContext {
// TODO: Replace with extend. // TODO: Replace with extend.
for local in locals { for local in locals {
value_stack value_stack.push(local).map_err(|_| TrapKind::StackOverflow)?;
.push(local)
.map_err(|_| TrapKind::StackOverflow)?;
} }
self.is_initialized = true; self.is_initialized = true;
@ -1322,10 +1226,7 @@ fn effective_address(address: u32, offset: u32) -> Result<u32, TrapKind> {
} }
} }
fn prepare_function_args( fn prepare_function_args(signature: &Signature, caller_stack: &mut ValueStack) -> Vec<RuntimeValue> {
signature: &Signature,
caller_stack: &mut ValueStack,
) -> Vec<RuntimeValue> {
let mut out = signature let mut out = signature
.params() .params()
.iter() .iter()
@ -1341,14 +1242,10 @@ pub fn check_function_args(signature: &Signature, args: &[RuntimeValue]) -> Resu
return Err(TrapKind::UnexpectedSignature.into()); return Err(TrapKind::UnexpectedSignature.into());
} }
if signature if signature.params().iter().zip(args).any(|(expected_type, param_value)| {
.params() let actual_type = param_value.value_type();
.iter() &actual_type != expected_type
.zip(args) }) {
.any(|(expected_type, param_value)| {
let actual_type = param_value.value_type();
&actual_type != expected_type
}) {
return Err(TrapKind::UnexpectedSignature.into()); return Err(TrapKind::UnexpectedSignature.into());
} }
@ -1405,13 +1302,7 @@ impl ValueStack {
} }
#[inline] #[inline]
fn pop_triple( fn pop_triple(&mut self) -> (RuntimeValueInternal, RuntimeValueInternal, RuntimeValueInternal) {
&mut self,
) -> (
RuntimeValueInternal,
RuntimeValueInternal,
RuntimeValueInternal,
) {
let right = self.pop(); let right = self.pop();
let mid = self.pop(); let mid = self.pop();
let left = self.pop(); let left = self.pop();
@ -1440,10 +1331,7 @@ impl ValueStack {
#[inline] #[inline]
fn push(&mut self, value: RuntimeValueInternal) -> Result<(), TrapKind> { fn push(&mut self, value: RuntimeValueInternal) -> Result<(), TrapKind> {
let cell = self let cell = self.buf.get_mut(self.sp).ok_or_else(|| TrapKind::StackOverflow)?;
.buf
.get_mut(self.sp)
.ok_or_else(|| TrapKind::StackOverflow)?;
*cell = value; *cell = value;
self.sp += 1; self.sp += 1;
Ok(()) Ok(())

View File

@ -109,13 +109,8 @@ impl TableInstance {
let new_size = self let new_size = self
.current_size() .current_size()
.checked_add(by) .checked_add(by)
.and_then(|new_size| { .and_then(|new_size| if maximum_size < new_size { None } else { Some(new_size) })
if maximum_size < new_size { .ok_or_else(|| {
None
} else {
Some(new_size)
}
}).ok_or_else(|| {
Error::Table(format!( Error::Table(format!(
"Trying to grow table by {} items when there are already {} items", "Trying to grow table by {} items when there are already {} items",
by, by,

View File

@ -2,9 +2,9 @@ use super::parse_wat;
use memory_units::Pages; use memory_units::Pages;
use types::ValueType; use types::ValueType;
use { use {
Error, Externals, FuncInstance, FuncRef, HostError, ImportsBuilder, MemoryDescriptor, Error, Externals, FuncInstance, FuncRef, HostError, ImportsBuilder, MemoryDescriptor, MemoryInstance, MemoryRef,
MemoryInstance, MemoryRef, ModuleImportResolver, ModuleInstance, ModuleRef, ResumableError, ModuleImportResolver, ModuleInstance, ModuleRef, ResumableError, RuntimeArgs, RuntimeValue, Signature,
RuntimeArgs, RuntimeValue, Signature, TableDescriptor, TableInstance, TableRef, Trap, TrapKind, TableDescriptor, TableInstance, TableRef, Trap, TrapKind,
}; };
#[derive(Debug, Clone, PartialEq)] #[derive(Debug, Clone, PartialEq)]
@ -85,11 +85,7 @@ const RECURSE_FUNC_INDEX: usize = 4;
const TRAP_SUB_FUNC_INDEX: usize = 5; const TRAP_SUB_FUNC_INDEX: usize = 5;
impl Externals for TestHost { impl Externals for TestHost {
fn invoke_index( fn invoke_index(&mut self, index: usize, args: RuntimeArgs) -> Result<Option<RuntimeValue>, Trap> {
&mut self,
index: usize,
args: RuntimeArgs,
) -> Result<Option<RuntimeValue>, Trap> {
match index { match index {
SUB_FUNC_INDEX => { SUB_FUNC_INDEX => {
let a: i32 = args.nth(0); let a: i32 = args.nth(0);
@ -131,9 +127,7 @@ impl Externals for TestHost {
Ok(Some(RuntimeValue::I32(buf[0] as i32))) Ok(Some(RuntimeValue::I32(buf[0] as i32)))
} }
RECURSE_FUNC_INDEX => { RECURSE_FUNC_INDEX => {
let val = args let val = args.nth_value_checked(0).expect("Exactly one argument expected");
.nth_value_checked(0)
.expect("Exactly one argument expected");
let instance = self let instance = self
.instance .instance
@ -146,9 +140,7 @@ impl Externals for TestHost {
.expect("expected to be Some"); .expect("expected to be Some");
if val.value_type() != result.value_type() { if val.value_type() != result.value_type() {
return Err( return Err(TrapKind::Host(Box::new(HostErrorWithCode { error_code: 123 })).into());
TrapKind::Host(Box::new(HostErrorWithCode { error_code: 123 })).into(),
);
} }
Ok(Some(result)) Ok(Some(result))
} }
@ -198,12 +190,7 @@ impl ModuleImportResolver for TestHost {
"get_mem" => GET_MEM_FUNC_INDEX, "get_mem" => GET_MEM_FUNC_INDEX,
"recurse" => RECURSE_FUNC_INDEX, "recurse" => RECURSE_FUNC_INDEX,
"trap_sub" => TRAP_SUB_FUNC_INDEX, "trap_sub" => TRAP_SUB_FUNC_INDEX,
_ => { _ => return Err(Error::Instantiation(format!("Export {} not found", field_name))),
return Err(Error::Instantiation(format!(
"Export {} not found",
field_name
)))
}
}; };
if !self.check_signature(index, signature) { if !self.check_signature(index, signature) {
@ -216,15 +203,8 @@ impl ModuleImportResolver for TestHost {
Ok(FuncInstance::alloc_host(signature.clone(), index)) Ok(FuncInstance::alloc_host(signature.clone(), index))
} }
fn resolve_memory( fn resolve_memory(&self, field_name: &str, _memory_type: &MemoryDescriptor) -> Result<MemoryRef, Error> {
&self, Err(Error::Instantiation(format!("Export {} not found", field_name)))
field_name: &str,
_memory_type: &MemoryDescriptor,
) -> Result<MemoryRef, Error> {
Err(Error::Instantiation(format!(
"Export {} not found",
field_name
)))
} }
} }
@ -484,10 +464,7 @@ fn defer_providing_externals() {
impl ModuleImportResolver for HostImportResolver { impl ModuleImportResolver for HostImportResolver {
fn resolve_func(&self, field_name: &str, signature: &Signature) -> Result<FuncRef, Error> { fn resolve_func(&self, field_name: &str, signature: &Signature) -> Result<FuncRef, Error> {
if field_name != "inc" { if field_name != "inc" {
return Err(Error::Instantiation(format!( return Err(Error::Instantiation(format!("Export {} not found", field_name)));
"Export {} not found",
field_name
)));
} }
if signature.params() != &[ValueType::I32] || signature.return_type() != None { if signature.params() != &[ValueType::I32] || signature.return_type() != None {
return Err(Error::Instantiation(format!( return Err(Error::Instantiation(format!(
@ -499,18 +476,11 @@ fn defer_providing_externals() {
Ok(FuncInstance::alloc_host(signature.clone(), INC_FUNC_INDEX)) Ok(FuncInstance::alloc_host(signature.clone(), INC_FUNC_INDEX))
} }
fn resolve_memory( fn resolve_memory(&self, field_name: &str, _memory_type: &MemoryDescriptor) -> Result<MemoryRef, Error> {
&self,
field_name: &str,
_memory_type: &MemoryDescriptor,
) -> Result<MemoryRef, Error> {
if field_name == "mem" { if field_name == "mem" {
Ok(self.mem.clone()) Ok(self.mem.clone())
} else { } else {
Err(Error::Instantiation(format!( Err(Error::Instantiation(format!("Export {} not found", field_name)))
"Export {} not found",
field_name
)))
} }
} }
} }
@ -522,11 +492,7 @@ fn defer_providing_externals() {
} }
impl<'a> Externals for HostExternals<'a> { impl<'a> Externals for HostExternals<'a> {
fn invoke_index( fn invoke_index(&mut self, index: usize, args: RuntimeArgs) -> Result<Option<RuntimeValue>, Trap> {
&mut self,
index: usize,
args: RuntimeArgs,
) -> Result<Option<RuntimeValue>, Trap> {
match index { match index {
INC_FUNC_INDEX => { INC_FUNC_INDEX => {
let a = args.nth::<u32>(0); let a = args.nth::<u32>(0);
@ -569,12 +535,8 @@ fn defer_providing_externals() {
{ {
let mut host_externals = HostExternals { acc: &mut acc }; let mut host_externals = HostExternals { acc: &mut acc };
instance instance.invoke_export("test", &[], &mut host_externals).unwrap(); // acc += 1;
.invoke_export("test", &[], &mut host_externals) instance.invoke_export("test", &[], &mut host_externals).unwrap(); // acc += 1;
.unwrap(); // acc += 1;
instance
.invoke_export("test", &[], &mut host_externals)
.unwrap(); // acc += 1;
} }
assert_eq!(acc, 91); assert_eq!(acc, 91);
} }
@ -587,11 +549,7 @@ fn two_envs_one_externals() {
struct HostExternals; struct HostExternals;
impl Externals for HostExternals { impl Externals for HostExternals {
fn invoke_index( fn invoke_index(&mut self, index: usize, _args: RuntimeArgs) -> Result<Option<RuntimeValue>, Trap> {
&mut self,
index: usize,
_args: RuntimeArgs,
) -> Result<Option<RuntimeValue>, Trap> {
match index { match index {
PRIVILEGED_FUNC_INDEX => { PRIVILEGED_FUNC_INDEX => {
println!("privileged!"); println!("privileged!");
@ -611,12 +569,7 @@ fn two_envs_one_externals() {
let index = match field_name { let index = match field_name {
"ordinary" => ORDINARY_FUNC_INDEX, "ordinary" => ORDINARY_FUNC_INDEX,
"privileged" => PRIVILEGED_FUNC_INDEX, "privileged" => PRIVILEGED_FUNC_INDEX,
_ => { _ => return Err(Error::Instantiation(format!("Export {} not found", field_name))),
return Err(Error::Instantiation(format!(
"Export {} not found",
field_name
)))
}
}; };
Ok(FuncInstance::alloc_host(signature.clone(), index)) Ok(FuncInstance::alloc_host(signature.clone(), index))
@ -632,12 +585,7 @@ fn two_envs_one_externals() {
"'priveleged' can be imported only in privileged context".into(), "'priveleged' can be imported only in privileged context".into(),
)) ))
} }
_ => { _ => return Err(Error::Instantiation(format!("Export {} not found", field_name))),
return Err(Error::Instantiation(format!(
"Export {} not found",
field_name
)))
}
}; };
Ok(FuncInstance::alloc_host(signature.clone(), index)) Ok(FuncInstance::alloc_host(signature.clone(), index))
@ -701,11 +649,7 @@ fn dynamically_add_host_func() {
} }
impl Externals for HostExternals { impl Externals for HostExternals {
fn invoke_index( fn invoke_index(&mut self, index: usize, _args: RuntimeArgs) -> Result<Option<RuntimeValue>, Trap> {
&mut self,
index: usize,
_args: RuntimeArgs,
) -> Result<Option<RuntimeValue>, Trap> {
match index { match index {
ADD_FUNC_FUNC_INDEX => { ADD_FUNC_FUNC_INDEX => {
// Allocate indicies for the new function. // Allocate indicies for the new function.
@ -724,9 +668,7 @@ fn dynamically_add_host_func() {
Ok(Some(RuntimeValue::I32(table_index as i32))) Ok(Some(RuntimeValue::I32(table_index as i32)))
} }
index if index as u32 <= self.added_funcs => { index if index as u32 <= self.added_funcs => Ok(Some(RuntimeValue::I32(index as i32))),
Ok(Some(RuntimeValue::I32(index as i32)))
}
_ => panic!("'env' module doesn't provide function at index {}", index), _ => panic!("'env' module doesn't provide function at index {}", index),
} }
} }
@ -736,28 +678,16 @@ fn dynamically_add_host_func() {
fn resolve_func(&self, field_name: &str, signature: &Signature) -> Result<FuncRef, Error> { fn resolve_func(&self, field_name: &str, signature: &Signature) -> Result<FuncRef, Error> {
let index = match field_name { let index = match field_name {
"add_func" => ADD_FUNC_FUNC_INDEX, "add_func" => ADD_FUNC_FUNC_INDEX,
_ => { _ => return Err(Error::Instantiation(format!("Export {} not found", field_name))),
return Err(Error::Instantiation(format!(
"Export {} not found",
field_name
)))
}
}; };
Ok(FuncInstance::alloc_host(signature.clone(), index)) Ok(FuncInstance::alloc_host(signature.clone(), index))
} }
fn resolve_table( fn resolve_table(&self, field_name: &str, _table_type: &TableDescriptor) -> Result<TableRef, Error> {
&self,
field_name: &str,
_table_type: &TableDescriptor,
) -> Result<TableRef, Error> {
if field_name == "table" { if field_name == "table" {
Ok(self.table.clone()) Ok(self.table.clone())
} else { } else {
Err(Error::Instantiation(format!( Err(Error::Instantiation(format!("Export {} not found", field_name)))
"Export {} not found",
field_name
)))
} }
} }
} }
@ -786,11 +716,9 @@ fn dynamically_add_host_func() {
"#, "#,
); );
let instance = ModuleInstance::new( let instance = ModuleInstance::new(&module, &ImportsBuilder::new().with_resolver("env", &host_externals))
&module, .expect("Failed to instantiate module")
&ImportsBuilder::new().with_resolver("env", &host_externals), .assert_no_start();
).expect("Failed to instantiate module")
.assert_no_start();
assert_eq!( assert_eq!(
instance instance

View File

@ -1,9 +1,9 @@
use memory_units::Pages; use memory_units::Pages;
use std::fs::File; use std::fs::File;
use { use {
Error, FuncRef, GlobalDescriptor, GlobalInstance, GlobalRef, ImportsBuilder, MemoryDescriptor, Error, FuncRef, GlobalDescriptor, GlobalInstance, GlobalRef, ImportsBuilder, MemoryDescriptor, MemoryInstance,
MemoryInstance, MemoryRef, Module, ModuleImportResolver, ModuleInstance, NopExternals, MemoryRef, Module, ModuleImportResolver, ModuleInstance, NopExternals, RuntimeValue, Signature, TableDescriptor,
RuntimeValue, Signature, TableDescriptor, TableInstance, TableRef, TableInstance, TableRef,
}; };
struct Env { struct Env {
@ -26,16 +26,10 @@ impl Env {
impl ModuleImportResolver for Env { impl ModuleImportResolver for Env {
fn resolve_func(&self, _field_name: &str, _func_type: &Signature) -> Result<FuncRef, Error> { fn resolve_func(&self, _field_name: &str, _func_type: &Signature) -> Result<FuncRef, Error> {
Err(Error::Instantiation( Err(Error::Instantiation("env module doesn't provide any functions".into()))
"env module doesn't provide any functions".into(),
))
} }
fn resolve_global( fn resolve_global(&self, field_name: &str, _global_type: &GlobalDescriptor) -> Result<GlobalRef, Error> {
&self,
field_name: &str,
_global_type: &GlobalDescriptor,
) -> Result<GlobalRef, Error> {
match field_name { match field_name {
"tableBase" => Ok(self.table_base.clone()), "tableBase" => Ok(self.table_base.clone()),
"memoryBase" => Ok(self.memory_base.clone()), "memoryBase" => Ok(self.memory_base.clone()),
@ -46,11 +40,7 @@ impl ModuleImportResolver for Env {
} }
} }
fn resolve_memory( fn resolve_memory(&self, field_name: &str, _memory_type: &MemoryDescriptor) -> Result<MemoryRef, Error> {
&self,
field_name: &str,
_memory_type: &MemoryDescriptor,
) -> Result<MemoryRef, Error> {
match field_name { match field_name {
"memory" => Ok(self.memory.clone()), "memory" => Ok(self.memory.clone()),
_ => Err(Error::Instantiation(format!( _ => Err(Error::Instantiation(format!(
@ -60,11 +50,7 @@ impl ModuleImportResolver for Env {
} }
} }
fn resolve_table( fn resolve_table(&self, field_name: &str, _table_type: &TableDescriptor) -> Result<TableRef, Error> {
&self,
field_name: &str,
_table_type: &TableDescriptor,
) -> Result<TableRef, Error> {
match field_name { match field_name {
"table" => Ok(self.table.clone()), "table" => Ok(self.table.clone()),
_ => Err(Error::Instantiation(format!( _ => Err(Error::Instantiation(format!(
@ -134,10 +120,7 @@ fn interpreter_accumulate_u8() {
let _ = env_memory.set(offset, BUF); let _ = env_memory.set(offset, BUF);
// Set up the function argument list and invoke the function // Set up the function argument list and invoke the function
let args = &[ let args = &[RuntimeValue::I32(BUF.len() as i32), RuntimeValue::I32(offset as i32)];
RuntimeValue::I32(BUF.len() as i32),
RuntimeValue::I32(offset as i32),
];
let retval = instance let retval = instance
.invoke_export(FUNCTION_NAME, args, &mut NopExternals) .invoke_export(FUNCTION_NAME, args, &mut NopExternals)
.expect("Failed to execute function"); .expect("Failed to execute function");

View File

@ -1,8 +1,6 @@
use alloc::borrow::Cow; use alloc::borrow::Cow;
use parity_wasm::elements::{ use parity_wasm::elements::{FunctionType, GlobalType, MemoryType, TableType, ValueType as EValueType};
FunctionType, GlobalType, MemoryType, TableType, ValueType as EValueType,
};
/// Signature of a [function]. /// Signature of a [function].
/// ///
@ -37,10 +35,7 @@ impl Signature {
/// let dynamic_params = vec![ValueType::I64]; /// let dynamic_params = vec![ValueType::I64];
/// let s3 = Signature::new(dynamic_params, None); /// let s3 = Signature::new(dynamic_params, None);
/// ``` /// ```
pub fn new<C: Into<Cow<'static, [ValueType]>>>( pub fn new<C: Into<Cow<'static, [ValueType]>>>(params: C, return_type: Option<ValueType>) -> Signature {
params: C,
return_type: Option<ValueType>,
) -> Signature {
Signature { Signature {
params: params.into(), params: params.into(),
return_type: return_type, return_type: return_type,

View File

@ -1,8 +1,6 @@
#[allow(unused_imports)] #[allow(unused_imports)]
use alloc::prelude::*; use alloc::prelude::*;
use parity_wasm::elements::{ use parity_wasm::elements::{BlockType, FunctionType, GlobalType, MemoryType, TableType, ValueType};
BlockType, FunctionType, GlobalType, MemoryType, TableType, ValueType,
};
use validation::Error; use validation::Error;
#[derive(Default, Debug)] #[derive(Default, Debug)]
@ -63,10 +61,7 @@ impl ModuleContext {
.ok_or_else(|| Error(format!("Type at index {} doesn't exists", idx)))?; .ok_or_else(|| Error(format!("Type at index {} doesn't exists", idx)))?;
let params = ty.params(); let params = ty.params();
let return_ty = ty let return_ty = ty.return_type().map(BlockType::Value).unwrap_or(BlockType::NoResult);
.return_type()
.map(BlockType::Value)
.unwrap_or(BlockType::NoResult);
Ok((params, return_ty)) Ok((params, return_ty))
} }

View File

@ -158,11 +158,7 @@ enum Outcome {
pub struct FunctionReader; pub struct FunctionReader;
impl FunctionReader { impl FunctionReader {
pub fn read_function( pub fn read_function(module: &ModuleContext, func: &Func, body: &FuncBody) -> Result<isa::Instructions, Error> {
module: &ModuleContext,
func: &Func,
body: &FuncBody,
) -> Result<isa::Instructions, Error> {
let (params, result_ty) = module.require_function_type(func.type_ref())?; let (params, result_ty) = module.require_function_type(func.type_ref())?;
let ins_size_estimate = body.code().elements().len(); let ins_size_estimate = body.code().elements().len();
@ -190,10 +186,7 @@ impl FunctionReader {
Ok(context.into_code()) Ok(context.into_code())
} }
fn read_function_body( fn read_function_body(context: &mut FunctionValidationContext, body: &[Instruction]) -> Result<(), Error> {
context: &mut FunctionValidationContext,
body: &[Instruction],
) -> Result<(), Error> {
let body_len = body.len(); let body_len = body.len();
if body_len == 0 { if body_len == 0 {
return Err(Error("Non-empty function body expected".into())); return Err(Error("Non-empty function body expected".into()));
@ -202,19 +195,16 @@ impl FunctionReader {
loop { loop {
let instruction = &body[context.position]; let instruction = &body[context.position];
let outcome = let outcome = FunctionReader::read_instruction(context, instruction).map_err(|err| {
FunctionReader::read_instruction(context, instruction).map_err(|err| { Error(format!(
Error(format!( "At instruction {:?}(@{}): {}",
"At instruction {:?}(@{}): {}", instruction, context.position, err
instruction, context.position, err ))
)) })?;
})?;
match outcome { match outcome {
Outcome::NextInstruction => (), Outcome::NextInstruction => (),
Outcome::Unreachable => { Outcome::Unreachable => make_top_frame_polymorphic(&mut context.value_stack, &mut context.frame_stack),
make_top_frame_polymorphic(&mut context.value_stack, &mut context.frame_stack)
}
} }
context.position += 1; context.position += 1;
@ -224,10 +214,7 @@ impl FunctionReader {
} }
} }
fn read_instruction( fn read_instruction(context: &mut FunctionValidationContext, instruction: &Instruction) -> Result<Outcome, Error> {
context: &mut FunctionValidationContext,
instruction: &Instruction,
) -> Result<Outcome, Error> {
use self::Instruction::*; use self::Instruction::*;
match *instruction { match *instruction {
// Nop instruction doesn't do anything. It is safe to just skip it. // Nop instruction doesn't do anything. It is safe to just skip it.
@ -267,11 +254,7 @@ impl FunctionReader {
let if_not = context.sink.new_label(); let if_not = context.sink.new_label();
let end_label = context.sink.new_label(); let end_label = context.sink.new_label();
pop_value( pop_value(&mut context.value_stack, &context.frame_stack, ValueType::I32.into())?;
&mut context.value_stack,
&context.frame_stack,
ValueType::I32.into(),
)?;
push_label( push_label(
BlockFrameType::IfTrue { if_not, end_label }, BlockFrameType::IfTrue { if_not, end_label },
block_type, block_type,
@ -334,9 +317,9 @@ impl FunctionReader {
// A `if` without an `else` can't return a result. // A `if` without an `else` can't return a result.
if block_type != BlockType::NoResult { if block_type != BlockType::NoResult {
return Err(Error(format!( return Err(Error(format!(
"If block without else required to have NoResult block type. But it has {:?} type", "If block without else required to have NoResult block type. But it has {:?} type",
block_type block_type
))); )));
} }
// Resolve `if_not` label. If the `if's` condition doesn't hold the control will jump // Resolve `if_not` label. If the `if's` condition doesn't hold the control will jump
@ -356,19 +339,11 @@ impl FunctionReader {
// Check the return type. // Check the return type.
if let BlockType::Value(value_type) = context.return_type()? { if let BlockType::Value(value_type) = context.return_type()? {
tee_value( tee_value(&mut context.value_stack, &context.frame_stack, value_type.into())?;
&mut context.value_stack,
&context.frame_stack,
value_type.into(),
)?;
} }
// Emit the return instruction. // Emit the return instruction.
let drop_keep = drop_keep_return( let drop_keep = drop_keep_return(&context.locals, &context.value_stack, &context.frame_stack);
&context.locals,
&context.value_stack,
&context.frame_stack,
);
context.sink.emit(isa::Instruction::Return(drop_keep)); context.sink.emit(isa::Instruction::Return(drop_keep));
} }
@ -401,23 +376,17 @@ impl FunctionReader {
let target = require_target(*depth, &context.value_stack, &context.frame_stack); let target = require_target(*depth, &context.value_stack, &context.frame_stack);
targets.push(target); targets.push(target);
} }
let default_target = let default_target = require_target(default, &context.value_stack, &context.frame_stack);
require_target(default, &context.value_stack, &context.frame_stack);
context.sink.emit_br_table(&targets, default_target); context.sink.emit_br_table(&targets, default_target);
return Ok(Outcome::Unreachable); return Ok(Outcome::Unreachable);
} }
Return => { Return => {
if let BlockType::Value(value_type) = context.return_type()? { if let BlockType::Value(value_type) = context.return_type()? {
tee_value( tee_value(&mut context.value_stack, &context.frame_stack, value_type.into())?;
&mut context.value_stack,
&context.frame_stack,
value_type.into(),
)?;
} }
let drop_keep = let drop_keep = drop_keep_return(&context.locals, &context.value_stack, &context.frame_stack);
drop_keep_return(&context.locals, &context.value_stack, &context.frame_stack);
context.sink.emit(isa::Instruction::Return(drop_keep)); context.sink.emit(isa::Instruction::Return(drop_keep));
return Ok(Outcome::Unreachable); return Ok(Outcome::Unreachable);
@ -1098,72 +1067,33 @@ impl FunctionReader {
struct Validator; struct Validator;
impl Validator { impl Validator {
fn validate_const( fn validate_const(context: &mut FunctionValidationContext, value_type: ValueType) -> Result<(), Error> {
context: &mut FunctionValidationContext,
value_type: ValueType,
) -> Result<(), Error> {
push_value(&mut context.value_stack, value_type.into())?; push_value(&mut context.value_stack, value_type.into())?;
Ok(()) Ok(())
} }
fn validate_unop( fn validate_unop(context: &mut FunctionValidationContext, value_type: ValueType) -> Result<(), Error> {
context: &mut FunctionValidationContext, pop_value(&mut context.value_stack, &context.frame_stack, value_type.into())?;
value_type: ValueType,
) -> Result<(), Error> {
pop_value(
&mut context.value_stack,
&context.frame_stack,
value_type.into(),
)?;
push_value(&mut context.value_stack, value_type.into())?; push_value(&mut context.value_stack, value_type.into())?;
Ok(()) Ok(())
} }
fn validate_binop( fn validate_binop(context: &mut FunctionValidationContext, value_type: ValueType) -> Result<(), Error> {
context: &mut FunctionValidationContext, pop_value(&mut context.value_stack, &context.frame_stack, value_type.into())?;
value_type: ValueType, pop_value(&mut context.value_stack, &context.frame_stack, value_type.into())?;
) -> Result<(), Error> {
pop_value(
&mut context.value_stack,
&context.frame_stack,
value_type.into(),
)?;
pop_value(
&mut context.value_stack,
&context.frame_stack,
value_type.into(),
)?;
push_value(&mut context.value_stack, value_type.into())?; push_value(&mut context.value_stack, value_type.into())?;
Ok(()) Ok(())
} }
fn validate_testop( fn validate_testop(context: &mut FunctionValidationContext, value_type: ValueType) -> Result<(), Error> {
context: &mut FunctionValidationContext, pop_value(&mut context.value_stack, &context.frame_stack, value_type.into())?;
value_type: ValueType,
) -> Result<(), Error> {
pop_value(
&mut context.value_stack,
&context.frame_stack,
value_type.into(),
)?;
push_value(&mut context.value_stack, ValueType::I32.into())?; push_value(&mut context.value_stack, ValueType::I32.into())?;
Ok(()) Ok(())
} }
fn validate_relop( fn validate_relop(context: &mut FunctionValidationContext, value_type: ValueType) -> Result<(), Error> {
context: &mut FunctionValidationContext, pop_value(&mut context.value_stack, &context.frame_stack, value_type.into())?;
value_type: ValueType, pop_value(&mut context.value_stack, &context.frame_stack, value_type.into())?;
) -> Result<(), Error> {
pop_value(
&mut context.value_stack,
&context.frame_stack,
value_type.into(),
)?;
pop_value(
&mut context.value_stack,
&context.frame_stack,
value_type.into(),
)?;
push_value(&mut context.value_stack, ValueType::I32.into())?; push_value(&mut context.value_stack, ValueType::I32.into())?;
Ok(()) Ok(())
} }
@ -1173,59 +1103,33 @@ impl Validator {
value_type1: ValueType, value_type1: ValueType,
value_type2: ValueType, value_type2: ValueType,
) -> Result<(), Error> { ) -> Result<(), Error> {
pop_value( pop_value(&mut context.value_stack, &context.frame_stack, value_type1.into())?;
&mut context.value_stack,
&context.frame_stack,
value_type1.into(),
)?;
push_value(&mut context.value_stack, value_type2.into())?; push_value(&mut context.value_stack, value_type2.into())?;
Ok(()) Ok(())
} }
fn validate_drop(context: &mut FunctionValidationContext) -> Result<(), Error> { fn validate_drop(context: &mut FunctionValidationContext) -> Result<(), Error> {
pop_value( pop_value(&mut context.value_stack, &context.frame_stack, StackValueType::Any)?;
&mut context.value_stack,
&context.frame_stack,
StackValueType::Any,
)?;
Ok(()) Ok(())
} }
fn validate_select(context: &mut FunctionValidationContext) -> Result<(), Error> { fn validate_select(context: &mut FunctionValidationContext) -> Result<(), Error> {
pop_value( pop_value(&mut context.value_stack, &context.frame_stack, ValueType::I32.into())?;
&mut context.value_stack, let select_type = pop_value(&mut context.value_stack, &context.frame_stack, StackValueType::Any)?;
&context.frame_stack,
ValueType::I32.into(),
)?;
let select_type = pop_value(
&mut context.value_stack,
&context.frame_stack,
StackValueType::Any,
)?;
pop_value(&mut context.value_stack, &context.frame_stack, select_type)?; pop_value(&mut context.value_stack, &context.frame_stack, select_type)?;
push_value(&mut context.value_stack, select_type)?; push_value(&mut context.value_stack, select_type)?;
Ok(()) Ok(())
} }
fn validate_get_local( fn validate_get_local(context: &mut FunctionValidationContext, index: u32) -> Result<(), Error> {
context: &mut FunctionValidationContext,
index: u32,
) -> Result<(), Error> {
let local_type = require_local(&context.locals, index)?; let local_type = require_local(&context.locals, index)?;
push_value(&mut context.value_stack, local_type.into())?; push_value(&mut context.value_stack, local_type.into())?;
Ok(()) Ok(())
} }
fn validate_set_local( fn validate_set_local(context: &mut FunctionValidationContext, index: u32) -> Result<(), Error> {
context: &mut FunctionValidationContext,
index: u32,
) -> Result<(), Error> {
let local_type = require_local(&context.locals, index)?; let local_type = require_local(&context.locals, index)?;
let value_type = pop_value( let value_type = pop_value(&mut context.value_stack, &context.frame_stack, StackValueType::Any)?;
&mut context.value_stack,
&context.frame_stack,
StackValueType::Any,
)?;
if StackValueType::from(local_type) != value_type { if StackValueType::from(local_type) != value_type {
return Err(Error(format!( return Err(Error(format!(
"Trying to update local {} of type {:?} with value of type {:?}", "Trying to update local {} of type {:?} with value of type {:?}",
@ -1235,23 +1139,13 @@ impl Validator {
Ok(()) Ok(())
} }
fn validate_tee_local( fn validate_tee_local(context: &mut FunctionValidationContext, index: u32) -> Result<(), Error> {
context: &mut FunctionValidationContext,
index: u32,
) -> Result<(), Error> {
let local_type = require_local(&context.locals, index)?; let local_type = require_local(&context.locals, index)?;
tee_value( tee_value(&mut context.value_stack, &context.frame_stack, local_type.into())?;
&mut context.value_stack,
&context.frame_stack,
local_type.into(),
)?;
Ok(()) Ok(())
} }
fn validate_get_global( fn validate_get_global(context: &mut FunctionValidationContext, index: u32) -> Result<(), Error> {
context: &mut FunctionValidationContext,
index: u32,
) -> Result<(), Error> {
let global_type: StackValueType = { let global_type: StackValueType = {
let global = context.module.require_global(index, None)?; let global = context.module.require_global(index, None)?;
global.content_type().into() global.content_type().into()
@ -1260,19 +1154,12 @@ impl Validator {
Ok(()) Ok(())
} }
fn validate_set_global( fn validate_set_global(context: &mut FunctionValidationContext, index: u32) -> Result<(), Error> {
context: &mut FunctionValidationContext,
index: u32,
) -> Result<(), Error> {
let global_type: StackValueType = { let global_type: StackValueType = {
let global = context.module.require_global(index, Some(true))?; let global = context.module.require_global(index, Some(true))?;
global.content_type().into() global.content_type().into()
}; };
let value_type = pop_value( let value_type = pop_value(&mut context.value_stack, &context.frame_stack, StackValueType::Any)?;
&mut context.value_stack,
&context.frame_stack,
StackValueType::Any,
)?;
if global_type != value_type { if global_type != value_type {
return Err(Error(format!( return Err(Error(format!(
"Trying to update global {} of type {:?} with value of type {:?}", "Trying to update global {} of type {:?} with value of type {:?}",
@ -1295,11 +1182,7 @@ impl Validator {
))); )));
} }
pop_value( pop_value(&mut context.value_stack, &context.frame_stack, ValueType::I32.into())?;
&mut context.value_stack,
&context.frame_stack,
ValueType::I32.into(),
)?;
context.module.require_memory(DEFAULT_MEMORY_INDEX)?; context.module.require_memory(DEFAULT_MEMORY_INDEX)?;
push_value(&mut context.value_stack, value_type.into())?; push_value(&mut context.value_stack, value_type.into())?;
Ok(()) Ok(())
@ -1319,16 +1202,8 @@ impl Validator {
} }
context.module.require_memory(DEFAULT_MEMORY_INDEX)?; context.module.require_memory(DEFAULT_MEMORY_INDEX)?;
pop_value( pop_value(&mut context.value_stack, &context.frame_stack, value_type.into())?;
&mut context.value_stack, pop_value(&mut context.value_stack, &context.frame_stack, ValueType::I32.into())?;
&context.frame_stack,
value_type.into(),
)?;
pop_value(
&mut context.value_stack,
&context.frame_stack,
ValueType::I32.into(),
)?;
Ok(()) Ok(())
} }
@ -1339,22 +1214,14 @@ impl Validator {
}; };
if !frame_type.is_loop() { if !frame_type.is_loop() {
if let BlockType::Value(value_type) = frame_block_type { if let BlockType::Value(value_type) = frame_block_type {
tee_value( tee_value(&mut context.value_stack, &context.frame_stack, value_type.into())?;
&mut context.value_stack,
&context.frame_stack,
value_type.into(),
)?;
} }
} }
Ok(()) Ok(())
} }
fn validate_br_if(context: &mut FunctionValidationContext, depth: u32) -> Result<(), Error> { fn validate_br_if(context: &mut FunctionValidationContext, depth: u32) -> Result<(), Error> {
pop_value( pop_value(&mut context.value_stack, &context.frame_stack, ValueType::I32.into())?;
&mut context.value_stack,
&context.frame_stack,
ValueType::I32.into(),
)?;
let (frame_type, frame_block_type) = { let (frame_type, frame_block_type) = {
let frame = require_label(depth, &context.frame_stack)?; let frame = require_label(depth, &context.frame_stack)?;
@ -1362,21 +1229,13 @@ impl Validator {
}; };
if !frame_type.is_loop() { if !frame_type.is_loop() {
if let BlockType::Value(value_type) = frame_block_type { if let BlockType::Value(value_type) = frame_block_type {
tee_value( tee_value(&mut context.value_stack, &context.frame_stack, value_type.into())?;
&mut context.value_stack,
&context.frame_stack,
value_type.into(),
)?;
} }
} }
Ok(()) Ok(())
} }
fn validate_br_table( fn validate_br_table(context: &mut FunctionValidationContext, table: &[u32], default: u32) -> Result<(), Error> {
context: &mut FunctionValidationContext,
table: &[u32],
default: u32,
) -> Result<(), Error> {
let required_block_type: BlockType = { let required_block_type: BlockType = {
let default_block = require_label(default, &context.frame_stack)?; let default_block = require_label(default, &context.frame_stack)?;
let required_block_type = if !default_block.frame_type.is_loop() { let required_block_type = if !default_block.frame_type.is_loop() {
@ -1402,17 +1261,9 @@ impl Validator {
required_block_type required_block_type
}; };
pop_value( pop_value(&mut context.value_stack, &context.frame_stack, ValueType::I32.into())?;
&mut context.value_stack,
&context.frame_stack,
ValueType::I32.into(),
)?;
if let BlockType::Value(value_type) = required_block_type { if let BlockType::Value(value_type) = required_block_type {
tee_value( tee_value(&mut context.value_stack, &context.frame_stack, value_type.into())?;
&mut context.value_stack,
&context.frame_stack,
value_type.into(),
)?;
} }
Ok(()) Ok(())
@ -1421,11 +1272,7 @@ impl Validator {
fn validate_call(context: &mut FunctionValidationContext, idx: u32) -> Result<(), Error> { fn validate_call(context: &mut FunctionValidationContext, idx: u32) -> Result<(), Error> {
let (argument_types, return_type) = context.module.require_function(idx)?; let (argument_types, return_type) = context.module.require_function(idx)?;
for argument_type in argument_types.iter().rev() { for argument_type in argument_types.iter().rev() {
pop_value( pop_value(&mut context.value_stack, &context.frame_stack, (*argument_type).into())?;
&mut context.value_stack,
&context.frame_stack,
(*argument_type).into(),
)?;
} }
if let BlockType::Value(value_type) = return_type { if let BlockType::Value(value_type) = return_type {
push_value(&mut context.value_stack, value_type.into())?; push_value(&mut context.value_stack, value_type.into())?;
@ -1433,10 +1280,7 @@ impl Validator {
Ok(()) Ok(())
} }
fn validate_call_indirect( fn validate_call_indirect(context: &mut FunctionValidationContext, idx: u32) -> Result<(), Error> {
context: &mut FunctionValidationContext,
idx: u32,
) -> Result<(), Error> {
{ {
let table = context.module.require_table(DEFAULT_TABLE_INDEX)?; let table = context.module.require_table(DEFAULT_TABLE_INDEX)?;
if table.elem_type() != TableElementType::AnyFunc { if table.elem_type() != TableElementType::AnyFunc {
@ -1448,18 +1292,10 @@ impl Validator {
} }
} }
pop_value( pop_value(&mut context.value_stack, &context.frame_stack, ValueType::I32.into())?;
&mut context.value_stack,
&context.frame_stack,
ValueType::I32.into(),
)?;
let (argument_types, return_type) = context.module.require_function_type(idx)?; let (argument_types, return_type) = context.module.require_function_type(idx)?;
for argument_type in argument_types.iter().rev() { for argument_type in argument_types.iter().rev() {
pop_value( pop_value(&mut context.value_stack, &context.frame_stack, (*argument_type).into())?;
&mut context.value_stack,
&context.frame_stack,
(*argument_type).into(),
)?;
} }
if let BlockType::Value(value_type) = return_type { if let BlockType::Value(value_type) = return_type {
push_value(&mut context.value_stack, value_type.into())?; push_value(&mut context.value_stack, value_type.into())?;
@ -1475,11 +1311,7 @@ impl Validator {
fn validate_grow_memory(context: &mut FunctionValidationContext) -> Result<(), Error> { fn validate_grow_memory(context: &mut FunctionValidationContext) -> Result<(), Error> {
context.module.require_memory(DEFAULT_MEMORY_INDEX)?; context.module.require_memory(DEFAULT_MEMORY_INDEX)?;
pop_value( pop_value(&mut context.value_stack, &context.frame_stack, ValueType::I32.into())?;
&mut context.value_stack,
&context.frame_stack,
ValueType::I32.into(),
)?;
push_value(&mut context.value_stack, ValueType::I32.into())?; push_value(&mut context.value_stack, ValueType::I32.into())?;
Ok(()) Ok(())
} }
@ -1543,10 +1375,7 @@ fn make_top_frame_polymorphic(
frame.polymorphic_stack = true; frame.polymorphic_stack = true;
} }
fn push_value( fn push_value(value_stack: &mut StackWithLimit<StackValueType>, value_type: StackValueType) -> Result<(), Error> {
value_stack: &mut StackWithLimit<StackValueType>,
value_type: StackValueType,
) -> Result<(), Error> {
Ok(value_stack.push(value_type.into())?) Ok(value_stack.push(value_type.into())?)
} }
@ -1564,19 +1393,14 @@ fn pop_value(
let actual_value = if stack_is_empty && is_stack_polymorphic { let actual_value = if stack_is_empty && is_stack_polymorphic {
StackValueType::Any StackValueType::Any
} else { } else {
let value_stack_min = frame_stack let value_stack_min = frame_stack.top().expect("at least 1 topmost block").value_stack_len;
.top()
.expect("at least 1 topmost block")
.value_stack_len;
if value_stack.len() <= value_stack_min { if value_stack.len() <= value_stack_min {
return Err(Error("Trying to access parent frame stack values.".into())); return Err(Error("Trying to access parent frame stack values.".into()));
} }
value_stack.pop()? value_stack.pop()?
}; };
match actual_value { match actual_value {
StackValueType::Specific(stack_value_type) if stack_value_type == value_type => { StackValueType::Specific(stack_value_type) if stack_value_type == value_type => Ok(actual_value),
Ok(actual_value)
}
StackValueType::Any => Ok(actual_value), StackValueType::Any => Ok(actual_value),
stack_value_type @ _ => Err(Error(format!( stack_value_type @ _ => Err(Error(format!(
"Expected value of type {:?} on top of stack. Got {:?}", "Expected value of type {:?} on top of stack. Got {:?}",
@ -1623,11 +1447,7 @@ fn pop_label(
match block_type { match block_type {
BlockType::NoResult => (), BlockType::NoResult => (),
BlockType::Value(required_value_type) => { BlockType::Value(required_value_type) => {
let _ = pop_value( let _ = pop_value(value_stack, frame_stack, StackValueType::Specific(required_value_type))?;
value_stack,
frame_stack,
StackValueType::Specific(required_value_type),
)?;
} }
} }
@ -1649,10 +1469,7 @@ fn top_label(frame_stack: &StackWithLimit<BlockFrame>) -> &BlockFrame {
.expect("this function can't be called with empty frame stack") .expect("this function can't be called with empty frame stack")
} }
fn require_label( fn require_label(depth: u32, frame_stack: &StackWithLimit<BlockFrame>) -> Result<&BlockFrame, Error> {
depth: u32,
frame_stack: &StackWithLimit<BlockFrame>,
) -> Result<&BlockFrame, Error> {
Ok(frame_stack.get(depth as usize)?) Ok(frame_stack.get(depth as usize)?)
} }
@ -1662,8 +1479,7 @@ fn require_target(
frame_stack: &StackWithLimit<BlockFrame>, frame_stack: &StackWithLimit<BlockFrame>,
) -> Target { ) -> Target {
let is_stack_polymorphic = top_label(frame_stack).polymorphic_stack; let is_stack_polymorphic = top_label(frame_stack).polymorphic_stack;
let frame = let frame = require_label(depth, frame_stack).expect("require_target called with a bogus depth");
require_label(depth, frame_stack).expect("require_target called with a bogus depth");
// Find out how many values we need to keep (copy to the new stack location after the drop). // Find out how many values we need to keep (copy to the new stack location after the drop).
let keep: isa::Keep = match (frame.frame_type, frame.block_type) { let keep: isa::Keep = match (frame.frame_type, frame.block_type) {
@ -1727,11 +1543,7 @@ fn require_local(locals: &Locals, idx: u32) -> Result<ValueType, Error> {
} }
/// See stack layout definition in mod isa. /// See stack layout definition in mod isa.
fn relative_local_depth( fn relative_local_depth(idx: u32, locals: &Locals, value_stack: &StackWithLimit<StackValueType>) -> Result<u32, Error> {
idx: u32,
locals: &Locals,
value_stack: &StackWithLimit<StackValueType>,
) -> Result<u32, Error> {
let value_stack_height = value_stack.len() as u32; let value_stack_height = value_stack.len() as u32;
let locals_and_params_count = locals.count(); let locals_and_params_count = locals.count();
@ -1779,11 +1591,7 @@ impl Sink {
self.ins.current_pc() self.ins.current_pc()
} }
fn pc_or_placeholder<F: FnOnce() -> isa::Reloc>( fn pc_or_placeholder<F: FnOnce() -> isa::Reloc>(&mut self, label: LabelId, reloc_creator: F) -> u32 {
&mut self,
label: LabelId,
reloc_creator: F,
) -> u32 {
match self.labels[label.0] { match self.labels[label.0] {
(Label::Resolved(dst_pc), _) => dst_pc, (Label::Resolved(dst_pc), _) => dst_pc,
(Label::NotResolved, ref mut unresolved) => { (Label::NotResolved, ref mut unresolved) => {
@ -1832,17 +1640,14 @@ impl Sink {
let pc = self.cur_pc(); let pc = self.cur_pc();
let mut isa_targets = Vec::new(); let mut isa_targets = Vec::new();
for (idx, &Target { label, drop_keep }) in for (idx, &Target { label, drop_keep }) in targets.iter().chain(iter::once(&default)).enumerate() {
targets.iter().chain(iter::once(&default)).enumerate()
{
let dst_pc = self.pc_or_placeholder(label, || isa::Reloc::BrTable { pc, idx }); let dst_pc = self.pc_or_placeholder(label, || isa::Reloc::BrTable { pc, idx });
isa_targets.push(isa::Target { isa_targets.push(isa::Target {
dst_pc, dst_pc,
drop_keep: drop_keep.into(), drop_keep: drop_keep.into(),
}); });
} }
self.ins self.ins.push(isa::Instruction::BrTable(isa_targets.into_boxed_slice()));
.push(isa::Instruction::BrTable(isa_targets.into_boxed_slice()));
} }
/// Create a new unresolved label. /// Create a new unresolved label.
@ -1879,12 +1684,10 @@ impl Sink {
// At this moment all labels should be resolved. // At this moment all labels should be resolved.
assert!( assert!(
{ {
self.labels self.labels.iter().all(|(state, unresolved)| match (state, unresolved) {
.iter() (Label::Resolved(_), unresolved) if unresolved.is_empty() => true,
.all(|(state, unresolved)| match (state, unresolved) { _ => false,
(Label::Resolved(_), unresolved) if unresolved.is_empty() => true, })
_ => false,
})
}, },
"there are unresolved labels left: {:?}", "there are unresolved labels left: {:?}",
self.labels self.labels

View File

@ -15,8 +15,8 @@ use common::stack;
use isa; use isa;
use memory_units::Pages; use memory_units::Pages;
use parity_wasm::elements::{ use parity_wasm::elements::{
BlockType, External, GlobalEntry, GlobalType, InitExpr, Instruction, Internal, MemoryType, BlockType, External, GlobalEntry, GlobalType, InitExpr, Instruction, Internal, MemoryType, Module, ResizableLimits,
Module, ResizableLimits, TableType, Type, ValueType, TableType, Type, ValueType,
}; };
mod context; mod context;
@ -194,11 +194,7 @@ pub fn validate_module(module: Module) -> Result<ValidatedModule, Error> {
); );
// Fill elements with imported values. // Fill elements with imported values.
for import_entry in module for import_entry in module.import_section().map(|i| i.entries()).unwrap_or_default() {
.import_section()
.map(|i| i.entries())
.unwrap_or_default()
{
match *import_entry.external() { match *import_entry.external() {
External::Function(idx) => context_builder.push_func_type_index(idx), External::Function(idx) => context_builder.push_func_type_index(idx),
External::Table(ref table) => context_builder.push_table(table.clone()), External::Table(ref table) => context_builder.push_table(table.clone()),
@ -237,10 +233,7 @@ pub fn validate_module(module: Module) -> Result<ValidatedModule, Error> {
let context = context_builder.build(); let context = context_builder.build();
let function_section_len = module let function_section_len = module.function_section().map(|s| s.entries().len()).unwrap_or(0);
.function_section()
.map(|s| s.entries().len())
.unwrap_or(0);
let code_section_len = module.code_section().map(|s| s.bodies().len()).unwrap_or(0); let code_section_len = module.code_section().map(|s| s.bodies().len()).unwrap_or(0);
if function_section_len != code_section_len { if function_section_len != code_section_len {
return Err(Error(format!( return Err(Error(format!(
@ -252,9 +245,7 @@ pub fn validate_module(module: Module) -> Result<ValidatedModule, Error> {
// validate every function body in user modules // validate every function body in user modules
if function_section_len != 0 { if function_section_len != 0 {
// tests use invalid code // tests use invalid code
let function_section = module let function_section = module.function_section().expect("function_section_len != 0; qed");
.function_section()
.expect("function_section_len != 0; qed");
let code_section = module let code_section = module
.code_section() .code_section()
.expect("function_section_len != 0; function_section_len == code_section_len; qed"); .expect("function_section_len != 0; function_section_len == code_section_len; qed");
@ -264,14 +255,10 @@ pub fn validate_module(module: Module) -> Result<ValidatedModule, Error> {
.bodies() .bodies()
.get(index as usize) .get(index as usize)
.ok_or(Error(format!("Missing body for function {}", index)))?; .ok_or(Error(format!("Missing body for function {}", index)))?;
let code = let code = FunctionReader::read_function(&context, function, function_body).map_err(|e| {
FunctionReader::read_function(&context, function, function_body).map_err(|e| { let Error(ref msg) = e;
let Error(ref msg) = e; Error(format!("Function #{} reading/validation error: {}", index, msg))
Error(format!( })?;
"Function #{} reading/validation error: {}",
index, msg
))
})?;
code_map.push(code); code_map.push(code);
} }
} }
@ -280,9 +267,7 @@ pub fn validate_module(module: Module) -> Result<ValidatedModule, Error> {
if let Some(start_fn_idx) = module.start_section() { if let Some(start_fn_idx) = module.start_section() {
let (params, return_ty) = context.require_function(start_fn_idx)?; let (params, return_ty) = context.require_function(start_fn_idx)?;
if return_ty != BlockType::NoResult || params.len() != 0 { if return_ty != BlockType::NoResult || params.len() != 0 {
return Err(Error( return Err(Error("start function expected to have type [] -> []".into()));
"start function expected to have type [] -> []".into(),
));
} }
} }
@ -321,10 +306,7 @@ pub fn validate_module(module: Module) -> Result<ValidatedModule, Error> {
} }
External::Global(ref global_type) => { External::Global(ref global_type) => {
if global_type.is_mutable() { if global_type.is_mutable() {
return Err(Error(format!( return Err(Error(format!("trying to import mutable global {}", import.field())));
"trying to import mutable global {}",
import.field()
)));
} }
} }
External::Memory(ref memory_type) => { External::Memory(ref memory_type) => {
@ -423,9 +405,7 @@ fn validate_global_entry(global_entry: &GlobalEntry, globals: &[GlobalType]) ->
fn expr_const_type(init_expr: &InitExpr, globals: &[GlobalType]) -> Result<ValueType, Error> { fn expr_const_type(init_expr: &InitExpr, globals: &[GlobalType]) -> Result<ValueType, Error> {
let code = init_expr.code(); let code = init_expr.code();
if code.len() != 2 { if code.len() != 2 {
return Err(Error( return Err(Error("Init expression should always be with length 2".into()));
"Init expression should always be with length 2".into(),
));
} }
let expr_ty: ValueType = match code[0] { let expr_ty: ValueType = match code[0] {
Instruction::I32Const(_) => ValueType::I32, Instruction::I32Const(_) => ValueType::I32,
@ -439,12 +419,7 @@ fn expr_const_type(init_expr: &InitExpr, globals: &[GlobalType]) -> Result<Value
} }
target_global.content_type() target_global.content_type()
} }
None => { None => return Err(Error(format!("Global {} doesn't exists or not yet defined", idx))),
return Err(Error(format!(
"Global {} doesn't exists or not yet defined",
idx
)))
}
}, },
_ => return Err(Error("Non constant opcode in init expr".into())), _ => return Err(Error("Non constant opcode in init expr".into())),
}; };

View File

@ -2,8 +2,8 @@ use super::{validate_module, ValidatedModule};
use isa; use isa;
use parity_wasm::builder::module; use parity_wasm::builder::module;
use parity_wasm::elements::{ use parity_wasm::elements::{
deserialize_buffer, BlockType, External, GlobalEntry, GlobalType, ImportEntry, InitExpr, deserialize_buffer, BlockType, External, GlobalEntry, GlobalType, ImportEntry, InitExpr, Instruction, Instructions,
Instruction, Instructions, MemoryType, Module, TableType, ValueType, MemoryType, Module, TableType, ValueType,
}; };
use wabt; use wabt;
@ -39,12 +39,7 @@ fn limits() {
assert_eq!(validate_module(m).is_ok(), is_valid); assert_eq!(validate_module(m).is_ok(), is_valid);
// defined memory // defined memory
let m = module() let m = module().memory().with_min(min).with_max(max).build().build();
.memory()
.with_min(min)
.with_max(max)
.build()
.build();
assert_eq!(validate_module(m).is_ok(), is_valid); assert_eq!(validate_module(m).is_ok(), is_valid);
// imported table // imported table
@ -185,10 +180,8 @@ fn funcs() {
.i32() .i32()
.build() .build()
.body() .body()
.with_instructions(Instructions::new(vec![ .with_instructions(Instructions::new(vec![Instruction::Call(1), Instruction::End]))
Instruction::Call(1), .build()
Instruction::End,
])).build()
.build() .build()
.function() .function()
.signature() .signature()
@ -196,10 +189,8 @@ fn funcs() {
.i32() .i32()
.build() .build()
.body() .body()
.with_instructions(Instructions::new(vec![ .with_instructions(Instructions::new(vec![Instruction::Call(0), Instruction::End]))
Instruction::Call(0), .build()
Instruction::End,
])).build()
.build() .build()
.build(); .build();
assert!(validate_module(m).is_ok()); assert!(validate_module(m).is_ok());

View File

@ -590,10 +590,7 @@ impl LittleEndianConvert for u8 {
} }
fn from_little_endian(buffer: &[u8]) -> Result<Self, Error> { fn from_little_endian(buffer: &[u8]) -> Result<Self, Error> {
buffer buffer.get(0).cloned().ok_or_else(|| Error::InvalidLittleEndianBuffer)
.get(0)
.cloned()
.ok_or_else(|| Error::InvalidLittleEndianBuffer)
} }
} }

View File

@ -6,10 +6,9 @@ use std::fs::File;
use wabt::script::{self, Action, Command, CommandKind, ScriptParser, Value}; use wabt::script::{self, Action, Command, CommandKind, ScriptParser, Value};
use wasmi::memory_units::Pages; use wasmi::memory_units::Pages;
use wasmi::{ use wasmi::{
Error as InterpreterError, Externals, FuncInstance, FuncRef, GlobalDescriptor, GlobalInstance, Error as InterpreterError, Externals, FuncInstance, FuncRef, GlobalDescriptor, GlobalInstance, GlobalRef,
GlobalRef, ImportResolver, ImportsBuilder, MemoryDescriptor, MemoryInstance, MemoryRef, Module, ImportResolver, ImportsBuilder, MemoryDescriptor, MemoryInstance, MemoryRef, Module, ModuleImportResolver,
ModuleImportResolver, ModuleInstance, ModuleRef, RuntimeArgs, RuntimeValue, Signature, ModuleInstance, ModuleRef, RuntimeArgs, RuntimeValue, Signature, TableDescriptor, TableInstance, TableRef, Trap,
TableDescriptor, TableInstance, TableRef, Trap,
}; };
fn spec_to_runtime_value(val: Value<u32, u64>) -> RuntimeValue { fn spec_to_runtime_value(val: Value<u32, u64>) -> RuntimeValue {
@ -64,11 +63,7 @@ impl SpecModule {
const PRINT_FUNC_INDEX: usize = 0; const PRINT_FUNC_INDEX: usize = 0;
impl Externals for SpecModule { impl Externals for SpecModule {
fn invoke_index( fn invoke_index(&mut self, index: usize, args: RuntimeArgs) -> Result<Option<RuntimeValue>, Trap> {
&mut self,
index: usize,
args: RuntimeArgs,
) -> Result<Option<RuntimeValue>, Trap> {
match index { match index {
PRINT_FUNC_INDEX => { PRINT_FUNC_INDEX => {
println!("print: {:?}", args); println!("print: {:?}", args);
@ -80,11 +75,7 @@ impl Externals for SpecModule {
} }
impl ModuleImportResolver for SpecModule { impl ModuleImportResolver for SpecModule {
fn resolve_func( fn resolve_func(&self, field_name: &str, func_type: &Signature) -> Result<FuncRef, InterpreterError> {
&self,
field_name: &str,
func_type: &Signature,
) -> Result<FuncRef, InterpreterError> {
let index = match field_name { let index = match field_name {
"print" => PRINT_FUNC_INDEX, "print" => PRINT_FUNC_INDEX,
"print_i32" => PRINT_FUNC_INDEX, "print_i32" => PRINT_FUNC_INDEX,
@ -110,11 +101,7 @@ impl ModuleImportResolver for SpecModule {
return Ok(func); return Ok(func);
} }
fn resolve_global( fn resolve_global(&self, field_name: &str, _global_type: &GlobalDescriptor) -> Result<GlobalRef, InterpreterError> {
&self,
field_name: &str,
_global_type: &GlobalDescriptor,
) -> Result<GlobalRef, InterpreterError> {
match field_name { match field_name {
"global_i32" => Ok(self.global_i32.clone()), "global_i32" => Ok(self.global_i32.clone()),
"global_f32" => Ok(self.global_f32.clone()), "global_f32" => Ok(self.global_f32.clone()),
@ -126,11 +113,7 @@ impl ModuleImportResolver for SpecModule {
} }
} }
fn resolve_memory( fn resolve_memory(&self, field_name: &str, _memory_type: &MemoryDescriptor) -> Result<MemoryRef, InterpreterError> {
&self,
field_name: &str,
_memory_type: &MemoryDescriptor,
) -> Result<MemoryRef, InterpreterError> {
if field_name == "memory" { if field_name == "memory" {
return Ok(self.memory.clone()); return Ok(self.memory.clone());
} }
@ -141,11 +124,7 @@ impl ModuleImportResolver for SpecModule {
))) )))
} }
fn resolve_table( fn resolve_table(&self, field_name: &str, _table_type: &TableDescriptor) -> Result<TableRef, InterpreterError> {
&self,
field_name: &str,
_table_type: &TableDescriptor,
) -> Result<TableRef, InterpreterError> {
if field_name == "table" { if field_name == "table" {
return Ok(self.table.clone()); return Ok(self.table.clone());
} }
@ -184,9 +163,10 @@ impl SpecDriver {
} }
fn module(&self, name: &str) -> Result<ModuleRef, InterpreterError> { fn module(&self, name: &str) -> Result<ModuleRef, InterpreterError> {
self.instances.get(name).cloned().ok_or_else(|| { self.instances
InterpreterError::Instantiation(format!("Module not registered {}", name)) .get(name)
}) .cloned()
.ok_or_else(|| InterpreterError::Instantiation(format!("Module not registered {}", name)))
} }
fn module_or_last(&self, name: Option<&str>) -> Result<ModuleRef, InterpreterError> { fn module_or_last(&self, name: Option<&str>) -> Result<ModuleRef, InterpreterError> {
@ -210,8 +190,7 @@ impl ImportResolver for SpecDriver {
if module_name == "spectest" { if module_name == "spectest" {
self.spec_module.resolve_func(field_name, func_type) self.spec_module.resolve_func(field_name, func_type)
} else { } else {
self.module(module_name)? self.module(module_name)?.resolve_func(field_name, func_type)
.resolve_func(field_name, func_type)
} }
} }
@ -224,8 +203,7 @@ impl ImportResolver for SpecDriver {
if module_name == "spectest" { if module_name == "spectest" {
self.spec_module.resolve_global(field_name, global_type) self.spec_module.resolve_global(field_name, global_type)
} else { } else {
self.module(module_name)? self.module(module_name)?.resolve_global(field_name, global_type)
.resolve_global(field_name, global_type)
} }
} }
@ -238,8 +216,7 @@ impl ImportResolver for SpecDriver {
if module_name == "spectest" { if module_name == "spectest" {
self.spec_module.resolve_memory(field_name, memory_type) self.spec_module.resolve_memory(field_name, memory_type)
} else { } else {
self.module(module_name)? self.module(module_name)?.resolve_memory(field_name, memory_type)
.resolve_memory(field_name, memory_type)
} }
} }
@ -252,8 +229,7 @@ impl ImportResolver for SpecDriver {
if module_name == "spectest" { if module_name == "spectest" {
self.spec_module.resolve_table(field_name, table_type) self.spec_module.resolve_table(field_name, table_type)
} else { } else {
self.module(module_name)? self.module(module_name)?.resolve_table(field_name, table_type)
.resolve_table(field_name, table_type)
} }
} }
} }
@ -271,11 +247,7 @@ fn try_load(wasm: &[u8], spec_driver: &mut SpecDriver) -> Result<(), Error> {
Ok(()) Ok(())
} }
fn load_module( fn load_module(wasm: &[u8], name: &Option<String>, spec_driver: &mut SpecDriver) -> Result<ModuleRef, Error> {
wasm: &[u8],
name: &Option<String>,
spec_driver: &mut SpecDriver,
) -> Result<ModuleRef, Error> {
let module = try_load_module(wasm)?; let module = try_load_module(wasm)?;
let instance = ModuleInstance::new(&module, spec_driver) let instance = ModuleInstance::new(&module, spec_driver)
.map_err(|e| Error::Load(e.to_string()))? .map_err(|e| Error::Load(e.to_string()))?
@ -288,10 +260,7 @@ fn load_module(
Ok(instance) Ok(instance)
} }
fn run_action( fn run_action(program: &mut SpecDriver, action: &Action<u32, u64>) -> Result<Option<RuntimeValue>, InterpreterError> {
program: &mut SpecDriver,
action: &Action<u32, u64>,
) -> Result<Option<RuntimeValue>, InterpreterError> {
match *action { match *action {
Action::Invoke { Action::Invoke {
ref module, ref module,
@ -300,37 +269,22 @@ fn run_action(
} => { } => {
let module = program let module = program
.module_or_last(module.as_ref().map(|x| x.as_ref())) .module_or_last(module.as_ref().map(|x| x.as_ref()))
.expect(&format!( .expect(&format!("Expected program to have loaded module {:?}", module));
"Expected program to have loaded module {:?}", let vec_args = args.iter().cloned().map(spec_to_runtime_value).collect::<Vec<_>>();
module
));
let vec_args = args
.iter()
.cloned()
.map(spec_to_runtime_value)
.collect::<Vec<_>>();
module.invoke_export(field, &vec_args, program.spec_module()) module.invoke_export(field, &vec_args, program.spec_module())
} }
Action::Get { Action::Get {
ref module, ref module, ref field, ..
ref field,
..
} => { } => {
let module = program let module = program
.module_or_last(module.as_ref().map(|x| x.as_ref())) .module_or_last(module.as_ref().map(|x| x.as_ref()))
.expect(&format!( .expect(&format!("Expected program to have loaded module {:?}", module));
"Expected program to have loaded module {:?}",
module
));
let global = module let global = module
.export_by_name(&field) .export_by_name(&field)
.ok_or_else(|| { .ok_or_else(|| InterpreterError::Global(format!("Expected to have export with name {}", field)))?
InterpreterError::Global(format!("Expected to have export with name {}", field)) .as_global()
})?.as_global()
.cloned() .cloned()
.ok_or_else(|| { .ok_or_else(|| InterpreterError::Global(format!("Expected export {} to be a global", field)))?;
InterpreterError::Global(format!("Expected export {} to be a global", field))
})?;
Ok(Some(global.get())) Ok(Some(global.get()))
} }
} }
@ -348,12 +302,10 @@ fn try_spec(name: &str) -> Result<(), Error> {
use std::io::Read; use std::io::Read;
let mut spec_source = Vec::new(); let mut spec_source = Vec::new();
let mut spec_file = File::open(&spec_script_path).expect("Can't open file"); let mut spec_file = File::open(&spec_script_path).expect("Can't open file");
spec_file spec_file.read_to_end(&mut spec_source).expect("Can't read file");
.read_to_end(&mut spec_source)
.expect("Can't read file");
let mut parser = ScriptParser::from_source_and_name(&spec_source, &format!("{}.wast", name)) let mut parser =
.expect("Can't read spec script"); ScriptParser::from_source_and_name(&spec_source, &format!("{}.wast", name)).expect("Can't read spec script");
let mut errors = vec![]; let mut errors = vec![];
while let Some(Command { kind, line }) = parser.next()? { while let Some(Command { kind, line }) = parser.next()? {
@ -377,22 +329,15 @@ fn try_spec(name: &str) -> Result<(), Error> {
match kind { match kind {
CommandKind::Module { name, module, .. } => { CommandKind::Module { name, module, .. } => {
load_module(&module.into_vec(), &name, &mut spec_driver) load_module(&module.into_vec(), &name, &mut spec_driver).expect("Failed to load module");
.expect("Failed to load module");
} }
CommandKind::AssertReturn { action, expected } => { CommandKind::AssertReturn { action, expected } => {
let result = run_action(&mut spec_driver, &action); let result = run_action(&mut spec_driver, &action);
match result { match result {
Ok(result) => { Ok(result) => {
let spec_expected = expected let spec_expected = expected.iter().cloned().map(spec_to_runtime_value).collect::<Vec<_>>();
.iter()
.cloned()
.map(spec_to_runtime_value)
.collect::<Vec<_>>();
let actual_result = result.into_iter().collect::<Vec<RuntimeValue>>(); let actual_result = result.into_iter().collect::<Vec<RuntimeValue>>();
for (actual_result, spec_expected) in for (actual_result, spec_expected) in actual_result.iter().zip(spec_expected.iter()) {
actual_result.iter().zip(spec_expected.iter())
{
assert_eq!(actual_result.value_type(), spec_expected.value_type()); assert_eq!(actual_result.value_type(), spec_expected.value_type());
// f32::NAN != f32::NAN // f32::NAN != f32::NAN
match spec_expected { match spec_expected {
@ -413,8 +358,7 @@ fn try_spec(name: &str) -> Result<(), Error> {
} }
} }
} }
CommandKind::AssertReturnCanonicalNan { action } CommandKind::AssertReturnCanonicalNan { action } | CommandKind::AssertReturnArithmeticNan { action } => {
| CommandKind::AssertReturnArithmeticNan { action } => {
let result = run_action(&mut spec_driver, &action); let result = run_action(&mut spec_driver, &action);
match result { match result {
Ok(result) => { Ok(result) => {
@ -426,9 +370,7 @@ fn try_spec(name: &str) -> Result<(), Error> {
RuntimeValue::F64(val) => if !val.is_nan() { RuntimeValue::F64(val) => if !val.is_nan() {
panic!("Expected nan value, got {:?}", val) panic!("Expected nan value, got {:?}", val)
}, },
val @ _ => { val @ _ => panic!("Expected action to return float value, got {:?}", val),
panic!("Expected action to return float value, got {:?}", val)
}
} }
} }
} }
@ -448,10 +390,7 @@ fn try_spec(name: &str) -> Result<(), Error> {
let result = run_action(&mut spec_driver, &action); let result = run_action(&mut spec_driver, &action);
match result { match result {
Ok(result) => { Ok(result) => {
panic!( panic!("Expected action to result in a trap, got result: {:?}", result);
"Expected action to result in a trap, got result: {:?}",
result
);
} }
Err(_e) => {} Err(_e) => {}
} }
@ -465,12 +404,10 @@ fn try_spec(name: &str) -> Result<(), Error> {
Err(_e) => {} Err(_e) => {}
} }
} }
CommandKind::AssertUninstantiable { module, .. } => { CommandKind::AssertUninstantiable { module, .. } => match try_load(&module.into_vec(), &mut spec_driver) {
match try_load(&module.into_vec(), &mut spec_driver) { Ok(_) => panic!("Expected error running start function at line {}", line),
Ok(_) => panic!("Expected error running start function at line {}", line), Err(_e) => {}
Err(_e) => {} },
}
}
CommandKind::Register { name, as_name, .. } => { CommandKind::Register { name, as_name, .. } => {
let module = match spec_driver.module_or_last(name.as_ref().map(|x| x.as_ref())) { let module = match spec_driver.module_or_last(name.as_ref().map(|x| x.as_ref())) {
Ok(module) => module, Ok(module) => module,