housekeeping, pr fixes

This commit is contained in:
vms 2021-04-21 19:18:45 +03:00
parent a48662d48c
commit 8de882c159
13 changed files with 225 additions and 172 deletions

View File

@ -1,4 +1,21 @@
/*
* Copyright 2021 Fluence Labs Limited
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
pub mod error;
mod macros;
pub mod memory_reader;
pub mod memory_writer;
@ -45,7 +62,7 @@ pub fn record_size(record_type: &IRecordType) -> usize {
}
pub fn type_tag_form_itype(itype: &IType) -> u32 {
const POINTER_CODE: u32 = 3; // u32 on the sdk
const POINTER_CODE: u32 = 3; // u32 in the sdk
match itype {
IType::Boolean => 0, // u8
@ -64,7 +81,7 @@ pub fn type_tag_form_itype(itype: &IType) -> u32 {
}
pub fn type_tag_form_ivalue(itype: &IValue) -> u32 {
const POINTER_CODE: u32 = 3; // u32 on the sdk
const POINTER_CODE: u32 = 3; // u32 in the sdk
match itype {
IValue::Boolean(_) => 0, // u8

View File

@ -0,0 +1,103 @@
/*
* Copyright 2021 Fluence Labs Limited
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#[macro_export]
macro_rules! value_der {
($self:expr, $offset:expr, @seq_start $($ids:tt),* @seq_end) => {
[$($self.reader.memory[$offset + $ids].get()),+]
};
($self:expr, $offset:expr, 1) => {
crate::value_der!($self, $offset, @seq_start 0 @seq_end);
};
($self:expr, $offset:expr, 2) => {
crate::value_der!($self, $offset, @seq_start 0, 1 @seq_end);
};
($self:expr, $offset:expr, 4) => {
crate::value_der!($self, $offset, @seq_start 0, 1, 2, 3 @seq_end);
};
($self:expr, $offset:expr, 8) => {
crate::value_der!($self, $offset, @seq_start 0, 1, 2, 3, 4, 5, 6, 7 @seq_end);
};
}
#[macro_export]
macro_rules! read_ty {
($func_name:ident, $ty:ty, 1) => {
pub fn $func_name(&self) -> $ty {
let offset = self.offset.get();
let result = <$ty>::from_le_bytes(crate::value_der!(self, offset, 1));
self.offset.set(offset + 1);
result
}
};
($func_name:ident, $ty:ty, 2) => {
pub fn $func_name(&self) -> $ty {
let offset = self.offset.get();
let result = <$ty>::from_le_bytes(crate::value_der!(self, offset, 2));
self.offset.set(offset + 2);
result
}
};
($func_name:ident, $ty:ty, 4) => {
pub fn $func_name(&self) -> $ty {
let offset = self.offset.get();
let result = <$ty>::from_le_bytes(crate::value_der!(self, offset, 4));
self.offset.set(offset + 4);
result
}
};
($func_name:ident, $ty:ty, 8) => {
pub fn $func_name(&self) -> $ty {
let offset = self.offset.get();
let result = <$ty>::from_le_bytes(crate::value_der!(self, offset, 8));
self.offset.set(offset + 8);
result
}
};
}
#[macro_export]
macro_rules! read_array_ty {
($func_name:ident, $ty:ident, $ity:ident) => {
pub fn $func_name(
&self,
offset: usize,
elements_count: usize,
) -> crate::MResult<Vec<crate::IValue>> {
let reader =
self.sequential_reader(offset, std::mem::size_of::<$ty>() * elements_count)?;
let mut result = Vec::with_capacity(elements_count);
for _ in 0..elements_count {
let value = paste::paste! { reader.[<read_ $ty>]()};
result.push(IValue::$ity(value));
}
Ok(result)
}
};
}

View File

@ -15,6 +15,8 @@
*/
use crate::error::MemoryAccessError;
use crate::read_array_ty;
use crate::read_ty;
use crate::IValue;
use crate::MResult;
@ -25,98 +27,13 @@ pub struct MemoryReader<'m> {
}
/// Reads values of basic types sequentially from the provided reader.
/// It don't check memory limits for the optimization purposes,
/// so it could created by the MemoryReader::sequential_reader method.
/// It doesn't check memory limits for the optimization purposes,
/// so it could be created only by the MemoryReader::sequential_reader method.
pub struct SequentialReader<'r, 'm> {
reader: &'r MemoryReader<'m>,
offset: Cell<usize>,
}
macro_rules! value_der {
($self:expr, $offset:expr, @seq_start $($ids:tt),* @seq_end) => {
[$($self.reader.memory[$offset + $ids].get()),+]
};
($self:expr, $offset:expr, 1) => {
value_der!($self, $offset, @seq_start 0 @seq_end);
};
($self:expr, $offset:expr, 2) => {
value_der!($self, $offset, @seq_start 0, 1 @seq_end);
};
($self:expr, $offset:expr, 4) => {
value_der!($self, $offset, @seq_start 0, 1, 2, 3 @seq_end);
};
($self:expr, $offset:expr, 8) => {
value_der!($self, $offset, @seq_start 0, 1, 2, 3, 4, 5, 6, 7 @seq_end);
};
}
macro_rules! read_ty {
($func_name:ident, $ty:ty, 1) => {
pub fn $func_name(&self) -> $ty {
let offset = self.offset.get();
let result = <$ty>::from_le_bytes(value_der!(self, offset, 1));
self.offset.set(offset + 1);
result
}
};
($func_name:ident, $ty:ty, 2) => {
pub fn $func_name(&self) -> $ty {
let offset = self.offset.get();
let result = <$ty>::from_le_bytes(value_der!(self, offset, 2));
self.offset.set(offset + 2);
result
}
};
($func_name:ident, $ty:ty, 4) => {
pub fn $func_name(&self) -> $ty {
let offset = self.offset.get();
let result = <$ty>::from_le_bytes(value_der!(self, offset, 4));
self.offset.set(offset + 4);
result
}
};
($func_name:ident, $ty:ty, 8) => {
pub fn $func_name(&self) -> $ty {
let offset = self.offset.get();
let result = <$ty>::from_le_bytes(value_der!(self, offset, 8));
self.offset.set(offset + 8);
result
}
};
}
macro_rules! read_array_ty {
($func_name:ident, $ty:ident, $ity:ident) => {
pub fn $func_name(
&self,
offset: usize,
elements_count: usize,
) -> crate::MResult<Vec<crate::IValue>> {
let reader =
self.sequential_reader(offset, std::mem::size_of::<$ty>() * elements_count)?;
let mut result = Vec::with_capacity(elements_count);
for _ in 0..elements_count {
let value = paste::paste! { reader.[<read_ $ty>]()};
result.push(IValue::$ity(value));
}
Ok(result)
}
};
}
impl<'m> MemoryReader<'m> {
pub fn new(memory: &'m [Cell<u8>]) -> Self {
Self { memory }
@ -161,6 +78,8 @@ impl<'m> MemoryReader<'m> {
pub fn check_access(&self, offset: usize, size: usize) -> MResult<()> {
let right = offset + size;
// the first condition is a check for overflow
if right < offset || right >= self.memory.len() {
return Err(MemoryAccessError::InvalidAccess {
offset,

View File

@ -25,7 +25,7 @@ pub struct MemoryWriter<'m> {
/// Writes values of basic types sequentially to the provided writer.
/// It don't check memory limits for the optimization purposes,
/// so it could created by the MemoryReader::sequential_reader method.
/// so it could be created only by the MemoryReader::sequential_reader method.
pub struct SequentialWriter<'w, 'm> {
writer: &'w MemoryWriter<'m>,
offset: Cell<usize>,
@ -87,6 +87,8 @@ impl<'m> MemoryWriter<'m> {
pub fn check_access(&self, offset: usize, size: usize) -> MResult<()> {
let right = offset + size;
// the first condition is a check for overflow
if right < offset || right >= self.memory.len() {
return Err(MemoryAccessError::InvalidAccess {
offset,

View File

@ -308,30 +308,6 @@ fn instruction<'input, E: ParseError<&'input [u8]>>(
(input, Instruction::ArrayLowerMemory { value_type })
}
/*
0x39 => (input, Instruction::ArraySize),
0x25 => {
consume!((input, argument_0) = uleb(input)?);
(
input,
Instruction::RecordLift {
type_index: argument_0 as u32,
},
)
}
0x26 => {
consume!((input, argument_0) = uleb(input)?);
(
input,
Instruction::RecordLower {
type_index: argument_0 as u32,
},
)
}
*/
0x3A => {
consume!((input, record_type_id) = uleb(input)?);
@ -360,6 +336,28 @@ fn instruction<'input, E: ParseError<&'input [u8]>>(
0x3E => (input, Instruction::BoolFromI32),
0x3F => (input, Instruction::I32FromBool),
0x40 => {
consume!((input, value) = uleb(input)?);
(
input,
Instruction::PushI32 {
value: value as i32,
},
)
}
0x41 => {
consume!((input, value) = uleb(input)?);
(
input,
Instruction::PushI64 {
value: value as i64,
},
)
}
_ => return Err(Err::Error(make_error(input, ErrorKind::ParseTo))),
})
}

View File

@ -53,10 +53,12 @@ mod keyword {
custom_keyword!(i32_from_s16 = "i32.from_s16");
custom_keyword!(i32_from_s32 = "i32.from_s32");
custom_keyword!(i32_from_s64 = "i32.from_s64");
custom_keyword!(i32_push = "i32.push");
custom_keyword!(i64_from_s8 = "i64.from_s8");
custom_keyword!(i64_from_s16 = "i64.from_s16");
custom_keyword!(i64_from_s32 = "i64.from_s32");
custom_keyword!(i64_from_s64 = "i64.from_s64");
custom_keyword!(i64_push = "i64.push");
custom_keyword!(u8_from_i32 = "u8.from_i32");
custom_keyword!(u8_from_i64 = "u8.from_i64");
custom_keyword!(u16_from_i32 = "u16.from_i32");
@ -73,6 +75,8 @@ mod keyword {
custom_keyword!(i64_from_u16 = "i64.from_u16");
custom_keyword!(i64_from_u32 = "i64.from_u32");
custom_keyword!(i64_from_u64 = "i64.from_u64");
custom_keyword!(f32_push = "f32.push");
custom_keyword!(f64_push = "f64.push");
custom_keyword!(string_lift_memory = "string.lift_memory");
custom_keyword!(string_lower_memory = "string.lower_memory");
custom_keyword!(string_size = "string.size");
@ -153,6 +157,12 @@ impl<'a> Parse<'a> for Instruction {
parser.parse::<keyword::i32_from_s64>()?;
Ok(Instruction::I32FromS64)
} else if lookahead.peek::<keyword::i32_push>() {
parser.parse::<keyword::i32_push>()?;
Ok(Instruction::PushI32 {
value: parser.parse()?,
})
} else if lookahead.peek::<keyword::i64_from_s8>() {
parser.parse::<keyword::i64_from_s8>()?;
@ -169,6 +179,12 @@ impl<'a> Parse<'a> for Instruction {
parser.parse::<keyword::i64_from_s64>()?;
Ok(Instruction::I64FromS64)
} else if lookahead.peek::<keyword::i64_push>() {
parser.parse::<keyword::i64_push>()?;
Ok(Instruction::PushI64 {
value: parser.parse()?,
})
} else if lookahead.peek::<keyword::u8_from_i32>() {
parser.parse::<keyword::u8_from_i32>()?;

View File

@ -243,17 +243,6 @@ where
0x38_u8.to_bytes(writer)?;
value_type.to_bytes(writer)?
}
/*
Instruction::ArraySize => 0x39_u8.to_bytes(writer)?,
Instruction::RecordLift { type_index } => {
0x25_u8.to_bytes(writer)?;
(*type_index as u64).to_bytes(writer)?
}
Instruction::RecordLower { type_index } => {
0x26_u8.to_bytes(writer)?;
(*type_index as u64).to_bytes(writer)?
}
*/
Instruction::RecordLiftMemory {
record_type_id: type_index,
} => {
@ -268,6 +257,14 @@ where
}
Instruction::Dup => 0x34_u8.to_bytes(writer)?,
Instruction::Swap2 => 0x35_u8.to_bytes(writer)?,
Instruction::PushI32 { value } => {
0x40_u8.to_bytes(writer)?;
(*value as u64).to_bytes(writer)?
}
Instruction::PushI64 { value } => {
0x41_u8.to_bytes(writer)?;
(*value as u64).to_bytes(writer)?
}
}
Ok(())

View File

@ -108,11 +108,6 @@ impl ToString for &Instruction {
Instruction::ArrayLowerMemory { value_type } => {
format!("array.lower_memory {}", value_type.to_string())
}
/*
Instruction::ArraySize => "byte_array.size".into(),
Instruction::RecordLift { type_index } => format!("record.lift {}", type_index),
Instruction::RecordLower { type_index } => format!("record.lower {}", type_index),
*/
Instruction::RecordLiftMemory {
record_type_id: type_index,
} => format!("record.lift_memory {}", type_index),
@ -121,6 +116,8 @@ impl ToString for &Instruction {
} => format!("record.lower_memory {}", type_index),
Instruction::Dup => "dup".into(),
Instruction::Swap2 => "swap2".into(),
Instruction::PushI32 { value } => format!("i32.push {}", value),
Instruction::PushI64 { value } => format!("i64.push {}", value),
}
}
}

View File

@ -4,6 +4,7 @@ mod call_core;
mod dup;
pub(self) mod lilo;
mod numbers;
mod push;
mod records;
mod strings;
mod swap2;
@ -21,6 +22,7 @@ pub(crate) use arrays::*;
pub(crate) use call_core::call_core;
pub(crate) use dup::dup;
pub(crate) use numbers::*;
pub(crate) use push::*;
pub(crate) use records::*;
pub(crate) use strings::*;
pub(crate) use swap2::swap2;
@ -183,6 +185,18 @@ pub enum Instruction {
record_type_id: u32,
},
/// The `i32.push` instruction.
PushI32 {
/// The value that should be pushed on the stack.
value: i32,
},
/// The `i64.push` instruction.
PushI64 {
/// The value that should be pushed on the stack.
value: i64,
},
/// The `dup` instructions.
Dup,

View File

@ -68,7 +68,7 @@ lowering_lifting!(s32_from_i32, "s32.from_i32", S32, I32);
lowering_lifting!(s32_from_i64, "s32.from_i64", S32, I64);
lowering_lifting!(s64_from_i32, "s64.from_i32", S64, I32);
lowering_lifting!(s64_from_i64, "s64.from_i64", S64, I64);
//lowering_lifting!(i32_from_bool, "i32.from_bool", I32, Boolean);
lowering_lifting!(i32_from_bool, "i32.from_bool", I32, Boolean);
lowering_lifting!(i32_from_s8, "i32.from_s8", I32, S8);
lowering_lifting!(i32_from_s16, "i32.from_s16", I32, S16);
lowering_lifting!(i32_from_s32, "i32.from_s32", I32, S32);
@ -132,44 +132,6 @@ executable_instruction!(
}
);
executable_instruction!(
i32_from_bool(instruction: Instruction) -> _ {
move |runtime| -> _ {
match runtime.stack.pop1() {
Some(IValue::Boolean(value)) => {
runtime
.stack
.push({
let converted_value = IValue::I32(value as _);
log::trace!("i32.from_bool: converting {:?} to {:?}" , value, converted_value);
converted_value
})
}
Some(wrong_value) => {
return instr_error!(
instruction.clone(),
InstructionErrorKind::InvalidValueOnTheStack {
expected_type: IType::I32,
received_value: wrong_value,
}
)
},
None => {
return instr_error!(
instruction.clone(),
InstructionErrorKind::StackIsTooSmall { needed: 1 }
)
}
}
Ok(())
}
}
);
#[cfg(test)]
mod tests {
test_executable_instruction!(

View File

@ -0,0 +1,25 @@
use crate::IValue;
executable_instruction!(
push_i32(value: i32) -> _ {
move |runtime| -> _ {
log::trace!("push_i32: push {} on the stack", value);
runtime.stack.push(IValue::I32(value));
Ok(())
}
}
);
executable_instruction!(
push_i64(value: i64) -> _ {
move |runtime| -> _ {
log::trace!("push_i32: push {} on the stack", value);
runtime.stack.push(IValue::I64(value));
Ok(())
}
}
);

View File

@ -9,7 +9,6 @@ use it_lilo_utils::memory_reader::MemoryReader;
use it_lilo_utils::memory_reader::SequentialReader;
use it_lilo_utils::record_size;
#[rustfmt::skip]
pub(crate) fn record_lift_memory_impl(
li_helper: &LiHelper<'_>,
record_type: &IRecordType,
@ -38,8 +37,10 @@ pub(crate) fn record_lift_memory_impl(
IType::F64 => values.push(IValue::F64(seq_reader.read_f64())),
IType::String => values.push(IValue::String(read_string(reader, &seq_reader)?)),
IType::ByteArray => values.push(read_byte_array(reader, &seq_reader)?),
IType::Array(ty) => values.push(read_array(&li_helper, &seq_reader, &**ty)?),
IType::Record(record_type_id) => values.push(read_record(li_helper, &seq_reader, *record_type_id)?),
IType::Array(ty) => values.push(read_array(&li_helper, &seq_reader, &**ty)?),
IType::Record(record_type_id) => {
values.push(read_record(li_helper, &seq_reader, *record_type_id)?)
}
}
}

View File

@ -233,6 +233,8 @@ where
Instruction::I64FromU16 => instructions::i64_from_u16(instruction),
Instruction::I64FromU32 => instructions::i64_from_u32(instruction),
Instruction::I64FromU64 => instructions::i64_from_u64(instruction),
Instruction::PushI32 { value } => instructions::push_i32(value),
Instruction::PushI64 { value } => instructions::push_i64(value),
Instruction::StringLiftMemory => instructions::string_lift_memory(instruction),
Instruction::StringLowerMemory => instructions::string_lower_memory(instruction),