Skip to content
This repository was archived by the owner on Oct 3, 2025. It is now read-only.

Commit dce86f8

Browse files
chore: progress on v2 tables
Signed-off-by: Henry Gressmann <mail@henrygressmann.de>
1 parent 9218c95 commit dce86f8

File tree

4 files changed

+99
-35
lines changed

4 files changed

+99
-35
lines changed

crates/tinywasm/src/runtime/interpreter/mod.rs

Lines changed: 40 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -507,9 +507,10 @@ impl<'store, 'stack> Executor<'store, 'stack> {
507507
fn exec_table_set(&mut self, table_index: u32) -> Result<()> {
508508
let table_idx = self.module.resolve_table_addr(table_index);
509509
let table = self.store.get_table(table_idx)?;
510-
let val = self.stack.values.pop()?.into();
510+
let val = self.stack.values.pop()?.as_reference();
511511
let idx = self.stack.values.pop()?.into();
512-
table.borrow_mut().set(idx, val)?;
512+
table.borrow_mut().set(idx, val.into())?;
513+
513514
Ok(())
514515
}
515516

@@ -557,18 +558,42 @@ impl<'store, 'stack> Executor<'store, 'stack> {
557558
#[inline(always)]
558559
// todo: this is just a placeholder, need to check the spec
559560
fn exec_table_grow(&mut self, table_index: u32) -> Result<()> {
560-
let table_idx = self.module.resolve_table_addr(table_index);
561-
let table = self.store.get_table(table_idx)?;
562-
let delta: i32 = self.stack.values.pop()?.into();
563-
let prev_size = table.borrow().size();
564-
table.borrow_mut().grow_to_fit((prev_size + delta) as usize)?;
565-
self.stack.values.push(prev_size.into());
561+
let table = self.store.get_table(self.module.resolve_table_addr(table_index))?;
562+
let sz = table.borrow().size();
563+
564+
let n: i32 = self.stack.values.pop()?.into();
565+
let val = self.stack.values.pop()?.as_reference();
566+
567+
match table.borrow_mut().grow(n, val.into()) {
568+
Ok(_) => self.stack.values.push(sz.into()),
569+
Err(_) => self.stack.values.push((-1_i32).into()),
570+
}
571+
566572
Ok(())
567573
}
568574

569575
#[inline(always)]
570-
fn exec_table_fill(&mut self, _table_index: u32) -> Result<()> {
571-
// TODO: implement
576+
fn exec_table_fill(&mut self, table_index: u32) -> Result<()> {
577+
let table = self.store.get_table(self.module.resolve_table_addr(table_index))?;
578+
579+
let n: i32 = self.stack.values.pop()?.into();
580+
let val = self.stack.values.pop()?.as_reference();
581+
let i: i32 = self.stack.values.pop()?.into();
582+
583+
if unlikely(i + n > table.borrow().size()) {
584+
return Err(Trap::TableOutOfBounds {
585+
offset: i as usize,
586+
len: n as usize,
587+
max: table.borrow().size() as usize,
588+
}
589+
.into());
590+
}
591+
592+
if n == 0 {
593+
return Ok(());
594+
}
595+
596+
table.borrow_mut().fill(self.module.func_addrs(), i as usize, n as usize, val.into())?;
572597
Ok(())
573598
}
574599

@@ -742,7 +767,11 @@ impl<'store, 'stack> Executor<'store, 'stack> {
742767
let table_idx: u32 = self.stack.values.pop()?.into();
743768
let table = table.borrow();
744769
assert!(table.kind.element_type == ValType::RefFunc, "table is not of type funcref");
745-
table.get(table_idx)?.addr().ok_or(Trap::UninitializedElement { index: table_idx as usize })?
770+
table
771+
.get(table_idx)
772+
.map_err(|_| Error::Trap(Trap::UndefinedElement { index: table_idx as usize }))?
773+
.addr()
774+
.ok_or(Trap::UninitializedElement { index: table_idx as usize })?
746775
};
747776

748777
let func_inst = self.store.get_func(func_ref)?;

crates/tinywasm/src/runtime/raw.rs

Lines changed: 14 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -31,14 +31,20 @@ impl RawWasmValue {
3131
ValType::F32 => WasmValue::F32(f32::from_bits(self.into())),
3232
ValType::F64 => WasmValue::F64(f64::from_bits(self.into())),
3333
ValType::V128 => panic!("RawWasmValue cannot be converted to V128"),
34-
ValType::RefExtern => match i64::from(self) {
35-
v if v < 0 => WasmValue::RefNull(ValType::RefExtern),
36-
addr => WasmValue::RefExtern(addr as u32),
37-
},
38-
ValType::RefFunc => match i64::from(self) {
39-
v if v < 0 => WasmValue::RefNull(ValType::RefFunc),
40-
addr => WasmValue::RefFunc(addr as u32),
41-
},
34+
ValType::RefExtern => {
35+
self.as_reference().map(WasmValue::RefExtern).unwrap_or(WasmValue::RefNull(ValType::RefExtern))
36+
}
37+
ValType::RefFunc => {
38+
self.as_reference().map(WasmValue::RefFunc).unwrap_or(WasmValue::RefNull(ValType::RefFunc))
39+
}
40+
}
41+
}
42+
43+
#[inline]
44+
pub(crate) fn as_reference(&self) -> Option<u32> {
45+
match i64::from(*self) {
46+
v if v < 0 => None,
47+
addr => Some(addr as u32),
4248
}
4349
}
4450
}

crates/tinywasm/src/store/table.rs

Lines changed: 44 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
use crate::{log, unlikely};
1+
use crate::log;
22
use crate::{Error, Result, Trap};
33
use alloc::{vec, vec::Vec};
44
use tinywasm_types::*;
@@ -36,8 +36,22 @@ impl TableInstance {
3636
})
3737
}
3838

