run cargo fmt

This commit is contained in:
Syrus Akbary
2018-11-21 20:59:23 -08:00
parent ccdabd26b5
commit 38f045da3c
16 changed files with 283 additions and 243 deletions

View File

@ -1,20 +1,10 @@
/// NOTE: These syscalls only support wasm_32 for now because they take u32 offset
use libc::{
c_int,
c_void,
size_t,
ssize_t,
exit,
read,
open,
close,
};
use std::os::raw::c_char;
use std::ffi::CStr;
use super::super::host; use super::super::host;
/// NOTE: These syscalls only support wasm_32 for now because they take u32 offset
use libc::{c_int, c_void, close, exit, open, read, size_t, ssize_t};
use std::ffi::CStr;
use std::os::raw::c_char;
use crate::webassembly::{Instance}; use crate::webassembly::Instance;
/// emscripten: _getenv /// emscripten: _getenv
pub extern "C" fn _getenv(name_ptr: c_int, instance: &mut Instance) -> c_int { pub extern "C" fn _getenv(name_ptr: c_int, instance: &mut Instance) -> c_int {
@ -27,8 +17,6 @@ pub extern "C" fn _getenv(name_ptr: c_int, instance: &mut Instance) -> c_int {
Ok(_) => { Ok(_) => {
unimplemented!(); unimplemented!();
} }
Err(_) => { Err(_) => 0,
0
}
} }
} }

View File

@ -1,17 +1,20 @@
use libc::{ use libc::{c_void, memcpy, size_t};
c_void,
size_t,
memcpy,
};
use crate::webassembly::{Instance}; use crate::webassembly::Instance;
/// emscripten: _emscripten_memcpy_big /// emscripten: _emscripten_memcpy_big
pub extern "C" fn _emscripten_memcpy_big(dest: u32, src: u32, len: u32, instance: &mut Instance) -> u32 { pub extern "C" fn _emscripten_memcpy_big(
dest: u32,
src: u32,
len: u32,
instance: &mut Instance,
) -> u32 {
debug!("emscripten::_emscripten_memcpy_big"); debug!("emscripten::_emscripten_memcpy_big");
let dest_addr = instance.memory_offset_addr(0, dest as usize) as *mut c_void; let dest_addr = instance.memory_offset_addr(0, dest as usize) as *mut c_void;
let src_addr = instance.memory_offset_addr(0, src as usize) as *mut c_void; let src_addr = instance.memory_offset_addr(0, src as usize) as *mut c_void;
unsafe { memcpy(dest_addr, src_addr, len as size_t); } unsafe {
memcpy(dest_addr, src_addr, len as size_t);
}
dest dest
} }

View File

@ -2,35 +2,87 @@ use crate::webassembly::{ImportObject, ImportValue};
// EMSCRIPTEN APIS // EMSCRIPTEN APIS
mod env; mod env;
mod io;
mod memory; mod memory;
mod process; mod process;
mod io;
mod utils;
mod syscalls; mod syscalls;
mod utils;
// SYSCALLS // SYSCALLS
use super::host;
pub use self::utils::is_emscripten_module; pub use self::utils::is_emscripten_module;
use super::host;
pub fn generate_emscripten_env<'a, 'b>() -> ImportObject<&'a str, &'b str> { pub fn generate_emscripten_env<'a, 'b>() -> ImportObject<&'a str, &'b str> {
let mut import_object = ImportObject::new(); let mut import_object = ImportObject::new();
import_object.set("env", "printf", ImportValue::Func(io::printf as *const u8)); import_object.set("env", "printf", ImportValue::Func(io::printf as *const u8));
import_object.set("env", "putchar", ImportValue::Func(io::putchar as *const u8)); import_object.set(
"env",
"putchar",
ImportValue::Func(io::putchar as *const u8),
);
// Emscripten Env // Emscripten Env
import_object.set("env", "_getenv", ImportValue::Func(env::_getenv as *const u8)); import_object.set(
"env",
"_getenv",
ImportValue::Func(env::_getenv as *const u8),
);
// Emscripten syscalls // Emscripten syscalls
import_object.set("env", "___syscall3", ImportValue::Func(syscalls::___syscall3 as *const u8)); import_object.set(
import_object.set("env", "___syscall4", ImportValue::Func(syscalls::___syscall4 as *const u8)); "env",
import_object.set("env", "___syscall5", ImportValue::Func(syscalls::___syscall5 as *const u8)); "___syscall3",
import_object.set("env", "___syscall54", ImportValue::Func(syscalls::___syscall54 as *const u8)); ImportValue::Func(syscalls::___syscall3 as *const u8),
import_object.set("env", "___syscall122", ImportValue::Func(syscalls::___syscall122 as *const u8)); );
import_object.set(
"env",
"___syscall4",
ImportValue::Func(syscalls::___syscall4 as *const u8),
);
import_object.set(
"env",
"___syscall5",
ImportValue::Func(syscalls::___syscall5 as *const u8),
);
import_object.set(
"env",
"___syscall54",
ImportValue::Func(syscalls::___syscall54 as *const u8),
);
import_object.set(
"env",
"___syscall122",
ImportValue::Func(syscalls::___syscall122 as *const u8),
);
// Emscripten other APIs // Emscripten other APIs
import_object.set("env", "abort", ImportValue::Func(process::em_abort as *const u8)); import_object.set(
import_object.set("env", "_abort", ImportValue::Func(process::_abort as *const u8)); "env",
import_object.set("env", "abortOnCannotGrowMemory", ImportValue::Func(process::abort_on_cannot_grow_memory as *const u8)); "abort",
import_object.set("env", "_emscripten_memcpy_big", ImportValue::Func(memory::_emscripten_memcpy_big as *const u8)); ImportValue::Func(process::em_abort as *const u8),
import_object.set("env", "enlargeMemory", ImportValue::Func(memory::enlarge_memory as *const u8)); );
import_object.set("env", "getTotalMemory", ImportValue::Func(memory::get_total_memory as *const u8)); import_object.set(
"env",
"_abort",
ImportValue::Func(process::_abort as *const u8),
);
import_object.set(
"env",
"abortOnCannotGrowMemory",
ImportValue::Func(process::abort_on_cannot_grow_memory as *const u8),
);
import_object.set(
"env",
"_emscripten_memcpy_big",
ImportValue::Func(memory::_emscripten_memcpy_big as *const u8),
);
import_object.set(
"env",
"enlargeMemory",
ImportValue::Func(memory::enlarge_memory as *const u8),
);
import_object.set(
"env",
"getTotalMemory",
ImportValue::Func(memory::get_total_memory as *const u8),
);
import_object import_object
} }

