Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit c9ecfea

Browse files
feat: const instruction global get
Signed-off-by: Henry Gressmann <[email protected]>
1 parent 4223bb7 commit c9ecfea

File tree

6 files changed

+107
-68
lines changed

6 files changed

+107
-68
lines changed

crates/tinywasm/src/imports.rs

Lines changed: 38 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -257,17 +257,7 @@ impl Imports {
257257

258258
if let Some(addr) = self.modules.get(&name.module) {
259259
let instance = store.get_module_instance(*addr)?;
260-
let export_addr = instance.export(&import.name)?;
261-
262-
// TODO: validate kind and type
263-
match &export_addr {
264-
ExternVal::Global(_) => {}
265-
ExternVal::Table(_) => {}
266-
ExternVal::Mem(_) => {}
267-
ExternVal::Func(_) => {}
268-
}
269-
270-
return Some(ResolvedExtern::Store(export_addr));
260+
return Some(ResolvedExtern::Store(instance.export(&import.name)?));
271261
}
272262

273263
None
@@ -354,13 +344,43 @@ impl Imports {
354344
.into());
355345
}
356346

357-
// TODO: check if the type matches
358-
359-
match val {
360-
ExternVal::Global(g) => imports.globals.push(g),
361-
ExternVal::Table(t) => imports.tables.push(t),
362-
ExternVal::Mem(m) => imports.memories.push(m),
363-
ExternVal::Func(f) => imports.funcs.push(f),
347+
match (val, &import.kind) {
348+
(ExternVal::Global(global_addr), ImportKind::Global(ty)) => {
349+
let global = store.get_global(global_addr as usize)?;
350+
Self::compare_types(import, &global.borrow().ty, ty)?;
351+
imports.globals.push(global_addr);
352+
}
353+
(ExternVal::Table(table_addr), ImportKind::Table(ty)) => {
354+
let table = store.get_table(table_addr as usize)?;
355+
// TODO: do we need to check any limits?
356+
Self::compare_types(import, &table.borrow().kind.element_type, &ty.element_type)?;
357+
imports.tables.push(table_addr);
358+
}
359+
(ExternVal::Mem(memory_addr), ImportKind::Memory(ty)) => {
360+
let mem = store.get_mem(memory_addr as usize)?;
361+
// TODO: do we need to check any limits?
362+
Self::compare_types(import, &mem.borrow().kind.arch, &ty.arch)?;
363+
imports.memories.push(memory_addr);
364+
}
365+
(ExternVal::Func(func_addr), ImportKind::Function(ty)) => {
366+
let func = store.get_func(func_addr as usize)?;
367+
let import_func_type = module.data.func_types.get(*ty as usize).ok_or_else(|| {
368+
crate::LinkingError::IncompatibleImportType {
369+
module: import.module.to_string(),
370+
name: import.name.to_string(),
371+
}
372+
})?;
373+
374+
Self::compare_types(import, func.func.ty(), import_func_type)?;
375+
imports.funcs.push(func_addr);
376+
}
377+
_ => {
378+
return Err(crate::LinkingError::IncompatibleImportType {
379+
module: import.module.to_string(),
380+
name: import.name.to_string(),
381+
}
382+
.into());
383+
}
364384
}
365385
}
366386
}

