Fix most compile-time errors

This commit is contained in:
Lachlan Sneff 2018-12-25 00:19:05 -05:00
parent fb04ba0bce
commit 5ce75fc0ad
11 changed files with 145 additions and 141 deletions

View File

@ -1,7 +1,5 @@
use std::ops::{Index, IndexMut};
use std::ptr::NonNull;
use std::marker::PhantomData;
use crate::runtime::types::MapIndex;
#[derive(Copy, Clone, Debug)]
#[repr(transparent)]
@ -105,41 +103,4 @@ impl<'a, T> From<&'a [T]> for BoundedSlice<T> {
len: slice.len(),
}
}
}
#[derive(Debug)]
#[repr(transparent)]
pub struct IndexedSlice<'a, T, I> {
ptr: NonNull<T>,
_phantom: PhantomData<I>,
}
impl<'a, T: 'a, I> IndexedSlice<T, I>
where
I: MapIndex,
{
pub(crate) fn new(ptr: *mut T) -> Self {
Self {
ptr: NonNull::new(ptr).unwrap(),
_phantom: PhantomData,
}
}
pub unsafe fn get(&self, index: I) -> &T {
let ptr = self.as_ptr();
&*ptr.add(index.index())
}
pub unsafe fn get_mut(&mut self, index: I) -> &mut T {
let ptr = self.as_mut_ptr();
&mut *ptr.add(index.index())
}
pub fn as_ptr(&self) -> *const T {
self.ptr.as_ptr()
}
pub fn as_mut_ptr(&mut self) -> *mut T {
self.ptr.as_ptr()
}
}

View File

