mirror of
https://github.com/fluencelabs/wasmer
synced 2025-06-28 16:11:32 +00:00
Formatted files
This commit is contained in:
@ -1,5 +1,5 @@
|
||||
use core::ptr::NonNull;
|
||||
use core::ops::{Index, IndexMut};
|
||||
use core::ptr::NonNull;
|
||||
|
||||
#[derive(Copy, Clone)]
|
||||
#[repr(transparent)]
|
||||
@ -17,7 +17,7 @@ impl<T> UncheckedSlice<T> {
|
||||
#[inline]
|
||||
unsafe fn get_unchecked_mut(&mut self, index: usize) -> &mut T {
|
||||
let ptr = self.ptr.as_ptr();
|
||||
&mut*(ptr.add(index) as *mut _)
|
||||
&mut *(ptr.add(index) as *mut _)
|
||||
}
|
||||
|
||||
pub unsafe fn dangling() -> UncheckedSlice<T> {
|
||||
@ -38,9 +38,7 @@ impl<T> UncheckedSlice<T> {
|
||||
impl<'a, T> From<&'a [T]> for UncheckedSlice<T> {
|
||||
fn from(slice: &[T]) -> UncheckedSlice<T> {
|
||||
let ptr: NonNull<[T]> = slice.into();
|
||||
UncheckedSlice {
|
||||
ptr: ptr.cast(),
|
||||
}
|
||||
UncheckedSlice { ptr: ptr.cast() }
|
||||
}
|
||||
}
|
||||
|
||||
@ -52,9 +50,7 @@ pub struct BoundedSlice<T> {
|
||||
impl<T> BoundedSlice<T> {
|
||||
pub fn get(&self, index: usize) -> Option<&T> {
|
||||
if index < self.len {
|
||||
unsafe {
|
||||
Some(self.data.get_unchecked(index))
|
||||
}
|
||||
unsafe { Some(self.data.get_unchecked(index)) }
|
||||
} else {
|
||||
None
|
||||
}
|
||||
@ -62,9 +58,7 @@ impl<T> BoundedSlice<T> {
|
||||
|
||||
pub fn get_mut(&mut self, index: usize) -> Option<&mut T> {
|
||||
if index < self.len {
|
||||
unsafe {
|
||||
Some(self.data.get_unchecked_mut(index))
|
||||
}
|
||||
unsafe { Some(self.data.get_unchecked_mut(index)) }
|
||||
} else {
|
||||
None
|
||||
}
|
||||
|
26
src/main.rs
26
src/main.rs
@ -2,29 +2,28 @@
|
||||
extern crate error_chain;
|
||||
#[macro_use]
|
||||
extern crate structopt;
|
||||
extern crate wabt;
|
||||
extern crate cranelift_codegen;
|
||||
extern crate cranelift_entity;
|
||||
extern crate cranelift_native;
|
||||
extern crate cranelift_wasm;
|
||||
extern crate cranelift_entity;
|
||||
extern crate wabt;
|
||||
#[macro_use]
|
||||
extern crate target_lexicon;
|
||||
extern crate spin;
|
||||
|
||||
use std::path::PathBuf;
|
||||
use std::error::Error;
|
||||
use std::fs::File;
|
||||
use std::io;
|
||||
use std::io::Read;
|
||||
use std::path::PathBuf;
|
||||
use std::process::exit;
|
||||
use std::error::Error;
|
||||
|
||||
use structopt::StructOpt;
|
||||
use wabt::wat2wasm;
|
||||
|
||||
pub mod webassembly;
|
||||
pub mod spec;
|
||||
pub mod common;
|
||||
|
||||
pub mod spec;
|
||||
pub mod webassembly;
|
||||
|
||||
#[derive(Debug, StructOpt)]
|
||||
#[structopt(name = "wasmer", about = "WASM execution runtime.")]
|
||||
@ -32,7 +31,7 @@ pub mod common;
|
||||
enum CLIOptions {
|
||||
/// Run a WebAssembly file. Formats accepted: wasm, wast
|
||||
#[structopt(name = "run")]
|
||||
Run(Run)
|
||||
Run(Run),
|
||||
}
|
||||
|
||||
#[derive(Debug, StructOpt)]
|
||||
@ -44,7 +43,7 @@ struct Run {
|
||||
path: PathBuf,
|
||||
}
|
||||
|
||||
/// Read the contents of a file
|
||||
/// Read the contents of a file
|
||||
fn read_file_contents(path: PathBuf) -> Result<Vec<u8>, io::Error> {
|
||||
let mut buffer: Vec<u8> = Vec::new();
|
||||
let mut file = File::open(path)?;
|
||||
@ -53,12 +52,11 @@ fn read_file_contents(path: PathBuf) -> Result<Vec<u8>, io::Error> {
|
||||
}
|
||||
|
||||
/// Execute a WASM/WAT file
|
||||
fn execute_wasm(wasm_path: PathBuf) -> Result<(), String>{
|
||||
let mut wasm_binary: Vec<u8> = read_file_contents(wasm_path).map_err(|err| String::from(err.description()))?;
|
||||
fn execute_wasm(wasm_path: PathBuf) -> Result<(), String> {
|
||||
let mut wasm_binary: Vec<u8> =
|
||||
read_file_contents(wasm_path).map_err(|err| String::from(err.description()))?;
|
||||
if !webassembly::utils::is_wasm_binary(&wasm_binary) {
|
||||
wasm_binary = wat2wasm(
|
||||
wasm_binary
|
||||
).map_err(|err| String::from(err.description()))?;
|
||||
wasm_binary = wat2wasm(wasm_binary).map_err(|err| String::from(err.description()))?;
|
||||
}
|
||||
|
||||
webassembly::instantiate(wasm_binary, None).map_err(|err| String::from(err.description()))?;
|
||||
|
115
src/spec/mod.rs
115
src/spec/mod.rs
@ -70,9 +70,9 @@ wast total: 0 passed; 17955 failed
|
||||
//! ```
|
||||
|
||||
pub extern crate wabt;
|
||||
pub use wabt::script::Value;
|
||||
pub use wabt::script::Action;
|
||||
pub use wabt::script::CommandKind;
|
||||
pub use wabt::script::Value;
|
||||
|
||||
use std::path::Path;
|
||||
use wabt::script::*;
|
||||
@ -93,7 +93,12 @@ pub trait ScriptHandler {
|
||||
///
|
||||
/// Targets either the last loaded module if `module` is None, or
|
||||
/// the module registered with the given name otherwise.
|
||||
fn action_invoke(&mut self, module: Option<String>, field: String, args: Vec<Value>) -> InvokationResult;
|
||||
fn action_invoke(
|
||||
&mut self,
|
||||
module: Option<String>,
|
||||
field: String,
|
||||
args: Vec<Value>,
|
||||
) -> InvokationResult;
|
||||
|
||||
/// Handles an `get` action.
|
||||
///
|
||||
@ -110,16 +115,18 @@ pub trait ScriptHandler {
|
||||
/// if a function call trapped or exhausted the stack.
|
||||
fn action(&mut self, action: Action) -> Vec<Value> {
|
||||
match action {
|
||||
Action::Invoke { module, field, args } => {
|
||||
Action::Invoke {
|
||||
module,
|
||||
field,
|
||||
args,
|
||||
} => {
|
||||
if let InvokationResult::Vals(v) = self.action_invoke(module, field, args) {
|
||||
v
|
||||
} else {
|
||||
panic!("invokation returned Trap or exhausted the stack");
|
||||
}
|
||||
}
|
||||
Action::Get { module, field } => {
|
||||
vec![self.action_get(module, field)]
|
||||
}
|
||||
Action::Get { module, field } => vec![self.action_get(module, field)],
|
||||
}
|
||||
}
|
||||
|
||||
@ -151,14 +158,16 @@ pub trait ScriptHandler {
|
||||
/// does not trap, or refers to an global.
|
||||
fn assert_trap(&mut self, action: Action) {
|
||||
match action {
|
||||
Action::Invoke { module, field, args } => {
|
||||
Action::Invoke {
|
||||
module,
|
||||
field,
|
||||
args,
|
||||
} => {
|
||||
if let InvokationResult::Vals(results) = self.action_invoke(module, field, args) {
|
||||
panic!("invokation did not trap, but returned {:?}", results);
|
||||
}
|
||||
}
|
||||
Action::Get { .. } => {
|
||||
panic!("a global access can not trap!")
|
||||
}
|
||||
Action::Get { .. } => panic!("a global access can not trap!"),
|
||||
}
|
||||
}
|
||||
|
||||
@ -267,27 +276,26 @@ impl<'a> ::std::cmp::PartialEq for NanCompare<'a> {
|
||||
if self.0.len() != other.0.len() {
|
||||
return false;
|
||||
}
|
||||
self.0.iter().zip(other.0.iter()).all(|pair| {
|
||||
match pair {
|
||||
(Value::I32(l), Value::I32(r)) => l == r,
|
||||
(Value::I64(l), Value::I64(r)) => l == r,
|
||||
(Value::F32(l), Value::F32(r)) if l.is_nan() && r.is_nan() => {
|
||||
l.payload() == r.payload()
|
||||
},
|
||||
(Value::F64(l), Value::F64(r)) if l.is_nan() && r.is_nan() => {
|
||||
l.payload() == r.payload()
|
||||
},
|
||||
(Value::F32(l), Value::F32(r)) => l == r,
|
||||
(Value::F64(l), Value::F64(r)) => l == r,
|
||||
_ => false,
|
||||
self.0.iter().zip(other.0.iter()).all(|pair| match pair {
|
||||
(Value::I32(l), Value::I32(r)) => l == r,
|
||||
(Value::I64(l), Value::I64(r)) => l == r,
|
||||
(Value::F32(l), Value::F32(r)) if l.is_nan() && r.is_nan() => {
|
||||
l.payload() == r.payload()
|
||||
}
|
||||
(Value::F64(l), Value::F64(r)) if l.is_nan() && r.is_nan() => {
|
||||
l.payload() == r.payload()
|
||||
}
|
||||
(Value::F32(l), Value::F32(r)) => l == r,
|
||||
(Value::F64(l), Value::F64(r)) => l == r,
|
||||
_ => false,
|
||||
})
|
||||
}
|
||||
}
|
||||
impl<'a> ::std::fmt::Debug for NanCompare<'a> {
|
||||
fn fmt(&self, formatter: &mut ::std::fmt::Formatter) -> ::std::fmt::Result {
|
||||
formatter.debug_list().entries(self.0.iter().map(|e| {
|
||||
match e {
|
||||
formatter
|
||||
.debug_list()
|
||||
.entries(self.0.iter().map(|e| match e {
|
||||
Value::F32(v) if v.is_nan() => {
|
||||
let p = v.payload();
|
||||
format!("F32(NaN:0x{:x})", p)
|
||||
@ -296,9 +304,9 @@ impl<'a> ::std::fmt::Debug for NanCompare<'a> {
|
||||
let p = v.payload();
|
||||
format!("F64(NaN:0x{:x})", p)
|
||||
}
|
||||
_ => format!("{:?}", e)
|
||||
}
|
||||
})).finish()
|
||||
_ => format!("{:?}", e),
|
||||
}))
|
||||
.finish()
|
||||
}
|
||||
}
|
||||
|
||||
@ -344,8 +352,12 @@ impl NanPayload for f32 {
|
||||
let p = bits & mask;
|
||||
p as u64
|
||||
}
|
||||
fn signif() -> u32 { 23 }
|
||||
fn infinite() -> Self { 1.0 / 0.0 }
|
||||
fn signif() -> u32 {
|
||||
23
|
||||
}
|
||||
fn infinite() -> Self {
|
||||
1.0 / 0.0
|
||||
}
|
||||
fn canonical_payload() -> u64 {
|
||||
1u64 << (Self::signif() - 1)
|
||||
}
|
||||
@ -374,8 +386,12 @@ impl NanPayload for f64 {
|
||||
let p = bits & mask;
|
||||
p
|
||||
}
|
||||
fn signif() -> u32 { 52 }
|
||||
fn infinite() -> Self { 1.0 / 0.0 }
|
||||
fn signif() -> u32 {
|
||||
52
|
||||
}
|
||||
fn infinite() -> Self {
|
||||
1.0 / 0.0
|
||||
}
|
||||
fn canonical_payload() -> u64 {
|
||||
1u64 << (Self::signif() - 1)
|
||||
}
|
||||
@ -423,24 +439,38 @@ impl SpectestResult {
|
||||
break;
|
||||
}
|
||||
}
|
||||
println!("wast total: {} passed; {} failed", self.successes, self.failures.len());
|
||||
println!(
|
||||
"wast total: {} passed; {} failed",
|
||||
self.successes,
|
||||
self.failures.len()
|
||||
);
|
||||
panic!("some wast commands failed");
|
||||
} else {
|
||||
println!("wast total: {} passed; {} failed", self.successes, self.failures.len());
|
||||
println!(
|
||||
"wast total: {} passed; {} failed",
|
||||
self.successes,
|
||||
self.failures.len()
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Run all scripts of the bundled webassembly testsuite on `handler`.
|
||||
pub fn run_mvp_spectest<T: ScriptHandler>(handler: &mut T) -> SpectestResult {
|
||||
run_all_in_directory(format!("{}/testsuite", env!("CARGO_MANIFEST_DIR")).as_ref(), handler)
|
||||
run_all_in_directory(
|
||||
format!("{}/testsuite", env!("CARGO_MANIFEST_DIR")).as_ref(),
|
||||
handler,
|
||||
)
|
||||
}
|
||||
|
||||
/// Module that is expected under the name "spectest" by all spectest testcases.
|
||||
///
|
||||
/// This is automatically registered by all `run_` functions in this modules
|
||||
/// that work at file granularity or higher.
|
||||
pub const SPECTEST_MODULE: &[u8] = include_bytes!(concat!(env!("CARGO_MANIFEST_DIR"), "/src/spec/spectest.wasm"));
|
||||
pub const SPECTEST_MODULE: &[u8] = include_bytes!(concat!(
|
||||
env!("CARGO_MANIFEST_DIR"),
|
||||
"/src/spec/spectest.wasm"
|
||||
));
|
||||
|
||||
/// Run all scripts in a given directory on `handler`.
|
||||
pub fn run_all_in_directory<T: ScriptHandler>(path: &Path, handler: &mut T) -> SpectestResult {
|
||||
@ -480,7 +510,7 @@ pub fn run_single_file<T: ScriptHandler>(path: &Path, handler: &mut T) -> Specte
|
||||
let filename = path.file_name().unwrap().to_str().unwrap();
|
||||
let source = fs::read(&path).unwrap();
|
||||
|
||||
let mut script = ScriptParser::<>::from_source_and_name(&source, filename).unwrap();
|
||||
let mut script = ScriptParser::from_source_and_name(&source, filename).unwrap();
|
||||
let mut fatal = false;
|
||||
|
||||
handler.reset();
|
||||
@ -507,7 +537,8 @@ pub fn run_single_file<T: ScriptHandler>(path: &Path, handler: &mut T) -> Specte
|
||||
|
||||
match r {
|
||||
Err(msg) => {
|
||||
res.failures.push(("<internal spectest module>".to_owned(), 0, msg));
|
||||
res.failures
|
||||
.push(("<internal spectest module>".to_owned(), 0, msg));
|
||||
fatal = true;
|
||||
}
|
||||
Ok(()) => {
|
||||
@ -518,7 +549,8 @@ pub fn run_single_file<T: ScriptHandler>(path: &Path, handler: &mut T) -> Specte
|
||||
|
||||
while let Some(Command { line, kind }) = script.next().unwrap() {
|
||||
if fatal {
|
||||
res.failures.push((filename.to_owned(), line, "<not attempted>".to_string()));
|
||||
res.failures
|
||||
.push((filename.to_owned(), line, "<not attempted>".to_string()));
|
||||
continue;
|
||||
}
|
||||
match run_single_command(kind, handler) {
|
||||
@ -541,7 +573,10 @@ pub fn run_single_file<T: ScriptHandler>(path: &Path, handler: &mut T) -> Specte
|
||||
/// Note that `T` needs to be exception safe, in the sense that any
|
||||
/// panic that happened during a method call should not affect it beyond
|
||||
/// a subsequent `reset()` call.
|
||||
pub fn run_single_command<T: ScriptHandler>(kind: CommandKind, handler: &mut T) -> Result<(), String> {
|
||||
pub fn run_single_command<T: ScriptHandler>(
|
||||
kind: CommandKind,
|
||||
handler: &mut T,
|
||||
) -> Result<(), String> {
|
||||
use std::panic::*;
|
||||
|
||||
if let Err(msg) = catch_unwind(AssertUnwindSafe(|| {
|
||||
|
@ -1,15 +1,15 @@
|
||||
use std::path::Path;
|
||||
use std::collections::HashMap;
|
||||
use std::path::Path;
|
||||
use std::rc::Rc;
|
||||
|
||||
use wabt::script::{Value, Action};
|
||||
use super::{InvokationResult, ScriptHandler, run_single_file};
|
||||
use super::{run_single_file, InvokationResult, ScriptHandler};
|
||||
use crate::webassembly::{compile, instantiate, Error, ErrorKind, Module};
|
||||
use wabt::script::{Action, Value};
|
||||
// use crate::webassembly::instance::InvokeResult;
|
||||
|
||||
struct StoreCtrl<'module> {
|
||||
last_module: Option<Module>,
|
||||
modules: HashMap<String, Rc<&'module Module>>
|
||||
modules: HashMap<String, Rc<&'module Module>>,
|
||||
}
|
||||
|
||||
impl<'module> StoreCtrl<'module> {
|
||||
@ -112,8 +112,7 @@ impl<'module> ScriptHandler for StoreCtrl<'module> {
|
||||
// println!("action invoke {}", module.unwrap_or("as".to_string()));
|
||||
// let modul = &self.last_module;
|
||||
// modul.expect("a");
|
||||
//
|
||||
|
||||
//
|
||||
}
|
||||
fn action_get(&mut self, module: Option<String>, field: String) -> Value {
|
||||
// println!("action get");
|
||||
@ -131,7 +130,7 @@ impl<'module> ScriptHandler for StoreCtrl<'module> {
|
||||
let module_wrapped = instantiate(bytes, None);
|
||||
match module_wrapped {
|
||||
Err(ErrorKind::CompileError(v)) => {}
|
||||
_ => panic!("Module compilation should have failed")
|
||||
_ => panic!("Module compilation should have failed"),
|
||||
}
|
||||
}
|
||||
fn assert_invalid(&mut self, bytes: Vec<u8>) {
|
||||
@ -140,7 +139,7 @@ impl<'module> ScriptHandler for StoreCtrl<'module> {
|
||||
// print!("IS INVALID?? {:?}", module_wrapped);
|
||||
match module_wrapped {
|
||||
Err(ErrorKind::CompileError(v)) => {}
|
||||
_ => assert!(false, "Module compilation should have failed")
|
||||
_ => assert!(false, "Module compilation should have failed"),
|
||||
}
|
||||
}
|
||||
fn assert_uninstantiable(&mut self, bytes: Vec<u8>) {
|
||||
@ -157,7 +156,11 @@ impl<'module> ScriptHandler for StoreCtrl<'module> {
|
||||
|
||||
fn do_test(test_name: String) {
|
||||
let mut handler = &mut StoreCtrl::new();
|
||||
let test_path_str = format!("{}/src/spec/tests/{}.wast", env!("CARGO_MANIFEST_DIR"), test_name);
|
||||
let test_path_str = format!(
|
||||
"{}/src/spec/tests/{}.wast",
|
||||
env!("CARGO_MANIFEST_DIR"),
|
||||
test_name
|
||||
);
|
||||
let test_path = Path::new(&test_path_str);
|
||||
let res = run_single_file(&test_path, handler);
|
||||
res.present()
|
||||
|
@ -6,20 +6,24 @@
|
||||
//! synchronously instantiate a given webassembly::Module object. However, the
|
||||
//! primary way to get an Instance is through the asynchronous
|
||||
//! webassembly::instantiateStreaming() function.
|
||||
use cranelift_wasm::{GlobalInit, FuncIndex};
|
||||
use super::module::Module;
|
||||
use super::module::{DataInitializer, Exportable};
|
||||
use cranelift_entity::EntityRef;
|
||||
use cranelift_wasm::{FuncIndex, GlobalInit};
|
||||
|
||||
use super::memory::LinearMemory;
|
||||
use std::marker::PhantomData;
|
||||
use std::{slice, mem};
|
||||
use std::sync::Arc;
|
||||
use std::{mem, slice};
|
||||
|
||||
use spin::RwLock;
|
||||
use super::super::common::slice::{BoundedSlice, UncheckedSlice};
|
||||
use spin::RwLock;
|
||||
|
||||
pub fn get_function_addr(base: *const (), functions: &[usize], func_index: &FuncIndex) -> *const () {
|
||||
pub fn get_function_addr(
|
||||
base: *const (),
|
||||
functions: &[usize],
|
||||
func_index: &FuncIndex,
|
||||
) -> *const () {
|
||||
let offset = functions[func_index.index()];
|
||||
(base as usize + offset) as _
|
||||
}
|
||||
@ -30,18 +34,14 @@ pub enum VmCtx {}
|
||||
impl VmCtx {
|
||||
pub fn data(&self) -> &VmCtxData {
|
||||
let heap_ptr = self as *const _ as *const VmCtxData;
|
||||
unsafe {
|
||||
&*heap_ptr.sub(1)
|
||||
}
|
||||
unsafe { &*heap_ptr.sub(1) }
|
||||
}
|
||||
|
||||
/// This is safe because the offset is 32 bits and thus
|
||||
/// cannot extend out of the guarded wasm memory.
|
||||
pub fn fastpath_offset_ptr<T>(&self, offset: u32) -> *const T {
|
||||
let heap_ptr = self as *const _ as *const u8;
|
||||
unsafe {
|
||||
heap_ptr.add(offset as usize) as *const T
|
||||
}
|
||||
unsafe { heap_ptr.add(offset as usize) as *const T }
|
||||
}
|
||||
}
|
||||
|
||||
@ -60,7 +60,6 @@ pub struct UserData {
|
||||
pub instance: Instance,
|
||||
}
|
||||
|
||||
|
||||
/// An Instance of a WebAssembly module
|
||||
#[derive(Debug)]
|
||||
pub struct Instance {
|
||||
@ -93,7 +92,10 @@ impl Instance {
|
||||
}
|
||||
// instantiate tables
|
||||
for table_element in &module.info.table_elements {
|
||||
assert!(table_element.base.is_none(), "globalvalue base not supported yet.");
|
||||
assert!(
|
||||
table_element.base.is_none(),
|
||||
"globalvalue base not supported yet."
|
||||
);
|
||||
let base = 0;
|
||||
|
||||
let table = &mut tables[table_element.table_index];
|
||||
@ -116,7 +118,8 @@ impl Instance {
|
||||
memories.reserve_exact(module.info.memories.len());
|
||||
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);
|
||||
}
|
||||
for init in &module.info.data_initializers {
|
||||
@ -135,7 +138,9 @@ impl Instance {
|
||||
globals.resize(globals_data_size, 0);
|
||||
|
||||
// cast the globals slice to a slice of i64.
|
||||
let globals_data = unsafe { slice::from_raw_parts_mut(globals.as_mut_ptr() as *mut i64, globals_count) };
|
||||
let globals_data = unsafe {
|
||||
slice::from_raw_parts_mut(globals.as_mut_ptr() as *mut i64, globals_count)
|
||||
};
|
||||
for (i, global) in module.info.globals.iter().enumerate() {
|
||||
let value: i64 = match global.entity.initializer {
|
||||
GlobalInit::I32Const(n) => n as _,
|
||||
@ -144,7 +149,7 @@ impl Instance {
|
||||
GlobalInit::F64Const(f) => unsafe { mem::transmute(f) },
|
||||
_ => unimplemented!(),
|
||||
};
|
||||
|
||||
|
||||
globals_data[i] = value;
|
||||
}
|
||||
};
|
||||
@ -167,7 +172,6 @@ impl Instance {
|
||||
// pub fn start_func(&self) -> extern fn(&VmCtx) {
|
||||
// self.start_func
|
||||
// }
|
||||
|
||||
}
|
||||
|
||||
impl Clone for Instance {
|
||||
|
@ -1,24 +1,24 @@
|
||||
pub mod errors;
|
||||
pub mod utils;
|
||||
pub mod module;
|
||||
pub mod memory;
|
||||
pub mod instance;
|
||||
pub mod memory;
|
||||
pub mod module;
|
||||
pub mod utils;
|
||||
|
||||
use std::str::FromStr;
|
||||
use std::time::{Duration, Instant};
|
||||
use cranelift_codegen::isa;
|
||||
use cranelift_native;
|
||||
use std::panic;
|
||||
use std::ptr;
|
||||
use cranelift_native;
|
||||
use std::str::FromStr;
|
||||
use std::time::{Duration, Instant};
|
||||
use target_lexicon::{self, Triple};
|
||||
use wasmparser;
|
||||
use cranelift_codegen::isa;
|
||||
// use cranelift_codegen::print_errors::pretty_verifier_error;
|
||||
// use cranelift_codegen::verifier;
|
||||
|
||||
pub use self::module::Module;
|
||||
pub use self::instance::Instance;
|
||||
pub use self::errors::{Error, ErrorKind};
|
||||
pub use self::instance::Instance;
|
||||
pub use self::memory::LinearMemory;
|
||||
pub use self::module::Module;
|
||||
|
||||
pub struct ResultObject {
|
||||
/// A webassembly::Module object representing the compiled WebAssembly module.
|
||||
@ -29,13 +29,12 @@ pub struct ResultObject {
|
||||
pub instance: Instance,
|
||||
}
|
||||
|
||||
pub struct ImportObject {
|
||||
}
|
||||
pub struct ImportObject {}
|
||||
|
||||
/// The webassembly::instantiate() function allows you to compile and
|
||||
/// instantiate WebAssembly code
|
||||
|
||||
/// Params:
|
||||
/// Params:
|
||||
/// * `buffer_source`: A `Vec<u8>` containing the
|
||||
/// binary code of the .wasm module you want to compile.
|
||||
|
||||
@ -46,16 +45,16 @@ pub struct ImportObject {
|
||||
/// webassembly::LinkError is thrown.
|
||||
|
||||
/// Errors:
|
||||
/// If the operation fails, the Result rejects with a
|
||||
/// If the operation fails, the Result rejects with a
|
||||
/// webassembly::CompileError, webassembly::LinkError, or
|
||||
/// webassembly::RuntimeError, depending on the cause of the failure.
|
||||
pub fn instantiate(buffer_source: Vec<u8>, import_object: Option<ImportObject>) -> Result<ResultObject, ErrorKind> {
|
||||
pub fn instantiate(
|
||||
buffer_source: Vec<u8>,
|
||||
import_object: Option<ImportObject>,
|
||||
) -> Result<ResultObject, ErrorKind> {
|
||||
let module = compile(buffer_source)?;
|
||||
let instance = Instance::new(&module, ptr::null(), &vec![]);
|
||||
Ok(ResultObject{
|
||||
module,
|
||||
instance
|
||||
})
|
||||
Ok(ResultObject { module, instance })
|
||||
}
|
||||
|
||||
/// The webassembly::compile() function compiles a webassembly::Module
|
||||
@ -63,19 +62,19 @@ pub fn instantiate(buffer_source: Vec<u8>, import_object: Option<ImportObject>)
|
||||
/// is necessary to a compile a module before it can be instantiated
|
||||
/// (otherwise, the webassembly::instantiate() function should be used).
|
||||
|
||||
/// Params:
|
||||
/// Params:
|
||||
/// * `buffer_source`: A `Vec<u8>` containing the
|
||||
/// binary code of the .wasm module you want to compile.
|
||||
|
||||
/// Errors:
|
||||
/// If the operation fails, the Result rejects with a
|
||||
/// If the operation fails, the Result rejects with a
|
||||
/// webassembly::CompileError.
|
||||
pub fn compile(buffer_source: Vec<u8>) -> Result<Module, ErrorKind> {
|
||||
// TODO: This should be automatically validated when creating the Module
|
||||
if !validate(&buffer_source) {
|
||||
return Err(ErrorKind::CompileError("Module not valid".to_string()));
|
||||
}
|
||||
|
||||
|
||||
let module = Module::from_bytes(buffer_source, triple!("riscv64"), None)?;
|
||||
|
||||
// let isa = isa::lookup(module.info.triple)
|
||||
@ -87,7 +86,7 @@ pub fn compile(buffer_source: Vec<u8>) -> Result<Module, ErrorKind> {
|
||||
// .map_err(|errors| panic!(pretty_verifier_error(func, Some(&*isa), None, errors)))
|
||||
// .unwrap();
|
||||
// };
|
||||
|
||||
|
||||
Ok(module)
|
||||
}
|
||||
|
||||
@ -95,7 +94,7 @@ pub fn compile(buffer_source: Vec<u8>) -> Result<Module, ErrorKind> {
|
||||
/// array of WebAssembly binary code, returning whether the bytes
|
||||
/// form a valid wasm module (true) or not (false).
|
||||
|
||||
/// Params:
|
||||
/// Params:
|
||||
/// * `buffer_source`: A `Vec<u8>` containing the
|
||||
/// binary code of the .wasm module you want to compile.
|
||||
pub fn validate(buffer_source: &Vec<u8>) -> bool {
|
||||
|
@ -4,27 +4,39 @@
|
||||
use cranelift_codegen::cursor::FuncCursor;
|
||||
use cranelift_codegen::ir::immediates::{Imm64, Offset32};
|
||||
use cranelift_codegen::ir::types::*;
|
||||
use cranelift_codegen::ir::{self, InstBuilder, FuncRef, ExtFuncData, ExternalName, Signature, AbiParam,
|
||||
ArgumentPurpose, ArgumentLoc, ArgumentExtension, Function};
|
||||
use cranelift_codegen::ir::{
|
||||
self, AbiParam, ArgumentExtension, ArgumentLoc, ArgumentPurpose, ExtFuncData, ExternalName,
|
||||
FuncRef, Function, InstBuilder, Signature,
|
||||
};
|
||||
use cranelift_codegen::settings;
|
||||
use cranelift_entity::{EntityRef, PrimaryMap};
|
||||
|
||||
use super::errors::ErrorKind;
|
||||
use super::memory::LinearMemory;
|
||||
use cranelift_wasm::{
|
||||
translate_module, // ReturnMode,
|
||||
DefinedFuncIndex,
|
||||
FuncEnvironment as FuncEnvironmentTrait,
|
||||
FuncIndex,
|
||||
FuncTranslator,
|
||||
Global,
|
||||
GlobalIndex,
|
||||
GlobalVariable,
|
||||
Memory,
|
||||
MemoryIndex,
|
||||
ModuleEnvironment,
|
||||
SignatureIndex,
|
||||
Table,
|
||||
TableIndex,
|
||||
WasmResult,
|
||||
};
|
||||
use std::string::String;
|
||||
use std::vec::Vec;
|
||||
use target_lexicon::{Triple, PointerWidth};
|
||||
use cranelift_wasm::{
|
||||
FuncTranslator,
|
||||
FuncEnvironment as FuncEnvironmentTrait, GlobalVariable, ModuleEnvironment, WasmResult,
|
||||
DefinedFuncIndex, FuncIndex, Global, GlobalIndex, Memory, MemoryIndex, SignatureIndex, Table,
|
||||
TableIndex, translate_module, // ReturnMode,
|
||||
};
|
||||
use super::memory::LinearMemory;
|
||||
use target_lexicon::{PointerWidth, Triple};
|
||||
|
||||
// use alloc::vec::Vec;
|
||||
// use alloc::string::String;
|
||||
|
||||
|
||||
/// Compute a `ir::ExternalName` for a given wasm function index.
|
||||
fn get_func_name(func_index: FuncIndex) -> ir::ExternalName {
|
||||
ir::ExternalName::user(0, func_index.index() as u32)
|
||||
@ -124,7 +136,6 @@ impl ModuleInfo {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/// A data initializer for linear memory.
|
||||
#[derive(Debug)]
|
||||
pub struct DataInitializer {
|
||||
@ -138,7 +149,6 @@ pub struct DataInitializer {
|
||||
pub data: Vec<u8>,
|
||||
}
|
||||
|
||||
|
||||
/// Possible values for a WebAssembly table element.
|
||||
#[derive(Clone, Debug)]
|
||||
pub enum TableElement {
|
||||
@ -161,7 +171,6 @@ pub struct TableElements {
|
||||
pub elements: Vec<FuncIndex>,
|
||||
}
|
||||
|
||||
|
||||
/// This `ModuleEnvironment` implementation is a "naïve" one, doing essentially nothing and
|
||||
/// emitting placeholders when forced to. Don't try to execute code translated for this
|
||||
/// environment, essentially here for translation debug purposes.
|
||||
@ -174,7 +183,6 @@ pub struct Module {
|
||||
|
||||
/// Vector of wasm bytecode size for each function.
|
||||
pub func_bytecode_sizes: Vec<usize>,
|
||||
|
||||
// How to return from functions.
|
||||
// return_mode: ReturnMode,
|
||||
}
|
||||
@ -204,11 +212,13 @@ impl Module {
|
||||
// }
|
||||
// }
|
||||
|
||||
pub fn from_bytes(buffer_source: Vec<u8>, triple: Triple, flags: Option<settings::Flags>) -> Result<Self, ErrorKind> {
|
||||
pub fn from_bytes(
|
||||
buffer_source: Vec<u8>,
|
||||
triple: Triple,
|
||||
flags: Option<settings::Flags>,
|
||||
) -> Result<Self, ErrorKind> {
|
||||
// let return_mode = ReturnMode::NormalReturns;
|
||||
let flags = flags.unwrap_or_else(|| {
|
||||
settings::Flags::new(settings::builder())
|
||||
});
|
||||
let flags = flags.unwrap_or_else(|| settings::Flags::new(settings::builder()));
|
||||
let mut module = Self {
|
||||
info: ModuleInfo::with_triple_flags(triple, flags),
|
||||
trans: FuncTranslator::new(),
|
||||
@ -216,7 +226,8 @@ impl Module {
|
||||
// return_mode,
|
||||
};
|
||||
// We iterate through the source bytes, generating the compiled module
|
||||
translate_module(&buffer_source, &mut module).map_err(|e| ErrorKind::CompileError(e.to_string()))?;
|
||||
translate_module(&buffer_source, &mut module)
|
||||
.map_err(|e| ErrorKind::CompileError(e.to_string()))?;
|
||||
|
||||
Ok(module)
|
||||
}
|
||||
@ -247,18 +258,17 @@ impl Module {
|
||||
))
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/// The `FuncEnvironment` implementation for use by the `Module`.
|
||||
pub struct FuncEnvironment<'environment> {
|
||||
pub mod_info: &'environment ModuleInfo,
|
||||
|
||||
// return_mode: ReturnMode,
|
||||
}
|
||||
|
||||
impl<'environment> FuncEnvironment<'environment> {
|
||||
pub fn new(mod_info: &'environment ModuleInfo) -> Self { // , return_mode: ReturnMode
|
||||
pub fn new(mod_info: &'environment ModuleInfo) -> Self {
|
||||
// , return_mode: ReturnMode
|
||||
Self {
|
||||
mod_info,
|
||||
// return_mode,
|
||||
@ -406,7 +416,7 @@ impl<'environment> FuncEnvironmentTrait for FuncEnvironment<'environment> {
|
||||
|
||||
let base = self.mod_info.tables_base.unwrap_or_else(|| {
|
||||
let tables_offset = self.ptr_size() as i32 * -1;
|
||||
let new_base = func.create_global_value(ir::GlobalValueData::VMContext { });
|
||||
let new_base = func.create_global_value(ir::GlobalValueData::VMContext {});
|
||||
// {
|
||||
// offset: tables_offset.into(),
|
||||
// });
|
||||
@ -435,7 +445,7 @@ impl<'environment> FuncEnvironmentTrait for FuncEnvironment<'environment> {
|
||||
let new_table_bounds = func.create_global_value(ir::GlobalValueData::Load {
|
||||
base: new_table_bounds_addr,
|
||||
offset: 0.into(),
|
||||
global_type: I32, // Might be self.pointer_type()
|
||||
global_type: I32, // Might be self.pointer_type()
|
||||
});
|
||||
|
||||
let table = func.create_table(ir::TableData {
|
||||
@ -444,7 +454,7 @@ impl<'environment> FuncEnvironmentTrait for FuncEnvironment<'environment> {
|
||||
// min_size: (self.mod_info.tables[table_index].size as i64).into(),
|
||||
bound_gv: new_table_bounds,
|
||||
element_size: (ptr_size as i64).into(),
|
||||
index_type: I32
|
||||
index_type: I32,
|
||||
});
|
||||
|
||||
table
|
||||
|
@ -1,4 +1,3 @@
|
||||
|
||||
/// Detect if a provided binary is a WASM file
|
||||
pub fn is_wasm_binary(binary: &Vec<u8>) -> bool {
|
||||
binary.starts_with(&[b'\0', b'a', b's', b'm'])
|
||||
|
Reference in New Issue
Block a user