mirror of
https://github.com/fluencelabs/wasmer
synced 2024-12-13 06:15:33 +00:00
run cargo fmt
This commit is contained in:
parent
ccdabd26b5
commit
38f045da3c
@ -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;
|
||||
/// 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
|
||||
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(_) => {
|
||||
unimplemented!();
|
||||
}
|
||||
Err(_) => {
|
||||
0
|
||||
}
|
||||
Err(_) => 0,
|
||||
}
|
||||
}
|
||||
|
@ -1,17 +1,20 @@
|
||||
use libc::{
|
||||
c_void,
|
||||
size_t,
|
||||
memcpy,
|
||||
};
|
||||
use libc::{c_void, memcpy, size_t};
|
||||
|
||||
use crate::webassembly::{Instance};
|
||||
use crate::webassembly::Instance;
|
||||
|
||||
/// 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");
|
||||
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;
|
||||
unsafe { memcpy(dest_addr, src_addr, len as size_t); }
|
||||
unsafe {
|
||||
memcpy(dest_addr, src_addr, len as size_t);
|
||||
}
|
||||
dest
|
||||
}
|
||||
|
||||
|
@ -2,35 +2,87 @@ use crate::webassembly::{ImportObject, ImportValue};
|
||||
|
||||
// EMSCRIPTEN APIS
|
||||
mod env;
|
||||
mod io;
|
||||
mod memory;
|
||||
mod process;
|
||||
mod io;
|
||||
mod utils;
|
||||
mod syscalls;
|
||||
mod utils;
|
||||
|
||||
// SYSCALLS
|
||||
use super::host;
|
||||
pub use self::utils::is_emscripten_module;
|
||||
use super::host;
|
||||
|
||||
pub fn generate_emscripten_env<'a, 'b>() -> ImportObject<&'a str, &'b str> {
|
||||
let mut import_object = ImportObject::new();
|
||||
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
|
||||
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
|
||||
import_object.set("env", "___syscall3", ImportValue::Func(syscalls::___syscall3 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));
|
||||
import_object.set(
|
||||
"env",
|
||||
"___syscall3",
|
||||
ImportValue::Func(syscalls::___syscall3 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
|
||||
import_object.set("env", "abort", ImportValue::Func(process::em_abort 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.set(
|
||||
"env",
|
||||
"abort",
|
||||
ImportValue::Func(process::em_abort 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
|
||||
}
|
||||
|
||||
|
@ -1,14 +1,14 @@
|
||||
use libc::{
|
||||
// c_int,
|
||||
// c_void,
|
||||
c_char,
|
||||
// size_t,
|
||||
// ssize_t,
|
||||
abort,
|
||||
// c_int,
|
||||
// c_void,
|
||||
c_char,
|
||||
};
|
||||
|
||||
use crate::webassembly::Instance;
|
||||
use std::ffi::CStr;
|
||||
use crate::webassembly::{Instance};
|
||||
|
||||
extern "C" fn abort_with_message(message: &str) {
|
||||
debug!("emscripten::abort_with_message");
|
||||
@ -19,7 +19,9 @@ extern "C" fn abort_with_message(message: &str) {
|
||||
/// emscripten: _abort
|
||||
pub extern "C" fn _abort() {
|
||||
debug!("emscripten::_abort");
|
||||
unsafe { abort(); }
|
||||
unsafe {
|
||||
abort();
|
||||
}
|
||||
}
|
||||
|
||||
/// emscripten: abort
|
||||
@ -40,4 +42,3 @@ pub extern "C" fn abort_on_cannot_grow_memory() {
|
||||
debug!("emscripten::abort_on_cannot_grow_memory");
|
||||
abort_with_message("Cannot enlarge memory arrays!");
|
||||
}
|
||||
|
||||
|
@ -1,23 +1,12 @@
|
||||
/// 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
|
||||
|
||||
use libc::{
|
||||
c_int,
|
||||
c_void,
|
||||
size_t,
|
||||
ssize_t,
|
||||
exit,
|
||||
read,
|
||||
write,
|
||||
open,
|
||||
close,
|
||||
};
|
||||
use libc::{c_int, c_void, close, exit, open, read, size_t, ssize_t, write};
|
||||
use std::{mem, ptr};
|
||||
|
||||
use std::os::raw::c_char;
|
||||
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
|
||||
macro_rules! vararg {
|
||||
@ -58,7 +47,6 @@ pub extern "C" fn ___syscall5(which: c_int, varargs: c_int, instance: &mut Insta
|
||||
-2
|
||||
}
|
||||
|
||||
|
||||
// sys_ioctl
|
||||
#[no_mangle]
|
||||
pub extern "C" fn ___syscall54(which: c_int, varargs: c_int, instance: &mut Instance) -> c_int {
|
||||
|
@ -10,12 +10,11 @@ pub fn is_emscripten_module(module: &Module) -> bool {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use crate::webassembly::instantiate;
|
||||
use super::is_emscripten_module;
|
||||
use super::super::generate_emscripten_env;
|
||||
use super::is_emscripten_module;
|
||||
use crate::webassembly::instantiate;
|
||||
|
||||
#[test]
|
||||
fn should_detect_emscripten_files() {
|
||||
@ -32,4 +31,4 @@ mod tests {
|
||||
let result_object = instantiate(wasm_bytes, import_object).expect("Not compiled properly");
|
||||
assert!(!is_emscripten_module(&result_object.module));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,19 +1,9 @@
|
||||
/// 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 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;
|
||||
use std::env;
|
||||
|
||||
pub extern "C" fn get_env(name: &str, instance: &mut Instance) -> Result<String, env::VarError> {
|
||||
|
@ -1,5 +1,5 @@
|
||||
pub mod syscalls;
|
||||
pub mod env;
|
||||
pub mod syscalls;
|
||||
|
||||
pub use self::syscalls::*;
|
||||
pub use self::env::*;
|
||||
pub use self::syscalls::*;
|
||||
|
@ -11,17 +11,13 @@ impl<T> UncheckedSlice<T> {
|
||||
#[inline]
|
||||
pub fn get_unchecked(&self, index: usize) -> &T {
|
||||
let ptr = self.ptr.as_ptr();
|
||||
unsafe {
|
||||
&*ptr.add(index)
|
||||
}
|
||||
unsafe { &*ptr.add(index) }
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn get_unchecked_mut(&mut self, index: usize) -> &mut T {
|
||||
let ptr = self.ptr.as_ptr();
|
||||
unsafe {
|
||||
&mut *(ptr.add(index) as *mut _)
|
||||
}
|
||||
unsafe { &mut *(ptr.add(index) as *mut _) }
|
||||
}
|
||||
|
||||
pub unsafe fn dangling() -> UncheckedSlice<T> {
|
||||
|
24
src/main.rs
24
src/main.rs
@ -25,8 +25,8 @@ use structopt::StructOpt;
|
||||
|
||||
#[macro_use]
|
||||
mod macros;
|
||||
pub mod common;
|
||||
pub mod apis;
|
||||
pub mod common;
|
||||
pub mod sighandler;
|
||||
#[cfg(test)]
|
||||
mod spectests;
|
||||
@ -83,17 +83,19 @@ fn execute_wasm(wasm_path: PathBuf) -> Result<(), String> {
|
||||
Some(&webassembly::Export::Function(index)) => index,
|
||||
_ => 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);
|
||||
}
|
||||
else {
|
||||
let func_index = instance
|
||||
.start_func
|
||||
.unwrap_or_else(|| match module.info.exports.get("main") {
|
||||
Some(&webassembly::Export::Function(index)) => index,
|
||||
_ => panic!("Main function not found"),
|
||||
});
|
||||
let main: extern fn(&webassembly::Instance) = get_instance_function!(instance, func_index);
|
||||
} else {
|
||||
let func_index =
|
||||
instance
|
||||
.start_func
|
||||
.unwrap_or_else(|| match module.info.exports.get("main") {
|
||||
Some(&webassembly::Export::Function(index)) => index,
|
||||
_ => panic!("Main function not found"),
|
||||
});
|
||||
let main: extern "C" fn(&webassembly::Instance) =
|
||||
get_instance_function!(instance, func_index);
|
||||
main(&instance);
|
||||
}
|
||||
|
||||
|
@ -3,10 +3,10 @@
|
||||
//! or webassembly::Memory objects.
|
||||
// Code inspired from: https://stackoverflow.com/a/45795699/1072990
|
||||
// Adapted to the Webassembly use case
|
||||
use crate::webassembly::LinearMemory;
|
||||
use std::borrow::Borrow;
|
||||
use std::collections::HashMap;
|
||||
use std::hash::{Hash, Hasher};
|
||||
use crate::webassembly::LinearMemory;
|
||||
|
||||
// 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
|
||||
@ -75,8 +75,7 @@ impl<A: Eq + Hash, B: Eq + Hash> ImportObject<A, B> {
|
||||
}
|
||||
|
||||
pub fn get(&self, a: &A, b: &B) -> Option<&ImportValue> {
|
||||
self.map
|
||||
.get(&BorrowedPair(a, b) as &KeyPair<A, B>)
|
||||
self.map.get(&BorrowedPair(a, b) as &KeyPair<A, B>)
|
||||
}
|
||||
|
||||
pub fn set(&mut self, a: A, b: B, v: ImportValue) {
|
||||
@ -127,6 +126,9 @@ mod tests {
|
||||
fn x() {}
|
||||
let mut import_object = ImportObject::new();
|
||||
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)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
@ -6,28 +6,28 @@
|
||||
//! synchronously instantiate a given webassembly::Module object. However, the
|
||||
//! primary way to get an Instance is through the asynchronous
|
||||
//! webassembly::instantiate_streaming() function.
|
||||
use cranelift_codegen::ir::{LibCall, Function};
|
||||
use cranelift_codegen::{binemit, Context};
|
||||
use cranelift_codegen::ir::{Function, LibCall};
|
||||
use cranelift_codegen::isa::TargetIsa;
|
||||
use cranelift_codegen::{binemit, Context};
|
||||
use cranelift_entity::EntityRef;
|
||||
use cranelift_wasm::{FuncIndex, GlobalInit};
|
||||
use rayon::prelude::*;
|
||||
|
||||
use region;
|
||||
use std::iter::FromIterator;
|
||||
use std::iter::Iterator;
|
||||
use std::mem::size_of;
|
||||
use std::ptr::write_unaligned;
|
||||
use std::slice;
|
||||
use std::sync::Arc;
|
||||
use std::iter::FromIterator;
|
||||
use std::mem::size_of;
|
||||
|
||||
use super::super::common::slice::{BoundedSlice, UncheckedSlice};
|
||||
use super::errors::ErrorKind;
|
||||
use super::import_object::{ImportObject, ImportValue};
|
||||
use super::math_intrinsics;
|
||||
use super::memory::LinearMemory;
|
||||
use super::module::{Export, ImportableExportable, Module};
|
||||
use super::relocation::{Reloc, RelocSink, RelocationType};
|
||||
use super::math_intrinsics;
|
||||
|
||||
type TablesSlice = UncheckedSlice<BoundedSlice<usize>>;
|
||||
type MemoriesSlice = UncheckedSlice<BoundedSlice<u8>>;
|
||||
@ -114,7 +114,6 @@ pub struct DataPointers {
|
||||
|
||||
// Pointer to globals
|
||||
pub globals: GlobalsSlice,
|
||||
|
||||
}
|
||||
|
||||
pub struct InstanceOptions {
|
||||
@ -125,7 +124,7 @@ pub struct InstanceOptions {
|
||||
pub isa: Box<TargetIsa>,
|
||||
}
|
||||
|
||||
extern fn mock_fn() -> i32 {
|
||||
extern "C" fn mock_fn() -> i32 {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -135,7 +134,10 @@ struct CompiledFunction {
|
||||
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 code_buf: Vec<u8> = Vec::new();
|
||||
@ -152,7 +154,7 @@ fn compile_function(isa: &TargetIsa, function_body: &Function) -> Result<Compile
|
||||
Ok(CompiledFunction {
|
||||
code_buf,
|
||||
reloc_sink,
|
||||
trap_sink
|
||||
trap_sink,
|
||||
})
|
||||
}
|
||||
|
||||
@ -191,23 +193,24 @@ impl Instance {
|
||||
// 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 (module, field) in module.info.imported_funcs.iter() {
|
||||
let imported = import_object
|
||||
.get(&module.as_str(), &field.as_str());
|
||||
let imported = import_object.get(&module.as_str(), &field.as_str());
|
||||
let function: &*const u8 = match imported {
|
||||
Some(ImportValue::Func(f)) => f,
|
||||
None => {
|
||||
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)
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
return Err(ErrorKind::LinkError(format!(
|
||||
"Imported function {}.{} was not provided in the import_functions",
|
||||
module, field
|
||||
)));
|
||||
}
|
||||
},
|
||||
other => panic!("Expected function import, received {:?}", other)
|
||||
}
|
||||
other => panic!("Expected function import, received {:?}", other),
|
||||
};
|
||||
// println!("GET FUNC {:?}", function);
|
||||
import_functions.push(*function);
|
||||
@ -218,15 +221,20 @@ impl Instance {
|
||||
// Compile the functions (from cranelift IR to machine code)
|
||||
let values: Vec<&Function> = Vec::from_iter(module.info.function_bodies.values());
|
||||
// let isa: &TargetIsa = &*options.isa;
|
||||
let compiled_funcs: Vec<CompiledFunction> = values.par_iter().map(|function_body| -> CompiledFunction {
|
||||
// let r = *Arc::from_raw(isa_ptr);
|
||||
compile_function(&*options.isa, function_body).unwrap()
|
||||
// unimplemented!()
|
||||
}).collect();
|
||||
let compiled_funcs: Vec<CompiledFunction> = values
|
||||
.par_iter()
|
||||
.map(|function_body| -> CompiledFunction {
|
||||
// let r = *Arc::from_raw(isa_ptr);
|
||||
compile_function(&*options.isa, function_body).unwrap()
|
||||
// unimplemented!()
|
||||
}).collect();
|
||||
|
||||
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;
|
||||
protect_codebuf(&code_buf).unwrap();
|
||||
@ -322,33 +330,39 @@ impl Instance {
|
||||
};
|
||||
|
||||
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 {
|
||||
GlobalInit::I32Const(n) => n as _,
|
||||
GlobalInit::I64Const(n) => n,
|
||||
GlobalInit::F32Const(f) => f as _, // unsafe { mem::transmute(f as f64) },
|
||||
GlobalInit::F64Const(f) => f as _, // unsafe { mem::transmute(f) },
|
||||
GlobalInit::GlobalRef(global_index) => {
|
||||
globals_data[global_index.index()]
|
||||
}
|
||||
GlobalInit::GlobalRef(global_index) => globals_data[global_index.index()],
|
||||
GlobalInit::Import() => {
|
||||
let (module_name, field_name) = import_name.as_ref().expect("Expected a import name for the global import");
|
||||
let imported = import_object.get(&module_name.as_str(), &field_name.as_str());
|
||||
let (module_name, field_name) = import_name
|
||||
.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 {
|
||||
Some(ImportValue::Global(value)) => {
|
||||
*value
|
||||
},
|
||||
Some(ImportValue::Global(value)) => *value,
|
||||
None => {
|
||||
if options.mock_missing_globals {
|
||||
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 {
|
||||
let table: Vec<usize> = match table.import_name.as_ref() {
|
||||
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 {
|
||||
Some(ImportValue::Table(t)) => {
|
||||
t.to_vec()
|
||||
},
|
||||
Some(ImportValue::Table(t)) => t.to_vec(),
|
||||
None => {
|
||||
if options.mock_missing_tables {
|
||||
let len = table.entity.size;
|
||||
let mut v = Vec::with_capacity(len);
|
||||
v.resize(len, 0);
|
||||
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 => {
|
||||
let len = table.entity.size;
|
||||
let mut v = Vec::with_capacity(len);
|
||||
@ -401,10 +417,8 @@ impl Instance {
|
||||
// instantiate tables
|
||||
for table_element in &module.info.table_elements {
|
||||
let base = match table_element.base {
|
||||
Some(global_index) => {
|
||||
globals_data[global_index.index()] as usize
|
||||
},
|
||||
None => 0
|
||||
Some(global_index) => globals_data[global_index.index()] as usize,
|
||||
None => 0,
|
||||
};
|
||||
|
||||
let table = &mut tables[table_element.table_index.index()];
|
||||
@ -430,10 +444,8 @@ impl Instance {
|
||||
// Get memories in module
|
||||
for memory in &module.info.memories {
|
||||
let memory = memory.entity;
|
||||
let v = LinearMemory::new(
|
||||
memory.pages_count as u32,
|
||||
memory.maximum.map(|m| m as u32),
|
||||
);
|
||||
let v =
|
||||
LinearMemory::new(memory.pages_count as u32, memory.maximum.map(|m| m as u32));
|
||||
memories.push(v);
|
||||
}
|
||||
|
||||
@ -458,10 +470,14 @@ impl Instance {
|
||||
// TODO: Refactor repetitive code
|
||||
let tables_pointer: Vec<BoundedSlice<usize>> =
|
||||
tables.iter().map(|table| table[..].into()).collect();
|
||||
let memories_pointer: Vec<BoundedSlice<u8>> =
|
||||
memories.iter().map(
|
||||
|mem| BoundedSlice::new(&mem[..], mem.current as usize * LinearMemory::WASM_PAGE_SIZE),
|
||||
).collect();
|
||||
let memories_pointer: Vec<BoundedSlice<u8>> = memories
|
||||
.iter()
|
||||
.map(|mem| {
|
||||
BoundedSlice::new(
|
||||
&mem[..],
|
||||
mem.current as usize * LinearMemory::WASM_PAGE_SIZE,
|
||||
)
|
||||
}).collect();
|
||||
let globals_pointer: GlobalsSlice = globals[..].into();
|
||||
|
||||
let data_pointers = DataPointers {
|
||||
@ -518,9 +534,7 @@ impl Instance {
|
||||
|
||||
pub fn memory_offset_addr(&self, index: usize, offset: usize) -> *const usize {
|
||||
let mem = &self.memories[index];
|
||||
unsafe {
|
||||
mem.mmap.as_ptr().offset(offset as isize) as *const usize
|
||||
}
|
||||
unsafe { mem.mmap.as_ptr().offset(offset as isize) as *const usize }
|
||||
}
|
||||
|
||||
// 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 {
|
||||
// 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
|
||||
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
|
||||
|
@ -132,8 +132,7 @@ impl fmt::Debug for 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.maximum == other.maximum
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1,19 +1,19 @@
|
||||
pub mod errors;
|
||||
pub mod import_object;
|
||||
pub mod instance;
|
||||
pub mod math_intrinsics;
|
||||
pub mod memory;
|
||||
pub mod module;
|
||||
pub mod relocation;
|
||||
pub mod utils;
|
||||
pub mod math_intrinsics;
|
||||
|
||||
use cranelift_codegen::isa::TargetIsa;
|
||||
use cranelift_codegen::{isa, settings};
|
||||
use std::panic;
|
||||
use std::str::FromStr;
|
||||
use target_lexicon;
|
||||
use wasmparser;
|
||||
use wasmparser::WasmDecoder;
|
||||
use cranelift_codegen::{isa, settings};
|
||||
use cranelift_codegen::isa::TargetIsa;
|
||||
|
||||
pub use self::errors::{Error, ErrorKind};
|
||||
pub use self::import_object::{ImportObject, ImportValue};
|
||||
@ -60,7 +60,7 @@ pub fn instantiate(
|
||||
mock_missing_imports: true,
|
||||
mock_missing_globals: true,
|
||||
mock_missing_tables: true,
|
||||
isa: isa
|
||||
isa: isa,
|
||||
},
|
||||
)?;
|
||||
debug!("webassembly - instance created");
|
||||
|
@ -15,27 +15,14 @@ use cranelift_codegen::isa::{CallConv, TargetFrontendConfig};
|
||||
use cranelift_entity::{EntityRef, PrimaryMap};
|
||||
|
||||
use cranelift_wasm::{
|
||||
translate_module,
|
||||
ReturnMode,
|
||||
DefinedFuncIndex,
|
||||
FuncEnvironment as FuncEnvironmentTrait,
|
||||
FuncIndex,
|
||||
FuncTranslator,
|
||||
Global,
|
||||
GlobalIndex,
|
||||
GlobalVariable,
|
||||
Memory,
|
||||
MemoryIndex,
|
||||
ModuleEnvironment,
|
||||
SignatureIndex,
|
||||
Table,
|
||||
TableIndex,
|
||||
WasmResult,
|
||||
translate_module, DefinedFuncIndex, FuncEnvironment as FuncEnvironmentTrait, FuncIndex,
|
||||
FuncTranslator, Global, GlobalIndex, GlobalVariable, Memory, MemoryIndex, ModuleEnvironment,
|
||||
ReturnMode, SignatureIndex, Table, TableIndex, WasmResult,
|
||||
};
|
||||
|
||||
use super::errors::ErrorKind;
|
||||
use super::memory::LinearMemory;
|
||||
use super::instance::Instance;
|
||||
use super::memory::LinearMemory;
|
||||
|
||||
/// Get the integer type used for representing pointers on this platform.
|
||||
fn native_pointer_type() -> ir::Type {
|
||||
@ -89,7 +76,7 @@ impl<T> ImportableExportable<T> {
|
||||
Self {
|
||||
entity,
|
||||
export_names: Vec::new(),
|
||||
import_name: import_name
|
||||
import_name: import_name,
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -245,7 +232,6 @@ pub struct Module {
|
||||
// return_mode: ReturnMode,
|
||||
}
|
||||
|
||||
|
||||
impl Module {
|
||||
/// Instantiate a Module given WASM bytecode
|
||||
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
|
||||
// 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 {
|
||||
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 ptr_size = native_pointer_size();
|
||||
// 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
|
||||
// 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 {
|
||||
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 ptr_size = native_pointer_size();
|
||||
|
||||
@ -438,7 +432,7 @@ impl<'environment> FuncEnvironmentTrait for FuncEnvironment<'environment> {
|
||||
base,
|
||||
offset: Offset32::new(memory_data_offset),
|
||||
global_type: self.pointer_type(),
|
||||
readonly: true
|
||||
readonly: true,
|
||||
});
|
||||
|
||||
// Load value at the (base + memory_data_offset)
|
||||
@ -455,16 +449,18 @@ impl<'environment> FuncEnvironmentTrait for FuncEnvironment<'environment> {
|
||||
base: heap_base,
|
||||
min_size: 0.into(),
|
||||
guard_size: (LinearMemory::DEFAULT_GUARD_SIZE as i64).into(),
|
||||
style: ir::HeapStyle::Dynamic {
|
||||
bound_gv,
|
||||
},
|
||||
index_type: I32
|
||||
style: ir::HeapStyle::Dynamic { bound_gv },
|
||||
index_type: I32,
|
||||
});
|
||||
|
||||
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 instance = func.create_global_value(ir::GlobalValueData::VMContext);
|
||||
@ -525,7 +521,6 @@ impl<'environment> FuncEnvironmentTrait for FuncEnvironment<'environment> {
|
||||
.special_param(ir::ArgumentPurpose::VMContext)
|
||||
.expect("Missing vmctx parameter");
|
||||
|
||||
|
||||
// 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.
|
||||
// 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 callee_scaled = pos.ins().imul_imm(callee_offset, entry_size);
|
||||
|
||||
let entry_addr = pos
|
||||
.ins()
|
||||
.table_addr(ptr, table, callee_offset, 0);
|
||||
let entry_addr = pos.ins().table_addr(ptr, table, callee_offset, 0);
|
||||
|
||||
let mut mflags = ir::MemFlags::new();
|
||||
mflags.set_notrap();
|
||||
@ -597,7 +590,11 @@ impl<'environment> FuncEnvironmentTrait for FuncEnvironment<'environment> {
|
||||
_heap: ir::Heap,
|
||||
val: 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 sig_ref = pos.func.import_signature(Signature {
|
||||
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 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())
|
||||
}
|
||||
|
||||
@ -634,7 +633,11 @@ impl<'environment> FuncEnvironmentTrait for FuncEnvironment<'environment> {
|
||||
memory_index: MemoryIndex,
|
||||
_heap: ir::Heap,
|
||||
) -> 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 sig_ref = pos.func.import_signature(Signature {
|
||||
call_conv: CallConv::SystemV,
|
||||
@ -712,7 +715,9 @@ impl<'data> ModuleEnvironment<'data> for Module {
|
||||
self.info.imported_funcs.len(),
|
||||
"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
|
||||
.imported_funcs
|
||||
.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) {
|
||||
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 {
|
||||
@ -731,16 +738,16 @@ impl<'data> ModuleEnvironment<'data> for Module {
|
||||
}
|
||||
|
||||
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(
|
||||
&mut self,
|
||||
global: Global,
|
||||
module: &'data str,
|
||||
field: &'data str,
|
||||
) {
|
||||
self.info.globals.push(ImportableExportable::new(global, Some((String::from(module), String::from(field)))));
|
||||
fn declare_global_import(&mut self, global: Global, module: &'data str, 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 {
|
||||
@ -748,16 +755,16 @@ impl<'data> ModuleEnvironment<'data> for Module {
|
||||
}
|
||||
|
||||
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(
|
||||
&mut self,
|
||||
table: Table,
|
||||
module: &'data str,
|
||||
field: &'data str,
|
||||
) {
|
||||
self.info.tables.push(ImportableExportable::new(table, Some((String::from(module), String::from(field)))));
|
||||
fn declare_table_import(&mut self, table: Table, module: &'data str, field: &'data str) {
|
||||
self.info.tables.push(ImportableExportable::new(
|
||||
table,
|
||||
Some((String::from(module), String::from(field))),
|
||||
));
|
||||
}
|
||||
|
||||
fn declare_table_elements(
|
||||
@ -776,16 +783,16 @@ impl<'data> ModuleEnvironment<'data> for Module {
|
||||
}
|
||||
|
||||
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(
|
||||
&mut self,
|
||||
memory: Memory,
|
||||
module: &'data str,
|
||||
field: &'data str,
|
||||
) {
|
||||
self.info.memories.push(ImportableExportable::new(memory, Some((String::from(module), String::from(field)))));
|
||||
fn declare_memory_import(&mut self, memory: Memory, module: &'data str, field: &'data str) {
|
||||
self.info.memories.push(ImportableExportable::new(
|
||||
memory,
|
||||
Some((String::from(module), String::from(field))),
|
||||
));
|
||||
}
|
||||
|
||||
fn declare_data_initialization(
|
||||
|
@ -11,12 +11,10 @@ pub fn print_instance_offsets(instance: &Instance) {
|
||||
let instance_address = instance as *const _ as usize;
|
||||
let data_ptr = &instance.data_pointers;
|
||||
|
||||
let tables_pointer_address_ptr: *const usize =
|
||||
unsafe { transmute(&data_ptr.tables) };
|
||||
let tables_pointer_address_ptr: *const usize = unsafe { transmute(&data_ptr.tables) };
|
||||
let tables_pointer_address = tables_pointer_address_ptr as usize;
|
||||
|
||||
let memories_pointer_address_ptr: *const usize =
|
||||
unsafe { transmute(&data_ptr.memories) };
|
||||
let memories_pointer_address_ptr: *const usize = unsafe { transmute(&data_ptr.memories) };
|
||||
let memories_pointer_address = memories_pointer_address_ptr as 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) };
|
||||
let memories_pointer_address_0_len = memories_pointer_address_ptr_0_len as usize;
|
||||
|
||||
let globals_pointer_address_ptr: *const usize =
|
||||
unsafe { transmute(&data_ptr.globals) };
|
||||
let globals_pointer_address_ptr: *const usize = unsafe { transmute(&data_ptr.globals) };
|
||||
let globals_pointer_address = globals_pointer_address_ptr as usize;
|
||||
|
||||
println!(
|
||||
@ -53,7 +50,6 @@ instance.data_pointers.globals \t- {:X} | offset - {:?}
|
||||
tables_pointer_address - instance_address,
|
||||
memories_pointer_address,
|
||||
memories_pointer_address - instance_address,
|
||||
|
||||
memories_pointer_address_0,
|
||||
0,
|
||||
memories_pointer_address_0_data,
|
||||
@ -61,7 +57,6 @@ instance.data_pointers.globals \t- {:X} | offset - {:?}
|
||||
data_ptr.memories.get_unchecked(0).len,
|
||||
memories_pointer_address_0_len,
|
||||
memories_pointer_address_0_len - memories_pointer_address_0_data,
|
||||
|
||||
globals_pointer_address,
|
||||
globals_pointer_address - instance_address,
|
||||
);
|
||||
|
Loading…
Reference in New Issue
Block a user