Skip to content

Commit

Permalink
refactor: init store returns result
Browse files Browse the repository at this point in the history
  • Loading branch information
nerodesu017 committed Dec 3, 2024
1 parent f76bbe8 commit 89b9679
Show file tree
Hide file tree
Showing 3 changed files with 61 additions and 20 deletions.
38 changes: 38 additions & 0 deletions src/core/error.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
use alloc::format;
use alloc::string::{String, ToString};

use crate::core::indices::GlobalIdx;
use crate::validation_stack::LabelKind;
use crate::RefType;
Expand Down Expand Up @@ -25,6 +28,13 @@ pub enum RuntimeError {
ExpectedAValueOnTheStack,
}

#[derive(Debug, PartialEq, Eq, Clone)]
pub enum StoreInstantiationError {
ActiveDataWriteOutOfBounds,
I64ValueOutOfReach(String),
MissingValueOnTheStack,
}

#[derive(Debug, PartialEq, Eq, Clone)]
pub enum Error {
/// The magic number at the very start of the given WASM file is invalid.
Expand Down Expand Up @@ -72,6 +82,7 @@ pub enum Error {
FunctionIsNotDefined(FuncIdx),
ReferencingAnUnreferencedFunction(FuncIdx),
FunctionTypeIsNotDefined(TypeIdx),
StoreInstantiationError(StoreInstantiationError),
}

impl Display for Error {
Expand Down Expand Up @@ -196,6 +207,7 @@ impl Display for Error {
"C.fn_types[{}] is NOT defined when it should be",
func_ty_idx
)),
Error::StoreInstantiationError(err) => err.fmt(f),
}
}
}
Expand All @@ -220,10 +232,36 @@ impl Display for RuntimeError {
}
}

impl Display for StoreInstantiationError {
fn fmt(&self, f: &mut Formatter<'_>) -> core::fmt::Result {
use StoreInstantiationError::*;
match self {
ActiveDataWriteOutOfBounds => {
f.write_str("Active data writing in memory is out of bounds")
}
I64ValueOutOfReach(s) => f.write_fmt(format_args!(
"I64 value {}is out of reach",
if !s.is_empty() {
format!("for {s} ")
} else {
"".to_string()
}
)),
MissingValueOnTheStack => f.write_str(""),
}
}
}

pub type Result<T> = core::result::Result<T, Error>;

impl From<RuntimeError> for Error {
fn from(value: RuntimeError) -> Self {
Self::RuntimeError(value)
}
}

impl From<StoreInstantiationError> for Error {
fn from(value: StoreInstantiationError) -> Self {
Self::StoreInstantiationError(value)
}
}
37 changes: 18 additions & 19 deletions src/execution/mod.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
use alloc::borrow::ToOwned;
use alloc::string::ToString;
use alloc::vec;
use alloc::vec::Vec;
Expand All @@ -10,6 +11,7 @@ use store::{DataInst, ElemInst, TableInst};
use value::{ExternAddr, FuncAddr, Ref};
use value_stack::Stack;

use crate::core::error::StoreInstantiationError;
use crate::core::reader::types::element::{ElemItems, ElemMode};
use crate::core::reader::types::export::{Export, ExportDesc};
use crate::core::reader::types::FuncType;
Expand All @@ -20,7 +22,7 @@ use crate::execution::store::{FuncInst, GlobalInst, MemInst, Store};
use crate::execution::value::Value;
use crate::validation::code::read_declared_locals;
use crate::value::InteropValueList;
use crate::{RefType, RuntimeError, ValType, ValidationInfo};
use crate::{RefType, Result as CustomResult, RuntimeError, ValType, ValidationInfo};

// TODO
pub(crate) mod assert_validated;
Expand Down Expand Up @@ -48,14 +50,14 @@ where
}