View File

@ -1,14 +1,14 @@
use libc::{ use libc::{
// c_int,
// c_void,
c_char,
// size_t, // size_t,
// ssize_t, // ssize_t,
abort, abort,
// c_int,
// c_void,
c_char,
}; };
use crate::webassembly::Instance;
use std::ffi::CStr; use std::ffi::CStr;
use crate::webassembly::{Instance};
extern "C" fn abort_with_message(message: &str) { extern "C" fn abort_with_message(message: &str) {
debug!("emscripten::abort_with_message"); debug!("emscripten::abort_with_message");
@ -19,7 +19,9 @@ extern "C" fn abort_with_message(message: &str) {
/// emscripten: _abort /// emscripten: _abort
pub extern "C" fn _abort() { pub extern "C" fn _abort() {
debug!("emscripten::_abort"); debug!("emscripten::_abort");
unsafe { abort(); } unsafe {
abort();
}
} }
/// emscripten: abort /// emscripten: abort
@ -40,4 +42,3 @@ pub extern "C" fn abort_on_cannot_grow_memory() {
debug!("emscripten::abort_on_cannot_grow_memory"); debug!("emscripten::abort_on_cannot_grow_memory");
abort_with_message("Cannot enlarge memory arrays!"); abort_with_message("Cannot enlarge memory arrays!");
} }

View File

@ -1,23 +1,12 @@
/// NOTE: These syscalls only support wasm_32 for now because they take u32 offset /// NOTE: These syscalls only support wasm_32 for now because they take u32 offset
/// Syscall list: https://www.cs.utexas.edu/~bismith/test/syscalls/syscalls32.html /// Syscall list: https://www.cs.utexas.edu/~bismith/test/syscalls/syscalls32.html
use libc::{c_int, c_void, close, exit, open, read, size_t, ssize_t, write};
use libc::{
c_int,
c_void,
size_t,
ssize_t,
exit,
read,
write,
open,
close,
};
use std::{mem, ptr}; use std::{mem, ptr};
use std::os::raw::c_char;
use std::ffi::CStr; use std::ffi::CStr;
use std::os::raw::c_char;
use crate::webassembly::{Instance}; use crate::webassembly::Instance;
// A macro to retrieve variadic arguments given a varargs offset // A macro to retrieve variadic arguments given a varargs offset
macro_rules! vararg { macro_rules! vararg {
@ -58,7 +47,6 @@ pub extern "C" fn ___syscall5(which: c_int, varargs: c_int, instance: &mut Insta
-2 -2
} }
// sys_ioctl // sys_ioctl
#[no_mangle] #[no_mangle]
pub extern "C" fn ___syscall54(which: c_int, varargs: c_int, instance: &mut Instance) -> c_int { pub extern "C" fn ___syscall54(which: c_int, varargs: c_int, instance: &mut Instance) -> c_int {

View File

@ -10,12 +10,11 @@ pub fn is_emscripten_module(module: &Module) -> bool {
return false; return false;
} }
#[cfg(test)] #[cfg(test)]
mod tests { mod tests {
use crate::webassembly::instantiate;
use super::is_emscripten_module;
use super::super::generate_emscripten_env; use super::super::generate_emscripten_env;
use super::is_emscripten_module;
use crate::webassembly::instantiate;
#[test] #[test]
fn should_detect_emscripten_files() { fn should_detect_emscripten_files() {
@ -32,4 +31,4 @@ mod tests {
let result_object = instantiate(wasm_bytes, import_object).expect("Not compiled properly"); let result_object = instantiate(wasm_bytes, import_object).expect("Not compiled properly");
assert!(!is_emscripten_module(&result_object.module)); assert!(!is_emscripten_module(&result_object.module));
} }
} }

View File

@ -1,19 +1,9 @@
/// NOTE: These syscalls only support wasm_32 for now because they take u32 offset /// NOTE: These syscalls only support wasm_32 for now because they take u32 offset
use libc::{c_int, c_void, close, exit, open, read, size_t, ssize_t};
use libc::{
c_int,
c_void,
size_t,
ssize_t,
exit,
read,
open,
close,
};
use std::os::raw::c_char;
use std::ffi::CStr; use std::ffi::CStr;
use std::os::raw::c_char;
use crate::webassembly::{Instance}; use crate::webassembly::Instance;
use std::env; use std::env;
pub extern "C" fn get_env(name: &str, instance: &mut Instance) -> Result<String, env::VarError> { pub extern "C" fn get_env(name: &str, instance: &mut Instance) -> Result<String, env::VarError> {

View File

@ -1,5 +1,5 @@
pub mod syscalls;
pub mod env; pub mod env;
pub mod syscalls;
pub use self::syscalls::*;
pub use self::env::*; pub use self::env::*;
pub use self::syscalls::*;

View File

@ -11,17 +11,13 @@ impl<T> UncheckedSlice<T> {
#[inline] #[inline]
pub fn get_unchecked(&self, index: usize) -> &T { pub fn get_unchecked(&self, index: usize) -> &T {
let ptr = self.ptr.as_ptr(); let ptr = self.ptr.as_ptr();
unsafe { unsafe { &*ptr.add(index) }
&*ptr.add(index)
}
} }
#[inline] #[inline]
pub fn get_unchecked_mut(&mut self, index: usize) -> &mut T { pub fn get_unchecked_mut(&mut self, index: usize) -> &mut T {
let ptr = self.ptr.as_ptr(); let ptr = self.ptr.as_ptr();
unsafe { unsafe { &mut *(ptr.add(index) as *mut _) }
&mut *(ptr.add(index) as *mut _)
}
} }
pub unsafe fn dangling() -> UncheckedSlice<T> { pub unsafe fn dangling() -> UncheckedSlice<T> {

View File

@ -25,8 +25,8 @@ use structopt::StructOpt;
#[macro_use] #[macro_use]
mod macros; mod macros;
pub mod common;
pub mod apis; pub mod apis;
pub mod common;
pub mod sighandler; pub mod sighandler;
#[cfg(test)] #[cfg(test)]
mod spectests; mod spectests;
@ -83,17 +83,19 @@ fn execute_wasm(wasm_path: PathBuf) -> Result<(), String> {
Some(&webassembly::Export::Function(index)) => index, Some(&webassembly::Export::Function(index)) => index,
_ => panic!("_main emscripten function not found"), _ => panic!("_main emscripten function not found"),
}; };
let main: extern fn(u32, u32, &webassembly::Instance) = get_instance_function!(instance, func_index); let main: extern "C" fn(u32, u32, &webassembly::Instance) =
get_instance_function!(instance, func_index);
main(0, 0, &instance); main(0, 0, &instance);
} } else {
else { let func_index =
let func_index = instance instance
.start_func .start_func
.unwrap_or_else(|| match module.info.exports.get("main") { .unwrap_or_else(|| match module.info.exports.get("main") {
Some(&webassembly::Export::Function(index)) => index, Some(&webassembly::Export::Function(index)) => index,
_ => panic!("Main function not found"), _ => panic!("Main function not found"),
}); });
let main: extern fn(&webassembly::Instance) = get_instance_function!(instance, func_index); let main: extern "C" fn(&webassembly::Instance) =
get_instance_function!(instance, func_index);
main(&instance); main(&instance);
} }

View File

@ -3,10 +3,10 @@
//! or webassembly::Memory objects. //! or webassembly::Memory objects.
// Code inspired from: https://stackoverflow.com/a/45795699/1072990 // Code inspired from: https://stackoverflow.com/a/45795699/1072990
// Adapted to the Webassembly use case // Adapted to the Webassembly use case
use crate::webassembly::LinearMemory;
use std::borrow::Borrow; use std::borrow::Borrow;
use std::collections::HashMap; use std::collections::HashMap;
use std::hash::{Hash, Hasher}; use std::hash::{Hash, Hasher};
use crate::webassembly::LinearMemory;
// We introduced the Pair and BorrowedPair types. We can't use (A, B) // We introduced the Pair and BorrowedPair types. We can't use (A, B)
// directly due to the orphan rule E0210. This is fine since the map // directly due to the orphan rule E0210. This is fine since the map
@ -75,8 +75,7 @@ impl<A: Eq + Hash, B: Eq + Hash> ImportObject<A, B> {
} }
pub fn get(&self, a: &A, b: &B) -> Option<&ImportValue> { pub fn get(&self, a: &A, b: &B) -> Option<&ImportValue> {
self.map self.map.get(&BorrowedPair(a, b) as &KeyPair<A, B>)
.get(&BorrowedPair(a, b) as &KeyPair<A, B>)
} }
pub fn set(&mut self, a: A, b: B, v: ImportValue) { pub fn set(&mut self, a: A, b: B, v: ImportValue) {
@ -127,6 +126,9 @@ mod tests {
fn x() {} fn x() {}
let mut import_object = ImportObject::new(); let mut import_object = ImportObject::new();
import_object.set("abc", "def", ImportValue::Func(x as *const u8)); import_object.set("abc", "def", ImportValue::Func(x as *const u8));
assert_eq!(*import_object.get(&"abc", &"def").unwrap(), ImportValue::Func(x as *const u8)); assert_eq!(
*import_object.get(&"abc", &"def").unwrap(),
ImportValue::Func(x as *const u8)
);
} }
} }

View File

@ -6,28 +6,28 @@
//! synchronously instantiate a given webassembly::Module object. However, the //! synchronously instantiate a given webassembly::Module object. However, the
//! primary way to get an Instance is through the asynchronous //! primary way to get an Instance is through the asynchronous
//! webassembly::instantiate_streaming() function. //! webassembly::instantiate_streaming() function.
use cranelift_codegen::ir::{LibCall, Function}; use cranelift_codegen::ir::{Function, LibCall};
use cranelift_codegen::{binemit, Context};
use cranelift_codegen::isa::TargetIsa; use cranelift_codegen::isa::TargetIsa;
use cranelift_codegen::{binemit, Context};
use cranelift_entity::EntityRef; use cranelift_entity::EntityRef;
use cranelift_wasm::{FuncIndex, GlobalInit}; use cranelift_wasm::{FuncIndex, GlobalInit};
use rayon::prelude::*; use rayon::prelude::*;
use region; use region;
use std::iter::FromIterator;
use std::iter::Iterator; use std::iter::Iterator;
use std::mem::size_of;
use std::ptr::write_unaligned; use std::ptr::write_unaligned;
use std::slice; use std::slice;
use std::sync::Arc; use std::sync::Arc;
use std::iter::FromIterator;
use std::mem::size_of;
use super::super::common::slice::{BoundedSlice, UncheckedSlice}; use super::super::common::slice::{BoundedSlice, UncheckedSlice};
use super::errors::ErrorKind; use super::errors::ErrorKind;
use super::import_object::{ImportObject, ImportValue}; use super::import_object::{ImportObject, ImportValue};
use super::math_intrinsics;
use super::memory::LinearMemory; use super::memory::LinearMemory;
use super::module::{Export, ImportableExportable, Module}; use super::module::{Export, ImportableExportable, Module};
use super::relocation::{Reloc, RelocSink, RelocationType}; use super::relocation::{Reloc, RelocSink, RelocationType};
use super::math_intrinsics;
type TablesSlice = UncheckedSlice<BoundedSlice<usize>>; type TablesSlice = UncheckedSlice<BoundedSlice<usize>>;
type MemoriesSlice = UncheckedSlice<BoundedSlice<u8>>; type MemoriesSlice = UncheckedSlice<BoundedSlice<u8>>;
@ -114,7 +114,6 @@ pub struct DataPointers {
// Pointer to globals // Pointer to globals
pub globals: GlobalsSlice, pub globals: GlobalsSlice,
} }
pub struct InstanceOptions { pub struct InstanceOptions {
@ -125,7 +124,7 @@ pub struct InstanceOptions {
pub isa: Box<TargetIsa>, pub isa: Box<TargetIsa>,
} }
extern fn mock_fn() -> i32 { extern "C" fn mock_fn() -> i32 {
return 0; return 0;
} }
@ -135,7 +134,10 @@ struct CompiledFunction {
trap_sink: binemit::NullTrapSink, trap_sink: binemit::NullTrapSink,
} }
fn compile_function(isa: &TargetIsa, function_body: &Function) -> Result<CompiledFunction, ErrorKind> { fn compile_function(
isa: &TargetIsa,
function_body: &Function,
) -> Result<CompiledFunction, ErrorKind> {
let mut func_context = Context::for_function(function_body.to_owned()); let mut func_context = Context::for_function(function_body.to_owned());
let mut code_buf: Vec<u8> = Vec::new(); let mut code_buf: Vec<u8> = Vec::new();
@ -152,7 +154,7 @@ fn compile_function(isa: &TargetIsa, function_body: &Function) -> Result<Compile
Ok(CompiledFunction { Ok(CompiledFunction {
code_buf, code_buf,
reloc_sink, reloc_sink,
trap_sink trap_sink,
}) })
} }
@ -191,23 +193,24 @@ impl Instance {
// We walk through the imported functions and set the relocations // We walk through the imported functions and set the relocations
// for each of this functions to be an empty vector (as is defined outside of wasm) // for each of this functions to be an empty vector (as is defined outside of wasm)
for (module, field) in module.info.imported_funcs.iter() { for (module, field) in module.info.imported_funcs.iter() {
let imported = import_object let imported = import_object.get(&module.as_str(), &field.as_str());
.get(&module.as_str(), &field.as_str());
let function: &*const u8 = match imported { let function: &*const u8 = match imported {
Some(ImportValue::Func(f)) => f, Some(ImportValue::Func(f)) => f,
None => { None => {
if options.mock_missing_imports { if options.mock_missing_imports {
debug!("The import {}.{} is not provided, therefore will be mocked.", module, field); debug!(
"The import {}.{} is not provided, therefore will be mocked.",
module, field
);
&(mock_fn as *const u8) &(mock_fn as *const u8)
} } else {
else {
return Err(ErrorKind::LinkError(format!( return Err(ErrorKind::LinkError(format!(
"Imported function {}.{} was not provided in the import_functions", "Imported function {}.{} was not provided in the import_functions",
module, field module, field
))); )));
} }
}, }
other => panic!("Expected function import, received {:?}", other) other => panic!("Expected function import, received {:?}", other),
}; };
// println!("GET FUNC {:?}", function); // println!("GET FUNC {:?}", function);
import_functions.push(*function); import_functions.push(*function);
@ -218,15 +221,20 @@ impl Instance {
// Compile the functions (from cranelift IR to machine code) // Compile the functions (from cranelift IR to machine code)
let values: Vec<&Function> = Vec::from_iter(module.info.function_bodies.values()); let values: Vec<&Function> = Vec::from_iter(module.info.function_bodies.values());
// let isa: &TargetIsa = &*options.isa; // let isa: &TargetIsa = &*options.isa;
let compiled_funcs: Vec<CompiledFunction> = values.par_iter().map(|function_body| -> CompiledFunction { let compiled_funcs: Vec<CompiledFunction> = values
// let r = *Arc::from_raw(isa_ptr); .par_iter()
compile_function(&*options.isa, function_body).unwrap() .map(|function_body| -> CompiledFunction {
// unimplemented!() // let r = *Arc::from_raw(isa_ptr);
}).collect(); compile_function(&*options.isa, function_body).unwrap()
// unimplemented!()
}).collect();
for compiled_func in compiled_funcs.into_iter() { for compiled_func in compiled_funcs.into_iter() {
let CompiledFunction {code_buf, reloc_sink, ..} = compiled_func; let CompiledFunction {
code_buf,
reloc_sink,
..
} = compiled_func;
// let func_offset = code_buf; // let func_offset = code_buf;
protect_codebuf(&code_buf).unwrap(); protect_codebuf(&code_buf).unwrap();
@ -322,33 +330,39 @@ impl Instance {
}; };
for (i, global) in module.info.globals.iter().enumerate() { for (i, global) in module.info.globals.iter().enumerate() {
let ImportableExportable {entity, import_name, ..} = global; let ImportableExportable {
entity,
import_name,
..
} = global;
let value: i64 = match entity.initializer { let value: i64 = match entity.initializer {
GlobalInit::I32Const(n) => n as _, GlobalInit::I32Const(n) => n as _,
GlobalInit::I64Const(n) => n, GlobalInit::I64Const(n) => n,
GlobalInit::F32Const(f) => f as _, // unsafe { mem::transmute(f as f64) }, GlobalInit::F32Const(f) => f as _, // unsafe { mem::transmute(f as f64) },
GlobalInit::F64Const(f) => f as _, // unsafe { mem::transmute(f) }, GlobalInit::F64Const(f) => f as _, // unsafe { mem::transmute(f) },
GlobalInit::GlobalRef(global_index) => { GlobalInit::GlobalRef(global_index) => globals_data[global_index.index()],
globals_data[global_index.index()]
}
GlobalInit::Import() => { GlobalInit::Import() => {
let (module_name, field_name) = import_name.as_ref().expect("Expected a import name for the global import"); let (module_name, field_name) = import_name
let imported = import_object.get(&module_name.as_str(), &field_name.as_str()); .as_ref()
.expect("Expected a import name for the global import");
let imported =
import_object.get(&module_name.as_str(), &field_name.as_str());
match imported { match imported {
Some(ImportValue::Global(value)) => { Some(ImportValue::Global(value)) => *value,
*value
},
None => { None => {
if options.mock_missing_globals { if options.mock_missing_globals {
0 0
} else {
panic!(
"Imported global value was not provided ({}.{})",
module_name, field_name
)
} }
else {
panic!("Imported global value was not provided ({}.{})", module_name, field_name)
}
},
_ => {
panic!("Expected global import, but received {:?} ({}.{})", imported, module_name, field_name)
} }
_ => panic!(
"Expected global import, but received {:?} ({}.{})",
imported, module_name, field_name
),
} }
} }
}; };
@ -367,27 +381,29 @@ impl Instance {
for table in &module.info.tables { for table in &module.info.tables {
let table: Vec<usize> = match table.import_name.as_ref() { let table: Vec<usize> = match table.import_name.as_ref() {
Some((module_name, field_name)) => { Some((module_name, field_name)) => {
let imported = import_object.get(&module_name.as_str(), &field_name.as_str()); let imported =
import_object.get(&module_name.as_str(), &field_name.as_str());
match imported { match imported {
Some(ImportValue::Table(t)) => { Some(ImportValue::Table(t)) => t.to_vec(),
t.to_vec()
},
None => { None => {
if options.mock_missing_tables { if options.mock_missing_tables {
let len = table.entity.size; let len = table.entity.size;
let mut v = Vec::with_capacity(len); let mut v = Vec::with_capacity(len);
v.resize(len, 0); v.resize(len, 0);
v v
} else {
panic!(
"Imported table value was not provided ({}.{})",
module_name, field_name
)
} }
else {
panic!("Imported table value was not provided ({}.{})", module_name, field_name)
}
},
_ => {
panic!("Expected global table, but received {:?} ({}.{})", imported, module_name, field_name)
} }
_ => panic!(
"Expected global table, but received {:?} ({}.{})",
imported, module_name, field_name
),
} }
}, }
None => { None => {
let len = table.entity.size; let len = table.entity.size;
let mut v = Vec::with_capacity(len); let mut v = Vec::with_capacity(len);
@ -401,10 +417,8 @@ impl Instance {
// instantiate tables // instantiate tables
for table_element in &module.info.table_elements { for table_element in &module.info.table_elements {
let base = match table_element.base { let base = match table_element.base {
Some(global_index) => { Some(global_index) => globals_data[global_index.index()] as usize,
globals_data[global_index.index()] as usize None => 0,
},
None => 0
}; };
let table = &mut tables[table_element.table_index.index()]; let table = &mut tables[table_element.table_index.index()];
@ -430,10 +444,8 @@ impl Instance {
// Get memories in module // Get memories in module
for memory in &module.info.memories { for memory in &module.info.memories {
let memory = memory.entity; let memory = memory.entity;
let v = LinearMemory::new( let v =
memory.pages_count as u32, LinearMemory::new(memory.pages_count as u32, memory.maximum.map(|m| m as u32));
memory.maximum.map(|m| m as u32),
);
memories.push(v); memories.push(v);
} }
@ -458,10 +470,14 @@ impl Instance {
// TODO: Refactor repetitive code // TODO: Refactor repetitive code
let tables_pointer: Vec<BoundedSlice<usize>> = let tables_pointer: Vec<BoundedSlice<usize>> =
tables.iter().map(|table| table[..].into()).collect(); tables.iter().map(|table| table[..].into()).collect();
let memories_pointer: Vec<BoundedSlice<u8>> = let memories_pointer: Vec<BoundedSlice<u8>> = memories
memories.iter().map( .iter()
|mem| BoundedSlice::new(&mem[..], mem.current as usize * LinearMemory::WASM_PAGE_SIZE), .map(|mem| {
).collect(); BoundedSlice::new(
&mem[..],
mem.current as usize * LinearMemory::WASM_PAGE_SIZE,
)
}).collect();
let globals_pointer: GlobalsSlice = globals[..].into(); let globals_pointer: GlobalsSlice = globals[..].into();
let data_pointers = DataPointers { let data_pointers = DataPointers {
@ -518,9 +534,7 @@ impl Instance {
pub fn memory_offset_addr(&self, index: usize, offset: usize) -> *const usize { pub fn memory_offset_addr(&self, index: usize, offset: usize) -> *const usize {
let mem = &self.memories[index]; let mem = &self.memories[index];
unsafe { unsafe { mem.mmap.as_ptr().offset(offset as isize) as *const usize }
mem.mmap.as_ptr().offset(offset as isize) as *const usize
}
} }
// Shows the value of a global variable. // Shows the value of a global variable.
@ -550,9 +564,13 @@ extern "C" fn grow_memory(size: u32, memory_index: u32, instance: &mut Instance)
if old_mem_size != -1 { if old_mem_size != -1 {
// Get new memory bytes // Get new memory bytes
let new_mem_bytes = (old_mem_size as usize + size as usize) * LinearMemory::WASM_PAGE_SIZE; let new_mem_bytes = (old_mem_size as usize + size as usize) * LinearMemory::WASM_PAGE_SIZE;
// Update data_pointer // Update data_pointer
instance.data_pointers.memories.get_unchecked_mut(memory_index as usize).len = new_mem_bytes; instance
.data_pointers
.memories
.get_unchecked_mut(memory_index as usize)
.len = new_mem_bytes;
} }
old_mem_size old_mem_size

View File

@ -132,8 +132,7 @@ impl fmt::Debug for LinearMemory {
// Not comparing based on memory content. That would be inefficient. // Not comparing based on memory content. That would be inefficient.
impl PartialEq for LinearMemory { impl PartialEq for LinearMemory {
fn eq(&self, other: &LinearMemory) -> bool { fn eq(&self, other: &LinearMemory) -> bool {
self.current == other.current && self.current == other.current && self.maximum == other.maximum
self.maximum == other.maximum
} }
} }

View File

@ -1,19 +1,19 @@
pub mod errors; pub mod errors;
pub mod import_object; pub mod import_object;
pub mod instance; pub mod instance;
pub mod math_intrinsics;
pub mod memory; pub mod memory;
pub mod module; pub mod module;
pub mod relocation; pub mod relocation;
pub mod utils; pub mod utils;
pub mod math_intrinsics;
use cranelift_codegen::isa::TargetIsa;
use cranelift_codegen::{isa, settings};
use std::panic; use std::panic;
use std::str::FromStr; use std::str::FromStr;
use target_lexicon; use target_lexicon;
use wasmparser; use wasmparser;
use wasmparser::WasmDecoder; use wasmparser::WasmDecoder;
use cranelift_codegen::{isa, settings};
use cranelift_codegen::isa::TargetIsa;
pub use self::errors::{Error, ErrorKind}; pub use self::errors::{Error, ErrorKind};
pub use self::import_object::{ImportObject, ImportValue}; pub use self::import_object::{ImportObject, ImportValue};
@ -60,7 +60,7 @@ pub fn instantiate(
mock_missing_imports: true, mock_missing_imports: true,
mock_missing_globals: true, mock_missing_globals: true,
mock_missing_tables: true, mock_missing_tables: true,
isa: isa isa: isa,
}, },
)?; )?;
debug!("webassembly - instance created"); debug!("webassembly - instance created");

View File

@ -15,27 +15,14 @@ use cranelift_codegen::isa::{CallConv, TargetFrontendConfig};
use cranelift_entity::{EntityRef, PrimaryMap}; use cranelift_entity::{EntityRef, PrimaryMap};
use cranelift_wasm::{ use cranelift_wasm::{
translate_module, translate_module, DefinedFuncIndex, FuncEnvironment as FuncEnvironmentTrait, FuncIndex,
ReturnMode, FuncTranslator, Global, GlobalIndex, GlobalVariable, Memory, MemoryIndex, ModuleEnvironment,
DefinedFuncIndex, ReturnMode, SignatureIndex, Table, TableIndex, WasmResult,
FuncEnvironment as FuncEnvironmentTrait,
FuncIndex,
FuncTranslator,
Global,
GlobalIndex,
GlobalVariable,
Memory,
MemoryIndex,
ModuleEnvironment,
SignatureIndex,
Table,
TableIndex,
WasmResult,
}; };
use super::errors::ErrorKind; use super::errors::ErrorKind;
use super::memory::LinearMemory;
use super::instance::Instance; use super::instance::Instance;
use super::memory::LinearMemory;
/// Get the integer type used for representing pointers on this platform. /// Get the integer type used for representing pointers on this platform.
fn native_pointer_type() -> ir::Type { fn native_pointer_type() -> ir::Type {
@ -89,7 +76,7 @@ impl<T> ImportableExportable<T> {
Self { Self {
entity, entity,
export_names: Vec::new(), export_names: Vec::new(),
import_name: import_name import_name: import_name,
} }
} }
} }
@ -245,7 +232,6 @@ pub struct Module {
// return_mode: ReturnMode, // return_mode: ReturnMode,
} }
impl Module { impl Module {
/// Instantiate a Module given WASM bytecode /// Instantiate a Module given WASM bytecode
pub fn from_bytes( pub fn from_bytes(
@ -365,7 +351,11 @@ impl<'environment> FuncEnvironmentTrait for FuncEnvironment<'environment> {
// however the 32-bit wasmer may be running on 64-bit arch, which means ptr_size here will // however the 32-bit wasmer may be running on 64-bit arch, which means ptr_size here will
// be 8 bytes. That will definitely gove the wrong offset values // be 8 bytes. That will definitely gove the wrong offset values
fn make_table(&mut self, func: &mut ir::Function, table_index: TableIndex) -> ir::Table { fn make_table(&mut self, func: &mut ir::Function, table_index: TableIndex) -> ir::Table {
assert_eq!(table_index.index(), 0, "Only one WebAssembly memory supported"); assert_eq!(
table_index.index(),
0,
"Only one WebAssembly memory supported"
);
let instance = func.create_global_value(ir::GlobalValueData::VMContext); let instance = func.create_global_value(ir::GlobalValueData::VMContext);
let ptr_size = native_pointer_size(); let ptr_size = native_pointer_size();
// Load value at (instance + TABLES_OFFSET) // Load value at (instance + TABLES_OFFSET)
@ -415,7 +405,11 @@ impl<'environment> FuncEnvironmentTrait for FuncEnvironment<'environment> {
// however the 32-bit wasmer may be running on 64-bit arch, which means ptr_size here will // however the 32-bit wasmer may be running on 64-bit arch, which means ptr_size here will
// be 8 bytes. That will definitely gove the wrong offset values // be 8 bytes. That will definitely gove the wrong offset values
fn make_heap(&mut self, func: &mut ir::Function, memory_index: MemoryIndex) -> ir::Heap { fn make_heap(&mut self, func: &mut ir::Function, memory_index: MemoryIndex) -> ir::Heap {
debug_assert_eq!(memory_index.index(), 0, "Only one WebAssembly memory supported"); debug_assert_eq!(
memory_index.index(),
0,
"Only one WebAssembly memory supported"
);
let instance = func.create_global_value(ir::GlobalValueData::VMContext); let instance = func.create_global_value(ir::GlobalValueData::VMContext);
let ptr_size = native_pointer_size(); let ptr_size = native_pointer_size();
@ -438,7 +432,7 @@ impl<'environment> FuncEnvironmentTrait for FuncEnvironment<'environment> {
base, base,
offset: Offset32::new(memory_data_offset), offset: Offset32::new(memory_data_offset),
global_type: self.pointer_type(), global_type: self.pointer_type(),
readonly: true readonly: true,
}); });
// Load value at the (base + memory_data_offset) // Load value at the (base + memory_data_offset)
@ -455,16 +449,18 @@ impl<'environment> FuncEnvironmentTrait for FuncEnvironment<'environment> {
base: heap_base, base: heap_base,
min_size: 0.into(), min_size: 0.into(),
guard_size: (LinearMemory::DEFAULT_GUARD_SIZE as i64).into(), guard_size: (LinearMemory::DEFAULT_GUARD_SIZE as i64).into(),
style: ir::HeapStyle::Dynamic { style: ir::HeapStyle::Dynamic { bound_gv },
bound_gv, index_type: I32,
},
index_type: I32
}); });
heap heap
} }
fn make_global(&mut self, func: &mut ir::Function, global_index: GlobalIndex) -> GlobalVariable { fn make_global(
&mut self,
func: &mut ir::Function,
global_index: GlobalIndex,
) -> GlobalVariable {
let ptr_size = native_pointer_size(); let ptr_size = native_pointer_size();
let instance = func.create_global_value(ir::GlobalValueData::VMContext); let instance = func.create_global_value(ir::GlobalValueData::VMContext);
@ -525,7 +521,6 @@ impl<'environment> FuncEnvironmentTrait for FuncEnvironment<'environment> {
.special_param(ir::ArgumentPurpose::VMContext) .special_param(ir::ArgumentPurpose::VMContext)
.expect("Missing vmctx parameter"); .expect("Missing vmctx parameter");
// The `callee` value is an index into a table of function pointers. // The `callee` value is an index into a table of function pointers.
// Apparently, that table is stored at absolute address 0 in this dummy environment. // Apparently, that table is stored at absolute address 0 in this dummy environment.
// TODO: Generate bounds checking code. // TODO: Generate bounds checking code.
@ -541,9 +536,7 @@ impl<'environment> FuncEnvironmentTrait for FuncEnvironment<'environment> {
// let entry_size = native_pointer_size() as i64 * 2; // let entry_size = native_pointer_size() as i64 * 2;
// let callee_scaled = pos.ins().imul_imm(callee_offset, entry_size); // let callee_scaled = pos.ins().imul_imm(callee_offset, entry_size);
let entry_addr = pos let entry_addr = pos.ins().table_addr(ptr, table, callee_offset, 0);
.ins()
.table_addr(ptr, table, callee_offset, 0);
let mut mflags = ir::MemFlags::new(); let mut mflags = ir::MemFlags::new();
mflags.set_notrap(); mflags.set_notrap();
@ -597,7 +590,11 @@ impl<'environment> FuncEnvironmentTrait for FuncEnvironment<'environment> {
_heap: ir::Heap, _heap: ir::Heap,
val: ir::Value, val: ir::Value,
) -> WasmResult<ir::Value> { ) -> WasmResult<ir::Value> {
debug_assert_eq!(memory_index.index(), 0, "non-default memories not supported yet"); debug_assert_eq!(
memory_index.index(),
0,
"non-default memories not supported yet"
);
let grow_mem_func = self.mod_info.grow_memory_extfunc.unwrap_or_else(|| { let grow_mem_func = self.mod_info.grow_memory_extfunc.unwrap_or_else(|| {
let sig_ref = pos.func.import_signature(Signature { let sig_ref = pos.func.import_signature(Signature {
call_conv: CallConv::SystemV, call_conv: CallConv::SystemV,
@ -624,7 +621,9 @@ impl<'environment> FuncEnvironmentTrait for FuncEnvironment<'environment> {
let memory_index_value = pos.ins().iconst(I32, imm64(memory_index.index())); let memory_index_value = pos.ins().iconst(I32, imm64(memory_index.index()));
let vmctx = pos.func.special_param(ArgumentPurpose::VMContext).unwrap(); let vmctx = pos.func.special_param(ArgumentPurpose::VMContext).unwrap();
let call_inst = pos.ins().call(grow_mem_func, &[val, memory_index_value, vmctx]); let call_inst = pos
.ins()
.call(grow_mem_func, &[val, memory_index_value, vmctx]);
Ok(*pos.func.dfg.inst_results(call_inst).first().unwrap()) Ok(*pos.func.dfg.inst_results(call_inst).first().unwrap())
} }
@ -634,7 +633,11 @@ impl<'environment> FuncEnvironmentTrait for FuncEnvironment<'environment> {
memory_index: MemoryIndex, memory_index: MemoryIndex,
_heap: ir::Heap, _heap: ir::Heap,
) -> WasmResult<ir::Value> { ) -> WasmResult<ir::Value> {
debug_assert_eq!(memory_index.index(), 0, "non-default memories not supported yet"); debug_assert_eq!(
memory_index.index(),
0,
"non-default memories not supported yet"
);
let cur_mem_func = self.mod_info.current_memory_extfunc.unwrap_or_else(|| { let cur_mem_func = self.mod_info.current_memory_extfunc.unwrap_or_else(|| {
let sig_ref = pos.func.import_signature(Signature { let sig_ref = pos.func.import_signature(Signature {
call_conv: CallConv::SystemV, call_conv: CallConv::SystemV,
@ -712,7 +715,9 @@ impl<'data> ModuleEnvironment<'data> for Module {
self.info.imported_funcs.len(), self.info.imported_funcs.len(),
"Imported functions must be declared first" "Imported functions must be declared first"
); );
self.info.functions.push(ImportableExportable::new(sig_index, None)); self.info
.functions
.push(ImportableExportable::new(sig_index, None));
self.info self.info
.imported_funcs .imported_funcs
.push((String::from(module), String::from(field))); .push((String::from(module), String::from(field)));
@ -723,7 +728,9 @@ impl<'data> ModuleEnvironment<'data> for Module {
} }
fn declare_func_type(&mut self, sig_index: SignatureIndex) { fn declare_func_type(&mut self, sig_index: SignatureIndex) {
self.info.functions.push(ImportableExportable::new(sig_index, None)); self.info
.functions
.push(ImportableExportable::new(sig_index, None));
} }
fn get_func_type(&self, func_index: FuncIndex) -> SignatureIndex { fn get_func_type(&self, func_index: FuncIndex) -> SignatureIndex {
@ -731,16 +738,16 @@ impl<'data> ModuleEnvironment<'data> for Module {
} }
fn declare_global(&mut self, global: Global) { fn declare_global(&mut self, global: Global) {
self.info.globals.push(ImportableExportable::new(global, None)); self.info
.globals
.push(ImportableExportable::new(global, None));
} }
fn declare_global_import( fn declare_global_import(&mut self, global: Global, module: &'data str, field: &'data str) {
&mut self, self.info.globals.push(ImportableExportable::new(
global: Global, global,
module: &'data str, Some((String::from(module), String::from(field))),
field: &'data str, ));
) {
self.info.globals.push(ImportableExportable::new(global, Some((String::from(module), String::from(field)))));
} }
fn get_global(&self, global_index: GlobalIndex) -> &Global { fn get_global(&self, global_index: GlobalIndex) -> &Global {
@ -748,16 +755,16 @@ impl<'data> ModuleEnvironment<'data> for Module {
} }
fn declare_table(&mut self, table: Table) { fn declare_table(&mut self, table: Table) {
self.info.tables.push(ImportableExportable::new(table, None)); self.info
.tables
.push(ImportableExportable::new(table, None));
} }
fn declare_table_import( fn declare_table_import(&mut self, table: Table, module: &'data str, field: &'data str) {
&mut self, self.info.tables.push(ImportableExportable::new(
table: Table, table,
module: &'data str, Some((String::from(module), String::from(field))),
field: &'data str, ));
) {
self.info.tables.push(ImportableExportable::new(table, Some((String::from(module), String::from(field)))));
} }
fn declare_table_elements( fn declare_table_elements(
@ -776,16 +783,16 @@ impl<'data> ModuleEnvironment<'data> for Module {
} }
fn declare_memory(&mut self, memory: Memory) { fn declare_memory(&mut self, memory: Memory) {
self.info.memories.push(ImportableExportable::new(memory, None)); self.info
.memories
.push(ImportableExportable::new(memory, None));
} }
fn declare_memory_import( fn declare_memory_import(&mut self, memory: Memory, module: &'data str, field: &'data str) {
&mut self, self.info.memories.push(ImportableExportable::new(
memory: Memory, memory,
module: &'data str, Some((String::from(module), String::from(field))),
field: &'data str, ));
) {
self.info.memories.push(ImportableExportable::new(memory, Some((String::from(module), String::from(field)))));
} }
fn declare_data_initialization( fn declare_data_initialization(

View File

@ -11,12 +11,10 @@ pub fn print_instance_offsets(instance: &Instance) {
let instance_address = instance as *const _ as usize; let instance_address = instance as *const _ as usize;
let data_ptr = &instance.data_pointers; let data_ptr = &instance.data_pointers;
let tables_pointer_address_ptr: *const usize = let tables_pointer_address_ptr: *const usize = unsafe { transmute(&data_ptr.tables) };
unsafe { transmute(&data_ptr.tables) };
let tables_pointer_address = tables_pointer_address_ptr as usize; let tables_pointer_address = tables_pointer_address_ptr as usize;
let memories_pointer_address_ptr: *const usize = let memories_pointer_address_ptr: *const usize = unsafe { transmute(&data_ptr.memories) };
unsafe { transmute(&data_ptr.memories) };
let memories_pointer_address = memories_pointer_address_ptr as usize; let memories_pointer_address = memories_pointer_address_ptr as usize;
let memories_pointer_address_ptr_0: *const usize = let memories_pointer_address_ptr_0: *const usize =
@ -31,8 +29,7 @@ pub fn print_instance_offsets(instance: &Instance) {
unsafe { transmute(&data_ptr.memories.get_unchecked(0).len) }; unsafe { transmute(&data_ptr.memories.get_unchecked(0).len) };
let memories_pointer_address_0_len = memories_pointer_address_ptr_0_len as usize; let memories_pointer_address_0_len = memories_pointer_address_ptr_0_len as usize;
let globals_pointer_address_ptr: *const usize = let globals_pointer_address_ptr: *const usize = unsafe { transmute(&data_ptr.globals) };
unsafe { transmute(&data_ptr.globals) };
let globals_pointer_address = globals_pointer_address_ptr as usize; let globals_pointer_address = globals_pointer_address_ptr as usize;
println!( println!(
@ -53,7 +50,6 @@ instance.data_pointers.globals \t- {:X} | offset - {:?}
tables_pointer_address - instance_address, tables_pointer_address - instance_address,
memories_pointer_address, memories_pointer_address,
memories_pointer_address - instance_address, memories_pointer_address - instance_address,
memories_pointer_address_0, memories_pointer_address_0,
0, 0,
memories_pointer_address_0_data, memories_pointer_address_0_data,
@ -61,7 +57,6 @@ instance.data_pointers.globals \t- {:X} | offset - {:?}
data_ptr.memories.get_unchecked(0).len, data_ptr.memories.get_unchecked(0).len,
memories_pointer_address_0_len, memories_pointer_address_0_len,
memories_pointer_address_0_len - memories_pointer_address_0_data, memories_pointer_address_0_len - memories_pointer_address_0_data,
globals_pointer_address, globals_pointer_address,
globals_pointer_address - instance_address, globals_pointer_address - instance_address,
); );