Skip to content

Commit

Permalink
feat: uninitialized elems
Browse files Browse the repository at this point in the history
Signed-off-by: Henry Gressmann <mail@henrygressmann.de>
  • Loading branch information
explodingcamera committed Jan 23, 2024
1 parent 3e71f86 commit 52eda3e
Show file tree
Hide file tree
Showing 7 changed files with 71 additions and 68 deletions.
9 changes: 3 additions & 6 deletions crates/parser/src/conversion.rs
Original file line number Diff line number Diff line change
@@ -1,9 +1,6 @@
use alloc::{boxed::Box, format, string::ToString, vec::Vec};
use log::debug;
use tinywasm_types::{
BlockArgs, ConstInstruction, ElementItem, Export, ExternalKind, FuncType, Global, GlobalType, Import, ImportKind,
Instruction, MemArg, MemoryArch, MemoryType, TableType, ValType,
};
use tinywasm_types::*;
use wasmparser::{FuncValidator, OperatorsReader, ValidatorResources};

use crate::{module::CodeSection, Result};
Expand Down Expand Up @@ -210,8 +207,8 @@ pub(crate) fn convert_valtype(valtype: &wasmparser::ValType) -> ValType {
}
}

pub(crate) fn convert_memarg(memarg: wasmparser::MemArg) -> MemArg {
MemArg { offset: memarg.offset, align: memarg.align, align_max: memarg.max_align, mem_addr: memarg.memory }
pub(crate) fn convert_memarg(memarg: wasmparser::MemArg) -> MemoryArg {
MemoryArg { offset: memarg.offset, align: memarg.align, align_max: memarg.max_align, mem_addr: memarg.memory }
}

pub(crate) fn process_const_operators(ops: OperatorsReader) -> Result<ConstInstruction> {
Expand Down
8 changes: 4 additions & 4 deletions crates/tinywasm/src/imports.rs
Original file line number Diff line number Diff line change
Expand Up @@ -215,13 +215,13 @@ pub(crate) enum ResolvedExtern<S, V> {
pub(crate) struct ResolvedImports {
pub(crate) globals: Vec<GlobalAddr>,
pub(crate) tables: Vec<TableAddr>,
pub(crate) mems: Vec<MemAddr>,
pub(crate) memories: Vec<MemAddr>,
pub(crate) funcs: Vec<FuncAddr>,
}

impl ResolvedImports {
pub(crate) fn new() -> Self {
Self { globals: Vec::new(), tables: Vec::new(), mems: Vec::new(), funcs: Vec::new() }
Self { globals: Vec::new(), tables: Vec::new(), memories: Vec::new(), funcs: Vec::new() }
}
}

Expand Down Expand Up @@ -318,7 +318,7 @@ impl Imports {
match &kind {
ExternalKind::Global => imports.globals.push(addr),
ExternalKind::Table => imports.tables.push(addr),
ExternalKind::Memory => imports.mems.push(addr),
ExternalKind::Memory => imports.memories.push(addr),
ExternalKind::Func => imports.funcs.push(addr),
}
}
Expand All @@ -338,7 +338,7 @@ impl Imports {
match val {
ExternVal::Global(g) => imports.globals.push(g),
ExternVal::Table(t) => imports.tables.push(t),
ExternVal::Mem(m) => imports.mems.push(m),
ExternVal::Mem(m) => imports.memories.push(m),
ExternVal::Func(f) => imports.funcs.push(f),
}
}
Expand Down
8 changes: 4 additions & 4 deletions crates/tinywasm/src/instance.rs
Original file line number Diff line number Diff line change
Expand Up @@ -66,10 +66,10 @@ impl ModuleInstance {
addrs.globals.extend(store.init_globals(data.globals.into(), idx)?);
addrs.funcs.extend(store.init_funcs(data.funcs.into(), idx)?);
addrs.tables.extend(store.init_tables(data.table_types.into(), idx)?);
addrs.mems.extend(store.init_mems(data.memory_types.into(), idx)?);
addrs.memories.extend(store.init_memories(data.memory_types.into(), idx)?);

let elem_addrs = store.init_elems(&addrs.tables, data.elements.into(), idx)?;
let data_addrs = store.init_datas(&addrs.mems, data.data.into(), idx)?;
let elem_addrs = store.init_elements(&addrs.tables, data.elements.into(), idx)?;
let data_addrs = store.init_datas(&addrs.memories, data.data.into(), idx)?;

let instance = ModuleInstanceInner {
store_id: store.id(),
Expand All @@ -78,7 +78,7 @@ impl ModuleInstance {
types: data.func_types,
func_addrs: addrs.funcs.into_boxed_slice(),
table_addrs: addrs.tables.into_boxed_slice(),
mem_addrs: addrs.mems.into_boxed_slice(),
mem_addrs: addrs.memories.into_boxed_slice(),
global_addrs: addrs.globals.into_boxed_slice(),
elem_addrs,
data_addrs: data_addrs,
Expand Down
58 changes: 32 additions & 26 deletions crates/tinywasm/src/store.rs
Original file line number Diff line number Diff line change
Expand Up @@ -86,9 +86,9 @@ impl Default for Store {
pub(crate) struct StoreData {
pub(crate) funcs: Vec<Rc<FunctionInstance>>,
pub(crate) tables: Vec<Rc<RefCell<TableInstance>>>,
pub(crate) mems: Vec<Rc<RefCell<MemoryInstance>>>,
pub(crate) memories: Vec<Rc<RefCell<MemoryInstance>>>,
pub(crate) globals: Vec<Rc<RefCell<GlobalInstance>>>,
pub(crate) elems: Vec<ElemInstance>,
pub(crate) elements: Vec<ElementInstance>,
pub(crate) datas: Vec<DataInstance>,
}

Expand Down Expand Up @@ -142,15 +142,15 @@ impl Store {
}

/// Add memories to the store, returning their addresses in the store
pub(crate) fn init_mems(&mut self, mems: Vec<MemoryType>, idx: ModuleInstanceAddr) -> Result<Vec<MemAddr>> {
let mem_count = self.data.mems.len();
pub(crate) fn init_memories(&mut self, memories: Vec<MemoryType>, idx: ModuleInstanceAddr) -> Result<Vec<MemAddr>> {
let mem_count = self.data.memories.len();
let mut mem_addrs = Vec::with_capacity(mem_count);
for (i, mem) in mems.into_iter().enumerate() {
for (i, mem) in memories.into_iter().enumerate() {
if let MemoryArch::I64 = mem.arch {
return Err(Error::UnsupportedFeature("64-bit memories".to_string()));
}
log::info!("adding memory: {:?}", mem);
self.data.mems.push(Rc::new(RefCell::new(MemoryInstance::new(mem, idx))));
self.data.memories.push(Rc::new(RefCell::new(MemoryInstance::new(mem, idx))));

mem_addrs.push((i + mem_count) as MemAddr);
}
Expand All @@ -175,16 +175,16 @@ impl Store {

/// Add elements to the store, returning their addresses in the store
/// Should be called after the tables have been added
pub(crate) fn init_elems(
pub(crate) fn init_elements(
&mut self,
table_addrs: &[TableAddr],
elems: Vec<Element>,
elements: Vec<Element>,
idx: ModuleInstanceAddr,
) -> Result<Box<[Addr]>> {
let elem_count = self.data.elems.len();
let elem_count = self.data.elements.len();
let mut elem_addrs = Vec::with_capacity(elem_count);
for (i, elem) in elems.into_iter().enumerate() {
let init = elem
for (i, element) in elements.into_iter().enumerate() {
let init = element
.items
.iter()
.map(|item| {
Expand All @@ -194,7 +194,7 @@ impl Store {
})
.collect::<Result<Vec<_>>>()?;

let items = match elem.kind {
let items = match element.kind {
// doesn't need to be initialized, can be initialized lazily using the `table.init` instruction
ElementKind::Passive => Some(init),

Expand Down Expand Up @@ -228,7 +228,7 @@ impl Store {
}
};

self.data.elems.push(ElemInstance::new(elem.kind, idx, items));
self.data.elements.push(ElementInstance::new(element.kind, idx, items));
elem_addrs.push((i + elem_count) as Addr);
}

Expand Down Expand Up @@ -262,7 +262,7 @@ impl Store {
let offset = self.eval_i32_const(&offset)?;

let mem =
self.data.mems.get_mut(mem_addr as usize).ok_or_else(|| {
self.data.memories.get_mut(mem_addr as usize).ok_or_else(|| {
Error::Other(format!("memory {} not found for data segment {}", mem_addr, i))
})?;

Expand Down Expand Up @@ -296,8 +296,8 @@ impl Store {
if let MemoryArch::I64 = mem.arch {
return Err(Error::UnsupportedFeature("64-bit memories".to_string()));
}
self.data.mems.push(Rc::new(RefCell::new(MemoryInstance::new(mem, idx))));
Ok(self.data.mems.len() as MemAddr - 1)
self.data.memories.push(Rc::new(RefCell::new(MemoryInstance::new(mem, idx))));
Ok(self.data.memories.len() as MemAddr - 1)
}

pub(crate) fn add_func(&mut self, func: Function, type_idx: TypeAddr, idx: ModuleInstanceAddr) -> Result<FuncAddr> {
Expand Down Expand Up @@ -348,7 +348,7 @@ impl Store {

/// Get the memory at the actual index in the store
pub(crate) fn get_mem(&self, addr: usize) -> Result<&Rc<RefCell<MemoryInstance>>> {
self.data.mems.get(addr).ok_or_else(|| Error::Other(format!("memory {} not found", addr)))
self.data.memories.get(addr).ok_or_else(|| Error::Other(format!("memory {} not found", addr)))
}

/// Get the table at the actual index in the store
Expand All @@ -357,8 +357,8 @@ impl Store {
}

/// Get the element at the actual index in the store
pub(crate) fn get_elem(&self, addr: usize) -> Result<&ElemInstance> {
self.data.elems.get(addr).ok_or_else(|| Error::Other(format!("element {} not found", addr)))
pub(crate) fn get_elem(&self, addr: usize) -> Result<&ElementInstance> {
self.data.elements.get(addr).ok_or_else(|| Error::Other(format!("element {} not found", addr)))
}

/// Get the global at the actual index in the store
Expand Down Expand Up @@ -413,25 +413,29 @@ impl FunctionInstance {
/// See <https://webassembly.github.io/spec/core/exec/runtime.html#table-instances>
#[derive(Debug)]
pub(crate) struct TableInstance {
pub(crate) elements: Vec<Addr>,
pub(crate) elements: Vec<Option<Addr>>,
pub(crate) _kind: TableType,
pub(crate) _owner: ModuleInstanceAddr, // index into store.module_instances
}

impl TableInstance {
pub(crate) fn new(kind: TableType, owner: ModuleInstanceAddr) -> Self {
Self { elements: vec![0; kind.size_initial as usize], _kind: kind, _owner: owner }
Self { elements: vec![None; kind.size_initial as usize], _kind: kind, _owner: owner }
}

pub(crate) fn get(&self, addr: usize) -> Result<Addr> {
self.elements.get(addr).copied().ok_or_else(|| Trap::UndefinedElement { index: addr }.into())
self.elements
.get(addr)
.copied()
.ok_or_else(|| Error::Trap(Trap::UndefinedElement { index: addr }))
.map(|elem| elem.ok_or_else(|| Trap::UninitializedElement { index: addr }.into()))?
}

pub(crate) fn set(&mut self, addr: usize, value: Addr) -> Result<()> {
if addr >= self.elements.len() {
return Err(Error::Other(format!("table element {} not found", addr)));
}
self.elements[addr] = value;
self.elements[addr] = Some(value);
Ok(())
}

Expand All @@ -440,6 +444,8 @@ impl TableInstance {
}

pub(crate) fn init(&mut self, offset: i32, init: &[Addr]) -> Result<()> {
let init = init.iter().map(|item| Some(*item)).collect::<Vec<_>>();

let offset = offset as usize;
let end = offset.checked_add(init.len()).ok_or_else(|| {
Error::Trap(crate::Trap::TableOutOfBounds { offset, len: init.len(), max: self.elements.len() })
Expand All @@ -449,7 +455,7 @@ impl TableInstance {
return Err(crate::Trap::TableOutOfBounds { offset, len: init.len(), max: self.elements.len() }.into());
}

self.elements[offset..end].copy_from_slice(init);
self.elements[offset..end].copy_from_slice(&init);
Ok(())
}
}
Expand Down Expand Up @@ -573,13 +579,13 @@ impl GlobalInstance {
///
/// See <https://webassembly.github.io/spec/core/exec/runtime.html#element-instances>
#[derive(Debug)]
pub(crate) struct ElemInstance {
pub(crate) struct ElementInstance {
pub(crate) kind: ElementKind,
pub(crate) items: Option<Vec<u32>>, // none is the element was dropped
_owner: ModuleInstanceAddr, // index into store.module_instances
}

impl ElemInstance {
impl ElementInstance {
pub(crate) fn new(kind: ElementKind, owner: ModuleInstanceAddr, items: Option<Vec<u32>>) -> Self {
Self { kind, _owner: owner, items }
}
Expand Down
Loading

0 comments on commit 52eda3e

Please sign in to comment.