impl<'b> RuntimeInstance<'b, EmptyHookSet> {
pub fn new(validation_info: &'_ ValidationInfo<'b>) -> Result<Self, RuntimeError> {
pub fn new(validation_info: &'_ ValidationInfo<'b>) -> CustomResult<Self> {
Self::new_with_hooks(DEFAULT_MODULE, validation_info, EmptyHookSet)
}

pub fn new_named(
module_name: &str,
validation_info: &'_ ValidationInfo<'b>,
) -> Result<Self, RuntimeError> {
) -> CustomResult<Self> {
Self::new_with_hooks(module_name, validation_info, EmptyHookSet)
}
}
Expand All @@ -68,10 +70,10 @@ where
module_name: &str,
validation_info: &'_ ValidationInfo<'b>,
hook_set: H,
) -> Result<Self, RuntimeError> {
) -> CustomResult<Self> {
trace!("Starting instantiation of bytecode");

let store = Self::init_store(validation_info);
let store = Self::init_store(validation_info)?;

let mut instance = RuntimeInstance {
wasm_bytecode: validation_info.wasm,
Expand Down Expand Up @@ -314,7 +316,8 @@ where
}
}

fn init_store(validation_info: &ValidationInfo) -> Store {
fn init_store(validation_info: &ValidationInfo) -> CustomResult<Store> {
use StoreInstantiationError::*;
let function_instances: Vec<FuncInst> = {
let mut wasm_reader = WasmReader::new(validation_info.wasm);

Expand Down Expand Up @@ -447,11 +450,7 @@ where
wasm.move_start_to(active_data.offset).unwrap_validated();
let mut stack = Stack::new();
run_const(wasm, &mut stack, ());
let value = stack.peek_unknown_value();
if value.is_none() {
panic!("No value on the stack for data segment offset");
}
value.unwrap()
stack.peek_unknown_value().ok_or(MissingValueOnTheStack)?
};

// TODO: this shouldn't be a simple value, should it? I mean it can't be, but it can also be any type of ValType
Expand All @@ -460,7 +459,7 @@ where
Value::I32(val) => val,
Value::I64(val) => {
if val > u32::MAX as u64 {
panic!("i64 value for data segment offset is out of reach")
return Err(I64ValueOutOfReach("data segment".to_owned()));
}
val as u32
}
Expand All @@ -472,19 +471,19 @@ where

let len = mem_inst.data.len();
if offset as usize + d.init.len() > len {
panic!("Active data writing in memory, out of bounds");
return Err(ActiveDataWriteOutOfBounds);
}
let data = mem_inst
.data
.get_mut(offset as usize..offset as usize + d.init.len())
.unwrap();
data.copy_from_slice(&d.init);
}
DataInst {
Ok(DataInst {
data: d.init.clone(),
}
})
})
.collect();
.collect::<Result<Vec<DataInst>, StoreInstantiationError>>()?;

let global_instances: Vec<GlobalInst> = validation_info
.globals
Expand All @@ -508,15 +507,15 @@ where
})
.collect();

Store {
Ok(Store {
funcs: function_instances,
mems: memory_instances,
globals: global_instances,
data: data_sections,
tables,
elements,
passive_elem_indexes,
}
})
}
}

Expand All @@ -534,7 +533,7 @@ fn get_address_offset(value: Value) -> u32 {
match value {
Value::I32(val) => val,
Value::Ref(rref) => match rref {
Ref::Extern(_) => panic!("Not yet implemented"),
Ref::Extern(_) => todo!("Not yet implemented"),
Ref::Func(func_addr) => func_addr.addr.unwrap() as u32,
},
// INFO: from wasmtime - implement only global
Expand Down
6 changes: 5 additions & 1 deletion tests/specification/run.rs
Original file line number Diff line number Diff line change
Expand Up @@ -112,7 +112,11 @@ pub fn run_spec_test(filepath: &str) -> WastTestReport {

let instance = try_to!(RuntimeInstance::new(&validation_info).map_err(|err| {
CompilationError::new(
Box::new(WasmInterpreterError(wasm::Error::RuntimeError(err))),
Box::new(WasmInterpreterError(wasm::Error::RuntimeError(match err {
wasm::Error::RuntimeError(runtime_error) => runtime_error,
// is it unreachable?
_ => unreachable!(""),
}))),
filepath,
"failed to create runtime instance",
)
Expand Down

0 comments on commit 89b9679

Please sign in to comment.