39+
pub(crate) fn fill(&mut self, func_addrs: &[u32], addr: usize, len: usize, val: TableElement) -> Result<()> {
40+
let val = val.map(|addr| self.resolve_func_ref(func_addrs, addr));
41+
let end = addr.checked_add(len).ok_or_else(|| self.trap_oob(addr, len))?;
42+
if end > self.elements.len() {
43+
return Err(self.trap_oob(addr, len));
44+
}
45+
46+
self.elements[addr..end].fill(val);
47+
Ok(())
48+
}
49+
3950
pub(crate) fn get(&self, addr: TableAddr) -> Result<&TableElement> {
40-
self.elements.get(addr as usize).ok_or_else(|| Error::Trap(Trap::UndefinedElement { index: addr as usize }))
51+
// self.elements.get(addr as usize).ok_or_else(|| Error::Trap(Trap::UndefinedElement { index: addr as usize }))
52+
self.elements.get(addr as usize).ok_or_else(|| {
53+
Error::Trap(Trap::TableOutOfBounds { offset: addr as usize, len: 1, max: self.elements.len() })
54+
})
4155
}
4256

4357
pub(crate) fn copy_from_slice(&mut self, dst: usize, src: &[TableElement]) -> Result<()> {
@@ -81,19 +95,28 @@ impl TableInstance {
8195
Ok(())
8296
}
8397

84-
pub(crate) fn set(&mut self, table_idx: TableAddr, value: Addr) -> Result<()> {
85-
self.grow_to_fit(table_idx as usize + 1)
86-
.map(|_| self.elements[table_idx as usize] = TableElement::Initialized(value))
98+
pub(crate) fn set(&mut self, table_idx: TableAddr, value: TableElement) -> Result<()> {
99+
if table_idx as usize >= self.elements.len() {
100+
return Err(self.trap_oob(table_idx as usize, 1));
101+
}
102+
103+
self.elements[table_idx as usize] = value;
104+
Ok(())
87105
}
88106

89-
pub(crate) fn grow_to_fit(&mut self, new_size: usize) -> Result<()> {
90-
if new_size > self.elements.len() {
91-
if unlikely(new_size > self.kind.size_max.unwrap_or(MAX_TABLE_SIZE) as usize) {
92-
return Err(crate::Trap::TableOutOfBounds { offset: new_size, len: 1, max: self.elements.len() }.into());
93-
}
107+
pub(crate) fn grow(&mut self, n: i32, init: TableElement) -> Result<()> {
108+
let len = n + self.elements.len() as i32;
109+
let max = self.kind.size_max.unwrap_or(MAX_TABLE_SIZE) as i32;
94110

95-
self.elements.resize(new_size, TableElement::Uninitialized);
111+
if len > max {
112+
return Err(Error::Trap(crate::Trap::TableOutOfBounds {
113+
offset: len as usize,
114+
len: 1,
115+
max: self.elements.len(),
116+
}));
96117
}
118+
119+
self.elements.resize(len as usize, init);
97120
Ok(())
98121
}
99122

@@ -186,15 +209,21 @@ mod tests {
186209
let kind = dummy_table_type();
187210
let mut table_instance = TableInstance::new(kind, 0);
188211

189-
table_instance.set(0, 0).expect("Setting table element failed");
212+
table_instance.set(0, TableElement::Initialized(0)).expect("Setting table element failed");
213+
table_instance.set(1, TableElement::Uninitialized).expect("Setting table element failed");
190214

191215
match table_instance.get_wasm_val(0) {
192216
Ok(WasmValue::RefFunc(_)) => {}
193217
_ => assert!(false, "get_wasm_val failed to return the correct WasmValue"),
194218
}
195219

220+
match table_instance.get_wasm_val(1) {
221+
Ok(WasmValue::RefNull(ValType::RefFunc)) => {}
222+
_ => assert!(false, "get_wasm_val failed to return the correct WasmValue"),
223+
}
224+
196225
match table_instance.get_wasm_val(999) {
197-
Err(Error::Trap(Trap::UndefinedElement { .. })) => {}
226+
Err(Error::Trap(Trap::TableOutOfBounds { .. })) => {}
198227
_ => assert!(false, "get_wasm_val failed to handle undefined element correctly"),
199228
}
200229
}
@@ -204,7 +233,7 @@ mod tests {
204233
let kind = dummy_table_type();
205234
let mut table_instance = TableInstance::new(kind, 0);
206235

207-
let result = table_instance.set(0, 1);
236+
let result = table_instance.set(0, TableElement::Initialized(1));
208237
assert!(result.is_ok(), "Setting table element failed");
209238

210239
let elem = table_instance.get(0);
@@ -219,7 +248,7 @@ mod tests {
219248
let kind = dummy_table_type();
220249
let mut table_instance = TableInstance::new(kind, 0);
221250

222-
let result = table_instance.set(15, 1);
251+
let result = table_instance.set(15, TableElement::Initialized(1));
223252
assert!(result.is_ok(), "Table grow on set failed");
224253

225254
let size = table_instance.size();

0 commit comments

Comments
 (0)