crates/tinywasm/src/instance.rs

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -66,12 +66,13 @@ impl ModuleInstance {
6666
let data = module.data;
6767

6868
// TODO: check if the compiler correctly optimizes this to prevent wasted allocations
69-
addrs.globals.extend(store.init_globals(data.globals.into(), idx)?);
7069
addrs.funcs.extend(store.init_funcs(data.funcs.into(), idx)?);
7170
addrs.tables.extend(store.init_tables(data.table_types.into(), idx)?);
7271
addrs.memories.extend(store.init_memories(data.memory_types.into(), idx)?);
7372

74-
let (elem_addrs, elem_trapped) = store.init_elements(&addrs.tables, &addrs.funcs, data.elements.into(), idx)?;
73+
let global_addrs = store.init_globals(addrs.globals, data.globals.into(), idx)?;
74+
let (elem_addrs, elem_trapped) =
75+
store.init_elements(&addrs.tables, &addrs.funcs, &global_addrs, data.elements.into(), idx)?;
7576
let (data_addrs, data_trapped) = store.init_datas(&addrs.memories, data.data.into(), idx)?;
7677

7778
let instance = ModuleInstanceInner {
@@ -82,7 +83,7 @@ impl ModuleInstance {
8283
func_addrs: addrs.funcs.into_boxed_slice(),
8384
table_addrs: addrs.tables.into_boxed_slice(),
8485
mem_addrs: addrs.memories.into_boxed_slice(),
85-
global_addrs: addrs.globals.into_boxed_slice(),
86+
global_addrs: global_addrs.into_boxed_slice(),
8687
elem_addrs,
8788
data_addrs,
8889
func_start: data.start_func,

crates/tinywasm/src/store.rs

Lines changed: 61 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -158,13 +158,20 @@ impl Store {
158158
}
159159

160160
/// Add globals to the store, returning their addresses in the store
161-
pub(crate) fn init_globals(&mut self, globals: Vec<Global>, idx: ModuleInstanceAddr) -> Result<Vec<Addr>> {
161+
pub(crate) fn init_globals(
162+
&mut self,
163+
mut imported_globals: Vec<GlobalAddr>,
164+
new_globals: Vec<Global>,
165+
idx: ModuleInstanceAddr,
166+
) -> Result<Vec<Addr>> {
162167
let global_count = self.data.globals.len();
163-
let mut global_addrs = Vec::with_capacity(global_count);
164-
for (i, global) in globals.iter().enumerate() {
168+
imported_globals.reserve_exact(new_globals.len());
169+
let mut global_addrs = imported_globals;
170+
171+
for (i, global) in new_globals.iter().enumerate() {
165172
self.data.globals.push(Rc::new(RefCell::new(GlobalInstance::new(
166173
global.ty,
167-
self.eval_const(&global.init)?,
174+
self.eval_const(&global.init, &global_addrs)?,
168175
idx,
169176
))));
170177
global_addrs.push((i + global_count) as Addr);
@@ -173,27 +180,41 @@ impl Store {
173180
Ok(global_addrs)
174181
}
175182

183+
fn elem_addr(&self, item: &ElementItem, globals: &[Addr]) -> Result<Option<u32>> {
184+
let res = match item {
185+
ElementItem::Func(addr) => Some(*addr),
186+
ElementItem::Expr(ConstInstruction::RefFunc(addr)) => Some(*addr),
187+
ElementItem::Expr(ConstInstruction::RefNull(_ty)) => None,
188+
ElementItem::Expr(ConstInstruction::GlobalGet(addr)) => {
189+
let addr = globals.get(*addr as usize).copied().ok_or_else(|| {
190+
Error::Other(format!("global {} not found. This should have been caught by the validator", addr))
191+
})?;
192+
193+
let global = self.data.globals[addr as usize].clone();
194+
let val = global.borrow().value;
195+
Some(val.into())
196+
}
197+
_ => return Err(Error::UnsupportedFeature(format!("const expression other than ref: {:?}", item))),
198+
};
199+
200+
Ok(res)
201+
}
202+
176203
/// Add elements to the store, returning their addresses in the store
177204
/// Should be called after the tables have been added
178205
pub(crate) fn init_elements(
179206
&mut self,
180207
table_addrs: &[TableAddr],
181208
func_addrs: &[FuncAddr],
209+
global_addrs: &[Addr],
182210
elements: Vec<Element>,
183211
idx: ModuleInstanceAddr,
184212
) -> Result<(Box<[Addr]>, Option<Trap>)> {
185213
let elem_count = self.data.elements.len();
186214
let mut elem_addrs = Vec::with_capacity(elem_count);
187215
for (i, element) in elements.into_iter().enumerate() {
188-
let init = element
189-
.items
190-
.iter()
191-
.map(|item| {
192-
item.addr().ok_or_else(|| {
193-
Error::UnsupportedFeature(format!("const expression other than ref: {:?}", item))
194-
})
195-
})
196-
.collect::<Result<Vec<_>>>()?;
216+
let init =
217+
element.items.iter().map(|item| self.elem_addr(item, global_addrs)).collect::<Result<Vec<_>>>()?;
197218

198219
log::error!("element kind: {:?}", element.kind);
199220

@@ -330,16 +351,23 @@ impl Store {
330351
}
331352

332353
/// Evaluate a constant expression
333-
pub(crate) fn eval_const(&self, const_instr: &tinywasm_types::ConstInstruction) -> Result<RawWasmValue> {
354+
pub(crate) fn eval_const(
355+
&self,
356+
const_instr: &tinywasm_types::ConstInstruction,
357+
module_global_addrs: &[Addr],
358+
) -> Result<RawWasmValue> {
334359
use tinywasm_types::ConstInstruction::*;
335360
let val = match const_instr {
336361
F32Const(f) => RawWasmValue::from(*f),
337362
F64Const(f) => RawWasmValue::from(*f),
338363
I32Const(i) => RawWasmValue::from(*i),
339364
I64Const(i) => RawWasmValue::from(*i),
340365
GlobalGet(addr) => {
341-
let addr = *addr as usize;
342-
let global = self.data.globals[addr].clone();
366+
let addr = module_global_addrs.get(*addr as usize).copied().ok_or_else(|| {
367+
Error::Other(format!("global {} not found. This should have been caught by the validator", addr))
368+
})?;
369+
370+
let global = self.data.globals[addr as usize].clone();
343371
let val = global.borrow().value;
344372
val
345373
}
@@ -369,8 +397,16 @@ impl Store {
369397
self.data.elements.get(addr).ok_or_else(|| Error::Other(format!("element {} not found", addr)))
370398
}
371399

400+
/// Get the global at the actual index in the store
401+
pub(crate) fn get_global(&self, addr: usize) -> Result<&Rc<RefCell<GlobalInstance>>> {
402+
self.data.globals.get(addr).ok_or_else(|| Error::Other(format!("global {} not found", addr)))
403+
}
404+
372405
/// Get the global at the actual index in the store
373406
pub fn get_global_val(&self, addr: usize) -> Result<RawWasmValue> {
407+
log::error!("getting global: {}", addr);
408+
log::error!("globals: {:?}", self.data.globals);
409+
374410
self.data
375411
.globals
376412
.get(addr)
@@ -461,25 +497,18 @@ impl TableInstance {
461497
}
462498

463499
pub(crate) fn set(&mut self, table_idx: usize, value: Addr) -> Result<()> {
464-
self.grow_to_fit(table_idx + 1)
465-
.ok_or_else(|| {
466-
Error::Trap(crate::Trap::TableOutOfBounds { offset: table_idx, len: 1, max: self.elements.len() })
467-
})
468-
.and_then(|_| {
469-
self.elements[table_idx] = TableElement::Initialized(value);
470-
Ok(())
471-
})
500+
self.grow_to_fit(table_idx + 1).map(|_| self.elements[table_idx] = TableElement::Initialized(value))
472501
}
473502

474-
pub(crate) fn grow_to_fit(&mut self, new_size: usize) -> Option<()> {
503+
pub(crate) fn grow_to_fit(&mut self, new_size: usize) -> Result<()> {
475504
if new_size > self.elements.len() {
476-
if new_size <= self.kind.size_max.unwrap_or(MAX_TABLE_SIZE) as usize {
477-
self.elements.resize(new_size, TableElement::Uninitialized);
478-
} else {
479-
return None;
505+
if new_size > self.kind.size_max.unwrap_or(MAX_TABLE_SIZE) as usize {
506+
return Err(crate::Trap::TableOutOfBounds { offset: new_size, len: 1, max: self.elements.len() }.into());
480507
}
508+
509+
self.elements.resize(new_size, TableElement::Uninitialized);
481510
}
482-
Some(())
511+
Ok(())
483512
}
484513

485514
pub(crate) fn size(&self) -> i32 {
@@ -620,13 +649,13 @@ impl MemoryInstance {
620649
#[derive(Debug)]
621650
pub(crate) struct GlobalInstance {
622651
pub(crate) value: RawWasmValue,
623-
pub(crate) _ty: GlobalType,
652+
pub(crate) ty: GlobalType,
624653
pub(crate) _owner: ModuleInstanceAddr, // index into store.module_instances
625654
}
626655

627656
impl GlobalInstance {
628657
pub(crate) fn new(ty: GlobalType, value: RawWasmValue, owner: ModuleInstanceAddr) -> Self {
629-
Self { _ty: ty, value, _owner: owner }
658+
Self { ty, value, _owner: owner }
630659
}
631660
}
632661

0 commit comments

Comments
 (0)