mirror of
https://github.com/fluencelabs/interface-types
synced 2024-12-04 07:10:21 +00:00
refactoring
This commit is contained in:
parent
6116c5c252
commit
cc44e387f7
24
Cargo.lock
generated
24
Cargo.lock
generated
@ -73,9 +73,9 @@ checksum = "3576a87f2ba00f6f106fdfcd16db1d698d648a26ad8e0573cad8537c3c362d2a"
|
||||
|
||||
[[package]]
|
||||
name = "lexical-core"
|
||||
version = "0.7.5"
|
||||
version = "0.7.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "21f866863575d0e1d654fbeeabdc927292fdf862873dc3c96c6f753357e13374"
|
||||
checksum = "6607c62aa161d23d17a9072cc5da0be67cdfc89d3afb1e8d9c842bebc2525ffe"
|
||||
dependencies = [
|
||||
"arrayvec",
|
||||
"bitflags",
|
||||
@ -127,9 +127,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "proc-macro2"
|
||||
version = "1.0.24"
|
||||
version = "1.0.26"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1e0704ee1a7e00d7bb417d0770ea303c1bccbabf0ef1667dae92b5967f5f8a71"
|
||||
checksum = "a152013215dca273577e18d2bf00fa862b89b24169fb78c4c95aeb07992c9cec"
|
||||
dependencies = [
|
||||
"unicode-xid",
|
||||
]
|
||||
@ -175,18 +175,18 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "serde"
|
||||
version = "1.0.124"
|
||||
version = "1.0.125"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "bd761ff957cb2a45fbb9ab3da6512de9de55872866160b23c25f1a841e99d29f"
|
||||
checksum = "558dc50e1a5a5fa7112ca2ce4effcb321b0300c0d4ccf0776a9f60cd89031171"
|
||||
dependencies = [
|
||||
"serde_derive",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "serde_derive"
|
||||
version = "1.0.124"
|
||||
version = "1.0.125"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1800f7693e94e186f5e25a28291ae1570da908aff7d97a095dec1e56ff99069b"
|
||||
checksum = "b093b7a2bb58203b5da3056c05b4ec1fed827dcfdb37347a8841695263b3d06d"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
@ -212,9 +212,9 @@ checksum = "a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f"
|
||||
|
||||
[[package]]
|
||||
name = "syn"
|
||||
version = "1.0.64"
|
||||
version = "1.0.70"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "3fd9d1e9976102a03c542daa2eff1b43f9d72306342f3f8b3ed5fb8908195d6f"
|
||||
checksum = "b9505f307c872bab8eb46f77ae357c8eba1fdacead58ee5a850116b1d7f82883"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
@ -255,9 +255,9 @@ checksum = "f7fe0bb3479651439c9112f72b6c505038574c9fbb575ed1bf3b797fa39dd564"
|
||||
|
||||
[[package]]
|
||||
name = "version_check"
|
||||
version = "0.9.2"
|
||||
version = "0.9.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b5a972e5669d67ba988ce3dc826706fb0a8b01471c088cb0b6110b805cc36aed"
|
||||
checksum = "5fecdca9a5291cc2b8dcf7dc02453fee791a280f3743cb0905f8822ae463b3fe"
|
||||
|
||||
[[package]]
|
||||
name = "wasmer-interface-types-fl"
|
||||
|
@ -14,90 +14,23 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
pub mod error;
|
||||
mod macros;
|
||||
pub mod memory_reader;
|
||||
pub mod memory_writer;
|
||||
#![deny(
|
||||
dead_code,
|
||||
nonstandard_style,
|
||||
unused_imports,
|
||||
unused_mut,
|
||||
unused_variables,
|
||||
unused_unsafe,
|
||||
unreachable_patterns
|
||||
)]
|
||||
#![warn(rust_2018_idioms)]
|
||||
|
||||
pub mod lifter;
|
||||
pub mod lowerer;
|
||||
pub mod traits;
|
||||
pub mod utils;
|
||||
|
||||
pub use fluence_it_types::ne_vec::NEVec;
|
||||
pub use fluence_it_types::IRecordType;
|
||||
pub use fluence_it_types::IType;
|
||||
pub use fluence_it_types::IValue;
|
||||
|
||||
pub type ReadResult<T> = std::result::Result<T, error::MemoryAccessError>;
|
||||
pub type WriteResult<T> = std::result::Result<T, error::MemoryWriteError>;
|
||||
|
||||
/// Size of a value in a serialized view.
|
||||
pub fn ser_type_size(ty: &IType) -> usize {
|
||||
const WASM_POINTER_SIZE: usize = 4;
|
||||
|
||||
match ty {
|
||||
IType::Boolean | IType::S8 | IType::U8 => 1,
|
||||
IType::S16 | IType::U16 => 2,
|
||||
IType::S32 | IType::U32 | IType::I32 | IType::F32 => 4,
|
||||
IType::Record(_) => 4,
|
||||
// Vec-like types are passed by pointer and size
|
||||
IType::String | IType::ByteArray | IType::Array(_) => 2 * WASM_POINTER_SIZE,
|
||||
IType::S64 | IType::U64 | IType::I64 | IType::F64 => 8,
|
||||
}
|
||||
}
|
||||
|
||||
/// Size of a value in a serialized view.
|
||||
pub fn ser_value_size(value: &IValue) -> u32 {
|
||||
match value {
|
||||
IValue::Boolean(_) | IValue::S8(_) | IValue::U8(_) => 1,
|
||||
IValue::S16(_) | IValue::U16(_) => 2,
|
||||
IValue::S32(_) | IValue::U32(_) | IValue::F32(_) | IValue::I32(_) => 4,
|
||||
IValue::S64(_) | IValue::U64(_) | IValue::F64(_) | IValue::I64(_) => 8,
|
||||
IValue::String(_) | IValue::ByteArray(_) | IValue::Array(_) => 2 * 4,
|
||||
IValue::Record(_) => 4,
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns the record size in bytes.
|
||||
pub fn record_size(record_type: &IRecordType) -> usize {
|
||||
record_type
|
||||
.fields
|
||||
.iter()
|
||||
.map(|f| ser_type_size(&f.ty))
|
||||
.sum()
|
||||
}
|
||||
|
||||
pub fn type_tag_form_itype(itype: &IType) -> u32 {
|
||||
const POINTER_CODE: u32 = 3; // u32 in the sdk
|
||||
|
||||
match itype {
|
||||
IType::Boolean => 0, // u8
|
||||
IType::U8 => 1, // u8
|
||||
IType::U16 => 2, // u16
|
||||
IType::U32 => 3, // u32
|
||||
IType::U64 => 4, // u64
|
||||
IType::S8 => 6, // i8
|
||||
IType::S16 => 7, // i16
|
||||
IType::S32 | IType::I32 => 8, // i32
|
||||
IType::S64 | IType::I64 => 9, // i64
|
||||
IType::F32 => 10, // f32
|
||||
IType::F64 => 11, // f64
|
||||
IType::ByteArray | IType::Array(_) | IType::Record(_) | IType::String => POINTER_CODE,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn type_tag_form_ivalue(itype: &IValue) -> u32 {
|
||||
const POINTER_CODE: u32 = 3; // u32 in the sdk
|
||||
|
||||
match itype {
|
||||
IValue::Boolean(_) => 0, // u8
|
||||
IValue::U8(_) => 1, // u8
|
||||
IValue::U16(_) => 2, // u16
|
||||
IValue::U32(_) => 3, // u32
|
||||
IValue::U64(_) => 4, // u64
|
||||
IValue::S8(_) => 6, // i8
|
||||
IValue::S16(_) => 7, // i16
|
||||
IValue::S32(_) | IValue::I32(_) => 8, // i32
|
||||
IValue::S64(_) | IValue::I64(_) => 9, // i64
|
||||
IValue::F32(_) => 10, // f32
|
||||
IValue::F64(_) => 11, // f64
|
||||
IValue::ByteArray(_) | IValue::Array(_) | IValue::Record(_) | IValue::String(_) => {
|
||||
POINTER_CODE
|
||||
}
|
||||
}
|
||||
}
|
||||
|
40
crates/it-lilo-utils/src/lifter/error.rs
Normal file
40
crates/it-lilo-utils/src/lifter/error.rs
Normal file
@ -0,0 +1,40 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
use crate::traits::RecordResolvableError;
|
||||
use thiserror::Error as ThisError;
|
||||
|
||||
#[derive(Debug, ThisError)]
|
||||
pub enum LiError {
|
||||
#[error(
|
||||
"Out-of-bound Wasm memory access: offset {offset}, size {size}, while memory_size {memory_size}"
|
||||
)]
|
||||
InvalidAccess {
|
||||
offset: usize,
|
||||
size: usize,
|
||||
memory_size: usize,
|
||||
},
|
||||
|
||||
#[error("{0}")]
|
||||
RecordResolvableError(#[from] RecordResolvableError),
|
||||
|
||||
#[error("{0}")]
|
||||
InvalidUTF8String(#[from] std::string::FromUtf8Error),
|
||||
|
||||
/// This error occurred when a record is created from empty values array.
|
||||
#[error("Record with name '{0}' can't be empty")]
|
||||
EmptyRecord(String),
|
||||
}
|
@ -1,22 +1,38 @@
|
||||
use super::lilo::*;
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
use super::record_lift_memory;
|
||||
use super::ILifter;
|
||||
use super::LiResult;
|
||||
use crate::traits::RecordResolvable;
|
||||
use crate::utils::ser_type_size;
|
||||
use crate::IType;
|
||||
use crate::IValue;
|
||||
|
||||
use crate::interpreter::instructions::record_lift_memory_impl;
|
||||
use it_lilo_utils::ser_type_size;
|
||||
|
||||
pub(crate) fn array_lift_memory_impl(
|
||||
li_helper: &LiHelper,
|
||||
pub fn array_lift_memory<R: RecordResolvable>(
|
||||
lifter: &ILifter<'_, '_, R>,
|
||||
value_type: &IType,
|
||||
offset: usize,
|
||||
elements_count: usize,
|
||||
) -> LiLoResult<IValue> {
|
||||
) -> LiResult<IValue> {
|
||||
if elements_count == 0 {
|
||||
return Ok(IValue::Array(vec![]));
|
||||
}
|
||||
|
||||
let reader = &li_helper.reader;
|
||||
let reader = &lifter.reader;
|
||||
|
||||
let ivalues = match value_type {
|
||||
IType::Boolean => reader.read_bool_array(offset, elements_count)?,
|
||||
@ -32,25 +48,24 @@ pub(crate) fn array_lift_memory_impl(
|
||||
IType::U64 => reader.read_u64_array(offset, elements_count)?,
|
||||
IType::F32 => reader.read_f32_array(offset, elements_count)?,
|
||||
IType::F64 => reader.read_f64_array(offset, elements_count)?,
|
||||
IType::String => read_string_array(li_helper, offset, elements_count)?,
|
||||
IType::ByteArray => read_array_array(li_helper, &IType::ByteArray, offset, elements_count)?,
|
||||
IType::Array(ty) => read_array_array(li_helper, &ty, offset, elements_count)?,
|
||||
IType::String => read_string_array(lifter, offset, elements_count)?,
|
||||
IType::ByteArray => read_array_array(lifter, &IType::ByteArray, offset, elements_count)?,
|
||||
IType::Array(ty) => read_array_array(lifter, &ty, offset, elements_count)?,
|
||||
IType::Record(record_type_id) => {
|
||||
read_record_array(li_helper, *record_type_id, offset, elements_count)?
|
||||
read_record_array(lifter, *record_type_id, offset, elements_count)?
|
||||
}
|
||||
};
|
||||
|
||||
Ok(IValue::Array(ivalues))
|
||||
}
|
||||
|
||||
// Vec<String> => Vec<u32> (2 * len of prev)
|
||||
fn read_string_array(
|
||||
li_helper: &LiHelper,
|
||||
fn read_string_array<R: RecordResolvable>(
|
||||
lifter: &ILifter<'_, '_, R>,
|
||||
offset: usize,
|
||||
elements_count: usize,
|
||||
) -> LiLoResult<Vec<IValue>> {
|
||||
) -> LiResult<Vec<IValue>> {
|
||||
let mut result = Vec::with_capacity(elements_count);
|
||||
let seq_reader = li_helper
|
||||
let seq_reader = lifter
|
||||
.reader
|
||||
.sequential_reader(offset, ser_type_size(&IType::String) * elements_count)?;
|
||||
|
||||
@ -58,7 +73,7 @@ fn read_string_array(
|
||||
let offset = seq_reader.read_u32();
|
||||
let size = seq_reader.read_u32();
|
||||
|
||||
let raw_str = li_helper.reader.read_raw_u8_array(offset as _, size as _)?;
|
||||
let raw_str = lifter.reader.read_raw_u8_array(offset as _, size as _)?;
|
||||
let str = String::from_utf8(raw_str)?;
|
||||
result.push(IValue::String(str));
|
||||
}
|
||||
@ -66,14 +81,14 @@ fn read_string_array(
|
||||
Ok(result)
|
||||
}
|
||||
|
||||
fn read_array_array(
|
||||
li_helper: &LiHelper,
|
||||
fn read_array_array<R: RecordResolvable>(
|
||||
lifter: &ILifter<'_, '_, R>,
|
||||
ty: &IType,
|
||||
offset: usize,
|
||||
elements_count: usize,
|
||||
) -> LiLoResult<Vec<IValue>> {
|
||||
) -> LiResult<Vec<IValue>> {
|
||||
let mut result = Vec::with_capacity(elements_count);
|
||||
let seq_reader = li_helper
|
||||
let seq_reader = lifter
|
||||
.reader
|
||||
.sequential_reader(offset, ser_type_size(ty) * elements_count)?;
|
||||
|
||||
@ -81,29 +96,29 @@ fn read_array_array(
|
||||
let offset = seq_reader.read_u32();
|
||||
let size = seq_reader.read_u32();
|
||||
|
||||
let array = array_lift_memory_impl(li_helper, ty, offset as _, size as _)?;
|
||||
let array = array_lift_memory(lifter, ty, offset as _, size as _)?;
|
||||
result.push(array);
|
||||
}
|
||||
|
||||
Ok(result)
|
||||
}
|
||||
|
||||
fn read_record_array(
|
||||
li_helper: &LiHelper,
|
||||
fn read_record_array<R: RecordResolvable>(
|
||||
lifter: &ILifter<'_, '_, R>,
|
||||
record_type_id: u64,
|
||||
offset: usize,
|
||||
elements_count: usize,
|
||||
) -> LiLoResult<Vec<IValue>> {
|
||||
) -> LiResult<Vec<IValue>> {
|
||||
let mut result = Vec::with_capacity(elements_count);
|
||||
let seq_reader = li_helper
|
||||
let seq_reader = lifter
|
||||
.reader
|
||||
.sequential_reader(offset, ser_type_size(&IType::Record(0)) * elements_count)?;
|
||||
|
||||
for _ in 0..elements_count {
|
||||
let offset = seq_reader.read_u32();
|
||||
let record_ty = (li_helper.record_resolver)(record_type_id)?;
|
||||
let record_ty = lifter.resolver.resolve_record(record_type_id)?;
|
||||
|
||||
let record = record_lift_memory_impl(li_helper, &record_ty, offset as _)?;
|
||||
let record = record_lift_memory(lifter, &record_ty, offset as _)?;
|
||||
result.push(record);
|
||||
}
|
||||
|
@ -1,23 +1,40 @@
|
||||
use super::lilo::*;
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
use super::ILifter;
|
||||
use super::LiError;
|
||||
use super::LiResult;
|
||||
use super::MemoryReader;
|
||||
use super::SequentialReader;
|
||||
use crate::traits::RecordResolvable;
|
||||
use crate::utils::record_size;
|
||||
use crate::IRecordType;
|
||||
use crate::IType;
|
||||
use crate::IValue;
|
||||
use crate::NEVec;
|
||||
|
||||
use it_lilo_utils::memory_reader::MemoryReader;
|
||||
use it_lilo_utils::memory_reader::SequentialReader;
|
||||
use it_lilo_utils::record_size;
|
||||
|
||||
pub(crate) fn record_lift_memory_impl(
|
||||
li_helper: &LiHelper<'_>,
|
||||
pub fn record_lift_memory<R: RecordResolvable>(
|
||||
lifter: &ILifter<'_, '_, R>,
|
||||
record_type: &IRecordType,
|
||||
offset: usize,
|
||||
) -> LiLoResult<IValue> {
|
||||
) -> LiResult<IValue> {
|
||||
let mut values = Vec::with_capacity(record_type.fields.len());
|
||||
|
||||
let size = record_size(record_type);
|
||||
let reader = &li_helper.reader;
|
||||
let reader = &lifter.reader;
|
||||
let seq_reader = reader.sequential_reader(offset, size)?;
|
||||
|
||||
for field in (*record_type.fields).iter() {
|
||||
@ -37,20 +54,23 @@ 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::Array(ty) => values.push(read_array(&lifter, &seq_reader, &**ty)?),
|
||||
IType::Record(record_type_id) => {
|
||||
values.push(read_record(li_helper, &seq_reader, *record_type_id)?)
|
||||
values.push(read_record(lifter, &seq_reader, *record_type_id)?)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
let record = NEVec::new(values.into_iter().collect())
|
||||
.map_err(|_| LiLoError::EmptyRecord(record_type.name.clone()))?;
|
||||
.map_err(|_| LiError::EmptyRecord(record_type.name.clone()))?;
|
||||
|
||||
Ok(IValue::Record(record))
|
||||
}
|
||||
|
||||
fn read_string(reader: &MemoryReader, seq_reader: &SequentialReader) -> LiLoResult<String> {
|
||||
fn read_string(
|
||||
reader: &MemoryReader<'_>,
|
||||
seq_reader: &SequentialReader<'_, '_>,
|
||||
) -> LiResult<String> {
|
||||
let offset = seq_reader.read_u32();
|
||||
let size = seq_reader.read_u32();
|
||||
|
||||
@ -60,7 +80,10 @@ fn read_string(reader: &MemoryReader, seq_reader: &SequentialReader) -> LiLoResu
|
||||
Ok(string)
|
||||
}
|
||||
|
||||
fn read_byte_array(reader: &MemoryReader, seq_reader: &SequentialReader) -> LiLoResult<IValue> {
|
||||
fn read_byte_array(
|
||||
reader: &MemoryReader<'_>,
|
||||
seq_reader: &SequentialReader<'_, '_>,
|
||||
) -> LiResult<IValue> {
|
||||
let offset = seq_reader.read_u32();
|
||||
let size = seq_reader.read_u32();
|
||||
|
||||
@ -69,25 +92,25 @@ fn read_byte_array(reader: &MemoryReader, seq_reader: &SequentialReader) -> LiLo
|
||||
Ok(IValue::ByteArray(array))
|
||||
}
|
||||
|
||||
fn read_array(
|
||||
li_helper: &LiHelper,
|
||||
seq_reader: &SequentialReader,
|
||||
fn read_array<R: RecordResolvable>(
|
||||
lifter: &ILifter<'_, '_, R>,
|
||||
seq_reader: &SequentialReader<'_, '_>,
|
||||
value_type: &IType,
|
||||
) -> LiLoResult<IValue> {
|
||||
) -> LiResult<IValue> {
|
||||
let offset = seq_reader.read_u32();
|
||||
let size = seq_reader.read_u32();
|
||||
|
||||
super::array_lift_memory_impl(li_helper, value_type, offset as _, size as _)
|
||||
super::array_lift_memory(lifter, value_type, offset as _, size as _)
|
||||
}
|
||||
|
||||
fn read_record(
|
||||
li_helper: &LiHelper,
|
||||
seq_reader: &SequentialReader,
|
||||
fn read_record<R: RecordResolvable>(
|
||||
lifter: &ILifter<'_, '_, R>,
|
||||
seq_reader: &SequentialReader<'_, '_>,
|
||||
record_type_id: u64,
|
||||
) -> LiLoResult<IValue> {
|
||||
) -> LiResult<IValue> {
|
||||
let offset = seq_reader.read_u32();
|
||||
|
||||
let record_type = (li_helper.record_resolver)(record_type_id)?;
|
||||
let record_type = lifter.resolver.resolve_record(record_type_id)?;
|
||||
|
||||
record_lift_memory_impl(li_helper, &record_type, offset as _)
|
||||
record_lift_memory(lifter, &record_type, offset as _)
|
||||
}
|
@ -101,7 +101,7 @@ macro_rules! read_array_ty {
|
||||
&self,
|
||||
offset: usize,
|
||||
elements_count: usize,
|
||||
) -> crate::ReadResult<Vec<crate::IValue>> {
|
||||
) -> super::LiResult<Vec<crate::IValue>> {
|
||||
let reader =
|
||||
self.sequential_reader(offset, std::mem::size_of::<$ty>() * elements_count)?;
|
||||
let mut result = Vec::with_capacity(elements_count);
|
@ -14,11 +14,11 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
use crate::error::MemoryAccessError;
|
||||
use super::LiError;
|
||||
use super::LiResult;
|
||||
use crate::read_array_ty;
|
||||
use crate::read_ty;
|
||||
use crate::IValue;
|
||||
use crate::ReadResult;
|
||||
|
||||
use std::cell::Cell;
|
||||
|
||||
@ -46,13 +46,13 @@ impl<'m> MemoryReader<'m> {
|
||||
&self,
|
||||
offset: usize,
|
||||
size: usize,
|
||||
) -> ReadResult<SequentialReader<'_, '_>> {
|
||||
) -> LiResult<SequentialReader<'_, '_>> {
|
||||
self.check_access(offset, size)?;
|
||||
|
||||
Ok(SequentialReader::new(&self, offset))
|
||||
}
|
||||
|
||||
pub fn read_raw_u8_array(&self, offset: usize, elements_count: usize) -> ReadResult<Vec<u8>> {
|
||||
pub fn read_raw_u8_array(&self, offset: usize, elements_count: usize) -> LiResult<Vec<u8>> {
|
||||
let reader = self.sequential_reader(offset, elements_count)?;
|
||||
let mut result = Vec::with_capacity(elements_count);
|
||||
|
||||
@ -64,7 +64,7 @@ impl<'m> MemoryReader<'m> {
|
||||
Ok(result)
|
||||
}
|
||||
|
||||
pub fn read_bool_array(&self, offset: usize, elements_count: usize) -> ReadResult<Vec<IValue>> {
|
||||
pub fn read_bool_array(&self, offset: usize, elements_count: usize) -> LiResult<Vec<IValue>> {
|
||||
let reader = self.sequential_reader(offset, elements_count)?;
|
||||
let mut result = Vec::with_capacity(elements_count);
|
||||
|
||||
@ -76,12 +76,12 @@ impl<'m> MemoryReader<'m> {
|
||||
Ok(result)
|
||||
}
|
||||
|
||||
pub fn check_access(&self, offset: usize, size: usize) -> ReadResult<()> {
|
||||
pub fn check_access(&self, offset: usize, size: usize) -> LiResult<()> {
|
||||
let right = offset + size;
|
||||
|
||||
// the first condition is a check for overflow
|
||||
if right < offset || right >= self.memory.len() {
|
||||
return Err(MemoryAccessError::InvalidAccess {
|
||||
return Err(LiError::InvalidAccess {
|
||||
offset,
|
||||
size,
|
||||
memory_size: self.memory.len(),
|
45
crates/it-lilo-utils/src/lifter/mod.rs
Normal file
45
crates/it-lilo-utils/src/lifter/mod.rs
Normal file
@ -0,0 +1,45 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
mod error;
|
||||
mod lift_array;
|
||||
mod lift_record;
|
||||
mod macros;
|
||||
mod memory_reader;
|
||||
|
||||
pub use error::LiError;
|
||||
pub use lift_array::array_lift_memory;
|
||||
pub use lift_record::record_lift_memory;
|
||||
pub use memory_reader::MemoryReader;
|
||||
pub use memory_reader::SequentialReader;
|
||||
|
||||
use super::traits::RecordResolvable;
|
||||
|
||||
use std::cell::Cell;
|
||||
|
||||
pub type LiResult<T> = std::result::Result<T, error::LiError>;
|
||||
|
||||
pub struct ILifter<'m, 'r, R: RecordResolvable> {
|
||||
pub reader: MemoryReader<'m>,
|
||||
pub resolver: &'r R,
|
||||
}
|
||||
|
||||
impl<'m, 'r, R: RecordResolvable> ILifter<'m, 'r, R> {
|
||||
pub fn new(memory: &'m [Cell<u8>], resolver: &'r R) -> Self {
|
||||
let reader = MemoryReader::new(memory);
|
||||
Self { reader, resolver }
|
||||
}
|
||||
}
|
28
crates/it-lilo-utils/src/lowerer/error.rs
Normal file
28
crates/it-lilo-utils/src/lowerer/error.rs
Normal file
@ -0,0 +1,28 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
use crate::traits::AllocatableError;
|
||||
use crate::traits::RecordResolvableError;
|
||||
use thiserror::Error as ThisError;
|
||||
|
||||
#[derive(Debug, ThisError)]
|
||||
pub enum LoError {
|
||||
#[error("{0}")]
|
||||
AllocatableError(#[from] AllocatableError),
|
||||
|
||||
#[error("{0}")]
|
||||
RecordResolvableError(#[from] RecordResolvableError),
|
||||
}
|
96
crates/it-lilo-utils/src/lowerer/lower_array.rs
Normal file
96
crates/it-lilo-utils/src/lowerer/lower_array.rs
Normal file
@ -0,0 +1,96 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
use super::ILowerer;
|
||||
use super::LoResult;
|
||||
use crate::traits::Allocatable;
|
||||
use crate::utils::ser_value_size;
|
||||
use crate::utils::type_tag_form_ivalue;
|
||||
use crate::IValue;
|
||||
|
||||
pub struct LoweredArray {
|
||||
pub offset: usize,
|
||||
pub size: usize,
|
||||
}
|
||||
|
||||
impl LoweredArray {
|
||||
pub fn new(offset: usize, size: usize) -> Self {
|
||||
Self { offset, size }
|
||||
}
|
||||
|
||||
pub fn empty() -> Self {
|
||||
Self { offset: 0, size: 0 }
|
||||
}
|
||||
}
|
||||
|
||||
pub fn array_lower_memory<A: Allocatable>(
|
||||
lowerer: &ILowerer<'_, A>,
|
||||
array_values: Vec<IValue>,
|
||||
) -> LoResult<LoweredArray> {
|
||||
if array_values.is_empty() {
|
||||
return Ok(LoweredArray::empty());
|
||||
}
|
||||
|
||||
let elements_count = array_values.len() as u32;
|
||||
let size = ser_value_size(&array_values[0]) * elements_count;
|
||||
let type_tag = type_tag_form_ivalue(&array_values[0]);
|
||||
let seq_writer = lowerer.writer.sequential_writer(size, type_tag)?;
|
||||
|
||||
// here it's known that all interface values have the same type
|
||||
for value in array_values {
|
||||
match value {
|
||||
IValue::Boolean(value) => seq_writer.write_u8(&lowerer.writer, value as _),
|
||||
IValue::S8(value) => seq_writer.write_u8(&lowerer.writer, value as _),
|
||||
IValue::S16(value) => seq_writer.write_array(&lowerer.writer, value.to_le_bytes()),
|
||||
IValue::S32(value) => seq_writer.write_array(&lowerer.writer, value.to_le_bytes()),
|
||||
IValue::S64(value) => seq_writer.write_array(&lowerer.writer, value.to_le_bytes()),
|
||||
IValue::U8(value) => seq_writer.write_array(&lowerer.writer, value.to_le_bytes()),
|
||||
IValue::U16(value) => seq_writer.write_array(&lowerer.writer, value.to_le_bytes()),
|
||||
IValue::U32(value) => seq_writer.write_array(&lowerer.writer, value.to_le_bytes()),
|
||||
IValue::U64(value) => seq_writer.write_array(&lowerer.writer, value.to_le_bytes()),
|
||||
IValue::I32(value) => seq_writer.write_array(&lowerer.writer, value.to_le_bytes()),
|
||||
IValue::I64(value) => seq_writer.write_array(&lowerer.writer, value.to_le_bytes()),
|
||||
IValue::F32(value) => seq_writer.write_array(&lowerer.writer, value.to_le_bytes()),
|
||||
IValue::F64(value) => seq_writer.write_array(&lowerer.writer, value.to_le_bytes()),
|
||||
IValue::String(value) => {
|
||||
let offset = lowerer.writer.write_bytes(value.as_bytes())? as u32;
|
||||
|
||||
seq_writer.write_array(&lowerer.writer, offset.to_le_bytes());
|
||||
seq_writer.write_array(&lowerer.writer, (value.len() as u32).to_le_bytes());
|
||||
}
|
||||
IValue::ByteArray(values) => {
|
||||
let offset = lowerer.writer.write_bytes(&values)? as u32;
|
||||
|
||||
seq_writer.write_array(&lowerer.writer, offset.to_le_bytes());
|
||||
seq_writer.write_array(&lowerer.writer, (values.len() as u32).to_le_bytes());
|
||||
}
|
||||
IValue::Array(values) => {
|
||||
let LoweredArray { offset, size } = array_lower_memory(lowerer, values)?;
|
||||
|
||||
seq_writer.write_array(&lowerer.writer, (offset as u32).to_le_bytes());
|
||||
seq_writer.write_array(&lowerer.writer, (size as u32).to_le_bytes());
|
||||
}
|
||||
IValue::Record(values) => {
|
||||
let offset = super::record_lower_memory(lowerer, values)? as u32;
|
||||
seq_writer.write_array(&lowerer.writer, offset.to_le_bytes());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
let offset = seq_writer.start_offset();
|
||||
let lowered_array = LoweredArray::new(offset as _, elements_count as _);
|
||||
Ok(lowered_array)
|
||||
}
|
@ -1,14 +1,32 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
use super::ILowerer;
|
||||
use super::LoResult;
|
||||
use super::LoweredArray;
|
||||
use crate::traits::Allocatable;
|
||||
use crate::IValue;
|
||||
use crate::NEVec;
|
||||
use it_lilo_utils::memory_writer::Heapable;
|
||||
use it_lilo_utils::memory_writer::MemoryWriter;
|
||||
use it_lilo_utils::WriteResult;
|
||||
|
||||
pub(crate) fn record_lower_memory_impl<T: Heapable>(
|
||||
writer: &MemoryWriter<T>,
|
||||
pub fn record_lower_memory<A: Allocatable>(
|
||||
lowerer: &ILowerer<'_, A>,
|
||||
values: NEVec<IValue>,
|
||||
) -> WriteResult<i32> {
|
||||
) -> LoResult<i32> {
|
||||
let average_field_size = 4;
|
||||
// TODO: avoid this additional allocation after fixing github.com/fluencelabs/fce/issues/77
|
||||
let mut result: Vec<u8> = Vec::with_capacity(average_field_size * values.len());
|
||||
|
||||
for value in values.into_vec() {
|
||||
@ -27,34 +45,34 @@ pub(crate) fn record_lower_memory_impl<T: Heapable>(
|
||||
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 offset = writer.write_bytes(value.as_bytes())? as u32;
|
||||
let offset = lowerer.writer.write_bytes(value.as_bytes())? as u32;
|
||||
|
||||
result.extend_from_slice(&offset.to_le_bytes());
|
||||
result.extend_from_slice(&(value.len() as u32).to_le_bytes());
|
||||
}
|
||||
IValue::ByteArray(value) => {
|
||||
let offset = writer.write_bytes(&value)? as u32;
|
||||
let offset = lowerer.writer.write_bytes(&value)? as u32;
|
||||
|
||||
result.extend_from_slice(&offset.to_le_bytes());
|
||||
result.extend_from_slice(&(value.len() as u32).to_le_bytes());
|
||||
}
|
||||
|
||||
IValue::Array(values) => {
|
||||
let (offset, size) = super::array_lower_memory_impl(writer, values)?;
|
||||
let LoweredArray { offset, size } = super::array_lower_memory(lowerer, values)?;
|
||||
|
||||
result.extend_from_slice(&(offset as u32).to_le_bytes());
|
||||
result.extend_from_slice(&(size as u32).to_le_bytes());
|
||||
}
|
||||
|
||||
IValue::Record(values) => {
|
||||
let offset = record_lower_memory_impl(writer, values)? as u32;
|
||||
let offset = record_lower_memory(lowerer, values)? as u32;
|
||||
|
||||
result.extend_from_slice(&offset.to_le_bytes());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
let result_pointer = writer.write_bytes(&result)?;
|
||||
let result_pointer = lowerer.writer.write_bytes(&result)?;
|
||||
|
||||
Ok(result_pointer as _)
|
||||
}
|
@ -14,21 +14,16 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
use crate::WriteResult;
|
||||
use super::LoResult;
|
||||
use crate::traits::Allocatable;
|
||||
use crate::traits::MemSlice;
|
||||
use crate::traits::DEFAULT_MEMORY_INDEX;
|
||||
use crate::utils::type_tag_form_itype;
|
||||
|
||||
use std::cell::Cell;
|
||||
|
||||
pub type MemSlice<'m> = &'m [Cell<u8>];
|
||||
|
||||
const MEMORY_INDEX: usize = 0;
|
||||
|
||||
pub trait Heapable {
|
||||
fn allocate(&self, size: u32, type_tag: u32) -> WriteResult<usize>;
|
||||
|
||||
fn memory_slice(&self, memory_index: usize) -> WriteResult<MemSlice<'_>>;
|
||||
}
|
||||
|
||||
pub struct MemoryWriter<'i, T: Heapable> {
|
||||
heap_manager: &'i T,
|
||||
pub struct MemoryWriter<'i, R: Allocatable> {
|
||||
heap_manager: &'i R,
|
||||
pub(self) memory: Cell<MemSlice<'i>>,
|
||||
}
|
||||
|
||||
@ -37,9 +32,9 @@ pub struct SequentialWriter {
|
||||
offset: Cell<usize>,
|
||||
}
|
||||
|
||||
impl<'i, T: Heapable> MemoryWriter<'i, T> {
|
||||
pub fn new(heap_manager: &'i T) -> WriteResult<Self> {
|
||||
let mem_slice = heap_manager.memory_slice(MEMORY_INDEX)?;
|
||||
impl<'i, A: Allocatable> MemoryWriter<'i, A> {
|
||||
pub fn new(heap_manager: &'i A) -> LoResult<Self> {
|
||||
let mem_slice = heap_manager.memory_slice(DEFAULT_MEMORY_INDEX)?;
|
||||
let memory = Cell::new(mem_slice);
|
||||
|
||||
let writer = Self {
|
||||
@ -49,17 +44,17 @@ impl<'i, T: Heapable> MemoryWriter<'i, T> {
|
||||
Ok(writer)
|
||||
}
|
||||
|
||||
pub fn write_bytes(&self, bytes: &[u8]) -> WriteResult<usize> {
|
||||
let byte_type_tag = crate::type_tag_form_itype(&crate::IType::U8);
|
||||
pub fn write_bytes(&self, bytes: &[u8]) -> LoResult<usize> {
|
||||
let byte_type_tag = type_tag_form_itype(&crate::IType::U8);
|
||||
let seq_writer = self.sequential_writer(bytes.len() as _, byte_type_tag)?;
|
||||
seq_writer.write_bytes(self, bytes);
|
||||
|
||||
Ok(seq_writer.start_offset())
|
||||
}
|
||||
|
||||
pub fn sequential_writer(&self, size: u32, type_tag: u32) -> WriteResult<SequentialWriter> {
|
||||
pub fn sequential_writer(&self, size: u32, type_tag: u32) -> LoResult<SequentialWriter> {
|
||||
let offset = self.heap_manager.allocate(size, type_tag)?;
|
||||
let new_mem_slice = self.heap_manager.memory_slice(MEMORY_INDEX)?;
|
||||
let new_mem_slice = self.heap_manager.memory_slice(DEFAULT_MEMORY_INDEX)?;
|
||||
self.memory.set(new_mem_slice);
|
||||
|
||||
Ok(SequentialWriter::new(offset))
|
||||
@ -78,9 +73,9 @@ impl SequentialWriter {
|
||||
self.start_offset
|
||||
}
|
||||
|
||||
pub fn write_array<T: Heapable, const N: usize>(
|
||||
pub fn write_array<A: Allocatable, const N: usize>(
|
||||
&self,
|
||||
writer: &MemoryWriter<T>,
|
||||
writer: &MemoryWriter<'_, A>,
|
||||
values: [u8; N],
|
||||
) {
|
||||
let offset = self.offset.get();
|
||||
@ -94,7 +89,7 @@ impl SequentialWriter {
|
||||
}
|
||||
|
||||
// specialization of write_array for u8
|
||||
pub fn write_u8<T: Heapable>(&self, writer: &MemoryWriter<T>, value: u8) {
|
||||
pub fn write_u8<A: Allocatable>(&self, writer: &MemoryWriter<'_, A>, value: u8) {
|
||||
let offset = self.offset.get();
|
||||
|
||||
writer.memory.get()[offset].set(value);
|
||||
@ -103,7 +98,7 @@ impl SequentialWriter {
|
||||
}
|
||||
|
||||
// specialization of write_array for u32
|
||||
pub fn write_u32<T: Heapable>(&self, writer: &MemoryWriter<T>, value: u32) {
|
||||
pub fn write_u32<A: Allocatable>(&self, writer: &MemoryWriter<'_, A>, value: u32) {
|
||||
let offset = self.offset.get();
|
||||
|
||||
let value = value.to_le_bytes();
|
||||
@ -118,7 +113,7 @@ impl SequentialWriter {
|
||||
}
|
||||
|
||||
#[allow(dead_code)]
|
||||
pub fn write_bytes<T: Heapable>(&self, writer: &MemoryWriter<T>, bytes: &[u8]) {
|
||||
pub fn write_bytes<A: Allocatable>(&self, writer: &MemoryWriter<'_, A>, bytes: &[u8]) {
|
||||
let offset = self.offset.get();
|
||||
|
||||
let memory = writer.memory.get();
|
43
crates/it-lilo-utils/src/lowerer/mod.rs
Normal file
43
crates/it-lilo-utils/src/lowerer/mod.rs
Normal file
@ -0,0 +1,43 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
mod error;
|
||||
mod lower_array;
|
||||
mod lower_record;
|
||||
mod memory_writer;
|
||||
|
||||
use crate::lowerer::memory_writer::MemoryWriter;
|
||||
use crate::traits::Allocatable;
|
||||
|
||||
pub use error::LoError;
|
||||
pub use lower_array::array_lower_memory;
|
||||
pub use lower_array::LoweredArray;
|
||||
pub use lower_record::record_lower_memory;
|
||||
|
||||
pub type LoResult<T> = std::result::Result<T, error::LoError>;
|
||||
|
||||
pub struct ILowerer<'m, A: Allocatable> {
|
||||
pub writer: MemoryWriter<'m, A>,
|
||||
}
|
||||
|
||||
impl<'m, A: Allocatable> ILowerer<'m, A> {
|
||||
pub fn new(allocatable: &'m A) -> LoResult<Self> {
|
||||
let writer = MemoryWriter::new(allocatable)?;
|
||||
let lowerer = Self { writer };
|
||||
|
||||
Ok(lowerer)
|
||||
}
|
||||
}
|
@ -14,22 +14,21 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
use std::cell::Cell;
|
||||
use thiserror::Error as ThisError;
|
||||
|
||||
#[derive(Debug, ThisError)]
|
||||
pub enum MemoryAccessError {
|
||||
#[error(
|
||||
"Out-of-bound Wasm memory access: offset {offset}, size {size}, while memory_size {memory_size}"
|
||||
)]
|
||||
InvalidAccess {
|
||||
offset: usize,
|
||||
size: usize,
|
||||
memory_size: usize,
|
||||
},
|
||||
pub const DEFAULT_MEMORY_INDEX: usize = 0;
|
||||
|
||||
pub type MemSlice<'m> = &'m [Cell<u8>];
|
||||
|
||||
pub trait Allocatable {
|
||||
fn allocate(&self, size: u32, type_tag: u32) -> Result<usize, AllocatableError>;
|
||||
|
||||
fn memory_slice(&self, memory_index: usize) -> Result<MemSlice<'_>, AllocatableError>;
|
||||
}
|
||||
|
||||
#[derive(Debug, ThisError)]
|
||||
pub enum MemoryWriteError {
|
||||
pub enum AllocatableError {
|
||||
/// The memory doesn't exist.
|
||||
#[error("memory `{memory_index}` does not exist")]
|
||||
MemoryIsMissing {
|
||||
@ -61,4 +60,9 @@ pub enum MemoryWriteError {
|
||||
probably a Wasm module's built with unsupported sdk version"
|
||||
)]
|
||||
AllocateFuncIncompatibleOutput,
|
||||
|
||||
// TODO: make it generic in future.
|
||||
/// User defined error.
|
||||
#[error("{0}")]
|
||||
UserDefinedError(String),
|
||||
}
|
21
crates/it-lilo-utils/src/traits/mod.rs
Normal file
21
crates/it-lilo-utils/src/traits/mod.rs
Normal file
@ -0,0 +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.
|
||||
*/
|
||||
|
||||
mod heapable;
|
||||
mod record_resolvable;
|
||||
|
||||
pub use heapable::*;
|
||||
pub use record_resolvable::*;
|
29
crates/it-lilo-utils/src/traits/record_resolvable.rs
Normal file
29
crates/it-lilo-utils/src/traits/record_resolvable.rs
Normal file
@ -0,0 +1,29 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
use crate::IRecordType;
|
||||
use thiserror::Error as ThisError;
|
||||
|
||||
pub trait RecordResolvable {
|
||||
fn resolve_record(&self, record_type_id: u64) -> Result<&IRecordType, RecordResolvableError>;
|
||||
}
|
||||
|
||||
#[derive(Debug, ThisError)]
|
||||
pub enum RecordResolvableError {
|
||||
/// Record for such type is wasn't found.
|
||||
#[error("Record with type id '{0}' not found")]
|
||||
RecordNotFound(u64),
|
||||
}
|
95
crates/it-lilo-utils/src/utils.rs
Normal file
95
crates/it-lilo-utils/src/utils.rs
Normal file
@ -0,0 +1,95 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
use crate::IRecordType;
|
||||
use crate::IType;
|
||||
use crate::IValue;
|
||||
|
||||
/// Size of a value in a serialized view.
|
||||
pub fn ser_type_size(ty: &IType) -> usize {
|
||||
const WASM_POINTER_SIZE: usize = 4;
|
||||
|
||||
match ty {
|
||||
IType::Boolean | IType::S8 | IType::U8 => 1,
|
||||
IType::S16 | IType::U16 => 2,
|
||||
IType::S32 | IType::U32 | IType::I32 | IType::F32 => 4,
|
||||
IType::Record(_) => 4,
|
||||
// Vec-like types are passed by pointer and size
|
||||
IType::String | IType::ByteArray | IType::Array(_) => 2 * WASM_POINTER_SIZE,
|
||||
IType::S64 | IType::U64 | IType::I64 | IType::F64 => 8,
|
||||
}
|
||||
}
|
||||
|
||||
/// Size of a value in a serialized view.
|
||||
pub fn ser_value_size(value: &IValue) -> u32 {
|
||||
match value {
|
||||
IValue::Boolean(_) | IValue::S8(_) | IValue::U8(_) => 1,
|
||||
IValue::S16(_) | IValue::U16(_) => 2,
|
||||
IValue::S32(_) | IValue::U32(_) | IValue::F32(_) | IValue::I32(_) => 4,
|
||||
IValue::S64(_) | IValue::U64(_) | IValue::F64(_) | IValue::I64(_) => 8,
|
||||
IValue::String(_) | IValue::ByteArray(_) | IValue::Array(_) => 2 * 4,
|
||||
IValue::Record(_) => 4,
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns the record size in bytes.
|
||||
pub fn record_size(record_type: &IRecordType) -> usize {
|
||||
record_type
|
||||
.fields
|
||||
.iter()
|
||||
.map(|f| ser_type_size(&f.ty))
|
||||
.sum()
|
||||
}
|
||||
|
||||
pub fn type_tag_form_itype(itype: &IType) -> u32 {
|
||||
const POINTER_CODE: u32 = 3; // u32 in the sdk
|
||||
|
||||
match itype {
|
||||
IType::Boolean => 0, // u8
|
||||
IType::U8 => 1, // u8
|
||||
IType::U16 => 2, // u16
|
||||
IType::U32 => 3, // u32
|
||||
IType::U64 => 4, // u64
|
||||
IType::S8 => 6, // i8
|
||||
IType::S16 => 7, // i16
|
||||
IType::S32 | IType::I32 => 8, // i32
|
||||
IType::S64 | IType::I64 => 9, // i64
|
||||
IType::F32 => 10, // f32
|
||||
IType::F64 => 11, // f64
|
||||
IType::ByteArray | IType::Array(_) | IType::Record(_) | IType::String => POINTER_CODE,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn type_tag_form_ivalue(itype: &IValue) -> u32 {
|
||||
const POINTER_CODE: u32 = 3; // u32 in the sdk
|
||||
|
||||
match itype {
|
||||
IValue::Boolean(_) => 0, // u8
|
||||
IValue::U8(_) => 1, // u8
|
||||
IValue::U16(_) => 2, // u16
|
||||
IValue::U32(_) => 3, // u32
|
||||
IValue::U64(_) => 4, // u64
|
||||
IValue::S8(_) => 6, // i8
|
||||
IValue::S16(_) => 7, // i16
|
||||
IValue::S32(_) | IValue::I32(_) => 8, // i32
|
||||
IValue::S64(_) | IValue::I64(_) => 9, // i64
|
||||
IValue::F32(_) => 10, // f32
|
||||
IValue::F64(_) => 11, // f64
|
||||
IValue::ByteArray(_) | IValue::Array(_) | IValue::Record(_) | IValue::String(_) => {
|
||||
POINTER_CODE
|
||||
}
|
||||
}
|
||||
}
|
@ -12,7 +12,8 @@ use std::{
|
||||
string::{self, ToString},
|
||||
};
|
||||
|
||||
use it_lilo_utils::error::MemoryWriteError;
|
||||
use it_lilo_utils::lifter::LiError;
|
||||
use it_lilo_utils::lowerer::LoError;
|
||||
use thiserror::Error as ThisError;
|
||||
|
||||
pub use fluence_it_types::WasmValueNativeCastError;
|
||||
@ -44,16 +45,13 @@ impl InstructionError {
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn from_lilo(instruction: Instruction, lilo: LiLoError) -> Self {
|
||||
let error_kind = InstructionErrorKind::LiLoError(lilo);
|
||||
pub(crate) fn from_li(instruction: Instruction, li: LiError) -> Self {
|
||||
let error_kind = InstructionErrorKind::LiError(li);
|
||||
Self::from_error_kind(instruction, error_kind)
|
||||
}
|
||||
|
||||
pub(crate) fn from_write_error(
|
||||
instruction: Instruction,
|
||||
write_error: MemoryWriteError,
|
||||
) -> Self {
|
||||
let error_kind = InstructionErrorKind::MemoryWriteError(write_error);
|
||||
pub(crate) fn from_lo(instruction: Instruction, lo: LoError) -> Self {
|
||||
let error_kind = InstructionErrorKind::LoError(lo);
|
||||
Self::from_error_kind(instruction, error_kind)
|
||||
}
|
||||
}
|
||||
@ -229,11 +227,11 @@ pub enum InstructionErrorKind {
|
||||
|
||||
/// Errors related to lifting/lowering records.
|
||||
#[error("{0}")]
|
||||
LiLoError(#[from] LiLoError),
|
||||
LiError(#[from] LiError),
|
||||
|
||||
/// Errors related to incorrect writing to memory.
|
||||
#[error("{0}")]
|
||||
MemoryWriteError(#[from] MemoryWriteError),
|
||||
LoError(#[from] LoError),
|
||||
}
|
||||
|
||||
impl From<(TryFromIntError, &'static str)> for InstructionErrorKind {
|
||||
@ -241,62 +239,3 @@ impl From<(TryFromIntError, &'static str)> for InstructionErrorKind {
|
||||
InstructionErrorKind::NegativeValue { subject }
|
||||
}
|
||||
}
|
||||
|
||||
/// Contains various errors encountered while lifting/lowering records and arrays.
|
||||
#[derive(Debug, ThisError)]
|
||||
pub enum LiLoError {
|
||||
/// This error occurred from out-of-bound memory access.
|
||||
#[error("{0}")]
|
||||
MemoryAccessError(#[from] it_lilo_utils::error::MemoryAccessError),
|
||||
|
||||
/// An error related to not found record in module record types.
|
||||
#[error("Record with type id {0} not found")]
|
||||
RecordTypeNotFound(u64),
|
||||
|
||||
/// The memory doesn't exist.
|
||||
#[error("memory `{memory_index}` does not exist")]
|
||||
MemoryIsMissing {
|
||||
/// The memory index.
|
||||
memory_index: usize,
|
||||
},
|
||||
|
||||
/// The local or import function doesn't exist.
|
||||
#[error("the allocate function with index `{function_index}` doesn't exist in Wasm module")]
|
||||
AllocateFuncIsMissing {
|
||||
/// The local or import function index.
|
||||
function_index: u32,
|
||||
},
|
||||
|
||||
/// Failed to call a allocate function.
|
||||
#[error("call to allocated was failed")]
|
||||
AllocateCallFailed,
|
||||
|
||||
/// Allocate input types doesn't match with needed.
|
||||
#[error(
|
||||
"allocate func doesn't receive two i32 values,\
|
||||
probably a Wasm module's built with unsupported sdk version"
|
||||
)]
|
||||
AllocateFuncIncompatibleSignature,
|
||||
|
||||
/// Allocate output types doesn't match with needed.
|
||||
#[error(
|
||||
"allocate func doesn't return a one value of I32 type,\
|
||||
probably a Wasm module's built with unsupported sdk version"
|
||||
)]
|
||||
AllocateFuncIncompatibleOutput,
|
||||
|
||||
/// The searched by id type doesn't exist.
|
||||
#[error("type with `{record_type_id}` is missing in a Wasm binary")]
|
||||
RecordTypeByNameIsMissing {
|
||||
/// The record type name.
|
||||
record_type_id: u64,
|
||||
},
|
||||
|
||||
/// Errors related to lifting incorrect UTF8 string from a Wasm module.
|
||||
#[error("corrupted UTF8 string {0}")]
|
||||
CorruptedUTF8String(#[from] std::string::FromUtf8Error),
|
||||
|
||||
/// This error occurred when a record is created from empty values array.
|
||||
#[error("Record with name '{0}' can't be empty")]
|
||||
EmptyRecord(String),
|
||||
}
|
||||
|
@ -1,11 +1,4 @@
|
||||
mod lift_array;
|
||||
mod lower_array;
|
||||
|
||||
pub(crate) use lift_array::array_lift_memory_impl;
|
||||
pub(crate) use lower_array::array_lower_memory_impl;
|
||||
|
||||
use super::lilo;
|
||||
use super::record_lower_memory_impl;
|
||||
|
||||
use crate::instr_error;
|
||||
use crate::interpreter::instructions::to_native;
|
||||
@ -14,7 +7,9 @@ use crate::{
|
||||
interpreter::Instruction,
|
||||
IType, IValue,
|
||||
};
|
||||
use it_lilo_utils::memory_writer::MemoryWriter;
|
||||
use it_lilo_utils::lifter::ILifter;
|
||||
use it_lilo_utils::lowerer::ILowerer;
|
||||
use it_lilo_utils::lowerer::LoweredArray;
|
||||
|
||||
use std::convert::TryInto;
|
||||
|
||||
@ -72,10 +67,15 @@ where
|
||||
.view();
|
||||
let memory = memory_view.deref();
|
||||
|
||||
let li_helper = lilo::LiHelper::new(&**instance, memory)
|
||||
.map_err(|e| InstructionError::from_lilo(instruction.clone(), e))?;
|
||||
let array = array_lift_memory_impl(&li_helper, &value_type, offset as _, size as _)
|
||||
.map_err(|e| InstructionError::from_lilo(instruction.clone(), e))?;
|
||||
let li_helper = lilo::LiHelper::new(&**instance);
|
||||
let lifter = ILifter::new(memory, &li_helper);
|
||||
let array = it_lilo_utils::lifter::array_lift_memory(
|
||||
&lifter,
|
||||
&value_type,
|
||||
offset as _,
|
||||
size as _,
|
||||
)
|
||||
.map_err(|e| InstructionError::from_li(instruction.clone(), e))?;
|
||||
|
||||
log::trace!("array.lift_memory: pushing {:?} on the stack", array);
|
||||
runtime.stack.push(array);
|
||||
@ -121,11 +121,12 @@ where
|
||||
}
|
||||
|
||||
let lo_helper = lilo::LoHelper::new(&**instance);
|
||||
let memory_writer = MemoryWriter::new(&lo_helper)
|
||||
.map_err(|e| InstructionError::from_write_error(instruction.clone(), e))?;
|
||||
let lowerer = ILowerer::new(&lo_helper)
|
||||
.map_err(|e| InstructionError::from_lo(instruction.clone(), e))?;
|
||||
|
||||
let (offset, size) = array_lower_memory_impl(&memory_writer, values)
|
||||
.map_err(|e| InstructionError::from_write_error(instruction.clone(), e))?;
|
||||
let LoweredArray { offset, size } =
|
||||
it_lilo_utils::lowerer::array_lower_memory(&lowerer, values)
|
||||
.map_err(|e| InstructionError::from_lo(instruction.clone(), e))?;
|
||||
|
||||
log::trace!(
|
||||
"array.lower_memory: pushing {}, {} on the stack",
|
||||
|
@ -1,65 +0,0 @@
|
||||
use crate::IValue;
|
||||
|
||||
use it_lilo_utils::memory_writer::Heapable;
|
||||
use it_lilo_utils::memory_writer::MemoryWriter;
|
||||
use it_lilo_utils::ser_value_size;
|
||||
use it_lilo_utils::type_tag_form_ivalue;
|
||||
use it_lilo_utils::WriteResult;
|
||||
|
||||
pub(crate) fn array_lower_memory_impl<T: Heapable>(
|
||||
writer: &MemoryWriter<T>,
|
||||
array_values: Vec<IValue>,
|
||||
) -> WriteResult<(usize, usize)> {
|
||||
if array_values.is_empty() {
|
||||
return Ok((0, 0));
|
||||
}
|
||||
|
||||
let elements_count = array_values.len() as u32;
|
||||
let size = ser_value_size(&array_values[0]) * elements_count;
|
||||
let type_tag = type_tag_form_ivalue(&array_values[0]);
|
||||
let seq_writer = writer.sequential_writer(size, type_tag)?;
|
||||
|
||||
// here it's known that all interface values have the same type
|
||||
for value in array_values {
|
||||
match value {
|
||||
IValue::Boolean(value) => seq_writer.write_u8(writer, value as _),
|
||||
IValue::S8(value) => seq_writer.write_u8(writer, value as _),
|
||||
IValue::S16(value) => seq_writer.write_array(writer, value.to_le_bytes()),
|
||||
IValue::S32(value) => seq_writer.write_array(writer, value.to_le_bytes()),
|
||||
IValue::S64(value) => seq_writer.write_array(writer, value.to_le_bytes()),
|
||||
IValue::U8(value) => seq_writer.write_array(writer, value.to_le_bytes()),
|
||||
IValue::U16(value) => seq_writer.write_array(writer, value.to_le_bytes()),
|
||||
IValue::U32(value) => seq_writer.write_array(writer, value.to_le_bytes()),
|
||||
IValue::U64(value) => seq_writer.write_array(writer, value.to_le_bytes()),
|
||||
IValue::I32(value) => seq_writer.write_array(writer, value.to_le_bytes()),
|
||||
IValue::I64(value) => seq_writer.write_array(writer, value.to_le_bytes()),
|
||||
IValue::F32(value) => seq_writer.write_array(writer, value.to_le_bytes()),
|
||||
IValue::F64(value) => seq_writer.write_array(writer, value.to_le_bytes()),
|
||||
IValue::String(value) => {
|
||||
let offset = writer.write_bytes(value.as_bytes())? as u32;
|
||||
|
||||
seq_writer.write_array(writer, offset.to_le_bytes());
|
||||
seq_writer.write_array(writer, (value.len() as u32).to_le_bytes());
|
||||
}
|
||||
IValue::ByteArray(values) => {
|
||||
let offset = writer.write_bytes(&values)? as u32;
|
||||
|
||||
seq_writer.write_array(writer, offset.to_le_bytes());
|
||||
seq_writer.write_array(writer, (values.len() as u32).to_le_bytes());
|
||||
}
|
||||
IValue::Array(values) => {
|
||||
let (offset, size) = array_lower_memory_impl(writer, values)?;
|
||||
|
||||
seq_writer.write_array(writer, (offset as u32).to_le_bytes());
|
||||
seq_writer.write_array(writer, (size as u32).to_le_bytes());
|
||||
}
|
||||
IValue::Record(values) => {
|
||||
let offset = super::record_lower_memory_impl(writer, values)? as u32;
|
||||
seq_writer.write_array(writer, offset.to_le_bytes());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
let offset = seq_writer.start_offset();
|
||||
Ok((offset as _, elements_count as _))
|
||||
}
|
@ -1,61 +1,61 @@
|
||||
use super::LiLoError;
|
||||
use super::LiLoResult;
|
||||
use crate::interpreter::wasm;
|
||||
use crate::IRecordType;
|
||||
|
||||
use it_lilo_utils::memory_reader::MemoryReader;
|
||||
use it_lilo_utils::traits::RecordResolvable;
|
||||
use it_lilo_utils::traits::RecordResolvableError;
|
||||
|
||||
use std::cell::Cell;
|
||||
use std::rc::Rc;
|
||||
use std::marker::PhantomData;
|
||||
|
||||
pub(crate) struct LiHelper<'i> {
|
||||
pub(crate) reader: MemoryReader<'i>,
|
||||
pub(crate) record_resolver: RecordResolver<'i>,
|
||||
}
|
||||
|
||||
impl<'instance> LiHelper<'instance> {
|
||||
pub(crate) fn new<Instance, Export, LocalImport, Memory, MemoryView>(
|
||||
instance: &'instance Instance,
|
||||
memory: &'instance [Cell<u8>],
|
||||
) -> LiLoResult<Self>
|
||||
where
|
||||
Export: wasm::structures::Export + 'instance,
|
||||
LocalImport: wasm::structures::LocalImport + 'instance,
|
||||
Memory: wasm::structures::Memory<MemoryView> + 'instance,
|
||||
MemoryView: wasm::structures::MemoryView,
|
||||
Instance: wasm::structures::Instance<Export, LocalImport, Memory, MemoryView>,
|
||||
{
|
||||
let record_resolver = build_record_resolver(instance)?;
|
||||
let reader = MemoryReader::new(memory);
|
||||
|
||||
let helper = Self {
|
||||
reader,
|
||||
record_resolver,
|
||||
};
|
||||
|
||||
Ok(helper)
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) type RecordResolver<'i> = Box<dyn Fn(u64) -> LiLoResult<Rc<IRecordType>> + 'i>;
|
||||
|
||||
pub(super) fn build_record_resolver<'instance, Instance, Export, LocalImport, Memory, MemoryView>(
|
||||
instance: &'instance Instance,
|
||||
) -> LiLoResult<RecordResolver<'instance>>
|
||||
pub struct LiHelper<'i, Instance, Export, LocalImport, Memory, MemoryView>
|
||||
where
|
||||
Export: wasm::structures::Export + 'instance,
|
||||
LocalImport: wasm::structures::LocalImport + 'instance,
|
||||
Memory: wasm::structures::Memory<MemoryView> + 'instance,
|
||||
Export: wasm::structures::Export + 'i,
|
||||
LocalImport: wasm::structures::LocalImport + 'i,
|
||||
Memory: wasm::structures::Memory<MemoryView> + 'i,
|
||||
MemoryView: wasm::structures::MemoryView,
|
||||
Instance: wasm::structures::Instance<Export, LocalImport, Memory, MemoryView>,
|
||||
{
|
||||
let resolver = move |record_type_id: u64| {
|
||||
let record = instance
|
||||
.wit_record_by_id(record_type_id)
|
||||
.ok_or(LiLoError::RecordTypeByNameIsMissing { record_type_id })?;
|
||||
|
||||
Ok(record.clone())
|
||||
};
|
||||
|
||||
Ok(Box::new(resolver))
|
||||
pub(crate) instance: &'i Instance,
|
||||
_export: PhantomData<Export>,
|
||||
_local_import: PhantomData<LocalImport>,
|
||||
_memory: PhantomData<Memory>,
|
||||
_memory_view: PhantomData<MemoryView>,
|
||||
}
|
||||
|
||||
impl<'i, Instance, Export, LocalImport, Memory, MemoryView>
|
||||
LiHelper<'i, Instance, Export, LocalImport, Memory, MemoryView>
|
||||
where
|
||||
Export: wasm::structures::Export + 'i,
|
||||
LocalImport: wasm::structures::LocalImport + 'i,
|
||||
Memory: wasm::structures::Memory<MemoryView> + 'i,
|
||||
MemoryView: wasm::structures::MemoryView,
|
||||
Instance: wasm::structures::Instance<Export, LocalImport, Memory, MemoryView>,
|
||||
{
|
||||
pub(crate) fn new(instance: &'i Instance) -> Self {
|
||||
Self {
|
||||
instance,
|
||||
_export: PhantomData,
|
||||
_local_import: PhantomData,
|
||||
_memory: PhantomData,
|
||||
_memory_view: PhantomData,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'i, Instance, Export, LocalImport, Memory, MemoryView> RecordResolvable
|
||||
for LiHelper<'i, Instance, Export, LocalImport, Memory, MemoryView>
|
||||
where
|
||||
Export: wasm::structures::Export + 'i,
|
||||
LocalImport: wasm::structures::LocalImport + 'i,
|
||||
Memory: wasm::structures::Memory<MemoryView> + 'i,
|
||||
MemoryView: wasm::structures::MemoryView,
|
||||
Instance: wasm::structures::Instance<Export, LocalImport, Memory, MemoryView>,
|
||||
{
|
||||
fn resolve_record(&self, record_type_id: u64) -> Result<&IRecordType, RecordResolvableError> {
|
||||
let record = self
|
||||
.instance
|
||||
.wit_record_by_id(record_type_id)
|
||||
.ok_or(RecordResolvableError::RecordNotFound(record_type_id))?;
|
||||
|
||||
Ok(record)
|
||||
}
|
||||
}
|
||||
|
@ -2,11 +2,10 @@ use crate::interpreter::wasm;
|
||||
use crate::interpreter::wasm::structures::FunctionIndex;
|
||||
use crate::IValue;
|
||||
|
||||
use it_lilo_utils::error::MemoryWriteError;
|
||||
use it_lilo_utils::memory_writer::Heapable;
|
||||
use it_lilo_utils::WriteResult;
|
||||
use it_lilo_utils::traits::Allocatable;
|
||||
use it_lilo_utils::traits::AllocatableError;
|
||||
use it_lilo_utils::traits::MemSlice;
|
||||
|
||||
use std::cell::Cell;
|
||||
use std::marker::PhantomData;
|
||||
|
||||
pub struct LoHelper<'i, Instance, Export, LocalImport, Memory, MemoryView>
|
||||
@ -18,10 +17,10 @@ where
|
||||
Instance: wasm::structures::Instance<Export, LocalImport, Memory, MemoryView>,
|
||||
{
|
||||
pub(crate) instance: &'i Instance,
|
||||
_phantom_export: PhantomData<Export>,
|
||||
_phantom_local_import: PhantomData<LocalImport>,
|
||||
_phantom_memory: PhantomData<Memory>,
|
||||
_phantom_memory_view: PhantomData<MemoryView>,
|
||||
_export: PhantomData<Export>,
|
||||
_local_import: PhantomData<LocalImport>,
|
||||
_memory: PhantomData<Memory>,
|
||||
_memory_view: PhantomData<MemoryView>,
|
||||
}
|
||||
|
||||
impl<'i, Instance, Export, LocalImport, Memory, MemoryView>
|
||||
@ -36,15 +35,15 @@ where
|
||||
pub(crate) fn new(instance: &'i Instance) -> Self {
|
||||
Self {
|
||||
instance,
|
||||
_phantom_export: PhantomData,
|
||||
_phantom_local_import: PhantomData,
|
||||
_phantom_memory: PhantomData,
|
||||
_phantom_memory_view: PhantomData,
|
||||
_export: PhantomData,
|
||||
_local_import: PhantomData,
|
||||
_memory: PhantomData,
|
||||
_memory_view: PhantomData,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'i, Instance, Export, LocalImport, Memory, MemoryView> Heapable
|
||||
impl<'i, Instance, Export, LocalImport, Memory, MemoryView> Allocatable
|
||||
for LoHelper<'i, Instance, Export, LocalImport, Memory, MemoryView>
|
||||
where
|
||||
Export: wasm::structures::Export + 'i,
|
||||
@ -53,16 +52,19 @@ where
|
||||
MemoryView: wasm::structures::MemoryView,
|
||||
Instance: wasm::structures::Instance<Export, LocalImport, Memory, MemoryView>,
|
||||
{
|
||||
fn allocate(&self, size: u32, type_tag: u32) -> WriteResult<usize> {
|
||||
fn allocate(&self, size: u32, type_tag: u32) -> Result<usize, AllocatableError> {
|
||||
use AllocatableError::*;
|
||||
|
||||
use crate::interpreter::instructions::ALLOCATE_FUNC_INDEX;
|
||||
use crate::interpreter::wasm::structures::TypedIndex;
|
||||
|
||||
let index = FunctionIndex::new(ALLOCATE_FUNC_INDEX as usize);
|
||||
let local_or_import = self.instance.local_or_import(index).ok_or(
|
||||
MemoryWriteError::AllocateFuncIsMissing {
|
||||
function_index: ALLOCATE_FUNC_INDEX,
|
||||
},
|
||||
)?;
|
||||
let local_or_import =
|
||||
self.instance
|
||||
.local_or_import(index)
|
||||
.ok_or(AllocateFuncIsMissing {
|
||||
function_index: ALLOCATE_FUNC_INDEX,
|
||||
})?;
|
||||
|
||||
let inputs = vec![IValue::I32(size as _), IValue::I32(type_tag as _)];
|
||||
// TODO: we could check it only once on the module startup or memorize check result
|
||||
@ -71,25 +73,25 @@ where
|
||||
local_or_import,
|
||||
&inputs,
|
||||
)
|
||||
.map_err(|_| MemoryWriteError::AllocateFuncIncompatibleSignature)?;
|
||||
.map_err(|_| AllocateFuncIncompatibleSignature)?;
|
||||
|
||||
let outcome = local_or_import
|
||||
.call(&inputs)
|
||||
.map_err(|_| MemoryWriteError::AllocateCallFailed)?;
|
||||
.map_err(|_| AllocateCallFailed)?;
|
||||
|
||||
if outcome.len() != 1 {
|
||||
return Err(MemoryWriteError::AllocateFuncIncompatibleOutput);
|
||||
return Err(AllocateFuncIncompatibleOutput);
|
||||
}
|
||||
|
||||
match outcome[0] {
|
||||
IValue::I32(offset) => Ok(offset as _),
|
||||
_ => Err(MemoryWriteError::AllocateFuncIncompatibleOutput),
|
||||
_ => Err(AllocateFuncIncompatibleOutput),
|
||||
}
|
||||
}
|
||||
|
||||
fn memory_slice(&self, memory_index: usize) -> WriteResult<&[Cell<u8>]> {
|
||||
fn memory_slice(&self, memory_index: usize) -> Result<MemSlice<'_>, AllocatableError> {
|
||||
self.instance
|
||||
.memory_slice(memory_index)
|
||||
.ok_or(MemoryWriteError::MemoryIsMissing { memory_index })
|
||||
.ok_or(AllocatableError::MemoryIsMissing { memory_index })
|
||||
}
|
||||
}
|
||||
|
@ -1,8 +1,5 @@
|
||||
mod li_helper;
|
||||
mod lo_helper;
|
||||
|
||||
pub(crate) use crate::errors::LiLoError;
|
||||
pub(crate) use li_helper::LiHelper;
|
||||
pub(crate) use lo_helper::LoHelper;
|
||||
|
||||
pub(crate) type LiLoResult<T> = std::result::Result<T, LiLoError>;
|
||||
|
@ -1,11 +1,3 @@
|
||||
mod lift_record;
|
||||
mod lower_record;
|
||||
|
||||
pub(crate) use lift_record::record_lift_memory_impl;
|
||||
pub(crate) use lower_record::record_lower_memory_impl;
|
||||
|
||||
use super::array_lift_memory_impl;
|
||||
use super::array_lower_memory_impl;
|
||||
use super::lilo;
|
||||
use crate::instr_error;
|
||||
use crate::interpreter::instructions::{is_record_fields_compatible_to_type, to_native};
|
||||
@ -13,7 +5,9 @@ use crate::IType;
|
||||
use crate::IValue;
|
||||
use crate::{errors::InstructionError, errors::InstructionErrorKind, interpreter::Instruction};
|
||||
|
||||
use it_lilo_utils::memory_writer::MemoryWriter;
|
||||
use it_lilo_utils::lifter::ILifter;
|
||||
use it_lilo_utils::lowerer::ILowerer;
|
||||
|
||||
use std::convert::TryInto;
|
||||
|
||||
pub(crate) fn record_lift_memory<Instance, Export, LocalImport, Memory, MemoryView>(
|
||||
@ -71,10 +65,10 @@ where
|
||||
.view();
|
||||
let memory = memory_view.deref();
|
||||
|
||||
let li_helper = lilo::LiHelper::new(&**instance, memory)
|
||||
.map_err(|e| InstructionError::from_lilo(instruction.clone(), e))?;
|
||||
let record = record_lift_memory_impl(&li_helper, record_type, offset)
|
||||
.map_err(|e| InstructionError::from_lilo(instruction.clone(), e))?;
|
||||
let li_helper = lilo::LiHelper::new(&**instance);
|
||||
let lifter = ILifter::new(memory, &li_helper);
|
||||
let record = it_lilo_utils::lifter::record_lift_memory(&lifter, record_type, offset)
|
||||
.map_err(|e| InstructionError::from_li(instruction.clone(), e))?;
|
||||
|
||||
log::debug!("record.lift_memory: pushing {:?} on the stack", record);
|
||||
runtime.stack.push(record);
|
||||
@ -114,10 +108,11 @@ where
|
||||
log::debug!("record.lower_memory: obtained {:?} values on the stack for record type = {}", record_fields, record_type_id);
|
||||
|
||||
let lo_helper = lilo::LoHelper::new(&**instance);
|
||||
let memory_writer = MemoryWriter::new(&lo_helper)
|
||||
.map_err(|e| InstructionError::from_write_error(instruction.clone(), e))?;
|
||||
let offset = record_lower_memory_impl(&memory_writer, record_fields)
|
||||
.map_err(|e| InstructionError::from_write_error(instruction.clone(), e))?;
|
||||
let memory_writer = ILowerer::new(&lo_helper)
|
||||
.map_err(|e| InstructionError::from_lo(instruction.clone(), e))?;
|
||||
let offset =
|
||||
it_lilo_utils::lowerer::record_lower_memory(&memory_writer, record_fields)
|
||||
.map_err(|e| InstructionError::from_lo(instruction.clone(), e))?;
|
||||
|
||||
log::debug!("record.lower_memory: pushing {} on the stack", offset);
|
||||
runtime.stack.push(IValue::I32(offset));
|
||||
|
Loading…
Reference in New Issue
Block a user