Add imported tables

This commit is contained in:
Brandon Fish
2019-01-13 10:46:04 -06:00
parent a9e58203f2
commit 902df8b303
4 changed files with 99 additions and 8 deletions

View File

@ -188,15 +188,11 @@ impl ImportBacking {
imports: &Imports,
vmctx: *mut vm::Ctx,
) -> Result<Self, String> {
assert!(
module.imported_tables.len() == 0,
"imported tables not yet supported"
);
Ok(ImportBacking {
functions: import_functions(module, imports, vmctx)?,
memories: import_memories(module, imports, vmctx)?,
tables: vec![].into_boxed_slice(),
tables: import_tables(module, imports, vmctx)?,
globals: import_globals(module, imports)?,
})
}
@ -246,6 +242,50 @@ fn import_memories(
Ok(memories.into_boxed_slice())
}
fn import_tables(
module: &ModuleInner,
imports: &Imports,
vmctx: *mut vm::Ctx,
) -> Result<Box<[vm::ImportedTable]>, String> {
let mut tables = Vec::with_capacity(module.imported_tables.len());
for (_index, (ImportName { namespace, name }, expected_table_desc)) in
&module.imported_tables
{
let table_import = imports
.get_namespace(namespace)
.and_then(|namespace| namespace.get_export(name));
match table_import {
Some(Export::Table {
local,
ctx,
table: table_desc,
}) => {
if expected_table_desc.fits_in_imported(&table_desc) {
tables.push(vm::ImportedTable {
table: local.inner(),
vmctx: match ctx {
Context::External(ctx) => ctx,
Context::Internal => vmctx,
},
});
} else {
return Err(format!(
"incorrect table description for {}:{}",
namespace, name,
));
}
}
Some(_) => {
return Err(format!("incorrect import type for {}:{}", namespace, name));
}
None => {
return Err(format!("import not found: {}:{}", namespace, name));
}
}
}
Ok(tables.into_boxed_slice())
}
fn import_functions(
module: &ModuleInner,
imports: &Imports,

View File

@ -1,10 +1,10 @@
use crate::recovery::call_protected;
use crate::{
backing::{ImportBacking, LocalBacking},
export::{Context, Export, ExportIter, FuncPointer, MemoryPointer},
export::{Context, Export, ExportIter, FuncPointer, MemoryPointer, TablePointer},
import::{Imports, Namespace},
module::{ExportIndex, Module, ModuleInner},
types::{FuncIndex, FuncSig, MapIndex, Memory, MemoryIndex, Type, Value},
types::{FuncIndex, FuncSig, MapIndex, Memory, MemoryIndex, Table, TableIndex, Type, Value},
vm,
};
use libffi::high::{arg as libffi_arg, call as libffi_call, CodePtr};
@ -168,7 +168,19 @@ impl Instance {
}
}
ExportIndex::Global(_global_index) => unimplemented!(),
ExportIndex::Table(_table_index) => unimplemented!(),
ExportIndex::Table(table_index) => {
let (local, ctx, table) = self.get_table_from_index(*table_index);
Export::Table {
local,
ctx: match ctx {
Context::Internal => {
Context::External(&*self.inner.vmctx as *const vm::Ctx as *mut vm::Ctx)
}
ctx @ Context::External(_) => ctx,
},
table,
}
},
}
}
@ -229,6 +241,35 @@ impl Instance {
)
}
}
fn get_table_from_index(&self, table_index: TableIndex) -> (TablePointer, Context, Table) {
if self.module.is_imported_table(table_index) {
let &(_, tab) = &self
.module
.imported_tables
.get(table_index)
.expect("missing imported table index");
let vm::ImportedTable { table, vmctx } =
&self.inner.import_backing.tables[table_index.index()];
(
unsafe { TablePointer::new(*table) },
Context::External(*vmctx),
*tab,
)
} else {
unimplemented!(); // TODO into_vm_tables requires &mut self
// let vm_table = &self.inner.backing.tables[table_index.index() as usize];
// (
// unsafe { TablePointer::new(&mut vm_table.into_vm_table()) },
// Context::Internal,
// *self
// .module
// .tables
// .get(table_index)
// .expect("broken invariant, tables"),
// )
}
}
}
impl Namespace for Instance {

View File

@ -56,6 +56,10 @@ impl ModuleInner {
pub(crate) fn is_imported_memory(&self, memory_index: MemoryIndex) -> bool {
memory_index.index() < self.imported_memories.len()
}
pub(crate) fn is_imported_table(&self, table_index: TableIndex) -> bool {
table_index.index() < self.imported_tables.len()
}
}
#[doc(hidden)]

View File

@ -80,6 +80,12 @@ pub struct Table {
pub max: Option<u32>,
}
impl Table {
pub(crate) fn fits_in_imported(&self, imported: &Table) -> bool {
self.max == imported.max && self.min <= imported.min
}
}
/// A global value initializer.
/// Overtime, this will be able to represent more and more
/// complex expressions.