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
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)
let function_section = module
.function_section()
.expect("No function section found");
let function_section = module.function_section().expect("No function section found");
// Type section stores function types which are referenced by function_section entries
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;
// Getting a type reference from a function section entry
let func_type_ref: usize =
function_section.entries()[function_index_in_section].type_ref() as usize;
let func_type_ref: usize = function_section.entries()[function_index_in_section].type_ref() as usize;
// Use the reference to get an actual function type
let function_type: &FunctionType = match &type_section.types()[func_type_ref] {
@ -112,7 +109,6 @@ fn main() {
println!(
"Result: {:?}",
main.invoke_export(func_name, &args, &mut NopExternals)
.expect("")
main.invoke_export(func_name, &args, &mut NopExternals).expect("")
);
}

View File

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

View File

@ -7,9 +7,9 @@ use std::env::args;
use std::fs::File;
use wasmi::memory_units::*;
use wasmi::{
Error, FuncInstance, FuncRef, GlobalDescriptor, GlobalInstance, GlobalRef, ImportsBuilder,
MemoryDescriptor, MemoryInstance, MemoryRef, Module, ModuleImportResolver, ModuleInstance,
NopExternals, RuntimeValue, Signature, TableDescriptor, TableInstance, TableRef,
Error, FuncInstance, FuncRef, GlobalDescriptor, GlobalInstance, GlobalRef, ImportsBuilder, MemoryDescriptor,
MemoryInstance, MemoryRef, Module, ModuleImportResolver, ModuleInstance, NopExternals, RuntimeValue, Signature,
TableDescriptor, TableInstance, TableRef,
};
fn load_from_file(filename: &str) -> Module {
@ -27,33 +27,21 @@ impl ModuleImportResolver for ResolveAll {
Ok(FuncInstance::alloc_host(signature.clone(), 0))
}
fn resolve_global(
&self,
_field_name: &str,
global_type: &GlobalDescriptor,
) -> Result<GlobalRef, Error> {
fn resolve_global(&self, _field_name: &str, global_type: &GlobalDescriptor) -> Result<GlobalRef, Error> {
Ok(GlobalInstance::alloc(
RuntimeValue::default(global_type.value_type()),
global_type.is_mutable(),
))
}
fn resolve_memory(
&self,
_field_name: &str,
memory_type: &MemoryDescriptor,
) -> Result<MemoryRef, Error> {
fn resolve_memory(&self, _field_name: &str, memory_type: &MemoryDescriptor) -> Result<MemoryRef, Error> {
Ok(MemoryInstance::alloc(
Pages(memory_type.initial() as usize),
memory_type.maximum().map(|m| Pages(m as usize)),
).unwrap())
}
fn resolve_table(
&self,
_field_name: &str,
table_type: &TableDescriptor,
) -> Result<TableRef, Error> {
fn resolve_table(&self, _field_name: &str, table_type: &TableDescriptor) -> Result<TableRef, Error> {
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.
write!(f, "Internal {{ signature={:?} }}", signature,)
}
&FuncInstanceInternal::Host { ref signature, .. } => {
write!(f, "Host {{ signature={:?} }}", signature)
}
&FuncInstanceInternal::Host { ref signature, .. } => write!(f, "Host {{ signature={:?} }}", signature),
}
}
}
@ -103,11 +101,7 @@ impl FuncInstance {
&self.0
}
pub(crate) fn alloc_internal(
module: Weak<ModuleInstance>,
signature: Rc<Signature>,
body: FuncBody,
) -> FuncRef {
pub(crate) fn alloc_internal(module: Weak<ModuleInstance>, signature: Rc<Signature>, body: FuncBody) -> FuncRef {
let func = FuncInstanceInternal::Internal {
signature,
module: module,
@ -144,8 +138,7 @@ impl FuncInstance {
interpreter.start_execution(externals)
}
FuncInstanceInternal::Host {
ref host_func_index,
..
ref host_func_index, ..
} => externals.invoke_index(*host_func_index, args.into()),
}
}
@ -164,10 +157,7 @@ impl FuncInstance {
/// [`Trap`]: #enum.Trap.html
/// [`start_execution`]: struct.FuncInvocation.html#method.start_execution
/// [`resume_execution`]: struct.FuncInvocation.html#method.resume_execution
pub fn invoke_resumable<'args>(
func: &FuncRef,
args: &'args [RuntimeValue],
) -> Result<FuncInvocation<'args>, Trap> {
pub fn invoke_resumable<'args>(func: &FuncRef, args: &'args [RuntimeValue]) -> Result<FuncInvocation<'args>, Trap> {
check_function_args(func.signature(), &args)?;
match *func.as_internal() {
FuncInstanceInternal::Internal { .. } => {
@ -177,8 +167,7 @@ impl FuncInstance {
})
}
FuncInstanceInternal::Host {
ref host_func_index,
..
ref host_func_index, ..
} => Ok(FuncInvocation {
kind: FuncInvocationKind::Host {
args,

View File

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

View File

@ -208,11 +208,7 @@ impl HostError {
/// ```
pub trait Externals {
/// Perform invoke of a host function by specified `index`.
fn invoke_index(
&mut self,
index: usize,
args: RuntimeArgs,
) -> Result<Option<RuntimeValue>, Trap>;
fn invoke_index(&mut self, index: usize, args: RuntimeArgs) -> Result<Option<RuntimeValue>, Trap>;
}
/// Implementation of [`Externals`] that just traps on [`invoke_index`].
@ -222,11 +218,7 @@ pub trait Externals {
pub struct NopExternals;
impl Externals for NopExternals {
fn invoke_index(
&mut self,
_index: usize,
_args: RuntimeArgs,
) -> Result<Option<RuntimeValue>, Trap> {
fn invoke_index(&mut self, _index: usize, _args: RuntimeArgs) -> Result<Option<RuntimeValue>, Trap> {
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.
/// Otherwise, link-time error will occur.
fn resolve_func(
&self,
_module_name: &str,
field_name: &str,
_signature: &Signature,
) -> Result<FuncRef, Error>;
fn resolve_func(&self, _module_name: &str, field_name: &str, _signature: &Signature) -> Result<FuncRef, Error>;
/// Resolve a global variable.
///
@ -124,11 +119,7 @@ impl<'a> ImportsBuilder<'a> {
}
/// Register an resolver by a name.
pub fn with_resolver<N: Into<String>>(
mut self,
name: N,
resolver: &'a ModuleImportResolver,
) -> Self {
pub fn with_resolver<N: Into<String>>(mut self, name: N, resolver: &'a ModuleImportResolver) -> Self {
self.modules.insert(name.into(), resolver);
self
}
@ -146,12 +137,7 @@ impl<'a> ImportsBuilder<'a> {
}
impl<'a> ImportResolver for ImportsBuilder<'a> {
fn resolve_func(
&self,
module_name: &str,
field_name: &str,
signature: &Signature,
) -> Result<FuncRef, Error> {
fn resolve_func(&self, module_name: &str, field_name: &str, signature: &Signature) -> Result<FuncRef, Error> {
self.resolver(module_name)
.ok_or_else(|| Error::Instantiation(format!("Module {} not found", module_name)))?
.resolve_func(field_name, signature)
@ -201,10 +187,7 @@ pub trait ModuleImportResolver {
///
/// [`ImportResolver::resolve_func`]: trait.ImportResolver.html#tymethod.resolve_func
fn resolve_func(&self, field_name: &str, _signature: &Signature) -> Result<FuncRef, Error> {
Err(Error::Instantiation(format!(
"Export {} not found",
field_name
)))
Err(Error::Instantiation(format!("Export {} not found", field_name)))
}
/// Resolve a global variable.
@ -212,15 +195,8 @@ pub trait ModuleImportResolver {
/// See [`ImportResolver::resolve_global`] for details.
///
/// [`ImportResolver::resolve_global`]: trait.ImportResolver.html#tymethod.resolve_global
fn resolve_global(
&self,
field_name: &str,
_global_type: &GlobalDescriptor,
) -> Result<GlobalRef, Error> {
Err(Error::Instantiation(format!(
"Export {} not found",
field_name
)))
fn resolve_global(&self, field_name: &str, _global_type: &GlobalDescriptor) -> Result<GlobalRef, Error> {
Err(Error::Instantiation(format!("Export {} not found", field_name)))
}
/// Resolve a memory.
@ -228,15 +204,8 @@ pub trait ModuleImportResolver {
/// See [`ImportResolver::resolve_memory`] for details.
///
/// [`ImportResolver::resolve_memory`]: trait.ImportResolver.html#tymethod.resolve_memory
fn resolve_memory(
&self,
field_name: &str,
_memory_type: &MemoryDescriptor,
) -> Result<MemoryRef, Error> {
Err(Error::Instantiation(format!(
"Export {} not found",
field_name
)))
fn resolve_memory(&self, field_name: &str, _memory_type: &MemoryDescriptor) -> Result<MemoryRef, Error> {
Err(Error::Instantiation(format!("Export {} not found", field_name)))
}
/// Resolve a table.
@ -244,15 +213,8 @@ pub trait ModuleImportResolver {
/// See [`ImportResolver::resolve_table`] for details.
///
/// [`ImportResolver::resolve_table`]: trait.ImportResolver.html#tymethod.resolve_table
fn resolve_table(
&self,
field_name: &str,
_table_type: &TableDescriptor,
) -> Result<TableRef, Error> {
Err(Error::Instantiation(format!(
"Export {} not found",
field_name
)))
fn resolve_table(&self, 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)))?
.as_func()
.cloned()
.ok_or_else(|| {
Error::Instantiation(format!("Export {} is not a function", field_name))
})?)
.ok_or_else(|| Error::Instantiation(format!("Export {} is not a function", field_name)))?)
}
fn resolve_global(
&self,
field_name: &str,
_global_type: &GlobalDescriptor,
) -> Result<GlobalRef, Error> {
fn resolve_global(&self, field_name: &str, _global_type: &GlobalDescriptor) -> Result<GlobalRef, Error> {
Ok(self
.export_by_name(field_name)
.ok_or_else(|| Error::Instantiation(format!("Export {} not found", field_name)))?
.as_global()
.cloned()
.ok_or_else(|| {
Error::Instantiation(format!("Export {} is not a global", field_name))
})?)
.ok_or_else(|| Error::Instantiation(format!("Export {} is not a global", field_name)))?)
}
fn resolve_memory(
&self,
field_name: &str,
_memory_type: &MemoryDescriptor,
) -> Result<MemoryRef, Error> {
fn resolve_memory(&self, field_name: &str, _memory_type: &MemoryDescriptor) -> Result<MemoryRef, Error> {
Ok(self
.export_by_name(field_name)
.ok_or_else(|| Error::Instantiation(format!("Export {} not found", field_name)))?
.as_memory()
.cloned()
.ok_or_else(|| {
Error::Instantiation(format!("Export {} is not a memory", field_name))
})?)
.ok_or_else(|| Error::Instantiation(format!("Export {} is not a memory", field_name)))?)
}
fn resolve_table(
&self,
field_name: &str,
_table_type: &TableDescriptor,
) -> Result<TableRef, Error> {
fn resolve_table(&self, field_name: &str, _table_type: &TableDescriptor) -> Result<TableRef, Error> {
Ok(self
.export_by_name(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]
fn next(&mut self) -> Option<<Self as Iterator>::Item> {
self.instructions
.get(self.position as usize)
.map(|instruction| {
self.position += 1;
instruction
})
self.instructions.get(self.position as usize).map(|instruction| {
self.position += 1;
instruction
})
}
}

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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