mirror of
https://github.com/fluencelabs/wasmer
synced 2025-05-16 20:41:19 +00:00
Add preliminary support for imports
This commit is contained in:
parent
93ef1e4220
commit
c06c65e7c6
11
Cargo.lock
generated
11
Cargo.lock
generated
@ -329,6 +329,15 @@ name = "glob"
|
||||
version = "0.2.11"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
[[package]]
|
||||
name = "hashbrown"
|
||||
version = "0.1.7"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"byteorder 1.2.7 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"scopeguard 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "indicatif"
|
||||
version = "0.10.3"
|
||||
@ -894,6 +903,7 @@ dependencies = [
|
||||
"errno 0.2.4 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"error-chain 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"field-offset 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"hashbrown 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"indicatif 0.10.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"libc 0.2.44 (git+https://github.com/rust-lang/libc)",
|
||||
"log 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
@ -978,6 +988,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
"checksum fuchsia-zircon-sys 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "3dcaa9ae7725d12cdb85b3ad99a434db70b468c09ded17e012d86b5c1010f7a7"
|
||||
"checksum gcc 0.3.55 (registry+https://github.com/rust-lang/crates.io-index)" = "8f5f3913fa0bfe7ee1fd8248b6b9f42a5af4b9d65ec2dd2c3c26132b950ecfc2"
|
||||
"checksum glob 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)" = "8be18de09a56b60ed0edf84bc9df007e30040691af7acd1c41874faac5895bfb"
|
||||
"checksum hashbrown 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)" = "64b7d419d0622ae02fe5da6b9a5e1964b610a65bb37923b976aeebb6dbb8f86e"
|
||||
"checksum indicatif 0.10.3 (registry+https://github.com/rust-lang/crates.io-index)" = "40ecd1e2ee08e6c255ce890f5a99d17000850e664e7acf119fb03b25b0575bfe"
|
||||
"checksum itoa 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)" = "1306f3464951f30e30d12373d31c79fbd52d236e5e896fd92f96ec7babbbe60b"
|
||||
"checksum lazy_static 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "a374c89b9db55895453a74c1e38861d9deec0b01b405a82516e9d5de4820dea1"
|
||||
|
@ -50,6 +50,7 @@ byteorder = "1"
|
||||
indicatif = "0.10"
|
||||
console = "0.7.1"
|
||||
field-offset = "0.1.1"
|
||||
hashbrown = "0.1"
|
||||
|
||||
[build-dependencies]
|
||||
wabt = "0.7.2"
|
||||
|
@ -5,11 +5,12 @@ use crate::runtime::{
|
||||
module::Module,
|
||||
types::FuncIndex,
|
||||
};
|
||||
use std::sync::Arc;
|
||||
|
||||
pub trait Compiler {
|
||||
fn compile(wasm: &[u8]) -> Box<Module>;
|
||||
fn compile(&self, wasm: &[u8]) -> Result<Arc<Module>, String>;
|
||||
}
|
||||
|
||||
pub trait FuncResolver {
|
||||
pub fn resolve(&self, index: FuncIndex) -> *const vm::Func;
|
||||
pub fn resolve(&self, index: FuncIndex) -> Option<*const vm::Func>;
|
||||
}
|
@ -1,16 +1,12 @@
|
||||
use super::vm;
|
||||
use crate::module::Module;
|
||||
use super::table::{TableBacking, TableScheme};
|
||||
use super::memory::LinearMemory;
|
||||
use super::instance::{InstanceOptions, InstanceABI};
|
||||
use std::mem;
|
||||
|
||||
use crate::runtime::{
|
||||
vm,
|
||||
module::Module,
|
||||
table::TableBacking,
|
||||
types::{Val, GlobalInit},
|
||||
memory::LinearMemory,
|
||||
instance::{Imports, Import},
|
||||
};
|
||||
use std::{ptr, mem};
|
||||
|
||||
|
||||
#[derive(Debug)]
|
||||
@ -24,9 +20,9 @@ pub struct LocalBacking {
|
||||
}
|
||||
|
||||
impl LocalBacking {
|
||||
pub fn new(module: &Module, imports: &ImportBacking, options: &InstanceOptions) -> Self {
|
||||
let mut memories = Self::generate_memories(module, options);
|
||||
let mut tables = Self::generate_tables(module, options);
|
||||
pub fn new(module: &Module, imports: &ImportBacking) -> Self {
|
||||
let mut memories = Self::generate_memories(module);
|
||||
let mut tables = Self::generate_tables(module);
|
||||
let globals = Self::generate_globals(module);
|
||||
|
||||
Self {
|
||||
@ -39,7 +35,7 @@ impl LocalBacking {
|
||||
}
|
||||
}
|
||||
|
||||
fn generate_memories(module: &Module, options: &InstanceOptions) -> Box<[LinearMemory]> {
|
||||
fn generate_memories(module: &Module) -> Box<[LinearMemory]> {
|
||||
let mut memories = Vec::with_capacity(module.memories.len());
|
||||
|
||||
for (_, mem) in &module.memories {
|
||||
@ -63,7 +59,7 @@ impl LocalBacking {
|
||||
memories.into_boxed_slice()
|
||||
}
|
||||
|
||||
fn finalize_memories(module: &Module, memories: &mut [LinearMemory], options: &InstanceOptions) -> Box<[vm::LocalMemory]> {
|
||||
fn finalize_memories(module: &Module, memories: &mut [LinearMemory]) -> Box<[vm::LocalMemory]> {
|
||||
for init in &module.data_initializers {
|
||||
debug_assert!(init.base.is_none(), "globalvar base not supported yet");
|
||||
let offset = init.offset;
|
||||
@ -78,16 +74,10 @@ impl LocalBacking {
|
||||
to_init.copy_from_slice(&init.data);
|
||||
}
|
||||
|
||||
if options.abi == InstanceABI::Emscripten {
|
||||
debug!("emscripten::setup memory");
|
||||
crate::apis::emscripten::emscripten_set_up_memory(&mut memories[0]);
|
||||
debug!("emscripten::finish setup memory");
|
||||
}
|
||||
|
||||
memories.iter_mut().map(|mem| mem.into_vm_memory()).collect::<Vec<_>>().into_boxed_slice()
|
||||
}
|
||||
|
||||
fn generate_tables(module: &Module, options: &InstanceOptions) -> Box<[TableBacking]> {
|
||||
fn generate_tables(module: &Module) -> Box<[TableBacking]> {
|
||||
let mut tables = Vec::with_capacity(module.tables.len());
|
||||
|
||||
for table in &module.tables {
|
||||
@ -98,7 +88,7 @@ impl LocalBacking {
|
||||
tables.into_boxed_slice()
|
||||
}
|
||||
|
||||
fn finalize_tables(module: &Module, tables: &[TableBacking], options: &InstanceOptions) -> Box<[vm::LocalTable]> {
|
||||
fn finalize_tables(module: &Module, tables: &[TableBacking]) -> Box<[vm::LocalTable]> {
|
||||
tables.iter().map(|table| table.into_vm_table()).collect::<Vec<_>>().into_boxed_slice()
|
||||
}
|
||||
|
||||
@ -196,4 +186,59 @@ pub struct ImportBacking {
|
||||
memories: Box<[vm::ImportedMemory]>,
|
||||
tables: Box<[vm::ImportedTable]>,
|
||||
globals: Box<[vm::ImportedGlobal]>,
|
||||
}
|
||||
|
||||
impl ImportBacking {
|
||||
pub fn new(module: &Module, imports: &Imports) -> Result<Self, String> {
|
||||
assert!(module.imported_memories.len() == 0, "imported memories not yet supported");
|
||||
assert!(module.imported_tables.len() == 0, "imported tables not yet supported");
|
||||
|
||||
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 import = imports.get(mod_name, item_name);
|
||||
if let Import::Func(func, signature) = import {
|
||||
if expected_sig == signature {
|
||||
functions.push(vm::ImportedFunc {
|
||||
func,
|
||||
vmctx: ptr::null_mut(),
|
||||
});
|
||||
} else {
|
||||
return Err(format!("unexpected signature for {}:{}", mod_name, item_name));
|
||||
}
|
||||
} else {
|
||||
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 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,
|
||||
},
|
||||
},
|
||||
});
|
||||
} else {
|
||||
return Err(format!("unexpected global type for {}:{}", mod_name, item_name));
|
||||
}
|
||||
} else {
|
||||
return Err(format!("incorrect type for {}:{}", mod_name, item_name));
|
||||
}
|
||||
}
|
||||
|
||||
Ok(ImportBacking {
|
||||
functions: functions.into_boxed_slice(),
|
||||
memories: vec![].into_boxed_slice(),
|
||||
tables: vec![].into_boxed_slice(),
|
||||
globals: globals.into_boxed_slice(),
|
||||
})
|
||||
}
|
||||
}
|
@ -1,26 +1,63 @@
|
||||
use crate::runtime::{
|
||||
vm,
|
||||
backing::{LocalBacking, ImportBacking},
|
||||
module::{ModuleName, ItemName},
|
||||
types::{Val, Memory, Table, Global, FuncSig},
|
||||
table::TableBacking,
|
||||
memory::LinearMemory,
|
||||
};
|
||||
use std::sync::Arc;
|
||||
use hashbrown::{HashMap, Entry};
|
||||
|
||||
pub struct Instance {
|
||||
pub vmctx: vm::Ctx,
|
||||
|
||||
pub finalized_funcs: Box<[*const vm::Func]>,
|
||||
|
||||
pub backing: LocalBacking,
|
||||
pub imports: ImportBacking,
|
||||
backing: LocalBacking,
|
||||
imports: ImportBacking,
|
||||
|
||||
pub module: Arc<Module>,
|
||||
}
|
||||
|
||||
impl Instance {
|
||||
pub fn new(module: Arc<Module>) -> Box<Instance> {
|
||||
pub fn new(module: Arc<Module>, imports: &Imports) -> Result<Box<Instance>, String> {
|
||||
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);
|
||||
|
||||
Box::new(Instance {
|
||||
Ok(Box::new(Instance {
|
||||
vmctx,
|
||||
finalized_funcs
|
||||
})
|
||||
backing,
|
||||
import_backing,
|
||||
module,
|
||||
}))
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, PartialEq, Eq)]
|
||||
pub enum Import {
|
||||
Func(*const vm::Func, FuncSig),
|
||||
Table(Arc<TableBacking>, Table),
|
||||
Memory(Arc<LinearMemory>, Memory),
|
||||
Global(Val),
|
||||
}
|
||||
|
||||
pub struct Imports {
|
||||
map: HashMap<ModuleName, HashMap<ItemName, Import>>,
|
||||
}
|
||||
|
||||
impl Imports {
|
||||
pub fn new() -> Self {
|
||||
Self {
|
||||
map: HashMap::new(),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn add(&mut self, module: ModuleName, name: ItemName, import: 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))
|
||||
}
|
||||
}
|
@ -238,9 +238,4 @@ impl DerefMut for LinearMemory {
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn round_up_to_page_size(size: usize) -> usize {
|
||||
let page_size = region::page::size();
|
||||
(size + (page_size - 1)) & !(page_size - 1)
|
||||
}
|
@ -1,9 +1,20 @@
|
||||
|
||||
pub mod vm;
|
||||
pub mod backing;
|
||||
pub mod types;
|
||||
pub mod memory;
|
||||
pub mod backend;
|
||||
pub mod module;
|
||||
pub mod instance;
|
||||
pub mod table;
|
||||
mod backing;
|
||||
mod types;
|
||||
mod memory;
|
||||
mod backend;
|
||||
mod module;
|
||||
mod instance;
|
||||
mod table;
|
||||
mod sig_registry;
|
||||
|
||||
pub use backend::Compiler;
|
||||
pub use instance::{Instance, Imports, Import};
|
||||
pub use 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> {
|
||||
let module = compiler.compile(wasm)?;
|
||||
Instance::new(module, imports)
|
||||
}
|
@ -1,7 +1,7 @@
|
||||
use crate::runtime::types::{
|
||||
Map,
|
||||
FuncIndex, MemoryIndex, TableIndex, GlobalIndex,
|
||||
Memory, Globals, GlobalDesc, Func, Table,
|
||||
Memory, Globals, GlobalDesc, FuncSig, Table,
|
||||
};
|
||||
use crate::runtime::backend::FuncResolver;
|
||||
|
||||
@ -13,7 +13,7 @@ pub struct Module {
|
||||
pub globals: Map<Global, GlobalIndex>,
|
||||
pub tables: Map<Table, TableIndex>,
|
||||
|
||||
pub imported_functions: Map<(ImportName, Func), FuncIndex>,
|
||||
pub imported_functions: Map<ImportName, FuncIndex>,
|
||||
pub imported_memories: Map<(ImportName, Memory), MemoryIndex>,
|
||||
pub imported_tables: Map<(ImportName, Table), TableIndex>,
|
||||
pub imported_globals: Map<(ImportName, GlobalDesc), GlobalIndex>,
|
||||
@ -23,7 +23,7 @@ pub struct Module {
|
||||
pub data_initializers: Vec<DataInitializer>,
|
||||
pub start_func: FuncIndex,
|
||||
|
||||
pub signatures: Map<Func, FuncIndex>,
|
||||
pub signatures: Map<FuncSig, FuncIndex>,
|
||||
}
|
||||
|
||||
pub type ModuleName = Vec<u8>;
|
||||
|
5
src/runtime/sig_registry.rs
Normal file
5
src/runtime/sig_registry.rs
Normal file
@ -0,0 +1,5 @@
|
||||
|
||||
|
||||
pub struct SignatureRegistry {
|
||||
|
||||
}
|
@ -25,6 +25,17 @@ pub enum Val {
|
||||
F64(u64),
|
||||
}
|
||||
|
||||
impl Val {
|
||||
pub fn ty(&self) -> Type {
|
||||
match self {
|
||||
Val::I32(_) => Type::I32,
|
||||
Val::I64(_) => Type::I64,
|
||||
Val::F32(_) => Type::F32,
|
||||
Val::F64(_) => Type::F64,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl From<i32> for Val {
|
||||
fn from(n: i32) -> Self {
|
||||
Self::I32(n)
|
||||
@ -105,8 +116,8 @@ impl Memory {
|
||||
}
|
||||
|
||||
/// A wasm func.
|
||||
#[derive(Debug)]
|
||||
pub struct Func {
|
||||
#[derive(Debug, PartialEq, Eq)]
|
||||
pub struct FuncSig {
|
||||
pub params: Vec<Type>,
|
||||
pub returns: Vec<Type>,
|
||||
}
|
||||
|
@ -1,19 +1,22 @@
|
||||
use std::{ptr, mem};
|
||||
use crate::runtime::types::{
|
||||
MemoryIndex, TableIndex, GlobalIndex, FuncIndex,
|
||||
SignatureIndex,
|
||||
use crate::runtime::{
|
||||
types::{
|
||||
MemoryIndex, TableIndex, GlobalIndex, FuncIndex,
|
||||
SignatureIndex,
|
||||
},
|
||||
backing::{LocalBacking, ImportBacking},
|
||||
};
|
||||
|
||||
#[derive(Debug)]
|
||||
#[repr(C)]
|
||||
pub struct Ctx<'a> {
|
||||
/// A pointer to an array of locally-defined memories, indexed by `DefinedMemoryIndex`.
|
||||
/// A pointer to an array of locally-defined memories, indexed by `MemoryIndex`.
|
||||
pub memories: *mut LocalMemory,
|
||||
|
||||
/// A pointer to an array of locally-defined tables, indexed by `DefinedTableIndex`.
|
||||
/// A pointer to an array of locally-defined tables, indexed by `TableIndex`.
|
||||
pub tables: *mut LocalTable,
|
||||
|
||||
/// A pointer to an array of locally-defined globals, indexed by `DefinedGlobalIndex`.
|
||||
/// A pointer to an array of locally-defined globals, indexed by `GlobalIndex`.
|
||||
pub globals: *mut LocalGlobal,
|
||||
|
||||
/// A pointer to an array of imported memories, indexed by `MemoryIndex,
|
||||
@ -34,23 +37,19 @@ pub struct Ctx<'a> {
|
||||
|
||||
impl Ctx {
|
||||
pub fn new(
|
||||
memories: *mut LocalMemory,
|
||||
tables: *mut LocalTable,
|
||||
globals: *mut LocalGlobal,
|
||||
imported_memories: *mut ImportedMemory,
|
||||
imported_tables: *mut ImportedTable,
|
||||
imported_globals: *mut ImportedGlobal,
|
||||
imported_funcs: *mut ImportedFunc,
|
||||
local_backing: &mut LocalBacking,
|
||||
import_backing: &mut ImportBacking,
|
||||
sig_ids: *mut SigId,
|
||||
) -> Self {
|
||||
Self {
|
||||
memories,
|
||||
tables,
|
||||
globals,
|
||||
imported_memories,
|
||||
imported_tables,
|
||||
imported_globals,
|
||||
imported_funcs,
|
||||
memories: local_backing.vm_memories.as_mut_ptr(),
|
||||
tables: local_backing.vm_tables.as_mut_ptr(),
|
||||
globals: local_backing.vm_globals.as_mut_ptr(),
|
||||
|
||||
imported_memories: import_backing.memories.as_mut_ptr(),
|
||||
imported_tables: import_backing.tables.as_mut_ptr(),
|
||||
imported_funcs: import_backing.functions.as_mut_ptr(),
|
||||
|
||||
sig_ids,
|
||||
}
|
||||
}
|
||||
@ -98,17 +97,12 @@ pub enum Func {}
|
||||
#[repr(C)]
|
||||
pub struct ImportedFunc {
|
||||
pub func: *const Func,
|
||||
pub vmctx: *mut Ctx,
|
||||
}
|
||||
|
||||
impl ImportedFunc {
|
||||
pub fn offset_func() -> u8 {
|
||||
0 * (mem::size_of::<usize>() as u8)
|
||||
}
|
||||
|
||||
pub fn offset_vmctx() -> u8 {
|
||||
1 * (mem::size_of::<usize>() as u8)
|
||||
}
|
||||
}
|
||||
|
||||
/// Definition of a table used by the VM. (obviously)
|
||||
@ -205,11 +199,11 @@ impl LocalGlobal {
|
||||
#[derive(Debug, Clone)]
|
||||
#[repr(C)]
|
||||
pub struct ImportedGlobal {
|
||||
pub global: *mut LocalGlobal,
|
||||
pub global: LocalGlobal,
|
||||
}
|
||||
|
||||
impl ImportedGlobal {
|
||||
pub fn offset_global() -> u8 {
|
||||
pub fn offset_data() -> u8 {
|
||||
0 * (mem::size_of::<usize>() as u8)
|
||||
}
|
||||
}
|
||||
@ -314,10 +308,10 @@ mod vm_offset_tests {
|
||||
offset_of!(ImportedFunc => func).get_byte_offset(),
|
||||
);
|
||||
|
||||
assert_eq!(
|
||||
ImportedFunc::offset_vmctx() as usize,
|
||||
offset_of!(ImportedFunc => vmctx).get_byte_offset(),
|
||||
);
|
||||
// assert_eq!(
|
||||
// ImportedFunc::offset_vmctx() as usize,
|
||||
// offset_of!(ImportedFunc => vmctx).get_byte_offset(),
|
||||
// );
|
||||
}
|
||||
|
||||
#[test]
|
||||
@ -378,8 +372,8 @@ mod vm_offset_tests {
|
||||
#[test]
|
||||
fn imported_global() {
|
||||
assert_eq!(
|
||||
ImportedGlobal::offset_global() as usize,
|
||||
offset_of!(ImportedGlobal => global).get_byte_offset(),
|
||||
ImportedGlobal::offset_data() as usize,
|
||||
offset_of!(ImportedGlobal => global: LocalGlobal => data).get_byte_offset(),
|
||||
);
|
||||
}
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user