mirror of
https://github.com/fluencelabs/parity-wasm
synced 2025-05-17 17:51:29 +00:00
LittleEndianConvert trait for memory access
This commit is contained in:
parent
c2aef456a5
commit
b7b93ac348
@ -44,7 +44,6 @@ mod program;
|
||||
mod runner;
|
||||
mod stack;
|
||||
mod table;
|
||||
mod utils;
|
||||
mod value;
|
||||
mod variable;
|
||||
|
||||
|
@ -6,9 +6,8 @@ use elements::{Opcode, BlockType, FunctionType};
|
||||
use interpreter::Error;
|
||||
use interpreter::module::{ModuleInstance, ItemIndex};
|
||||
use interpreter::stack::StackWithLimit;
|
||||
use interpreter::utils::{to_little_endian_bytes, from_little_endian_bytes};
|
||||
use interpreter::value::{RuntimeValue, TryInto, WrapInto, TryTruncateInto, ExtendInto, TransmuteInto,
|
||||
ArithmeticOps, Integer, Float};
|
||||
ArithmeticOps, Integer, Float, LittleEndianConvert};
|
||||
use interpreter::variable::VariableInstance;
|
||||
|
||||
const DEFAULT_MEMORY_INDEX: u32 = 0;
|
||||
@ -397,21 +396,21 @@ impl Interpreter {
|
||||
}
|
||||
|
||||
fn run_load<T>(context: &mut FunctionContext, offset: u32, align: u32) -> Result<InstructionOutcome, Error>
|
||||
where RuntimeValue: From<T> {
|
||||
where RuntimeValue: From<T>, T: LittleEndianConvert {
|
||||
context.module()
|
||||
.memory(ItemIndex::IndexSpace(DEFAULT_MEMORY_INDEX))
|
||||
.and_then(|m| m.get(effective_address(offset, align)?, 4))
|
||||
.map(|b| from_little_endian_bytes::<T>(&b))
|
||||
.and_then(|b| T::from_little_endian(b))
|
||||
.and_then(|n| context.value_stack_mut().push(n.into()))
|
||||
.map(|_| InstructionOutcome::RunNextInstruction)
|
||||
}
|
||||
|
||||
fn run_load_extend<T, U>(context: &mut FunctionContext, offset: u32, align: u32) -> Result<InstructionOutcome, Error>
|
||||
where T: ExtendInto<U>, RuntimeValue: From<U> {
|
||||
where T: ExtendInto<U>, RuntimeValue: From<U>, T: LittleEndianConvert {
|
||||
let stack_value: U = context.module()
|
||||
.memory(ItemIndex::IndexSpace(DEFAULT_MEMORY_INDEX))
|
||||
.and_then(|m| m.get(effective_address(offset, align)?, mem::size_of::<T>()))
|
||||
.map(|b| from_little_endian_bytes::<T>(&b))
|
||||
.and_then(|b| T::from_little_endian(b))
|
||||
.map(|v| v.extend_into())?;
|
||||
context
|
||||
.value_stack_mut()
|
||||
@ -420,11 +419,11 @@ impl Interpreter {
|
||||
}
|
||||
|
||||
fn run_store<T>(context: &mut FunctionContext, offset: u32, align: u32) -> Result<InstructionOutcome, Error>
|
||||
where RuntimeValue: TryInto<T, Error> {
|
||||
where RuntimeValue: TryInto<T, Error>, T: LittleEndianConvert {
|
||||
let stack_value = context
|
||||
.value_stack_mut()
|
||||
.pop_as::<T>()
|
||||
.map(|n| to_little_endian_bytes::<T>(n))?;
|
||||
.map(|n| n.into_little_endian())?;
|
||||
context.module()
|
||||
.memory(ItemIndex::IndexSpace(DEFAULT_MEMORY_INDEX))
|
||||
.and_then(|m| m.set(effective_address(offset, align)?, &stack_value))
|
||||
@ -432,9 +431,9 @@ impl Interpreter {
|
||||
}
|
||||
|
||||
fn run_store_wrap<T, U>(context: &mut FunctionContext, offset: u32, align: u32) -> Result<InstructionOutcome, Error>
|
||||
where RuntimeValue: TryInto<T, Error>, T: WrapInto<U> {
|
||||
where RuntimeValue: TryInto<T, Error>, T: WrapInto<U>, U: LittleEndianConvert {
|
||||
let stack_value: T = context.value_stack_mut().pop().and_then(|v| v.try_into())?;
|
||||
let stack_value = to_little_endian_bytes::<U>(stack_value.wrap_into());
|
||||
let stack_value = stack_value.wrap_into().into_little_endian();
|
||||
context.module()
|
||||
.memory(ItemIndex::IndexSpace(DEFAULT_MEMORY_INDEX))
|
||||
.and_then(|m| m.set(effective_address(offset, align)?, &stack_value))
|
||||
|
@ -1,7 +0,0 @@
|
||||
pub fn to_little_endian_bytes<T>(_number: T) -> Vec<u8> {
|
||||
unimplemented!()
|
||||
}
|
||||
|
||||
pub fn from_little_endian_bytes<T>(_buffer: &[u8]) -> T {
|
||||
unimplemented!()
|
||||
}
|
@ -1,5 +1,7 @@
|
||||
use std::{i32, i64, u32, u64, f32};
|
||||
use std::io;
|
||||
use std::mem;
|
||||
use byteorder::{LittleEndian, ReadBytesExt, WriteBytesExt};
|
||||
use interpreter::Error;
|
||||
use interpreter::variable::VariableType;
|
||||
|
||||
@ -50,6 +52,14 @@ pub trait TransmuteInto<T> {
|
||||
fn transmute_into(self) -> T;
|
||||
}
|
||||
|
||||
/// Convert from and to little endian.
|
||||
pub trait LittleEndianConvert where Self: Sized {
|
||||
/// Convert to little endian bufer.
|
||||
fn into_little_endian(self) -> Vec<u8>;
|
||||
/// Convert from little endian bufer.
|
||||
fn from_little_endian(buffer: Vec<u8>) -> Result<Self, Error>;
|
||||
}
|
||||
|
||||
/// Arithmetic operations.
|
||||
pub trait ArithmeticOps<T> {
|
||||
/// Add two values.
|
||||
@ -331,6 +341,8 @@ macro_rules! impl_transmute_into {
|
||||
}
|
||||
}
|
||||
|
||||
impl_transmute_into!(i8, u8);
|
||||
impl_transmute_into!(u8, i8);
|
||||
impl_transmute_into!(i32, u32);
|
||||
impl_transmute_into!(u32, i32);
|
||||
impl_transmute_into!(i32, f32);
|
||||
@ -340,6 +352,130 @@ impl_transmute_into!(u64, i64);
|
||||
impl_transmute_into!(i64, f64);
|
||||
impl_transmute_into!(f64, i64);
|
||||
|
||||
impl LittleEndianConvert for i8 {
|
||||
fn into_little_endian(self) -> Vec<u8> {
|
||||
vec![self.transmute_into()]
|
||||
}
|
||||
|
||||
fn from_little_endian(buffer: Vec<u8>) -> Result<Self, Error> {
|
||||
buffer.get(0)
|
||||
.map(|v| v.transmute_into())
|
||||
.ok_or(Error::Value("invalid little endian buffer".into()))
|
||||
}
|
||||
}
|
||||
|
||||
impl LittleEndianConvert for u8 {
|
||||
fn into_little_endian(self) -> Vec<u8> {
|
||||
vec![self]
|
||||
}
|
||||
|
||||
fn from_little_endian(buffer: Vec<u8>) -> Result<Self, Error> {
|
||||
buffer.get(0)
|
||||
.cloned()
|
||||
.ok_or(Error::Value("invalid little endian buffer".into()))
|
||||
}
|
||||
}
|
||||
|
||||
impl LittleEndianConvert for i16 {
|
||||
fn into_little_endian(self) -> Vec<u8> {
|
||||
let mut vec = Vec::with_capacity(2);
|
||||
vec.write_i16::<LittleEndian>(self)
|
||||
.expect("i16 is written without any errors");
|
||||
vec
|
||||
}
|
||||
|
||||
fn from_little_endian(buffer: Vec<u8>) -> Result<Self, Error> {
|
||||
io::Cursor::new(buffer).read_i16::<LittleEndian>()
|
||||
.map_err(|e| Error::Value(e.to_string()))
|
||||
}
|
||||
}
|
||||
|
||||
impl LittleEndianConvert for u16 {
|
||||
fn into_little_endian(self) -> Vec<u8> {
|
||||
let mut vec = Vec::with_capacity(2);
|
||||
vec.write_u16::<LittleEndian>(self)
|
||||
.expect("u16 is written without any errors");
|
||||
vec
|
||||
}
|
||||
|
||||
fn from_little_endian(buffer: Vec<u8>) -> Result<Self, Error> {
|
||||
io::Cursor::new(buffer).read_u16::<LittleEndian>()
|
||||
.map_err(|e| Error::Value(e.to_string()))
|
||||
}
|
||||
}
|
||||
|
||||
impl LittleEndianConvert for i32 {
|
||||
fn into_little_endian(self) -> Vec<u8> {
|
||||
let mut vec = Vec::with_capacity(4);
|
||||
vec.write_i32::<LittleEndian>(self)
|
||||
.expect("i32 is written without any errors");
|
||||
vec
|
||||
}
|
||||
|
||||
fn from_little_endian(buffer: Vec<u8>) -> Result<Self, Error> {
|
||||
io::Cursor::new(buffer).read_i32::<LittleEndian>()
|
||||
.map_err(|e| Error::Value(e.to_string()))
|
||||
}
|
||||
}
|
||||
|
||||
impl LittleEndianConvert for u32 {
|
||||
fn into_little_endian(self) -> Vec<u8> {
|
||||
let mut vec = Vec::with_capacity(4);
|
||||
vec.write_u32::<LittleEndian>(self)
|
||||
.expect("u32 is written without any errors");
|
||||
vec
|
||||
}
|
||||
|
||||
fn from_little_endian(buffer: Vec<u8>) -> Result<Self, Error> {
|
||||
io::Cursor::new(buffer).read_u32::<LittleEndian>()
|
||||
.map_err(|e| Error::Value(e.to_string()))
|
||||
}
|
||||
}
|
||||
|
||||
impl LittleEndianConvert for i64 {
|
||||
fn into_little_endian(self) -> Vec<u8> {
|
||||
let mut vec = Vec::with_capacity(8);
|
||||
vec.write_i64::<LittleEndian>(self)
|
||||
.expect("i64 is written without any errors");
|
||||
vec
|
||||
}
|
||||
|
||||
fn from_little_endian(buffer: Vec<u8>) -> Result<Self, Error> {
|
||||
io::Cursor::new(buffer).read_i64::<LittleEndian>()
|
||||
.map_err(|e| Error::Value(e.to_string()))
|
||||
}
|
||||
}
|
||||
|
||||
impl LittleEndianConvert for f32 {
|
||||
fn into_little_endian(self) -> Vec<u8> {
|
||||
let mut vec = Vec::with_capacity(4);
|
||||
vec.write_i32::<LittleEndian>(self.transmute_into())
|
||||
.expect("i32 is written without any errors");
|
||||
vec
|
||||
}
|
||||
|
||||
fn from_little_endian(buffer: Vec<u8>) -> Result<Self, Error> {
|
||||
io::Cursor::new(buffer).read_i32::<LittleEndian>()
|
||||
.map(TransmuteInto::transmute_into)
|
||||
.map_err(|e| Error::Value(e.to_string()))
|
||||
}
|
||||
}
|
||||
|
||||
impl LittleEndianConvert for f64 {
|
||||
fn into_little_endian(self) -> Vec<u8> {
|
||||
let mut vec = Vec::with_capacity(8);
|
||||
vec.write_i64::<LittleEndian>(self.transmute_into())
|
||||
.expect("i64 is written without any errors");
|
||||
vec
|
||||
}
|
||||
|
||||
fn from_little_endian(buffer: Vec<u8>) -> Result<Self, Error> {
|
||||
io::Cursor::new(buffer).read_i64::<LittleEndian>()
|
||||
.map(TransmuteInto::transmute_into)
|
||||
.map_err(|e| Error::Value(e.to_string()))
|
||||
}
|
||||
}
|
||||
|
||||
macro_rules! impl_integer_arithmetic_ops {
|
||||
($type: ident) => {
|
||||
impl ArithmeticOps<$type> for $type {
|
||||
|
Loading…
x
Reference in New Issue
Block a user