Split codegen into multiple modules

This commit is contained in:
Lachlan Sneff
2019-01-16 17:59:12 -08:00
parent 5872d879f9
commit bb9ed66cea
14 changed files with 1310 additions and 100 deletions

View File

@ -42,7 +42,7 @@ impl LocalBacking {
let vm_memories = Self::finalize_memories(module, imports, &mut memories);
let vm_tables = Self::finalize_tables(module, imports, &mut tables, vmctx);
let vm_globals = Self::finalize_globals(module, globals);
let vm_globals = Self::finalize_globals(module, imports, globals);
Self {
memories,
@ -86,16 +86,27 @@ impl LocalBacking {
.iter()
.filter(|init| init.data.len() > 0)
{
assert!(init.base.is_none(), "global base not supported yet");
let init_base = match init.base {
Initializer::Const(Value::I32(offset)) => offset as u32,
Initializer::Const(_) => panic!("a const initializer must be the i32 type"),
Initializer::GetGlobal(imported_global_index) => {
if module.imported_globals[imported_global_index].1.ty == Type::I32 {
unsafe { (*imports.globals[imported_global_index].global).data as u32 }
} else {
panic!("unsupported global type for initialzer")
}
}
} as usize;
match init.memory_index.local_or_import(module) {
LocalOrImport::Local(local_memory_index) => {
let memory_desc = &module.memories[local_memory_index];
let data_top = init.offset + init.data.len();
assert!(memory_desc.min as usize >= data_top);
let data_top = init_base + init.data.len();
println!("data_top: {}", data_top);
assert!((memory_desc.min * LinearMemory::PAGE_SIZE) as usize >= data_top);
let mem: &mut LinearMemory = &mut memories[local_memory_index];
let to_init = &mut mem[init.offset..init.offset + init.data.len()];
let to_init = &mut mem[init_base..init_base + init.data.len()];
to_init.copy_from_slice(&init.data);
}
LocalOrImport::Import(imported_memory_index) => {
@ -130,12 +141,12 @@ impl LocalBacking {
tables: &mut SliceMap<LocalTableIndex, TableBacking>,
vmctx: *mut vm::Ctx,
) -> BoxedMap<LocalTableIndex, vm::LocalTable> {
for init in &module.table_initializers {
for init in &module.elem_initializers {
let init_base = match init.base {
Initializer::Const(Value::I32(offset)) => offset as u32,
Initializer::Const(_) => panic!("a const initializer must be the i32 type"),
Initializer::GetGlobal(imported_global_index) => {
if module.imported_globals[imported_global_index].1.desc.ty == Type::I32 {
if module.imported_globals[imported_global_index].1.ty == Type::I32 {
unsafe { (*imports.globals[imported_global_index].global).data as u32 }
} else {
panic!("unsupported global type for initialzer")
@ -243,14 +254,20 @@ impl LocalBacking {
fn finalize_globals(
module: &ModuleInner,
imports: &ImportBacking,
mut globals: BoxedMap<LocalGlobalIndex, vm::LocalGlobal>,
) -> BoxedMap<LocalGlobalIndex, vm::LocalGlobal> {
for ((_, to), (_, from)) in globals.iter_mut().zip(module.globals.into_iter()) {
for ((_, to), (_, from)) in globals.iter_mut().zip(module.globals.iter()) {
to.data = match from.init {
Value::I32(x) => x as u64,
Value::I64(x) => x as u64,
Value::F32(x) => x.to_bits() as u64,
Value::F64(x) => x.to_bits(),
Initializer::Const(ref value) => match value {
Value::I32(x) => *x as u64,
Value::I64(x) => *x as u64,
Value::F32(x) => x.to_bits() as u64,
Value::F64(x) => x.to_bits(),
},
Initializer::GetGlobal(imported_global_index) => unsafe {
(*imports.globals[imported_global_index].global).data
},
};
}
@ -416,13 +433,13 @@ fn import_globals(
imports: &mut Imports,
) -> Result<BoxedMap<ImportedGlobalIndex, vm::ImportedGlobal>, String> {
let mut globals = Map::with_capacity(module.imported_globals.len());
for (_, (ImportName { namespace, name }, imported_global)) in &module.imported_globals {
for (_, (ImportName { namespace, name }, imported_global_desc)) in &module.imported_globals {
let import = imports
.get_namespace(namespace)
.and_then(|namespace| namespace.get_export(name));
match import {
Some(Export::Global { local, global }) => {
if global == imported_global.desc {
if global == *imported_global_desc {
globals.push(vm::ImportedGlobal {
global: local.inner(),
});

View File

@ -277,13 +277,16 @@ impl InstanceInner {
)
}
LocalOrImport::Import(imported_global_index) => {
let &(_, imported_global) = &module
let &(_, imported_global_desc) = &module
.imported_globals
.get(imported_global_index)
.expect("missing imported global index");
let vm::ImportedGlobal { global } =
&self.import_backing.globals[imported_global_index];
(unsafe { GlobalPointer::new(*global) }, imported_global.desc)
(
unsafe { GlobalPointer::new(*global) },
*imported_global_desc,
)
}
}
}

View File

@ -4,7 +4,7 @@ use crate::{
sig_registry::SigRegistry,
structures::Map,
types::{
FuncIndex, Global, GlobalIndex, ImportedFuncIndex, ImportedGlobal, ImportedGlobalIndex,
FuncIndex, Global, GlobalDesc, GlobalIndex, ImportedFuncIndex, ImportedGlobalIndex,
ImportedMemoryIndex, ImportedTableIndex, Initializer, LocalGlobalIndex, LocalMemoryIndex,
LocalTableIndex, Memory, MemoryIndex, SigIndex, Table, TableIndex,
},
@ -26,12 +26,13 @@ pub struct ModuleInner {
pub imported_functions: Map<ImportedFuncIndex, ImportName>,
pub imported_memories: Map<ImportedMemoryIndex, (ImportName, Memory)>,
pub imported_tables: Map<ImportedTableIndex, (ImportName, Table)>,
pub imported_globals: Map<ImportedGlobalIndex, (ImportName, ImportedGlobal)>,
pub imported_globals: Map<ImportedGlobalIndex, (ImportName, GlobalDesc)>,
pub exports: HashMap<String, ExportIndex>,
pub data_initializers: Vec<DataInitializer>,
pub table_initializers: Vec<TableInitializer>,
pub elem_initializers: Vec<TableInitializer>,
pub start_func: Option<FuncIndex>,
pub func_assoc: Map<FuncIndex, SigIndex>,
@ -82,10 +83,8 @@ pub enum ExportIndex {
pub struct DataInitializer {
/// The index of the memory to initialize.
pub memory_index: MemoryIndex,
/// Optionally a globalvalue base to initialize at.
pub base: Option<GlobalIndex>,
/// A constant offset to initialize at.
pub offset: usize,
/// Either a constant offset or a `get_global`
pub base: Initializer,
/// The initialization data.
pub data: Vec<u8>,
}

View File

@ -4,7 +4,7 @@ use std::{
marker::PhantomData,
mem,
ops::{Deref, DerefMut},
slice,
slice, vec,
};
/// Dense item map
@ -45,6 +45,10 @@ where
K::new(len)
}
pub fn next_index(&self) -> K {
K::new(self.len())
}
pub fn reserve_exact(&mut self, size: usize) {
self.elems.reserve_exact(size);
}
@ -105,6 +109,49 @@ where
}
}
pub struct IntoIter<K, V>
where
K: TypedIndex,
{
enumerated: iter::Enumerate<vec::IntoIter<V>>,
_marker: PhantomData<K>,
}
impl<K, V> IntoIter<K, V>
where
K: TypedIndex,
{
pub(in crate::structures) fn new(into_iter: vec::IntoIter<V>) -> Self {
Self {
enumerated: into_iter.enumerate(),
_marker: PhantomData,
}
}
}
impl<K, V> Iterator for IntoIter<K, V>
where
K: TypedIndex,
{
type Item = (K, V);
fn next(&mut self) -> Option<(K, V)> {
self.enumerated.next().map(|(i, v)| (K::new(i), v))
}
}
impl<K, V> IntoIterator for Map<K, V>
where
K: TypedIndex,
{
type Item = (K, V);
type IntoIter = IntoIter<K, V>;
fn into_iter(self) -> Self::IntoIter {
IntoIter::new(self.elems.into_iter())
}
}
impl<'a, K, V> IntoIterator for &'a Map<K, V>
where
K: TypedIndex,

View File

@ -7,6 +7,8 @@ pub use self::map::{Iter, IterMut, Map};
pub use self::slice::SliceMap;
pub trait TypedIndex {
#[doc(hidden)]
fn new(index: usize) -> Self;
#[doc(hidden)]
fn index(&self) -> usize;
}

View File

@ -101,23 +101,11 @@ pub struct GlobalDesc {
pub ty: Type,
}
#[derive(Debug, Clone, PartialEq)]
pub enum ImportedGlobalInit {
GetGlobal(ImportedGlobalIndex),
Import,
}
#[derive(Debug, Clone, PartialEq)]
pub struct ImportedGlobal {
pub desc: GlobalDesc,
pub init: ImportedGlobalInit,
}
/// A wasm global.
#[derive(Debug, Clone)]
pub struct Global {
pub desc: GlobalDesc,
pub init: Value,
pub init: Initializer,
}
/// A wasm memory.
@ -174,10 +162,12 @@ macro_rules! define_map_index {
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
pub struct $ty (u32);
impl TypedIndex for $ty {
#[doc(hidden)]
fn new(index: usize) -> Self {
$ty (index as _)
}
#[doc(hidden)]
fn index(&self) -> usize {
self.0 as usize
}
@ -247,10 +237,12 @@ define_local_or_import![
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
pub struct SigIndex(u32);
impl TypedIndex for SigIndex {
#[doc(hidden)]
fn new(index: usize) -> Self {
SigIndex(index as _)
}
#[doc(hidden)]
fn index(&self) -> usize {
self.0 as usize
}
@ -263,3 +255,22 @@ where
Local(T::Local),
Import(T::Import),
}
impl<T> LocalOrImport<T>
where
T: LocalImport,
{
pub fn local(self) -> Option<T::Local> {
match self {
LocalOrImport::Local(local) => Some(local),
LocalOrImport::Import(_) => None,
}
}
pub fn import(self) -> Option<T::Import> {
match self {
LocalOrImport::Import(import) => Some(import),
LocalOrImport::Local(_) => None,
}
}
}

View File

@ -127,6 +127,10 @@ impl LocalTable {
pub fn offset_current_elements() -> u8 {
1 * (mem::size_of::<usize>() as u8)
}
pub fn size() -> u8 {
mem::size_of::<Self>() as u8
}
}
#[derive(Debug, Clone)]
@ -146,6 +150,10 @@ impl ImportedTable {
pub fn offset_vmctx() -> u8 {
1 * (mem::size_of::<usize>() as u8)
}
pub fn size() -> u8 {
mem::size_of::<Self>() as u8
}
}
/// Definition of a memory used by the VM.
@ -166,6 +174,10 @@ impl LocalMemory {
pub fn offset_size() -> u8 {
1 * (mem::size_of::<usize>() as u8)
}
pub fn size() -> u8 {
mem::size_of::<Self>() as u8
}
}
#[derive(Debug, Clone)]
@ -184,6 +196,10 @@ impl ImportedMemory {
pub fn offset_vmctx() -> u8 {
1 * (mem::size_of::<usize>() as u8)
}
pub fn size() -> u8 {
mem::size_of::<Self>() as u8
}
}
/// Definition of a global used by the VM.
@ -257,6 +273,10 @@ impl Anyfunc {
pub fn offset_sig_id() -> u8 {
2 * (mem::size_of::<usize>() as u8)
}
pub fn size() -> u8 {
mem::size_of::<Self>() as u8
}
}
#[cfg(test)]