mirror of
https://github.com/fluencelabs/parity-wasm
synced 2025-05-18 02:01:30 +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 runner;
|
||||||
mod stack;
|
mod stack;
|
||||||
mod table;
|
mod table;
|
||||||
mod utils;
|
|
||||||
mod value;
|
mod value;
|
||||||
mod variable;
|
mod variable;
|
||||||
|
|
||||||
|
@ -6,9 +6,8 @@ use elements::{Opcode, BlockType, FunctionType};
|
|||||||
use interpreter::Error;
|
use interpreter::Error;
|
||||||
use interpreter::module::{ModuleInstance, ItemIndex};
|
use interpreter::module::{ModuleInstance, ItemIndex};
|
||||||
use interpreter::stack::StackWithLimit;
|
use interpreter::stack::StackWithLimit;
|
||||||
use interpreter::utils::{to_little_endian_bytes, from_little_endian_bytes};
|
|
||||||
use interpreter::value::{RuntimeValue, TryInto, WrapInto, TryTruncateInto, ExtendInto, TransmuteInto,
|
use interpreter::value::{RuntimeValue, TryInto, WrapInto, TryTruncateInto, ExtendInto, TransmuteInto,
|
||||||
ArithmeticOps, Integer, Float};
|
ArithmeticOps, Integer, Float, LittleEndianConvert};
|
||||||
use interpreter::variable::VariableInstance;
|
use interpreter::variable::VariableInstance;
|
||||||
|
|
||||||
const DEFAULT_MEMORY_INDEX: u32 = 0;
|
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>
|
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()
|
context.module()
|
||||||
.memory(ItemIndex::IndexSpace(DEFAULT_MEMORY_INDEX))
|
.memory(ItemIndex::IndexSpace(DEFAULT_MEMORY_INDEX))
|
||||||
.and_then(|m| m.get(effective_address(offset, align)?, 4))
|
.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()))
|
.and_then(|n| context.value_stack_mut().push(n.into()))
|
||||||
.map(|_| InstructionOutcome::RunNextInstruction)
|
.map(|_| InstructionOutcome::RunNextInstruction)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn run_load_extend<T, U>(context: &mut FunctionContext, offset: u32, align: u32) -> Result<InstructionOutcome, Error>
|
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()
|
let stack_value: U = context.module()
|
||||||
.memory(ItemIndex::IndexSpace(DEFAULT_MEMORY_INDEX))
|
.memory(ItemIndex::IndexSpace(DEFAULT_MEMORY_INDEX))
|
||||||
.and_then(|m| m.get(effective_address(offset, align)?, mem::size_of::<T>()))
|
.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())?;
|
.map(|v| v.extend_into())?;
|
||||||
context
|
context
|
||||||
.value_stack_mut()
|
.value_stack_mut()
|
||||||
@ -420,11 +419,11 @@ impl Interpreter {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn run_store<T>(context: &mut FunctionContext, offset: u32, align: u32) -> Result<InstructionOutcome, Error>
|
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
|
let stack_value = context
|
||||||
.value_stack_mut()
|
.value_stack_mut()
|
||||||
.pop_as::<T>()
|
.pop_as::<T>()
|
||||||
.map(|n| to_little_endian_bytes::<T>(n))?;
|
.map(|n| n.into_little_endian())?;
|
||||||
context.module()
|
context.module()
|
||||||
.memory(ItemIndex::IndexSpace(DEFAULT_MEMORY_INDEX))
|
.memory(ItemIndex::IndexSpace(DEFAULT_MEMORY_INDEX))
|
||||||
.and_then(|m| m.set(effective_address(offset, align)?, &stack_value))
|
.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>
|
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: 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()
|
context.module()
|
||||||
.memory(ItemIndex::IndexSpace(DEFAULT_MEMORY_INDEX))
|
.memory(ItemIndex::IndexSpace(DEFAULT_MEMORY_INDEX))
|
||||||
.and_then(|m| m.set(effective_address(offset, align)?, &stack_value))
|
.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::{i32, i64, u32, u64, f32};
|
||||||
|
use std::io;
|
||||||
use std::mem;
|
use std::mem;
|
||||||
|
use byteorder::{LittleEndian, ReadBytesExt, WriteBytesExt};
|
||||||
use interpreter::Error;
|
use interpreter::Error;
|
||||||
use interpreter::variable::VariableType;
|
use interpreter::variable::VariableType;
|
||||||
|
|
||||||
@ -50,6 +52,14 @@ pub trait TransmuteInto<T> {
|
|||||||
fn transmute_into(self) -> 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.
|
/// Arithmetic operations.
|
||||||
pub trait ArithmeticOps<T> {
|
pub trait ArithmeticOps<T> {
|
||||||
/// Add two values.
|
/// 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!(i32, u32);
|
||||||
impl_transmute_into!(u32, i32);
|
impl_transmute_into!(u32, i32);
|
||||||
impl_transmute_into!(i32, f32);
|
impl_transmute_into!(i32, f32);
|
||||||
@ -340,6 +352,130 @@ impl_transmute_into!(u64, i64);
|
|||||||
impl_transmute_into!(i64, f64);
|
impl_transmute_into!(i64, f64);
|
||||||
impl_transmute_into!(f64, i64);
|
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 {
|
macro_rules! impl_integer_arithmetic_ops {
|
||||||
($type: ident) => {
|
($type: ident) => {
|
||||||
impl ArithmeticOps<$type> for $type {
|
impl ArithmeticOps<$type> for $type {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user