@ -1,5 +1,4 @@
use crate::runtime::module::Module;
use crate::runtime::types::FuncIndex;
use crate::runtime::{
vm,
module::Module,
@ -12,5 +11,5 @@ pub trait Compiler {
}
pub trait FuncResolver {
pub fn resolve(&self, index: FuncIndex) -> Option<*const vm::Func>;
fn resolve(&self, index: FuncIndex) -> Option<*const vm::Func>;
}

View File

@ -2,11 +2,10 @@ use crate::runtime::{
vm,
module::Module,
table::TableBacking,
types::{Val, GlobalInit},
types::{Val, GlobalInit, MapIndex},
memory::LinearMemory,
instance::{Imports, Import},
};
use std::{ptr, mem};
#[derive(Debug)]
@ -14,9 +13,9 @@ pub struct LocalBacking {
memories: Box<[LinearMemory]>,
tables: Box<[TableBacking]>,
vm_memories: Box<[vm::LocalMemory]>,
vm_tables: Box<[vm::LocalTable]>,
vm_globals: Box<[vm::LocalGlobal]>,
pub vm_memories: Box<[vm::LocalMemory]>,
pub vm_tables: Box<[vm::LocalTable]>,
pub vm_globals: Box<[vm::LocalGlobal]>,
}
impl LocalBacking {
@ -29,8 +28,8 @@ impl LocalBacking {
memories,
tables,
vm_memories: Self::finalize_memories(module, &mut memories[..], options),
vm_tables: Self::finalize_tables(module, &mut tables[..], options),
vm_memories: Self::finalize_memories(module, &mut memories[..]),
vm_tables: Self::finalize_tables(module, &mut tables[..]),
vm_globals: Self::finalize_globals(module, imports, globals),
}
}
@ -42,7 +41,7 @@ impl LocalBacking {
// If we use emscripten, we set a fixed initial and maximum
debug!(
"Instance - init memory ({}, {:?})",
memory.min, memory.max
mem.min, mem.max
);
// let memory = if options.abi == InstanceABI::Emscripten {
// // We use MAX_PAGES, so at the end the result is:
@ -80,7 +79,7 @@ impl LocalBacking {
fn generate_tables(module: &Module) -> Box<[TableBacking]> {
let mut tables = Vec::with_capacity(module.tables.len());
for table in &module.tables {
for (_, table) in &module.tables {
let table_backing = TableBacking::new(table);
tables.push(table_backing);
}
@ -99,13 +98,13 @@ impl LocalBacking {
}
fn finalize_globals(module: &Module, imports: &ImportBacking, globals: Box<[vm::LocalGlobal]>) -> Box<[vm::LocalGlobal]> {
for (to, from) in globals.iter_mut().zip(module.globals.iter()) {
*to = match from.init {
for (to, (_, from)) in globals.iter_mut().zip(module.globals.into_iter()) {
to.data = match from.init {
GlobalInit::Val(Val::I32(x)) => x as u64,
GlobalInit::Val(Val::I64(x)) => x as u64,
GlobalInit::Val(Val::F32(x)) => x as u64,
GlobalInit::Val(Val::F64(x)) => x,
GlobalInit::GetGlobal(index) => unsafe { (*imports.globals[index.index()].global).data },
GlobalInit::GetGlobal(index) => unsafe { (imports.globals[index.index()].global).data },
};
}
@ -182,10 +181,10 @@ impl LocalBacking {
#[derive(Debug)]
pub struct ImportBacking {
functions: Box<[vm::ImportedFunc]>,
memories: Box<[vm::ImportedMemory]>,
tables: Box<[vm::ImportedTable]>,
globals: Box<[vm::ImportedGlobal]>,
pub functions: Box<[vm::ImportedFunc]>,
pub memories: Box<[vm::ImportedMemory]>,
pub tables: Box<[vm::ImportedTable]>,
pub globals: Box<[vm::ImportedGlobal]>,
}
impl ImportBacking {
@ -195,42 +194,43 @@ impl ImportBacking {
let mut functions = Vec::with_capacity(module.imported_functions.len());
for (index, (mod_name, item_name)) in &module.imported_functions {
let expected_sig = module.signatures[index];
let expected_sig_index = module.signature_assoc[index];
let expected_sig = module.signatures[expected_sig_index];
let import = imports.get(mod_name, item_name);
if let Import::Func(func, signature) = import {
if expected_sig == signature {
if let Some(Import::Func(func, signature)) = import {
if &expected_sig == signature {
functions.push(vm::ImportedFunc {
func,
vmctx: ptr::null_mut(),
func: *func,
// vmctx: ptr::null_mut(),
});
} else {
return Err(format!("unexpected signature for {}:{}", mod_name, item_name));
return Err(format!("unexpected signature for {:?}:{:?}", mod_name, item_name));
}
} else {
return Err(format!("incorrect type for {}:{}", mod_name, item_name));
return Err(format!("incorrect type for {:?}:{:?}", mod_name, item_name));
}
}
let mut globals = Vec::with_capacity(module.imported_globals.len());
for (_, ((mod_name, item_name), global_desc)) in &module.imported_globals {
let import = imports.get(mod_name, item_name);
if let Import::Global(val) = import {
if let Some(Import::Global(val)) = import {
if val.ty() == global_desc.ty {
globals.push(vm::ImportedGlobal {
global: vm::LocalGlobal {
data: match val {
Val::I32(n) => n as u64,
Val::I64(n) => n as u64,
Val::F32(n) => n as u64,
Val::F64(n) => n,
Val::I32(n) => *n as u64,
Val::I64(n) => *n as u64,
Val::F32(n) => *n as u64,
Val::F64(n) => *n,
},
},
});
} else {
return Err(format!("unexpected global type for {}:{}", mod_name, item_name));
return Err(format!("unexpected global type for {:?}:{:?}", mod_name, item_name));
}
} else {
return Err(format!("incorrect type for {}:{}", mod_name, item_name));
return Err(format!("incorrect type for {:?}:{:?}", mod_name, item_name));
}
}

View File

@ -1,21 +1,24 @@
use crate::runtime::{
vm,
backing::{LocalBacking, ImportBacking},
module::{ModuleName, ItemName},
types::{Val, Memory, Table, Global, FuncSig},
module::{Module, ModuleName, ItemName},
types::{Val, Memory, Table, FuncSig},
table::TableBacking,
memory::LinearMemory,
sig_registry::SigRegistry,
};
use std::sync::Arc;
use hashbrown::{HashMap, Entry};
use hashbrown::HashMap;
pub struct Instance {
pub vmctx: vm::Ctx,
backing: LocalBacking,
imports: ImportBacking,
import_backing: ImportBacking,
pub module: Arc<Module>,
pub sig_registry: SigRegistry,
}
impl Instance {
@ -23,18 +26,21 @@ impl Instance {
let mut import_backing = ImportBacking::new(&*module, imports)?;
let mut backing = LocalBacking::new(&*module, &import_backing);
let vmctx = vm::Ctx::new(&mut backing, &mut imports);
let sig_registry = SigRegistry::new();
let vmctx = vm::Ctx::new(&mut backing, &mut import_backing, &sig_registry);
Ok(Box::new(Instance {
vmctx,
backing,
import_backing,
module,
sig_registry,
}))
}
}
#[derive(Debug, PartialEq, Eq)]
#[derive(Debug)]
pub enum Import {
Func(*const vm::Func, FuncSig),
Table(Arc<TableBacking>, Table),
@ -54,10 +60,10 @@ impl Imports {
}
pub fn add(&mut self, module: ModuleName, name: ItemName, import: Import) {
self.map.entry(module).or_insert(HashMap::new()).insert(name, import)
self.map.entry(module).or_insert(HashMap::new()).insert(name, import);
}
pub fn get(&self, module: ModuleName, name: ItemName) -> Option<&Import> {
self.map.get().and_then(|m| m.get(name))
pub fn get(&self, module: &[u8], name: &[u8]) -> Option<&Import> {
self.map.get(module).and_then(|m| m.get(name))
}
}

View File

@ -10,7 +10,7 @@ use std::slice;
use crate::common::mmap::Mmap;
use crate::runtime::{
vm::LocalMemory,
types::{Memory, Map, FuncIndex},
types::Memory,
};
/// A linear memory instance.
@ -62,7 +62,7 @@ impl LinearMemory {
assert!(!mem.shared, "shared memories must have a maximum size.");
(mem.min as usize * Self::PAGE_SIZE as usize, mem.min, 0, false)
}
};
let mut mmap = Mmap::with_size(mmap_size).unwrap();
@ -103,7 +103,7 @@ impl LinearMemory {
/// Returns the maximum number of wasm pages allowed.
pub fn maximum_size(&self) -> u32 {
self.maximum.unwrap_or(Self::MAX_PAGES)
self.max.unwrap_or(Self::MAX_PAGES)
}
pub fn into_vm_memory(&mut self) -> LocalMemory {
@ -131,7 +131,7 @@ impl LinearMemory {
None => return None,
};
if let Some(val) = self.maximum {
if let Some(val) = self.max {
if new_pages > val {
return None;
}
@ -147,7 +147,7 @@ impl LinearMemory {
if new_bytes > self.mmap.len() - self.offset_guard_size {
let mmap_size = new_bytes.checked_add(self.offset_guard_size)?;
let mut new_mmap = Mmap::with_size(request_bytes).ok()?;
let mut new_mmap = Mmap::with_size(mmap_size).ok()?;
unsafe {
region::protect(
@ -158,7 +158,7 @@ impl LinearMemory {
}
let copy_size = self.mmap.len() - self.offset_guard_size;
new_mmap.as_mut_slice()[..copy_size].copy_from_slice(self.mmap.as_slice()[..copy_size]);
new_mmap.as_mut_slice()[..copy_size].copy_from_slice(&self.mmap.as_slice()[..copy_size]);
self.mmap = new_mmap;
}
@ -182,7 +182,7 @@ impl LinearMemory {
None => return None,
};
if let Some(val) = self.maximum {
if let Some(val) = self.max {
if new_pages > val {
return None;
}
@ -213,7 +213,7 @@ impl LinearMemory {
// Not comparing based on memory content. That would be inefficient.
impl PartialEq for LinearMemory {
fn eq(&self, other: &LinearMemory) -> bool {
self.current == other.current && self.maximum == other.maximum
self.current == other.current && self.max == other.max
}
}

View File

@ -9,9 +9,9 @@ mod instance;
mod table;
mod sig_registry;
pub use backend::Compiler;
pub use instance::{Instance, Imports, Import};
pub use module::{ModuleName, ItemName, Module};
pub use self::backend::Compiler;
pub use self::instance::{Instance, Imports, Import};
pub use self::module::{ModuleName, ItemName, Module};
/// Compile a webassembly module using the provided compiler and linked with the provided imports.
pub fn compile(compiler: &dyn Compiler, wasm: &[u8], imports: &Imports) -> Result<Box<Instance>, String> {

View File

@ -1,12 +1,11 @@
use crate::runtime::types::{
Map,
FuncIndex, MemoryIndex, TableIndex, GlobalIndex,
Memory, Globals, GlobalDesc, FuncSig, Table,
FuncIndex, MemoryIndex, TableIndex, GlobalIndex, SigIndex,
Memory, Global, GlobalDesc, FuncSig, Table,
};
use crate::runtime::backend::FuncResolver;
/// This is used to instantiate a new webassembly module.
#[derive(Debug)]
pub struct Module {
pub functions: Box<dyn FuncResolver>,
pub memories: Map<Memory, MemoryIndex>,
@ -23,7 +22,8 @@ pub struct Module {
pub data_initializers: Vec<DataInitializer>,
pub start_func: FuncIndex,
pub signatures: Map<FuncSig, FuncIndex>,
pub signature_assoc: Map<SigIndex, FuncIndex>,
pub signatures: Map<FuncSig, SigIndex>,
}
pub type ModuleName = Vec<u8>;

View File

@ -1,5 +1,32 @@
use hashbrown::HashMap;
use crate::runtime::{
types::{Map, SigIndex, FuncSig},
vm,
};
pub struct SignatureRegistry {
pub struct SigRegistry {
sig_set: HashMap<FuncSig, vm::SigId>,
signatures: Map<vm::SigId, SigIndex>,
}
impl SigRegistry {
pub fn new() -> Self {
Self {
sig_set: HashMap::new(),
signatures: Map::new(),
}
}
pub fn into_vm_signatures(&self) -> *const vm::SigId {
self.signatures.as_ptr()
}
pub fn register(&mut self, signature: FuncSig, sig_index: SigIndex) {
let index = self.sig_set.len();
let vm_sig_id = *self.sig_set.entry(signature).or_insert_with(|| {
vm::SigId(index as u32)
});
self.signatures.push(vm_sig_id);
}
}

View File

@ -1,7 +1,7 @@
use super::vm;
use crate::runtime::types::{ElementType, Table};
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
#[derive(Debug, Clone)]
enum TableElements {
/// This is intended to be a caller-checked Anyfunc.
Anyfunc(Box<[vm::Anyfunc]>),
@ -18,7 +18,7 @@ impl TableBacking {
match table.ty {
ElementType::Anyfunc => {
Self {
elements: TableElements::Anyfunc(vec![vm::Anyfunc::null(); table.min].into_boxed_slice()),
elements: TableElements::Anyfunc(vec![vm::Anyfunc::null(); table.min as usize].into_boxed_slice()),
max: table.max,
}
}

View File

@ -1,7 +1,10 @@
use std::marker::PhantomData;
use std::{slice, iter};
use std::{
slice, iter,
ops::{Index, IndexMut},
};
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub enum Type {
/// The `i32` type.
I32,
@ -38,25 +41,25 @@ impl Val {
impl From<i32> for Val {
fn from(n: i32) -> Self {
Self::I32(n)
Val::I32(n)
}
}
impl From<i64> for Val {
fn from(n: i64) -> Self {
Self::I64(n)
Val::I64(n)
}
}
impl From<f32> for Val {
fn from(n: f32) -> Self {
Self::F32(n.to_bits())
Val::F32(n.to_bits())
}
}
impl From<f64> for Val {
fn from(n: f64) -> Self {
Self::I64(n.to_bits())
Val::F64(n.to_bits())
}
}
@ -116,7 +119,7 @@ impl Memory {
}
/// A wasm func.
#[derive(Debug, PartialEq, Eq)]
#[derive(Debug, PartialEq, Eq, Hash)]
pub struct FuncSig {
pub params: Vec<Type>,
pub returns: Vec<Type>,
@ -137,7 +140,10 @@ where
_marker: PhantomData<I>,
}
impl Map {
impl<T, I> Map<T, I>
where
I: MapIndex,
{
pub fn new() -> Self {
Self {
elems: Vec::new(),
@ -165,6 +171,10 @@ impl Map {
self.elems.push(value);
I::new(len)
}
pub fn as_ptr(&self) -> *const T {
self.elems.as_ptr()
}
}
impl<T, I> Index<I> for Map<T, I>
@ -206,13 +216,13 @@ where
type IntoIter = IterMut<'a, T, I>;
fn into_iter(self) -> Self::IntoIter {
Iter::new(self.elems.iter_mut())
IterMut::new(self.elems.iter_mut())
}
}
pub struct Iter<'a, T: 'a, I: MapIndex> {
enumerated: iter::Enumerate<slice::Iter<'A, T>>,
_marker: PhantomData,
enumerated: iter::Enumerate<slice::Iter<'a, T>>,
_marker: PhantomData<I>,
}
impl<'a, T: 'a, I: MapIndex> Iter<'a, T, I> {
@ -227,18 +237,18 @@ impl<'a, T: 'a, I: MapIndex> Iter<'a, T, I> {
impl<'a, T: 'a, I: MapIndex> Iterator for Iter<'a, T, I> {
type Item = (I, &'a T);
fn next(&mut self) -> Self::Item {
self.enumerated.next().map(|i, v| (I::new(i), v))
fn next(&mut self) -> Option<Self::Item> {
self.enumerated.next().map(|(i, v)| (I::new(i), v))
}
}
pub struct IterMut<'a, T: 'a, I: MapIndex> {
enumerated: iter::Enumerate<slice::Iter<'A, T>>,
_marker: PhantomData,
enumerated: iter::Enumerate<slice::IterMut<'a, T>>,
_marker: PhantomData<I>,
}
impl<'a, T: 'a, I: MapIndex> IterMut<'a, T, I> {
fn new(iter: slice::Iter<'a, T>) -> Self {
fn new(iter: slice::IterMut<'a, T>) -> Self {
Self {
enumerated: iter.enumerate(),
_marker: PhantomData,
@ -249,8 +259,8 @@ impl<'a, T: 'a, I: MapIndex> IterMut<'a, T, I> {
impl<'a, T: 'a, I: MapIndex> Iterator for IterMut<'a, T, I> {
type Item = (I, &'a mut T);
fn next(&mut self) -> Self::Item {
self.enumerated.next().map(|i, v| (I::new(i), v))
fn next(&mut self) -> Option<Self::Item> {
self.enumerated.next().map(|(i, v)| (I::new(i), v))
}
}
@ -268,7 +278,7 @@ macro_rules! define_map_index {
}
}
};
($($ty:ident),*) => {
($($ty:ident,)*) => {
$(
define_map_index!($ty);
)*
@ -277,5 +287,5 @@ macro_rules! define_map_index {
define_map_index![
FuncIndex, MemoryIndex, GlobalIndex, TableIndex,
SignatureIndex,
SigIndex,
];

View File

@ -1,15 +1,16 @@
use std::{ptr, mem};
use crate::runtime::{
types::{
MemoryIndex, TableIndex, GlobalIndex, FuncIndex,
SignatureIndex,
},
// types::{
// MemoryIndex, TableIndex, GlobalIndex, FuncIndex,
// SigIndex,
// },
backing::{LocalBacking, ImportBacking},
sig_registry::SigRegistry,
};
#[derive(Debug)]
#[repr(C)]
pub struct Ctx<'a> {
pub struct Ctx {
/// A pointer to an array of locally-defined memories, indexed by `MemoryIndex`.
pub memories: *mut LocalMemory,
@ -32,14 +33,14 @@ pub struct Ctx<'a> {
pub imported_funcs: *mut ImportedFunc,
/// Signature identifiers for signature-checked indirect calls.
pub sig_ids: *mut SigId,
pub signatures: *const SigId,
}
impl Ctx {
pub fn new(
local_backing: &mut LocalBacking,
import_backing: &mut ImportBacking,
sig_ids: *mut SigId,
sig_registry: &SigRegistry,
) -> Self {
Self {
memories: local_backing.vm_memories.as_mut_ptr(),
@ -48,9 +49,10 @@ impl Ctx {
imported_memories: import_backing.memories.as_mut_ptr(),
imported_tables: import_backing.tables.as_mut_ptr(),
imported_globals: import_backing.globals.as_mut_ptr(),
imported_funcs: import_backing.functions.as_mut_ptr(),
sig_ids,
signatures: sig_registry.into_vm_signatures(),
}
}
@ -82,7 +84,7 @@ impl Ctx {
6 * (mem::size_of::<usize>() as u8)
}
pub fn offset_sig_ids() -> u8 {
pub fn offset_signatures() -> u8 {
7 * (mem::size_of::<usize>() as u8)
}
}
@ -210,7 +212,7 @@ impl ImportedGlobal {
#[derive(Debug, Clone)]
#[repr(transparent)]
pub struct SigId(u32);
pub struct SigId(pub u32);
/// Caller-checked anyfunc
#[derive(Debug, Clone)]
@ -225,7 +227,6 @@ impl Anyfunc {
Self {
func_data: ImportedFunc {
func: ptr::null(),
vmctx: ptr::null_mut(),
},
sig_id: SigId(u32::max_value()),
}
@ -235,9 +236,9 @@ impl Anyfunc {
0 * (mem::size_of::<usize>() as u8)
}
pub fn offset_vmctx() -> u8 {
1 * (mem::size_of::<usize>() as u8)
}
// pub fn offset_vmctx() -> u8 {
// 1 * (mem::size_of::<usize>() as u8)
// }
pub fn offset_sig_id() -> u8 {
2 * (mem::size_of::<usize>() as u8)
@ -296,8 +297,8 @@ mod vm_offset_tests {
);
assert_eq!(
Ctx::offset_sig_ids() as usize,
offset_of!(Ctx => sig_ids).get_byte_offset(),
Ctx::offset_signatures() as usize,
offset_of!(Ctx => signatures).get_byte_offset(),
);
}
@ -384,10 +385,10 @@ mod vm_offset_tests {
offset_of!(Anyfunc => func_data: ImportedFunc => func).get_byte_offset(),
);
assert_eq!(
Anyfunc::offset_vmctx() as usize,
offset_of!(Anyfunc => func_data: ImportedFunc => vmctx).get_byte_offset(),
);
// assert_eq!(
// Anyfunc::offset_vmctx() as usize,
// offset_of!(Anyfunc => func_data: ImportedFunc => vmctx).get_byte_offset(),
// );
assert_eq!(
Anyfunc::offset_sig_id() as usize,