diff --git a/wasmer-it/src/errors.rs b/wasmer-it/src/errors.rs index 7f63489..aa5c267 100644 --- a/wasmer-it/src/errors.rs +++ b/wasmer-it/src/errors.rs @@ -127,8 +127,8 @@ pub enum InstructionErrorKind { /// The memory doesn't exist. MemoryIsMissing { - /// The memory indeX. - memory_index: u32, + /// The memory index. + memory_index: usize, }, /// Tried to read out of bounds of the memory. diff --git a/wasmer-it/src/interpreter/instructions/arrays.rs b/wasmer-it/src/interpreter/instructions/arrays.rs index 28d732f..3c9834e 100644 --- a/wasmer-it/src/interpreter/instructions/arrays.rs +++ b/wasmer-it/src/interpreter/instructions/arrays.rs @@ -1,9 +1,17 @@ +mod lift_array; +mod lower_array; mod read_arrays; +mod utils; +mod write_arrays; +pub(crate) use lift_array::array_lift_memory_impl; +pub(crate) use lower_array::array_lower_memory_impl; + +use super::allocate; use super::read_from_instance_mem; use super::record_lift_memory_; +use super::record_lower_memory_; use super::write_to_instance_mem; -use read_arrays::*; use crate::instr_error; use crate::interpreter::instructions::to_native; @@ -15,60 +23,6 @@ use crate::{ use std::convert::TryInto; -pub(super) fn array_lift_memory_<'instance, Instance, Export, LocalImport, Memory, MemoryView>( - instance: &'instance Instance, - value_type: &IType, - offset: usize, - elements_count: usize, - instruction: Instruction, -) -> Result -where - Export: crate::interpreter::wasm::structures::Export, - LocalImport: crate::interpreter::wasm::structures::LocalImport, - Memory: crate::interpreter::wasm::structures::Memory, - MemoryView: crate::interpreter::wasm::structures::MemoryView, - Instance: crate::interpreter::wasm::structures::Instance - + 'instance, -{ - if elements_count == 0 { - return Ok(IValue::Array(vec![])); - } - - match value_type { - IType::Boolean => read_bool_array(instance, instruction.clone(), offset, elements_count), - IType::S8 => read_s8_array(instance, instruction.clone(), offset, elements_count), - IType::S16 => read_s16_array(instance, instruction.clone(), offset, elements_count), - IType::S32 => read_s32_array(instance, instruction.clone(), offset, elements_count), - IType::S64 => read_s64_array(instance, instruction.clone(), offset, elements_count), - IType::I32 => read_i32_array(instance, instruction.clone(), offset, elements_count), - IType::I64 => read_i64_array(instance, instruction.clone(), offset, elements_count), - IType::U8 => read_u8_array(instance, instruction.clone(), offset, elements_count), - IType::U16 => read_u16_array(instance, instruction.clone(), offset, elements_count), - IType::U32 => read_u32_array(instance, instruction.clone(), offset, elements_count), - IType::U64 => read_u64_array(instance, instruction.clone(), offset, elements_count), - IType::F32 => read_f32_array(instance, instruction.clone(), offset, elements_count), - IType::F64 => read_f64_array(instance, instruction.clone(), offset, elements_count), - IType::String => read_string_array(instance, instruction.clone(), offset, elements_count), - IType::Record(record_type_id) => read_record_array( - instance, - instruction.clone(), - *record_type_id, - offset, - elements_count, - ), - IType::ByteArray => read_array_array( - instance, - instruction.clone(), - &IType::ByteArray, - offset, - elements_count, - ), - IType::Array(ty) => { - read_array_array(instance, instruction.clone(), &ty, offset, elements_count) - } - } -} - pub(crate) fn array_lift_memory( instruction: Instruction, value_type: IType, @@ -110,7 +64,7 @@ where ); let instance = &mut runtime.wasm_instance; - let array = array_lift_memory_( + let array = array_lift_memory_impl( *instance, &value_type, offset as _, @@ -126,72 +80,6 @@ where }) } -pub(super) fn array_lower_memory_( - instance: &mut Instance, - instruction: Instruction, - array_values: Vec, -) -> Result<(usize, usize), InstructionError> -where - Export: crate::interpreter::wasm::structures::Export, - LocalImport: crate::interpreter::wasm::structures::LocalImport, - Memory: crate::interpreter::wasm::structures::Memory, - MemoryView: crate::interpreter::wasm::structures::MemoryView, - Instance: - crate::interpreter::wasm::structures::Instance, -{ - let mut result: Vec = Vec::with_capacity(array_values.len()); - - // here it's known that all interface values have the same type - for value in array_values { - match value { - IValue::S8(value) => result.push(value as _), - IValue::S16(value) => result.push(value as _), - IValue::S32(value) => result.push(value as _), - IValue::S64(value) => result.push(value as _), - IValue::U8(value) => result.push(value as _), - IValue::U16(value) => result.push(value as _), - IValue::U32(value) => result.push(value as _), - IValue::U64(value) => result.push(value as _), - IValue::I32(value) => result.push(value as _), - IValue::I64(value) => result.push(value as _), - IValue::F32(value) => result.push(value as _), - IValue::F64(value) => result.push(value.to_bits()), - IValue::String(value) => { - let string_pointer = if !value.is_empty() { - write_to_instance_mem(instance, instruction.clone(), value.as_bytes())? - } else { - 0 - }; - - result.push(string_pointer as _); - result.push(value.len() as _); - } - - IValue::Array(values) => { - let (array_offset, array_size) = if !values.is_empty() { - array_lower_memory_(instance, instruction.clone(), values)? - } else { - (0, 0) - }; - - result.push(array_offset as _); - result.push(array_size as _); - } - - IValue::Record(values) => { - let record_offset = - super::record_lower_memory_(instance, instruction.clone(), values)?; - result.push(record_offset as _); - } - } - } - - let result = safe_transmute::transmute_to_bytes::(&result); - let result_pointer = write_to_instance_mem(instance, instruction, &result)?; - - Ok((result_pointer as _, result.len() as _)) -} - pub(crate) fn array_lower_memory( instruction: Instruction, value_type: IType, @@ -230,7 +118,7 @@ where } let (offset, size) = - array_lower_memory_(*instance, instruction.clone(), values)?; + array_lower_memory_impl(*instance, instruction.clone(), values)?; log::trace!( "array.lower_memory: pushing {}, {} on the stack", diff --git a/wasmer-it/src/interpreter/instructions/arrays/lift_array.rs b/wasmer-it/src/interpreter/instructions/arrays/lift_array.rs new file mode 100644 index 0000000..4520d0f --- /dev/null +++ b/wasmer-it/src/interpreter/instructions/arrays/lift_array.rs @@ -0,0 +1,57 @@ +use super::read_arrays::*; + +use crate::{errors::InstructionError, interpreter::Instruction, IType, IValue}; + +pub(crate) fn array_lift_memory_impl<'instance, Instance, Export, LocalImport, Memory, MemoryView>( + instance: &'instance Instance, + value_type: &IType, + offset: usize, + elements_count: usize, + instruction: Instruction, +) -> Result +where + Export: crate::interpreter::wasm::structures::Export, + LocalImport: crate::interpreter::wasm::structures::LocalImport, + Memory: crate::interpreter::wasm::structures::Memory, + MemoryView: crate::interpreter::wasm::structures::MemoryView, + Instance: crate::interpreter::wasm::structures::Instance + + 'instance, +{ + if elements_count == 0 { + return Ok(IValue::Array(vec![])); + } + + match value_type { + IType::Boolean => read_bool_array(instance, instruction.clone(), offset, elements_count), + IType::S8 => read_s8_array(instance, instruction.clone(), offset, elements_count), + IType::S16 => read_s16_array(instance, instruction.clone(), offset, elements_count), + IType::S32 => read_s32_array(instance, instruction.clone(), offset, elements_count), + IType::S64 => read_s64_array(instance, instruction.clone(), offset, elements_count), + IType::I32 => read_i32_array(instance, instruction.clone(), offset, elements_count), + IType::I64 => read_i64_array(instance, instruction.clone(), offset, elements_count), + IType::U8 => read_u8_array(instance, instruction.clone(), offset, elements_count), + IType::U16 => read_u16_array(instance, instruction.clone(), offset, elements_count), + IType::U32 => read_u32_array(instance, instruction.clone(), offset, elements_count), + IType::U64 => read_u64_array(instance, instruction.clone(), offset, elements_count), + IType::F32 => read_f32_array(instance, instruction.clone(), offset, elements_count), + IType::F64 => read_f64_array(instance, instruction.clone(), offset, elements_count), + IType::String => read_string_array(instance, instruction.clone(), offset, elements_count), + IType::Record(record_type_id) => read_record_array( + instance, + instruction.clone(), + *record_type_id, + offset, + elements_count, + ), + IType::ByteArray => read_array_array( + instance, + instruction.clone(), + &IType::ByteArray, + offset, + elements_count, + ), + IType::Array(ty) => { + read_array_array(instance, instruction.clone(), &ty, offset, elements_count) + } + } +} diff --git a/wasmer-it/src/interpreter/instructions/arrays/lower_array.rs b/wasmer-it/src/interpreter/instructions/arrays/lower_array.rs new file mode 100644 index 0000000..b539878 --- /dev/null +++ b/wasmer-it/src/interpreter/instructions/arrays/lower_array.rs @@ -0,0 +1,107 @@ +use super::utils::MemoryWriter; +use super::write_to_instance_mem; + +use crate::{ + errors::{InstructionError, InstructionErrorKind}, + interpreter::Instruction, + IValue, +}; + +pub(crate) fn array_lower_memory_impl( + instance: &mut Instance, + instruction: Instruction, + array_values: Vec, +) -> Result<(usize, usize), InstructionError> +where + Export: crate::interpreter::wasm::structures::Export, + LocalImport: crate::interpreter::wasm::structures::LocalImport, + Memory: crate::interpreter::wasm::structures::Memory, + MemoryView: crate::interpreter::wasm::structures::MemoryView, + Instance: + crate::interpreter::wasm::structures::Instance, +{ + if array_values.is_empty() { + return Ok((0, 0)); + } + + let size_to_allocate = value_size(&array_values[0]) * array_values.len(); + let offset = super::allocate(instance, instruction.clone(), size_to_allocate)?; + + let memory_index = 0; + let memory_view = &instance + .memory(memory_index) + .ok_or_else(|| { + InstructionError::new( + instruction.clone(), + InstructionErrorKind::MemoryIsMissing { memory_index }, + ) + })? + .view(); + let writer = MemoryWriter::new(memory_view, offset); + + let values_count = array_values.len(); + + // here it's known that all interface values have the same type + for value in array_values { + match value { + IValue::Boolean(value) => writer.write_u8(value as _), + IValue::S8(value) => writer.write_u8(value as _), + IValue::S16(value) => writer.write_array(value.to_le_bytes()), + IValue::S32(value) => writer.write_array(value.to_le_bytes()), + IValue::S64(value) => writer.write_array(value.to_le_bytes()), + IValue::U8(value) => writer.write_array(value.to_le_bytes()), + IValue::U16(value) => writer.write_array(value.to_le_bytes()), + IValue::U32(value) => writer.write_array(value.to_le_bytes()), + IValue::U64(value) => writer.write_array(value.to_le_bytes()), + IValue::I32(value) => writer.write_array(value.to_le_bytes()), + IValue::I64(value) => writer.write_array(value.to_le_bytes()), + IValue::F32(value) => writer.write_array(value.to_le_bytes()), + IValue::F64(value) => writer.write_array(value.to_le_bytes()), + IValue::String(value) => { + let string_pointer = + write_to_instance_mem(instance, instruction.clone(), value.as_bytes())?; + + writer.write_array(string_pointer.to_le_bytes()); + writer.write_array(value.len().to_le_bytes()); + } + IValue::ByteArray(values) => writer.write_slice(&values), + IValue::Array(values) => { + let (array_offset, array_size) = + array_lower_memory_impl(instance, instruction.clone(), values)?; + + writer.write_array(array_offset.to_le_bytes()); + writer.write_array(array_size.to_le_bytes()); + } + + IValue::Record(values) => { + let record_offset = + super::record_lower_memory_(instance, instruction.clone(), values)?; + writer.write_array(record_offset.to_le_bytes()); + } + } + } + + Ok((offset as _, values_count as _)) +} + +fn value_size(value: &IValue) -> usize { + match value { + IValue::Boolean(_) => 1, + IValue::S8(_) => 1, + IValue::S16(_) => 2, + IValue::S32(_) => 4, + IValue::S64(_) => 8, + IValue::U8(_) => 1, + IValue::U16(_) => 2, + IValue::U32(_) => 4, + IValue::U64(_) => 8, + IValue::F32(_) => 4, + IValue::F64(_) => 8, + IValue::String(_) => 4, + IValue::ByteArray(_) => 4, + IValue::Array(_) => 4, + IValue::I32(_) => 4, + IValue::I64(_) => 8, + IValue::Record(_) => 4, + } +} diff --git a/wasmer-it/src/interpreter/instructions/arrays/read_arrays.rs b/wasmer-it/src/interpreter/instructions/arrays/read_arrays.rs index dafd139..5870732 100644 --- a/wasmer-it/src/interpreter/instructions/arrays/read_arrays.rs +++ b/wasmer-it/src/interpreter/instructions/arrays/read_arrays.rs @@ -55,9 +55,9 @@ where MemoryView: wasm::structures::MemoryView + 'instance, Instance: wasm::structures::Instance, { - let memory_index: u32 = 0; + let memory_index = 0; let memory_view = instance - .memory(memory_index as usize) + .memory(memory_index) .ok_or_else(|| { InstructionError::new( instruction.clone(), @@ -112,7 +112,7 @@ def_read_func!(read_s8_array, (i8, elements_count), { |memory_view: &[Cell]| { let mut result = Vec::with_capacity(elements_count); for element_id in 0..elements_count { - let value = i8::from_be_bytes([Cell::get(&memory_view[element_id])]); + let value = i8::from_le_bytes([Cell::get(&memory_view[element_id])]); result.push(IValue::S8(value)); } @@ -124,7 +124,7 @@ def_read_func!(read_u16_array, (u16, elements_count), { |memory_view: &[Cell]| { let mut result = Vec::with_capacity(elements_count); for element_id in 0..elements_count { - let value = u16::from_be_bytes([ + let value = u16::from_le_bytes([ Cell::get(&memory_view[2 * element_id]), Cell::get(&memory_view[2 * element_id + 1]), ]); @@ -139,7 +139,7 @@ def_read_func!(read_s16_array, (i16, elements_count), { |memory_view: &[Cell]| { let mut result = Vec::with_capacity(elements_count); for element_id in 0..elements_count { - let value = i16::from_be_bytes([ + let value = i16::from_le_bytes([ Cell::get(&memory_view[2 * element_id]), Cell::get(&memory_view[2 * element_id + 1]), ]); @@ -154,7 +154,7 @@ def_read_func!(read_u32_array, (u32, elements_count), { |memory_view: &[Cell]| { let mut result = Vec::with_capacity(elements_count); for element_id in 0..elements_count { - let value = u32::from_be_bytes([ + let value = u32::from_le_bytes([ Cell::get(&memory_view[4 * element_id]), Cell::get(&memory_view[4 * element_id + 1]), Cell::get(&memory_view[4 * element_id + 2]), @@ -171,7 +171,7 @@ def_read_func!(read_f32_array, (f32, elements_count), { |memory_view: &[Cell]| { let mut result = Vec::with_capacity(elements_count); for element_id in 0..elements_count { - let value = f32::from_be_bytes([ + let value = f32::from_le_bytes([ Cell::get(&memory_view[4 * element_id]), Cell::get(&memory_view[4 * element_id + 1]), Cell::get(&memory_view[4 * element_id + 2]), @@ -188,7 +188,7 @@ def_read_func!(read_s32_array, (i32, elements_count), { |memory_view: &[Cell]| { let mut result = Vec::with_capacity(elements_count); for element_id in 0..elements_count { - let value = i32::from_be_bytes([ + let value = i32::from_le_bytes([ Cell::get(&memory_view[4 * element_id]), Cell::get(&memory_view[4 * element_id + 1]), Cell::get(&memory_view[4 * element_id + 2]), @@ -205,7 +205,7 @@ def_read_func!(read_i32_array, (i32, elements_count), { |memory_view: &[Cell]| { let mut result = Vec::with_capacity(elements_count); for element_id in 0..elements_count { - let value = i32::from_be_bytes([ + let value = i32::from_le_bytes([ Cell::get(&memory_view[4 * element_id]), Cell::get(&memory_view[4 * element_id + 1]), Cell::get(&memory_view[4 * element_id + 2]), @@ -222,7 +222,7 @@ def_read_func!(read_u64_array, (u64, elements_count), { |memory_view: &[Cell]| { let mut result = Vec::with_capacity(elements_count); for element_id in 0..elements_count { - let value = u64::from_be_bytes([ + let value = u64::from_le_bytes([ Cell::get(&memory_view[4 * element_id]), Cell::get(&memory_view[4 * element_id + 1]), Cell::get(&memory_view[4 * element_id + 2]), @@ -243,7 +243,7 @@ def_read_func!(read_f64_array, (f64, elements_count), { |memory_view: &[Cell]| { let mut result = Vec::with_capacity(elements_count); for element_id in 0..elements_count { - let value = f64::from_be_bytes([ + let value = f64::from_le_bytes([ Cell::get(&memory_view[4 * element_id]), Cell::get(&memory_view[4 * element_id + 1]), Cell::get(&memory_view[4 * element_id + 2]), @@ -264,7 +264,7 @@ def_read_func!(read_s64_array, (i64, elements_count), { |memory_view: &[Cell]| { let mut result = Vec::with_capacity(elements_count); for element_id in 0..elements_count { - let value = i64::from_be_bytes([ + let value = i64::from_le_bytes([ Cell::get(&memory_view[4 * element_id]), Cell::get(&memory_view[4 * element_id + 1]), Cell::get(&memory_view[4 * element_id + 2]), @@ -285,7 +285,7 @@ def_read_func!(read_i64_array, (i64, elements_count), { |memory_view: &[Cell]| { let mut result = Vec::with_capacity(elements_count); for element_id in 0..elements_count { - let value = i64::from_be_bytes([ + let value = i64::from_le_bytes([ Cell::get(&memory_view[4 * element_id]), Cell::get(&memory_view[4 * element_id + 1]), Cell::get(&memory_view[4 * element_id + 2]), @@ -459,7 +459,7 @@ where )?; IValue::ByteArray(value) } - _ => super::array_lift_memory_( + _ => super::array_lift_memory_impl( instance, &*ty, *array_offset as _, diff --git a/wasmer-it/src/interpreter/instructions/arrays/utils.rs b/wasmer-it/src/interpreter/instructions/arrays/utils.rs new file mode 100644 index 0000000..015f97b --- /dev/null +++ b/wasmer-it/src/interpreter/instructions/arrays/utils.rs @@ -0,0 +1,47 @@ +use std::cell::Cell; + +pub(super) struct MemoryWriter<'m> { + memory_view: &'m [Cell], + offset: Cell, +} + +impl<'m> MemoryWriter<'m> { + pub(crate) fn new(memory_view: &'m [Cell], offset: usize) -> Self { + let offset = Cell::new(offset); + + Self { + memory_view, + offset, + } + } + + pub(crate) fn write_u8(&self, value: u8) { + let offset = self.offset.get(); + self.memory_view[offset].set(value); + self.offset.set(offset + 1); + } + + pub(crate) fn write_slice(&self, values: &[u8]) { + let offset = self.offset.get(); + + for (id, value) in values.iter().enumerate() { + // don't check for memory overflow here for optimization purposes + // assuming that caller site work well + self.memory_view[offset + id].set(*value); + } + + self.offset.set(offset + values.len()); + } + + pub(crate) fn write_array(&self, values: [u8; N]) { + let offset = self.offset.get(); + + for id in 0..N { + // don't check for memory overflow here for optimization purposes + // assuming that caller site work well + self.memory_view[offset + id].set(values[id]); + } + + self.offset.set(offset + values.len()); + } +} diff --git a/wasmer-it/src/interpreter/instructions/arrays/write_arrays.rs b/wasmer-it/src/interpreter/instructions/arrays/write_arrays.rs new file mode 100644 index 0000000..8b13789 --- /dev/null +++ b/wasmer-it/src/interpreter/instructions/arrays/write_arrays.rs @@ -0,0 +1 @@ + diff --git a/wasmer-it/src/interpreter/instructions/records.rs b/wasmer-it/src/interpreter/instructions/records.rs index ede5fc0..27f7621 100644 --- a/wasmer-it/src/interpreter/instructions/records.rs +++ b/wasmer-it/src/interpreter/instructions/records.rs @@ -14,93 +14,6 @@ use crate::{ use std::convert::TryInto; -/* -/// Build an `IValue::Record` based on values on the stack. -/// -/// To fill a record, every field `field_1` to `field_n` must get its -/// value from the stack with `value_1` to `value_n`. It is not -/// possible to use `Stack::pop` because the one-pass algorithm does -/// not know exactly the number of values to read from the stack -/// ahead-of-time, so `Stack::pop1` is used. It implies that values -/// are read one after the other from the stack, in a natural reverse -/// order, from `value_n` to `value_1`. Thus, the `values` vector must -/// be filled from the end to the beginning. It is not safely possible -/// to fill the `values` vector with empty values though (so that it -/// is possible to access to last positions). So a `VecDeque` type is -/// used: it is a double-ended queue. -fn record_lift_( - stack: &mut Stack, - record_type: &RecordType, -) -> Result { - let length = record_type.fields.len(); - let mut values = VecDeque::with_capacity(length); - for field in record_type.fields.iter().rev() { - match field { - IType::Record(record_type) => { - values.push_front(record_lift_(stack, &record_type)?) - } - ty => { - let value = stack.pop1().unwrap(); - let value_type = (&value).into(); - if ty != &value_type { - return Err(InstructionErrorKind::InvalidValueOnTheStack { - expected_type: ty.clone(), - received_type: value_type, - }); - } - values.push_front(value) - } - } - } - Ok(IValue::Record( - NEVec::new(values.into_iter().collect()) - .expect("Record must have at least one field, zero given"), - )) -} - -pub(crate) fn record_lift( - type_index: u32, - instruction: Instruction, -) -> crate::interpreter::ExecutableInstruction -where - Export: crate::interpreter::wasm::structures::Export, - LocalImport: crate::interpreter::wasm::structures::LocalImport, - Memory: crate::interpreter::wasm::structures::Memory, - MemoryView: crate::interpreter::wasm::structures::MemoryView, - Instance: - crate::interpreter::wasm::structures::Instance, -{ - #[allow(unused_imports)] - use crate::interpreter::stack::Stackable; - Box::new({ - move |runtime| -> _ { - let instance = &runtime.wasm_instance; - let record_type = match instance.wit_type(type_index).ok_or_else(|| { - InstructionError::new( - instruction.clone(), - InstructionErrorKind::TypeIsMissing { type_index }, - ) - })? { - Type::Record(record_type) => record_type, - Type::Function { .. } => { - return Err(InstructionError::new( - instruction.clone(), - InstructionErrorKind::InvalidTypeKind { - expected_kind: TypeKind::Record, - received_kind: TypeKind::Function, - }, - )) - } - }; - let record = record_lift_(&mut runtime.stack, &record_type) - .map_err(|k| InstructionError::new(instruction.clone(), k))?; - runtime.stack.push(record); - Ok(()) - } - }) -} - */ - pub(super) fn record_lift_memory_<'instance, Instance, Export, LocalImport, Memory, MemoryView>( instance: &'instance Instance, record_type: &IRecordType, @@ -115,33 +28,18 @@ where Instance: crate::interpreter::wasm::structures::Instance + 'instance, { - fn record_size(record_type: &IRecordType) -> usize { - let mut record_size = 0; - - for field_type in record_type.fields.iter() { - let params_count = match field_type.ty { - IType::String | IType::Array(_) => 2, - _ => 1, - }; - - record_size += std::mem::size_of::() * params_count; - } - - record_size - } - let length = record_type.fields.len(); let mut values = Vec::with_capacity(length); let size = record_size(record_type); let data = read_from_instance_mem(instance, instruction.clone(), offset, size)?; - // TODO: add error handling - let data = - safe_transmute::transmute_many::(&data).unwrap(); let mut field_id = 0; for field in (*record_type.fields).iter() { let value = data[field_id]; match &field.ty { + IType::Boolean => { + values.push(IValue::Boolean(value as _)); + } IType::S8 => { values.push(IValue::S8(value as _)); } @@ -202,7 +100,7 @@ where let array_size = data[field_id]; if array_size != 0 { - let array = super::array_lift_memory_( + let array = super::array_lift_memory_impl( instance, &**ty, array_offset as _, @@ -243,6 +141,29 @@ where )) } +/// Returns record size in bytes. +fn record_size(record_type: &IRecordType) -> usize { + let mut record_size = 0; + + for field_type in record_type.fields.iter() { + record_size += match field_type.ty { + IType::Boolean | IType::S8 | IType::U8 => 1, + IType::S16 | IType::U16 => 2, + IType::S32 + | IType::U32 + | IType::I32 + | IType::F32 + | IType::String + | IType::ByteArray + | IType::Array(_) + | IType::Record(_) => 32, + IType::S64 | IType::U64 | IType::I64 | IType::F64 => 64, + }; + } + + record_size +} + pub(crate) fn record_lift_memory( record_type_id: u64, instruction: Instruction, @@ -310,53 +231,53 @@ where Instance: crate::interpreter::wasm::structures::Instance, { - let mut result: Vec = Vec::with_capacity(values.len()); + let mut result: Vec = Vec::with_capacity(values.len()); for value in values.into_vec() { match value { + IValue::Boolean(value) => result.push(value as _), IValue::S8(value) => result.push(value as _), - IValue::S16(value) => result.push(value as _), - IValue::S32(value) => result.push(value as _), - IValue::S64(value) => result.push(value as _), - IValue::U8(value) => result.push(value as _), - IValue::U16(value) => result.push(value as _), - IValue::U32(value) => result.push(value as _), - IValue::U64(value) => result.push(value as _), - IValue::I32(value) => result.push(value as _), - IValue::I64(value) => result.push(value as _), - IValue::F32(value) => result.push(value as _), - IValue::F64(value) => result.push(value.to_bits()), + IValue::S16(value) => result.extend_from_slice(&value.to_le_bytes()), + IValue::S32(value) => result.extend_from_slice(&value.to_le_bytes()), + IValue::S64(value) => result.extend_from_slice(&value.to_le_bytes()), + IValue::U8(value) => result.push(value), + IValue::U16(value) => result.extend_from_slice(&value.to_le_bytes()), + IValue::U32(value) => result.extend_from_slice(&value.to_le_bytes()), + IValue::U64(value) => result.extend_from_slice(&value.to_le_bytes()), + IValue::I32(value) => result.extend_from_slice(&value.to_le_bytes()), + IValue::I64(value) => result.extend_from_slice(&value.to_le_bytes()), + IValue::F32(value) => result.extend_from_slice(&value.to_le_bytes()), + IValue::F64(value) => result.extend_from_slice(&value.to_le_bytes()), IValue::String(value) => { - let string_pointer = if !value.is_empty() { - write_to_instance_mem(instance, instruction.clone(), value.as_bytes())? - } else { - 0 - }; + let string_pointer = + write_to_instance_mem(instance, instruction.clone(), value.as_bytes())?; - result.push(string_pointer as _); - result.push(value.len() as _); + result.extend_from_slice(&string_pointer.to_le_bytes()); + result.extend_from_slice(&value.len().to_le_bytes()); + } + IValue::ByteArray(value) => { + let array_pointer = write_to_instance_mem(instance, instruction.clone(), &value)?; + + result.extend_from_slice(&array_pointer.to_le_bytes()); + result.extend_from_slice(&value.len().to_le_bytes()); } IValue::Array(values) => { - let (offset, size) = if !values.is_empty() { - super::array_lower_memory_(instance, instruction.clone(), values)? - } else { - (0, 0) - }; + let (offset, size) = + super::array_lower_memory_impl(instance, instruction.clone(), values)?; - result.push(offset as _); - result.push(size as _); + result.extend_from_slice(&offset.to_le_bytes()); + result.extend_from_slice(&size.to_le_bytes()); } IValue::Record(values) => { let record_ptr = record_lower_memory_(instance, instruction.clone(), values)?; - result.push(record_ptr as _); + result.extend_from_slice(&record_ptr.to_le_bytes()); } } } - let result = safe_transmute::transmute_to_bytes::(&result); let result_pointer = write_to_instance_mem(instance, instruction, &result)?; Ok(result_pointer as _) @@ -414,65 +335,3 @@ where } }) } - -/* -pub(crate) fn record_lower( - type_index: u32, - instruction: Instruction, -) -> crate::interpreter::ExecutableInstruction -where - Export: crate::interpreter::wasm::structures::Export, - LocalImport: crate::interpreter::wasm::structures::LocalImport, - Memory: crate::interpreter::wasm::structures::Memory, - MemoryView: crate::interpreter::wasm::structures::MemoryView, - Instance: - crate::interpreter::wasm::structures::Instance, -{ - #[allow(unused_imports)] - use crate::interpreter::stack::Stackable; - Box::new({ - move |runtime| -> _ { - let instance = &runtime.wasm_instance; - let record_type = match instance.wit_type(type_index).ok_or_else(|| { - InstructionError::new( - instruction.clone(), - InstructionErrorKind::TypeIsMissing { type_index }, - ) - })? { - Type::Record(record_type) => record_type, - Type::Function { .. } => { - return Err(InstructionError::new( - instruction.clone(), - InstructionErrorKind::InvalidTypeKind { - expected_kind: TypeKind::Record, - received_kind: TypeKind::Function, - }, - )) - } - }; - match runtime.stack.pop1() { - Some(IValue::Record(record_values)) - if record_type == &(&*record_values).into() => - { - let values = FlattenIValueIterator::new(&record_values); - for value in values { - runtime.stack.push(value.clone()); - } - Ok(()) - } - Some(value) => Err(InstructionError::new( - instruction.clone(), - InstructionErrorKind::InvalidValueOnTheStack { - expected_type: IType::Record(record_type.clone()), - received_type: (&value).into(), - }, - )), - None => Err(InstructionError::new( - instruction.clone(), - InstructionErrorKind::StackIsTooSmall { needed: 1 }, - )), - } - } - }) -} - */ diff --git a/wasmer-it/src/interpreter/instructions/records/lift_record.rs b/wasmer-it/src/interpreter/instructions/records/lift_record.rs new file mode 100644 index 0000000..e69de29 diff --git a/wasmer-it/src/interpreter/instructions/records/lower_record.rs b/wasmer-it/src/interpreter/instructions/records/lower_record.rs new file mode 100644 index 0000000..e69de29 diff --git a/wasmer-it/src/interpreter/instructions/strings.rs b/wasmer-it/src/interpreter/instructions/strings.rs index b3c2ae2..e50367d 100644 --- a/wasmer-it/src/interpreter/instructions/strings.rs +++ b/wasmer-it/src/interpreter/instructions/strings.rs @@ -19,10 +19,10 @@ executable_instruction!( ) })?; - let memory_index: u32 = 0; + let memory_index = 0; let memory = runtime .wasm_instance - .memory(memory_index as usize) + .memory(memory_index) .ok_or_else(|| { InstructionError::new( instruction.clone(), @@ -96,9 +96,9 @@ executable_instruction!( })?; let instance = &mut runtime.wasm_instance; - let memory_index: u32 = 0; + let memory_index = 0; let memory_view = instance - .memory(memory_index as usize) + .memory(memory_index) .ok_or_else(|| { InstructionError::new( instruction.clone(), diff --git a/wasmer-it/src/interpreter/instructions/utils.rs b/wasmer-it/src/interpreter/instructions/utils.rs index 8a330f1..f743357 100644 --- a/wasmer-it/src/interpreter/instructions/utils.rs +++ b/wasmer-it/src/interpreter/instructions/utils.rs @@ -24,9 +24,9 @@ where MemoryView: wasm::structures::MemoryView, Instance: wasm::structures::Instance, { - let memory_index: u32 = 0; + let memory_index = 0; let memory_view = instance - .memory(memory_index as usize) + .memory(memory_index) .ok_or_else(|| { InstructionError::new( instruction.clone(), @@ -66,11 +66,15 @@ where MemoryView: wasm::structures::MemoryView, Instance: wasm::structures::Instance, { + if bytes.is_empty() { + return Ok(0); + } + let offset = allocate(instance, instruction.clone(), bytes.len() as _)?; - let memory_index: u32 = 0; + let memory_index = 0; let memory_view = instance - .memory(memory_index as usize) + .memory(memory_index) .ok_or_else(|| { InstructionError::new( instruction.clone(),