mirror of
https://github.com/fluencelabs/wasmer
synced 2025-06-29 08:31:32 +00:00
run cargo fmt
This commit is contained in:
@ -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
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -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
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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!");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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 {
|
||||||
|
@ -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() {
|
||||||
|
@ -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> {
|
||||||
|
@ -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::*;
|
||||||
|
@ -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> {
|
||||||
|
14
src/main.rs
14
src/main.rs
@ -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);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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)
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -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
|
||||||
|
.par_iter()
|
||||||
|
.map(|function_body| -> CompiledFunction {
|
||||||
// let r = *Arc::from_raw(isa_ptr);
|
// let r = *Arc::from_raw(isa_ptr);
|
||||||
compile_function(&*options.isa, function_body).unwrap()
|
compile_function(&*options.isa, function_body).unwrap()
|
||||||
// unimplemented!()
|
// unimplemented!()
|
||||||
}).collect();
|
}).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 {
|
||||||
else {
|
panic!(
|
||||||
panic!("Imported table value was not provided ({}.{})", module_name, field_name)
|
"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.
|
||||||
@ -552,7 +566,11 @@ extern "C" fn grow_memory(size: u32, memory_index: u32, instance: &mut Instance)
|
|||||||
// 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
|
||||||
|
@ -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
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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");
|
||||||
|
@ -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(
|
||||||
|
@ -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,
|
||||||
);
|
);
|
||||||
|
Reference in New Issue
Block a user