Merge remote-tracking branch 'origin/master' into feature/llvm-osr

This commit is contained in:
losfair
2019-08-19 13:06:59 -07:00
31 changed files with 892 additions and 585 deletions

33
CONTRIBUTING.md Normal file
View File

@ -0,0 +1,33 @@
# How to Contribute to Wasmer
Thank you for your interest in contributing to Wasmer. This document outlines some recommendations on how to contribute.
## Issues & Feature Requests
Please use the issue template and provide a failing example if possible to help us recreate the issue.
## Pull Requests
For large changes, please try reaching the Wasmer using Github Issues or Spectrum Chat to ensure we can accept the change once it is ready.
We recommend trying the following commands before sending a pull request to ensure code quality:
- `cargo fmt --all` Ensures all code is correctly formatted.
- Run `cargo test` in the crates that you are modifying.
- Run `cargo build --all` (nightly) or `cargo build --all --exclude wasmer-singlepass-backend`
A comprehensive CI test suite will be run by a Wasmer team member after the PR has been created.
### Common Build Issues
**LLVM Dependency**
The LLVM backend requires LLVM to be installed to compile.
So, you may run into the following error:
```
Didn't find usable system-wide LLVM.
No suitable version of LLVM was found system-wide or pointed
```
**Singlepass Nightly Only**
The singlepass crate depends on nightly so you may need to add the `+nightly` cargo flag to compile this crate.
`error[E0554]: #![feature] may not be used on the stable release channel`

24
Cargo.lock generated
View File

@ -66,7 +66,7 @@ name = "backtrace-sys"
version = "0.1.28" version = "0.1.28"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [ dependencies = [
"cc 1.0.38 (registry+https://github.com/rust-lang/crates.io-index)", "cc 1.0.40 (registry+https://github.com/rust-lang/crates.io-index)",
"libc 0.2.60 (registry+https://github.com/rust-lang/crates.io-index)", "libc 0.2.60 (registry+https://github.com/rust-lang/crates.io-index)",
] ]
@ -144,7 +144,7 @@ name = "capstone-sys"
version = "0.10.0" version = "0.10.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [ dependencies = [
"cc 1.0.38 (registry+https://github.com/rust-lang/crates.io-index)", "cc 1.0.40 (registry+https://github.com/rust-lang/crates.io-index)",
] ]
[[package]] [[package]]
@ -180,7 +180,7 @@ dependencies = [
[[package]] [[package]]
name = "cc" name = "cc"
version = "1.0.38" version = "1.0.40"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]] [[package]]
@ -243,7 +243,7 @@ name = "cmake"
version = "0.1.40" version = "0.1.40"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [ dependencies = [
"cc 1.0.38 (registry+https://github.com/rust-lang/crates.io-index)", "cc 1.0.40 (registry+https://github.com/rust-lang/crates.io-index)",
] ]
[[package]] [[package]]
@ -658,7 +658,7 @@ name = "libloading"
version = "0.5.1" version = "0.5.1"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [ dependencies = [
"cc 1.0.38 (registry+https://github.com/rust-lang/crates.io-index)", "cc 1.0.40 (registry+https://github.com/rust-lang/crates.io-index)",
"winapi 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", "winapi 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)",
] ]
@ -667,7 +667,7 @@ name = "llvm-sys"
version = "80.1.1" version = "80.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [ dependencies = [
"cc 1.0.38 (registry+https://github.com/rust-lang/crates.io-index)", "cc 1.0.40 (registry+https://github.com/rust-lang/crates.io-index)",
"lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
"libc 0.2.60 (registry+https://github.com/rust-lang/crates.io-index)", "libc 0.2.60 (registry+https://github.com/rust-lang/crates.io-index)",
"regex 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)", "regex 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
@ -730,7 +730,7 @@ version = "0.14.1"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [ dependencies = [
"bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)", "bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)",
"cc 1.0.38 (registry+https://github.com/rust-lang/crates.io-index)", "cc 1.0.40 (registry+https://github.com/rust-lang/crates.io-index)",
"cfg-if 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)", "cfg-if 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)",
"libc 0.2.60 (registry+https://github.com/rust-lang/crates.io-index)", "libc 0.2.60 (registry+https://github.com/rust-lang/crates.io-index)",
"void 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", "void 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)",
@ -956,7 +956,7 @@ version = "6.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [ dependencies = [
"bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)", "bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)",
"cc 1.0.38 (registry+https://github.com/rust-lang/crates.io-index)", "cc 1.0.40 (registry+https://github.com/rust-lang/crates.io-index)",
"rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", "rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)",
] ]
@ -1373,7 +1373,7 @@ name = "wabt-sys"
version = "0.6.1" version = "0.6.1"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [ dependencies = [
"cc 1.0.38 (registry+https://github.com/rust-lang/crates.io-index)", "cc 1.0.40 (registry+https://github.com/rust-lang/crates.io-index)",
"cmake 0.1.40 (registry+https://github.com/rust-lang/crates.io-index)", "cmake 0.1.40 (registry+https://github.com/rust-lang/crates.io-index)",
"glob 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)", "glob 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)",
] ]
@ -1507,7 +1507,7 @@ version = "0.6.0"
dependencies = [ dependencies = [
"byteorder 1.3.2 (registry+https://github.com/rust-lang/crates.io-index)", "byteorder 1.3.2 (registry+https://github.com/rust-lang/crates.io-index)",
"capstone 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)", "capstone 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)",
"cc 1.0.38 (registry+https://github.com/rust-lang/crates.io-index)", "cc 1.0.40 (registry+https://github.com/rust-lang/crates.io-index)",
"goblin 0.0.24 (registry+https://github.com/rust-lang/crates.io-index)", "goblin 0.0.24 (registry+https://github.com/rust-lang/crates.io-index)",
"inkwell 0.1.0 (git+https://github.com/wasmerio/inkwell?branch=llvm8-0)", "inkwell 0.1.0 (git+https://github.com/wasmerio/inkwell?branch=llvm8-0)",
"lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
@ -1566,7 +1566,7 @@ version = "0.6.0"
dependencies = [ dependencies = [
"bincode 1.1.4 (registry+https://github.com/rust-lang/crates.io-index)", "bincode 1.1.4 (registry+https://github.com/rust-lang/crates.io-index)",
"blake2b_simd 0.5.6 (registry+https://github.com/rust-lang/crates.io-index)", "blake2b_simd 0.5.6 (registry+https://github.com/rust-lang/crates.io-index)",
"cc 1.0.38 (registry+https://github.com/rust-lang/crates.io-index)", "cc 1.0.40 (registry+https://github.com/rust-lang/crates.io-index)",
"colored 1.8.0 (registry+https://github.com/rust-lang/crates.io-index)", "colored 1.8.0 (registry+https://github.com/rust-lang/crates.io-index)",
"digest 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)", "digest 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)",
"errno 0.2.4 (registry+https://github.com/rust-lang/crates.io-index)", "errno 0.2.4 (registry+https://github.com/rust-lang/crates.io-index)",
@ -1747,7 +1747,7 @@ dependencies = [
"checksum cargo_toml 0.6.4 (registry+https://github.com/rust-lang/crates.io-index)" = "097f5ce64ba566a83d9d914fd005de1e5937fdd57d8c5d99a7593040955d75a9" "checksum cargo_toml 0.6.4 (registry+https://github.com/rust-lang/crates.io-index)" = "097f5ce64ba566a83d9d914fd005de1e5937fdd57d8c5d99a7593040955d75a9"
"checksum cast 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "926013f2860c46252efceabb19f4a6b308197505082c609025aa6706c011d427" "checksum cast 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "926013f2860c46252efceabb19f4a6b308197505082c609025aa6706c011d427"
"checksum cbindgen 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "0e7e19db9a3892c88c74cbbdcd218196068a928f1b60e736c448b13a1e81f277" "checksum cbindgen 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "0e7e19db9a3892c88c74cbbdcd218196068a928f1b60e736c448b13a1e81f277"
"checksum cc 1.0.38 (registry+https://github.com/rust-lang/crates.io-index)" = "ce400c638d48ee0e9ab75aef7997609ec57367ccfe1463f21bf53c3eca67bf46" "checksum cc 1.0.40 (registry+https://github.com/rust-lang/crates.io-index)" = "b548a4ee81fccb95919d4e22cfea83c7693ebfd78f0495493178db20b3139da7"
"checksum cexpr 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)" = "a7fa24eb00d5ffab90eaeaf1092ac85c04c64aaf358ea6f84505b8116d24c6af" "checksum cexpr 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)" = "a7fa24eb00d5ffab90eaeaf1092ac85c04c64aaf358ea6f84505b8116d24c6af"
"checksum cfg-if 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)" = "b486ce3ccf7ffd79fdeb678eac06a9e6c09fc88d33836340becb8fffe87c5e33" "checksum cfg-if 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)" = "b486ce3ccf7ffd79fdeb678eac06a9e6c09fc88d33836340becb8fffe87c5e33"
"checksum cgmath 0.16.1 (registry+https://github.com/rust-lang/crates.io-index)" = "64a4b57c8f4e3a2e9ac07e0f6abc9c24b6fc9e1b54c3478cfb598f3d0023e51c" "checksum cgmath 0.16.1 (registry+https://github.com/rust-lang/crates.io-index)" = "64a4b57c8f4e3a2e9ac07e0f6abc9c24b6fc9e1b54c3478cfb598f3d0023e51c"

View File

@ -1,6 +1,6 @@
<p align="center"> <p align="center">
<a href="https://wasmer.io" target="_blank" rel="noopener noreferrer"> <a href="https://wasmer.io" target="_blank" rel="noopener noreferrer">
<img width="400" src="https://raw.githubusercontent.com/wasmerio/wasmer/master/logo.png" alt="Wasmer logo"> <img width="300" src="https://raw.githubusercontent.com/wasmerio/wasmer/master/logo.png" alt="Wasmer logo">
</a> </a>
</p> </p>

View File

@ -1,6 +1,8 @@
#![deny( #![deny(
dead_code, dead_code,
nonstandard_style,
unused_imports, unused_imports,
unused_mut,
unused_variables, unused_variables,
unused_unsafe, unused_unsafe,
unreachable_patterns unreachable_patterns

View File

@ -42,7 +42,7 @@ macro_rules! assert_emscripten_output {
// let module = compile(&wasm_bytes[..]) // let module = compile(&wasm_bytes[..])
// .map_err(|err| format!("Can't create the WebAssembly module: {}", err)).unwrap(); // NOTE: Need to figure what the unwrap is for ?? // .map_err(|err| format!("Can't create the WebAssembly module: {}", err)).unwrap(); // NOTE: Need to figure what the unwrap is for ??
let mut emscripten_globals = EmscriptenGlobals::new(&module); let mut emscripten_globals = EmscriptenGlobals::new(&module).expect("globals are valid");
let import_object = generate_emscripten_env(&mut emscripten_globals); let import_object = generate_emscripten_env(&mut emscripten_globals);
let mut instance = module.instantiate(&import_object) let mut instance = module.instantiate(&import_object)

View File

@ -1,6 +1,8 @@
#![deny( #![deny(
dead_code, dead_code,
nonstandard_style,
unused_imports, unused_imports,
unused_mut,
unused_variables, unused_variables,
unused_unsafe, unused_unsafe,
unreachable_patterns unreachable_patterns
@ -14,7 +16,7 @@ use std::collections::HashMap;
use std::path::PathBuf; use std::path::PathBuf;
use std::{f64, ffi::c_void}; use std::{f64, ffi::c_void};
use wasmer_runtime_core::{ use wasmer_runtime_core::{
error::CallResult, error::{CallError, CallResult, ResolveError},
export::Export, export::Export,
func, func,
global::Global, global::Global,
@ -371,10 +373,11 @@ pub fn run_emscripten_instance(
0 => { 0 => {
instance.call(func_name, &[])?; instance.call(func_name, &[])?;
} }
_ => panic!( _ => {
"The emscripten main function has received an incorrect number of params {}", return Err(CallError::Resolve(ResolveError::ExportWrongType {
num_params name: "main".to_string(),
), }))
}
}; };
} }
@ -402,11 +405,18 @@ fn store_module_arguments(ctx: &mut Ctx, args: Vec<&str>) -> (u32, u32) {
(argc as u32 - 1, argv_offset) (argc as u32 - 1, argv_offset)
} }
pub fn emscripten_set_up_memory(memory: &Memory, globals: &EmscriptenGlobalsData) { pub fn emscripten_set_up_memory(
memory: &Memory,
globals: &EmscriptenGlobalsData,
) -> Result<(), String> {
let dynamictop_ptr = globals.dynamictop_ptr; let dynamictop_ptr = globals.dynamictop_ptr;
let dynamic_base = globals.dynamic_base; let dynamic_base = globals.dynamic_base;
if (dynamictop_ptr / 4) as usize >= memory.view::<u32>().len() {
return Err("dynamictop_ptr beyond memory len".to_string());
}
memory.view::<u32>()[(dynamictop_ptr / 4) as usize].set(dynamic_base); memory.view::<u32>()[(dynamictop_ptr / 4) as usize].set(dynamic_base);
Ok(())
} }
pub struct EmscriptenGlobalsData { pub struct EmscriptenGlobalsData {
@ -434,7 +444,7 @@ pub struct EmscriptenGlobals {
} }
impl EmscriptenGlobals { impl EmscriptenGlobals {
pub fn new(module: &Module /*, static_bump: u32 */) -> Self { pub fn new(module: &Module /*, static_bump: u32 */) -> Result<Self, String> {
let mut use_old_abort_on_cannot_grow_memory = false; let mut use_old_abort_on_cannot_grow_memory = false;
for ( for (
index, index,
@ -456,8 +466,8 @@ impl EmscriptenGlobals {
} }
} }
let (table_min, table_max) = get_emscripten_table_size(&module); let (table_min, table_max) = get_emscripten_table_size(&module)?;
let (memory_min, memory_max, shared) = get_emscripten_memory_size(&module); let (memory_min, memory_max, shared) = get_emscripten_memory_size(&module)?;
// Memory initialization // Memory initialization
let memory_type = MemoryDescriptor { let memory_type = MemoryDescriptor {
@ -486,7 +496,7 @@ impl EmscriptenGlobals {
static_top += 16; static_top += 16;
let (dynamic_base, dynamictop_ptr) = let (dynamic_base, dynamictop_ptr) =
get_emscripten_metadata(&module).unwrap_or_else(|| { get_emscripten_metadata(&module)?.unwrap_or_else(|| {
let dynamictop_ptr = static_alloc(&mut static_top, 4); let dynamictop_ptr = static_alloc(&mut static_top, 4);
( (
align_memory(align_memory(static_top) + TOTAL_STACK), align_memory(align_memory(static_top) + TOTAL_STACK),
@ -510,7 +520,7 @@ impl EmscriptenGlobals {
} }
}; };
emscripten_set_up_memory(&memory, &data); emscripten_set_up_memory(&memory, &data)?;
let mut null_func_names = vec![]; let mut null_func_names = vec![];
for ( for (
@ -528,14 +538,14 @@ impl EmscriptenGlobals {
} }
} }
Self { Ok(Self {
data, data,
memory, memory,
table, table,
memory_min, memory_min,
memory_max, memory_max,
null_func_names, null_func_names,
} })
} }
} }

View File

@ -33,37 +33,43 @@ pub fn is_emscripten_module(module: &Module) -> bool {
false false
} }
pub fn get_emscripten_table_size(module: &Module) -> (u32, Option<u32>) { pub fn get_emscripten_table_size(module: &Module) -> Result<(u32, Option<u32>), String> {
assert!( if module.info().imported_tables.len() == 0 {
module.info().imported_tables.len() > 0, return Err("Emscripten requires at least one imported table".to_string());
"Emscripten requires at least one imported table" }
);
let (_, table) = &module.info().imported_tables[ImportedTableIndex::new(0)]; let (_, table) = &module.info().imported_tables[ImportedTableIndex::new(0)];
(table.minimum, table.maximum) Ok((table.minimum, table.maximum))
} }
pub fn get_emscripten_memory_size(module: &Module) -> (Pages, Option<Pages>, bool) { pub fn get_emscripten_memory_size(module: &Module) -> Result<(Pages, Option<Pages>, bool), String> {
assert!( if module.info().imported_memories.len() == 0 {
module.info().imported_tables.len() > 0, return Err("Emscripten requires at least one imported memory".to_string());
"Emscripten requires at least one imported memory" }
);
let (_, memory) = &module.info().imported_memories[ImportedMemoryIndex::new(0)]; let (_, memory) = &module.info().imported_memories[ImportedMemoryIndex::new(0)];
(memory.minimum, memory.maximum, memory.shared) Ok((memory.minimum, memory.maximum, memory.shared))
} }
/// Reads values written by `-s EMIT_EMSCRIPTEN_METADATA=1` /// Reads values written by `-s EMIT_EMSCRIPTEN_METADATA=1`
/// Assumes values start from the end in this order: /// Assumes values start from the end in this order:
/// Last export: Dynamic Base /// Last export: Dynamic Base
/// Second-to-Last export: Dynamic top pointer /// Second-to-Last export: Dynamic top pointer
pub fn get_emscripten_metadata(module: &Module) -> Option<(u32, u32)> { pub fn get_emscripten_metadata(module: &Module) -> Result<Option<(u32, u32)>, String> {
let max_idx = &module.info().globals.iter().map(|(k, _)| k).max()?; let max_idx = match module.info().globals.iter().map(|(k, _)| k).max() {
let snd_max_idx = &module Some(x) => x,
None => return Ok(None),
};
let snd_max_idx = match module
.info() .info()
.globals .globals
.iter() .iter()
.map(|(k, _)| k) .map(|(k, _)| k)
.filter(|k| k != max_idx) .filter(|k| *k != max_idx)
.max()?; .max()
{
Some(x) => x,
None => return Ok(None),
};
use wasmer_runtime_core::types::{GlobalInit, Initializer::Const, Value::I32}; use wasmer_runtime_core::types::{GlobalInit, Initializer::Const, Value::I32};
if let ( if let (
@ -76,15 +82,23 @@ pub fn get_emscripten_metadata(module: &Module) -> Option<(u32, u32)> {
.. ..
}, },
) = ( ) = (
&module.info().globals[*max_idx], &module.info().globals[max_idx],
&module.info().globals[*snd_max_idx], &module.info().globals[snd_max_idx],
) { ) {
Some(( let dynamic_base = (*dynamic_base as u32).checked_sub(32).ok_or(format!(
align_memory(*dynamic_base as u32 - 32), "emscripten unexpected dynamic_base {}",
align_memory(*dynamictop_ptr as u32 - 32), *dynamic_base as u32
)) ))?;
let dynamictop_ptr = (*dynamictop_ptr as u32).checked_sub(32).ok_or(format!(
"emscripten unexpected dynamictop_ptr {}",
*dynamictop_ptr as u32
))?;
Ok(Some((
align_memory(dynamic_base),
align_memory(dynamictop_ptr),
)))
} else { } else {
None Ok(None)
} }
} }

View File

@ -1,6 +1,8 @@
#![deny( #![deny(
dead_code, dead_code,
nonstandard_style,
unused_imports, unused_imports,
unused_mut,
unused_variables, unused_variables,
unused_unsafe, unused_unsafe,
unreachable_patterns unreachable_patterns

View File

@ -1,6 +1,8 @@
#![deny( #![deny(
dead_code, dead_code,
nonstandard_style,
unused_imports, unused_imports,
unused_mut,
unused_variables, unused_variables,
unused_unsafe, unused_unsafe,
unreachable_patterns unreachable_patterns

View File

@ -1,6 +1,8 @@
#![deny( #![deny(
dead_code, dead_code,
nonstandard_style,
unused_imports, unused_imports,
unused_mut,
unused_variables, unused_variables,
unused_unsafe, unused_unsafe,
unreachable_patterns unreachable_patterns

View File

@ -1,263 +0,0 @@
//! This is mostly copied from https://docs.rs/integer-atomics/1.0.2/src/integer_atomics/atomic.rs.html
//! Many thanks to "main()" for writing this.
use std::cell::UnsafeCell;
use std::mem;
use std::num::Wrapping;
use std::ops::{Add, BitAnd, BitOr, BitXor, Sub};
use std::panic::RefUnwindSafe;
use std::sync::atomic::{AtomicUsize, Ordering};
pub trait IntCast:
Copy
+ Eq
+ Add<Output = Self>
+ BitAnd<Output = Self>
+ BitOr<Output = Self>
+ BitXor<Output = Self>
+ Sub<Output = Self>
{
type Public: PartialEq + Copy;
fn from(u: usize) -> Self;
fn to(self) -> usize;
fn new(p: Self::Public) -> Self;
fn unwrap(self) -> Self::Public;
}
macro_rules! intcast {
($($type:ident)+) => {
$(
impl IntCast for $type {
type Public = $type;
fn from(u: usize) -> Self {
u as $type
}
fn to(self) -> usize {
self as usize
}
fn new(p: $type) -> Self {
p
}
fn unwrap(self) -> $type {
self
}
}
)+
}
}
intcast! { u8 i8 u16 i16 u32 i32 u64 i64 }
#[repr(transparent)]
pub struct Atomic<T> {
v: UnsafeCell<Wrapping<T>>,
}
impl<T: Default + IntCast> Default for Atomic<T> {
fn default() -> Self {
Self::new(T::default().unwrap())
}
}
// TODO: impl Debug
unsafe impl<T> Sync for Atomic<T> {}
impl<T> RefUnwindSafe for Atomic<T> {}
fn inject<T>(a: usize, b: usize, offset: usize) -> usize {
let mask = ((1 << (mem::size_of::<T>() * 8)) - 1) << offset;
(a & !mask) | (b << offset)
}
// straight from libcore's atomic.rs
#[inline]
fn strongest_failure_ordering(order: Ordering) -> Ordering {
use self::Ordering::*;
match order {
Release => Relaxed,
Relaxed => Relaxed,
SeqCst => SeqCst,
Acquire => Acquire,
AcqRel => Acquire,
_ => unreachable!(),
}
}
impl<T: IntCast> Atomic<T> {
#[inline]
fn proxy(&self) -> (&AtomicUsize, usize) {
let ptr = self.v.get() as usize;
let aligned = ptr & !(mem::size_of::<usize>() - 1);
(
unsafe { &*(aligned as *const AtomicUsize) },
(ptr - aligned) * 8,
)
}
#[inline]
pub(super) fn new(v: T::Public) -> Self {
Atomic {
v: UnsafeCell::new(Wrapping(T::new(v))),
}
}
#[inline]
pub fn get_mut(&mut self) -> &mut T::Public {
unsafe { &mut *(self.v.get() as *mut T::Public) }
}
#[inline]
pub fn into_inner(self) -> T::Public {
self.v.into_inner().0.unwrap()
}
#[inline]
pub fn load(&self, order: Ordering) -> T::Public {
let (p, o) = self.proxy();
T::from(p.load(order) >> o).unwrap()
}
#[inline]
fn op<F: Fn(T) -> Option<T>>(&self, f: F, order: Ordering) -> T::Public {
self.op_new(f, order, strongest_failure_ordering(order))
}
#[inline]
fn op_new<F: Fn(T) -> Option<T>>(
&self,
f: F,
success: Ordering,
failure: Ordering,
) -> T::Public {
let (p, o) = self.proxy();
let mut old = p.load(Ordering::Relaxed);
loop {
let old_t = T::from(old >> o);
let new_t = match f(old_t) {
Some(x) => x,
None => return old_t.unwrap(),
};
match Self::op_weak(p, o, old, new_t, success, failure) {
Ok(()) => return T::from(old >> o).unwrap(),
Err(prev) => old = prev,
};
}
}
#[inline]
fn op_weak(
p: &AtomicUsize,
o: usize,
old: usize,
new_t: T,
success: Ordering,
failure: Ordering,
) -> Result<(), usize> {
let new = inject::<T>(old, new_t.to(), o);
p.compare_exchange_weak(old, new, success, failure)
.map(|_| ())
}
#[inline]
pub fn store(&self, val: T::Public, order: Ordering) {
self.op(|_| Some(T::new(val)), order);
}
#[inline]
pub fn swap(&self, val: T::Public, order: Ordering) -> T::Public {
self.op(|_| Some(T::new(val)), order)
}
#[inline]
pub fn compare_and_swap(
&self,
current: T::Public,
new: T::Public,
order: Ordering,
) -> T::Public {
self.op(
|x| {
if x == T::new(current) {
Some(T::new(new))
} else {
None
}
},
order,
)
}
#[inline]
pub fn compare_exchange(
&self,
current: T::Public,
new: T::Public,
success: Ordering,
failure: Ordering,
) -> Result<T::Public, T::Public> {
match self.op_new(
|x| {
if x == T::new(current) {
Some(T::new(new))
} else {
None
}
},
success,
failure,
) {
x if x == current => Ok(x),
x => Err(x),
}
}
#[inline]
pub fn compare_exchange_weak(
&self,
current: T::Public,
new: T::Public,
success: Ordering,
failure: Ordering,
) -> Result<T::Public, T::Public> {
let (p, o) = self.proxy();
let old = p.load(Ordering::Relaxed);
let old_t = T::from(old >> o).unwrap();
if old_t != current {
return Err(old_t);
}
Self::op_weak(p, o, old, T::new(new), success, failure)
.map(|()| current)
.map_err(|x| T::from(x >> o).unwrap())
}
#[inline]
pub fn fetch_add(&self, val: T::Public, order: Ordering) -> T::Public {
self.op(|x| Some(x + T::new(val)), order)
}
#[inline]
pub fn fetch_sub(&self, val: T::Public, order: Ordering) -> T::Public {
self.op(|x| Some(x - T::new(val)), order)
}
#[inline]
pub fn fetch_and(&self, val: T::Public, order: Ordering) -> T::Public {
self.op(|x| Some(x & T::new(val)), order)
}
#[inline]
pub fn fetch_or(&self, val: T::Public, order: Ordering) -> T::Public {
self.op(|x| Some(x | T::new(val)), order)
}
#[inline]
pub fn fetch_xor(&self, val: T::Public, order: Ordering) -> T::Public {
self.op(|x| Some(x ^ T::new(val)), order)
}
}

View File

@ -14,12 +14,10 @@ use std::{
rc::Rc, rc::Rc,
}; };
pub use self::atomic::Atomic;
pub use self::dynamic::DynamicMemory; pub use self::dynamic::DynamicMemory;
pub use self::static_::{SharedStaticMemory, StaticMemory}; pub use self::static_::{SharedStaticMemory, StaticMemory};
pub use self::view::{Atomically, MemoryView}; pub use self::view::{Atomically, MemoryView};
mod atomic;
mod dynamic; mod dynamic;
pub mod ptr; pub mod ptr;
mod static_; mod static_;

View File

@ -1,8 +1,44 @@
use super::atomic::{Atomic, IntCast};
use crate::types::ValueType; use crate::types::ValueType;
use std::sync::atomic::{
AtomicI16, AtomicI32, AtomicI64, AtomicI8, AtomicU16, AtomicU32, AtomicU64, AtomicU8,
};
use std::{cell::Cell, marker::PhantomData, ops::Deref, slice}; use std::{cell::Cell, marker::PhantomData, ops::Deref, slice};
pub trait Atomic {
type Output;
}
impl Atomic for i8 {
type Output = AtomicI8;
}
impl Atomic for i16 {
type Output = AtomicI16;
}
impl Atomic for i32 {
type Output = AtomicI32;
}
impl Atomic for i64 {
type Output = AtomicI64;
}
impl Atomic for u8 {
type Output = AtomicU8;
}
impl Atomic for u16 {
type Output = AtomicU16;
}
impl Atomic for u32 {
type Output = AtomicU32;
}
impl Atomic for u64 {
type Output = AtomicU64;
}
impl Atomic for f32 {
type Output = AtomicU32;
}
impl Atomic for f64 {
type Output = AtomicU64;
}
pub trait Atomicity {} pub trait Atomicity {}
pub struct Atomically; pub struct Atomically;
impl Atomicity for Atomically {} impl Atomicity for Atomically {}
@ -28,10 +64,10 @@ where
} }
} }
impl<'a, T: IntCast> MemoryView<'a, T, NonAtomically> { impl<'a, T: Atomic> MemoryView<'a, T> {
pub fn atomically(&self) -> MemoryView<'a, T, Atomically> { pub fn atomically(&self) -> MemoryView<'a, T::Output, Atomically> {
MemoryView { MemoryView {
ptr: self.ptr, ptr: self.ptr as *mut T::Output,
length: self.length, length: self.length,
_phantom: PhantomData, _phantom: PhantomData,
} }
@ -45,9 +81,9 @@ impl<'a, T> Deref for MemoryView<'a, T, NonAtomically> {
} }
} }
impl<'a, T: IntCast> Deref for MemoryView<'a, T, Atomically> { impl<'a, T> Deref for MemoryView<'a, T, Atomically> {
type Target = [Atomic<T>]; type Target = [T];
fn deref(&self) -> &[Atomic<T>] { fn deref(&self) -> &[T] {
unsafe { slice::from_raw_parts(self.ptr as *const Atomic<T>, self.length) } unsafe { slice::from_raw_parts(self.ptr as *const T, self.length) }
} }
} }

View File

@ -1,6 +1,8 @@
#![deny( #![deny(
dead_code, dead_code,
nonstandard_style,
unused_imports, unused_imports,
unused_mut,
unused_variables, unused_variables,
unused_unsafe, unused_unsafe,
unreachable_patterns unreachable_patterns
@ -98,7 +100,7 @@ pub use wasmer_runtime_core::{compile_with, validate};
pub use wasmer_runtime_core::{func, imports}; pub use wasmer_runtime_core::{func, imports};
pub mod memory { pub mod memory {
pub use wasmer_runtime_core::memory::{Atomic, Atomically, Memory, MemoryView}; pub use wasmer_runtime_core::memory::{Atomically, Memory, MemoryView};
} }
pub mod wasm { pub mod wasm {

View File

@ -447,25 +447,25 @@ impl ModuleCodeGenerator<X64FunctionCode, X64ExecutionContext, CodegenError>
mut self, mut self,
_: &ModuleInfo, _: &ModuleInfo,
) -> Result<(X64ExecutionContext, Box<dyn CacheGen>), CodegenError> { ) -> Result<(X64ExecutionContext, Box<dyn CacheGen>), CodegenError> {
let (assembler, breakpoints) = match self.functions.last_mut() { let (assembler, function_labels, breakpoints) = match self.functions.last_mut() {
Some(x) => (x.assembler.take().unwrap(), x.breakpoints.take().unwrap()), Some(x) => (
None => { x.assembler.take().unwrap(),
return Err(CodegenError { x.function_labels.take().unwrap(),
message: "no function", x.breakpoints.take().unwrap(),
}); ),
} None => (
self.assembler.take().unwrap(),
self.function_labels.take().unwrap(),
HashMap::new(),
),
}; };
let total_size = assembler.get_offset().0; let total_size = assembler.get_offset().0;
let _output = assembler.finalize().unwrap(); let _output = assembler.finalize().unwrap();
let mut output = CodeMemory::new(_output.len()); let mut output = CodeMemory::new(_output.len());
output[0.._output.len()].copy_from_slice(&_output); output[0.._output.len()].copy_from_slice(&_output);
output.make_executable(); output.make_executable();
let function_labels = if let Some(x) = self.functions.last() {
x.function_labels.as_ref().unwrap()
} else {
self.function_labels.as_ref().unwrap()
};
let mut out_labels: Vec<FuncPtr> = vec![]; let mut out_labels: Vec<FuncPtr> = vec![];
let mut out_offsets: Vec<AssemblyOffset> = vec![]; let mut out_offsets: Vec<AssemblyOffset> = vec![];

View File

@ -1,6 +1,8 @@
#![deny( #![deny(
dead_code, dead_code,
nonstandard_style,
unused_imports, unused_imports,
unused_mut,
unused_variables, unused_variables,
unused_unsafe, unused_unsafe,
unreachable_patterns unreachable_patterns

View File

@ -896,39 +896,6 @@ singlepass:fail:address.wast:586 # AssertTrap - expected trap, got Runtime:Error
singlepass:fail:address.wast:588 # AssertTrap - expected trap, got [] singlepass:fail:address.wast:588 # AssertTrap - expected trap, got []
singlepass:fail:address.wast:589 # AssertTrap - expected trap, got [] singlepass:fail:address.wast:589 # AssertTrap - expected trap, got []
singlepass:fail:align.wast:864 # AssertTrap - expected trap, got Runtime:Error unknown error singlepass:fail:align.wast:864 # AssertTrap - expected trap, got Runtime:Error unknown error
singlepass:fail:binary-leb128.wast:2 # Module - caught panic Any
singlepass:fail:binary-leb128.wast:7 # Module - caught panic Any
singlepass:fail:binary-leb128.wast:12 # Module - caught panic Any
singlepass:fail:binary-leb128.wast:18 # Module - caught panic Any
singlepass:fail:binary-leb128.wast:24 # Module - caught panic Any
singlepass:fail:binary-leb128.wast:32 # Module - caught panic Any
singlepass:fail:binary-leb128.wast:40 # Module - caught panic Any
singlepass:fail:binary-leb128.wast:48 # Module - caught panic Any
singlepass:fail:binary-leb128.wast:56 # Module - caught panic Any
singlepass:fail:binary-leb128.wast:65 # Module - caught panic Any
singlepass:fail:binary-leb128.wast:74 # Module - caught panic Any
singlepass:fail:binary-leb128.wast:86 # Module - caught panic Any
singlepass:fail:binary-leb128.wast:98 # Module - caught panic Any
singlepass:fail:binary-leb128.wast:157 # Module - caught panic Any
singlepass:fail:binary-leb128.wast:164 # Module - caught panic Any
singlepass:fail:binary-leb128.wast:171 # Module - caught panic Any
singlepass:fail:binary-leb128.wast:178 # Module - caught panic Any
singlepass:fail:binary-leb128.wast:186 # Module - caught panic Any
singlepass:fail:binary-leb128.wast:193 # Module - caught panic Any
singlepass:fail:binary-leb128.wast:200 # Module - caught panic Any
singlepass:fail:binary-leb128.wast:207 # Module - caught panic Any
singlepass:fail:binary.wast:1 # Module - caught panic Any
singlepass:fail:binary.wast:2 # Module - caught panic Any
singlepass:fail:binary.wast:3 # Module - caught panic Any
singlepass:fail:binary.wast:4 # Module - caught panic Any
singlepass:fail:binary.wast:406 # Module - caught panic Any
singlepass:fail:binary.wast:412 # Module - caught panic Any
singlepass:fail:binary.wast:418 # Module - caught panic Any
singlepass:fail:binary.wast:446 # Module - caught panic Any
singlepass:fail:binary.wast:498 # Module - caught panic Any
singlepass:fail:binary.wast:514 # Module - caught panic Any
singlepass:fail:binary.wast:530 # Module - caught panic Any
singlepass:fail:binary.wast:661 # Module - caught panic Any
singlepass:fail:call.wast:289 # AssertTrap - expected trap, got Runtime:Error unknown error singlepass:fail:call.wast:289 # AssertTrap - expected trap, got Runtime:Error unknown error
singlepass:fail:call_indirect.wast:469 # AssertTrap - expected trap, got Runtime:Error unknown error singlepass:fail:call_indirect.wast:469 # AssertTrap - expected trap, got Runtime:Error unknown error
singlepass:fail:call_indirect.wast:470 # AssertTrap - expected trap, got Runtime:Error unknown error singlepass:fail:call_indirect.wast:470 # AssertTrap - expected trap, got Runtime:Error unknown error
@ -943,10 +910,6 @@ singlepass:fail:call_indirect.wast:493 # AssertTrap - expected trap, got Runtime
singlepass:fail:call_indirect.wast:494 # AssertTrap - expected trap, got Runtime:Error unknown error singlepass:fail:call_indirect.wast:494 # AssertTrap - expected trap, got Runtime:Error unknown error
singlepass:fail:call_indirect.wast:500 # AssertTrap - expected trap, got Runtime:Error unknown error singlepass:fail:call_indirect.wast:500 # AssertTrap - expected trap, got Runtime:Error unknown error
singlepass:fail:call_indirect.wast:501 # AssertTrap - expected trap, got Runtime:Error unknown error singlepass:fail:call_indirect.wast:501 # AssertTrap - expected trap, got Runtime:Error unknown error
singlepass:fail:comments.wast:10 # Module - caught panic Any
singlepass:fail:comments.wast:52 # Module - caught panic Any
singlepass:fail:comments.wast:62 # Module - caught panic Any
singlepass:fail:comments.wast:71 # Module - caught panic Any
singlepass:fail:conversions.wast:70 # AssertTrap - expected trap, got Runtime:Error unknown error singlepass:fail:conversions.wast:70 # AssertTrap - expected trap, got Runtime:Error unknown error
singlepass:fail:conversions.wast:71 # AssertTrap - expected trap, got Runtime:Error unknown error singlepass:fail:conversions.wast:71 # AssertTrap - expected trap, got Runtime:Error unknown error
singlepass:fail:conversions.wast:72 # AssertTrap - expected trap, got Runtime:Error unknown error singlepass:fail:conversions.wast:72 # AssertTrap - expected trap, got Runtime:Error unknown error
@ -1014,98 +977,7 @@ singlepass:fail:conversions.wast:239 # AssertTrap - expected trap, got Runtime:E
singlepass:fail:conversions.wast:240 # AssertTrap - expected trap, got Runtime:Error unknown error singlepass:fail:conversions.wast:240 # AssertTrap - expected trap, got Runtime:Error unknown error
singlepass:fail:conversions.wast:241 # AssertTrap - expected trap, got Runtime:Error unknown error singlepass:fail:conversions.wast:241 # AssertTrap - expected trap, got Runtime:Error unknown error
singlepass:fail:conversions.wast:242 # AssertTrap - expected trap, got Runtime:Error unknown error singlepass:fail:conversions.wast:242 # AssertTrap - expected trap, got Runtime:Error unknown error
singlepass:fail:custom.wast:1 # Module - caught panic Any
singlepass:fail:custom.wast:14 # Module - caught panic Any
singlepass:fail:data.wast:5 # Module - caught panic Any
singlepass:fail:data.wast:23 # Module - caught panic Any
singlepass:fail:data.wast:27 # Module - caught panic Any
singlepass:fail:data.wast:32 # Module - caught panic Any
singlepass:fail:data.wast:40 # Module - caught panic Any
singlepass:fail:data.wast:50 # Module - caught panic Any
singlepass:fail:data.wast:55 # Module - caught panic Any
singlepass:fail:data.wast:61 # Module - caught panic Any
singlepass:fail:data.wast:66 # Module - caught panic Any
singlepass:fail:data.wast:78 # Module - caught panic Any
singlepass:fail:data.wast:83 # Module - caught panic Any
singlepass:fail:data.wast:89 # Module - caught panic Any
singlepass:fail:data.wast:94 # Module - caught panic Any
singlepass:fail:data.wast:98 # Module - caught panic Any
singlepass:fail:data.wast:103 # Module - caught panic Any
singlepass:fail:data.wast:108 # Module - caught panic Any
singlepass:fail:data.wast:113 # Module - caught panic Any
singlepass:fail:data.wast:117 # Module - caught panic Any
singlepass:fail:data.wast:122 # Module - caught panic Any
singlepass:fail:data.wast:127 # Module - caught panic Any
singlepass:fail:data.wast:132 # Module - caught panic Any
singlepass:fail:data.wast:137 # Module - caught panic Any
singlepass:fail:data.wast:143 # Module - caught panic Any
singlepass:fail:data.wast:149 # Module - caught panic Any
singlepass:fail:data.wast:154 # Module - caught panic Any
singlepass:fail:data.wast:162 # AssertUnlinkable - caught panic Any
singlepass:fail:data.wast:170 # AssertUnlinkable - caught panic Any
singlepass:fail:data.wast:178 # AssertUnlinkable - caught panic Any
singlepass:fail:data.wast:186 # AssertUnlinkable - caught panic Any
singlepass:fail:data.wast:194 # AssertUnlinkable - caught panic Any
singlepass:fail:data.wast:211 # AssertUnlinkable - caught panic Any
singlepass:fail:data.wast:220 # AssertUnlinkable - caught panic Any
singlepass:fail:data.wast:227 # AssertUnlinkable - caught panic Any
singlepass:fail:data.wast:235 # AssertUnlinkable - caught panic Any
singlepass:fail:data.wast:243 # AssertUnlinkable - caught panic Any
singlepass:fail:data.wast:251 # AssertUnlinkable - caught panic Any
singlepass:fail:data.wast:258 # AssertUnlinkable - caught panic Any
singlepass:fail:data.wast:266 # AssertUnlinkable - caught panic Any
singlepass:fail:data.wast:273 # AssertUnlinkable - caught panic Any
singlepass:fail:elem.wast:97 # Module - caught panic Any
singlepass:fail:elem.wast:101 # Module - caught panic Any
singlepass:fail:elem.wast:106 # Module - caught panic Any
singlepass:fail:elem.wast:111 # Module - caught panic Any
singlepass:fail:elem.wast:170 # AssertUnlinkable - caught panic Any
singlepass:fail:elem.wast:353 # AssertTrap - expected trap, got Runtime:Error unknown error singlepass:fail:elem.wast:353 # AssertTrap - expected trap, got Runtime:Error unknown error
singlepass:fail:exports.wast:24 # Module - caught panic Any
singlepass:fail:exports.wast:25 # Module - caught panic Any
singlepass:fail:exports.wast:56 # Module - caught panic Any
singlepass:fail:exports.wast:57 # Module - caught panic Any
singlepass:fail:exports.wast:58 # Module - caught panic Any
singlepass:fail:exports.wast:60 # Module - caught panic Any
singlepass:fail:exports.wast:61 # Module - caught panic Any
singlepass:fail:exports.wast:62 # Module - caught panic Any
singlepass:fail:exports.wast:63 # Module - caught panic Any
singlepass:fail:exports.wast:64 # Module - caught panic Any
singlepass:fail:exports.wast:65 # Module - caught panic Any
singlepass:fail:exports.wast:67 # Module - caught panic Any
singlepass:fail:exports.wast:71 # AssertReturn Get - No instance available None
singlepass:fail:exports.wast:72 # AssertReturn Get - No instance available Some("$Global")
singlepass:fail:exports.wast:73 # Module - caught panic Any
singlepass:fail:exports.wast:74 # Module - caught panic Any
singlepass:fail:exports.wast:75 # AssertReturn Get - No instance available Some("$Global")
singlepass:fail:exports.wast:105 # Module - caught panic Any
singlepass:fail:exports.wast:106 # Module - caught panic Any
singlepass:fail:exports.wast:110 # Module - caught panic Any
singlepass:fail:exports.wast:111 # Module - caught panic Any
singlepass:fail:exports.wast:112 # Module - caught panic Any
singlepass:fail:exports.wast:113 # Module - caught panic Any
singlepass:fail:exports.wast:114 # Module - caught panic Any
singlepass:fail:exports.wast:115 # Module - caught panic Any
singlepass:fail:exports.wast:116 # Module - caught panic Any
singlepass:fail:exports.wast:117 # Module - caught panic Any
singlepass:fail:exports.wast:118 # Module - caught panic Any
singlepass:fail:exports.wast:119 # Module - caught panic Any
singlepass:fail:exports.wast:120 # Module - caught panic Any
singlepass:fail:exports.wast:121 # Module - caught panic Any
singlepass:fail:exports.wast:154 # Module - caught panic Any
singlepass:fail:exports.wast:155 # Module - caught panic Any
singlepass:fail:exports.wast:159 # Module - caught panic Any
singlepass:fail:exports.wast:160 # Module - caught panic Any
singlepass:fail:exports.wast:161 # Module - caught panic Any
singlepass:fail:exports.wast:162 # Module - caught panic Any
singlepass:fail:exports.wast:163 # Module - caught panic Any
singlepass:fail:exports.wast:164 # Module - caught panic Any
singlepass:fail:exports.wast:165 # Module - caught panic Any
singlepass:fail:exports.wast:166 # Module - caught panic Any
singlepass:fail:exports.wast:167 # Module - caught panic Any
singlepass:fail:exports.wast:168 # Module - caught panic Any
singlepass:fail:exports.wast:169 # Module - caught panic Any
singlepass:fail:exports.wast:170 # Module - caught panic Any
singlepass:fail:f32.wast:1620 # AssertReturn - result F32(0) ("0x0") does not match expected F32(2147483648) ("0x80000000") singlepass:fail:f32.wast:1620 # AssertReturn - result F32(0) ("0x0") does not match expected F32(2147483648) ("0x80000000")
singlepass:fail:f32.wast:1652 # "AssertReturnArithmeticNan" - value is not arithmetic nan F32(NaN) singlepass:fail:f32.wast:1652 # "AssertReturnArithmeticNan" - value is not arithmetic nan F32(NaN)
singlepass:fail:f32.wast:1654 # "AssertReturnArithmeticNan" - value is not arithmetic nan F32(NaN) singlepass:fail:f32.wast:1654 # "AssertReturnArithmeticNan" - value is not arithmetic nan F32(NaN)
@ -1534,10 +1406,6 @@ singlepass:fail:func_ptrs.wast:90 # AssertTrap - expected trap, got Runtime:Erro
singlepass:fail:func_ptrs.wast:91 # AssertTrap - expected trap, got Runtime:Error unknown error singlepass:fail:func_ptrs.wast:91 # AssertTrap - expected trap, got Runtime:Error unknown error
singlepass:fail:globals.wast:221 # AssertTrap - expected trap, got Runtime:Error unknown error singlepass:fail:globals.wast:221 # AssertTrap - expected trap, got Runtime:Error unknown error
singlepass:fail:globals.wast:243 # AssertInvalid - Should be invalid singlepass:fail:globals.wast:243 # AssertInvalid - Should be invalid
singlepass:fail:globals.wast:248 # Module - caught panic Any
singlepass:fail:globals.wast:249 # Module - caught panic Any
singlepass:fail:globals.wast:301 # Module - caught panic Any
singlepass:fail:globals.wast:331 # Module - caught panic Any
singlepass:fail:i32.wast:62 # AssertTrap - expected trap, got Runtime:Error unknown error singlepass:fail:i32.wast:62 # AssertTrap - expected trap, got Runtime:Error unknown error
singlepass:fail:i32.wast:63 # AssertTrap - expected trap, got Runtime:Error unknown error singlepass:fail:i32.wast:63 # AssertTrap - expected trap, got Runtime:Error unknown error
singlepass:fail:i32.wast:64 # AssertTrap - expected trap, got Runtime:Error unknown error singlepass:fail:i32.wast:64 # AssertTrap - expected trap, got Runtime:Error unknown error
@ -1575,102 +1443,14 @@ singlepass:fail:i64.wast:248 # AssertReturn - result I64(1) ("0x1") does not mat
singlepass:fail:i64.wast:249 # AssertReturn - result I64(62) ("0x3e") does not match expected I64(1) ("0x1") singlepass:fail:i64.wast:249 # AssertReturn - result I64(62) ("0x3e") does not match expected I64(1) ("0x1")
singlepass:fail:i64.wast:252 # AssertReturn - result I64(0) ("0x0") does not match expected I64(64) ("0x40") singlepass:fail:i64.wast:252 # AssertReturn - result I64(0) ("0x0") does not match expected I64(64) ("0x40")
singlepass:fail:if.wast:440 # AssertTrap - expected trap, got Runtime:Error unknown error singlepass:fail:if.wast:440 # AssertTrap - expected trap, got Runtime:Error unknown error
singlepass:fail:imports.wast:98 # Module - caught panic Any
singlepass:fail:imports.wast:99 # Module - caught panic Any
singlepass:fail:imports.wast:100 # Module - caught panic Any
singlepass:fail:imports.wast:101 # Module - caught panic Any
singlepass:fail:imports.wast:102 # Module - caught panic Any
singlepass:fail:imports.wast:103 # Module - caught panic Any
singlepass:fail:imports.wast:104 # Module - caught panic Any
singlepass:fail:imports.wast:107 # AssertUnlinkable - caught panic Any
singlepass:fail:imports.wast:111 # AssertUnlinkable - caught panic Any
singlepass:fail:imports.wast:116 # AssertUnlinkable - caught panic Any
singlepass:fail:imports.wast:120 # AssertUnlinkable - caught panic Any
singlepass:fail:imports.wast:124 # AssertUnlinkable - caught panic Any
singlepass:fail:imports.wast:128 # AssertUnlinkable - caught panic Any
singlepass:fail:imports.wast:132 # AssertUnlinkable - caught panic Any
singlepass:fail:imports.wast:136 # AssertUnlinkable - caught panic Any
singlepass:fail:imports.wast:140 # AssertUnlinkable - caught panic Any
singlepass:fail:imports.wast:144 # AssertUnlinkable - caught panic Any
singlepass:fail:imports.wast:148 # AssertUnlinkable - caught panic Any
singlepass:fail:imports.wast:152 # AssertUnlinkable - caught panic Any
singlepass:fail:imports.wast:156 # AssertUnlinkable - caught panic Any
singlepass:fail:imports.wast:160 # AssertUnlinkable - caught panic Any
singlepass:fail:imports.wast:164 # AssertUnlinkable - caught panic Any
singlepass:fail:imports.wast:168 # AssertUnlinkable - caught panic Any
singlepass:fail:imports.wast:172 # AssertUnlinkable - caught panic Any
singlepass:fail:imports.wast:176 # AssertUnlinkable - caught panic Any
singlepass:fail:imports.wast:181 # AssertUnlinkable - caught panic Any
singlepass:fail:imports.wast:185 # AssertUnlinkable - caught panic Any
singlepass:fail:imports.wast:189 # AssertUnlinkable - caught panic Any
singlepass:fail:imports.wast:193 # AssertUnlinkable - caught panic Any
singlepass:fail:imports.wast:197 # AssertUnlinkable - caught panic Any
singlepass:fail:imports.wast:201 # AssertUnlinkable - caught panic Any
singlepass:fail:imports.wast:231 # Module - caught panic Any
singlepass:fail:imports.wast:232 # Module - caught panic Any
singlepass:fail:imports.wast:235 # AssertUnlinkable - caught panic Any
singlepass:fail:imports.wast:239 # AssertUnlinkable - caught panic Any
singlepass:fail:imports.wast:244 # AssertUnlinkable - caught panic Any
singlepass:fail:imports.wast:248 # AssertUnlinkable - caught panic Any
singlepass:fail:imports.wast:252 # AssertUnlinkable - caught panic Any
singlepass:fail:imports.wast:256 # AssertUnlinkable - caught panic Any
singlepass:fail:imports.wast:260 # AssertUnlinkable - caught panic Any
singlepass:fail:imports.wast:264 # AssertUnlinkable - caught panic Any
singlepass:fail:imports.wast:283 # AssertTrap - expected trap, got Runtime:Error unknown error singlepass:fail:imports.wast:283 # AssertTrap - expected trap, got Runtime:Error unknown error
singlepass:fail:imports.wast:286 # AssertTrap - expected trap, got Runtime:Error unknown error singlepass:fail:imports.wast:286 # AssertTrap - expected trap, got Runtime:Error unknown error
singlepass:fail:imports.wast:287 # AssertTrap - expected trap, got Runtime:Error unknown error singlepass:fail:imports.wast:287 # AssertTrap - expected trap, got Runtime:Error unknown error
singlepass:fail:imports.wast:302 # AssertTrap - expected trap, got Runtime:Error unknown error singlepass:fail:imports.wast:302 # AssertTrap - expected trap, got Runtime:Error unknown error
singlepass:fail:imports.wast:305 # AssertTrap - expected trap, got Runtime:Error unknown error singlepass:fail:imports.wast:305 # AssertTrap - expected trap, got Runtime:Error unknown error
singlepass:fail:imports.wast:306 # AssertTrap - expected trap, got Runtime:Error unknown error singlepass:fail:imports.wast:306 # AssertTrap - expected trap, got Runtime:Error unknown error
singlepass:fail:imports.wast:322 # Module - caught panic Any
singlepass:fail:imports.wast:323 # Module - caught panic Any
singlepass:fail:imports.wast:324 # Module - caught panic Any
singlepass:fail:imports.wast:325 # Module - caught panic Any
singlepass:fail:imports.wast:326 # Module - caught panic Any
singlepass:fail:imports.wast:327 # Module - caught panic Any
singlepass:fail:imports.wast:328 # Module - caught panic Any
singlepass:fail:imports.wast:329 # Module - caught panic Any
singlepass:fail:imports.wast:330 # Module - caught panic Any
singlepass:fail:imports.wast:331 # Module - caught panic Any
singlepass:fail:imports.wast:332 # Module - caught panic Any
singlepass:fail:imports.wast:335 # AssertUnlinkable - caught panic Any
singlepass:fail:imports.wast:339 # AssertUnlinkable - caught panic Any
singlepass:fail:imports.wast:344 # AssertUnlinkable - caught panic Any
singlepass:fail:imports.wast:348 # AssertUnlinkable - caught panic Any
singlepass:fail:imports.wast:352 # AssertUnlinkable - caught panic Any
singlepass:fail:imports.wast:356 # AssertUnlinkable - caught panic Any
singlepass:fail:imports.wast:361 # AssertUnlinkable - caught panic Any
singlepass:fail:imports.wast:365 # AssertUnlinkable - caught panic Any
singlepass:fail:imports.wast:369 # AssertUnlinkable - caught panic Any
singlepass:fail:imports.wast:373 # AssertUnlinkable - caught panic Any
singlepass:fail:imports.wast:391 # AssertTrap - expected trap, got Runtime:Error unknown error singlepass:fail:imports.wast:391 # AssertTrap - expected trap, got Runtime:Error unknown error
singlepass:fail:imports.wast:402 # AssertTrap - expected trap, got Runtime:Error unknown error singlepass:fail:imports.wast:402 # AssertTrap - expected trap, got Runtime:Error unknown error
singlepass:fail:imports.wast:417 # Module - caught panic Any
singlepass:fail:imports.wast:418 # Module - caught panic Any
singlepass:fail:imports.wast:419 # Module - caught panic Any
singlepass:fail:imports.wast:420 # Module - caught panic Any
singlepass:fail:imports.wast:421 # Module - caught panic Any
singlepass:fail:imports.wast:422 # Module - caught panic Any
singlepass:fail:imports.wast:423 # Module - caught panic Any
singlepass:fail:imports.wast:424 # Module - caught panic Any
singlepass:fail:imports.wast:425 # Module - caught panic Any
singlepass:fail:imports.wast:428 # AssertUnlinkable - caught panic Any
singlepass:fail:imports.wast:432 # AssertUnlinkable - caught panic Any
singlepass:fail:imports.wast:437 # AssertUnlinkable - caught panic Any
singlepass:fail:imports.wast:441 # AssertUnlinkable - caught panic Any
singlepass:fail:imports.wast:445 # AssertUnlinkable - caught panic Any
singlepass:fail:imports.wast:449 # AssertUnlinkable - caught panic Any
singlepass:fail:imports.wast:454 # AssertUnlinkable - caught panic Any
singlepass:fail:imports.wast:458 # AssertUnlinkable - caught panic Any
singlepass:fail:imports.wast:462 # AssertUnlinkable - caught panic Any
singlepass:fail:imports.wast:466 # AssertUnlinkable - caught panic Any
singlepass:fail:imports.wast:470 # AssertUnlinkable - caught panic Any
singlepass:fail:imports.wast:474 # AssertUnlinkable - caught panic Any
singlepass:fail:imports.wast:479 # AssertUnlinkable - caught panic Any
singlepass:fail:imports.wast:483 # AssertUnlinkable - caught panic Any
singlepass:fail:imports.wast:571 # Module - caught panic Any
singlepass:fail:imports.wast:572 # Register - No instance available
singlepass:fail:imports.wast:574 # AssertUnlinkable - caught panic Any
singlepass:fail:int_exprs.wast:113 # AssertTrap - expected trap, got Runtime:Error unknown error singlepass:fail:int_exprs.wast:113 # AssertTrap - expected trap, got Runtime:Error unknown error
singlepass:fail:int_exprs.wast:114 # AssertTrap - expected trap, got Runtime:Error unknown error singlepass:fail:int_exprs.wast:114 # AssertTrap - expected trap, got Runtime:Error unknown error
singlepass:fail:int_exprs.wast:115 # AssertTrap - expected trap, got Runtime:Error unknown error singlepass:fail:int_exprs.wast:115 # AssertTrap - expected trap, got Runtime:Error unknown error
@ -1685,12 +1465,6 @@ singlepass:fail:int_exprs.wast:198 # AssertTrap - expected trap, got Runtime:Err
singlepass:fail:int_exprs.wast:199 # AssertTrap - expected trap, got Runtime:Error unknown error singlepass:fail:int_exprs.wast:199 # AssertTrap - expected trap, got Runtime:Error unknown error
singlepass:fail:int_exprs.wast:349 # AssertTrap - expected trap, got Runtime:Error unknown error singlepass:fail:int_exprs.wast:349 # AssertTrap - expected trap, got Runtime:Error unknown error
singlepass:fail:int_exprs.wast:350 # AssertTrap - expected trap, got Runtime:Error unknown error singlepass:fail:int_exprs.wast:350 # AssertTrap - expected trap, got Runtime:Error unknown error
singlepass:fail:linking.wast:22 # Module - caught panic Any
singlepass:fail:linking.wast:26 # Register - No instance available
singlepass:fail:linking.wast:28 # AssertUnlinkable - caught panic Any
singlepass:fail:linking.wast:32 # AssertUnlinkable - caught panic Any
singlepass:fail:linking.wast:87 # AssertUnlinkable - caught panic Any
singlepass:fail:linking.wast:91 # AssertUnlinkable - caught panic Any
singlepass:fail:linking.wast:134 # AssertReturn - Call failed RuntimeError: unknown error singlepass:fail:linking.wast:134 # AssertReturn - Call failed RuntimeError: unknown error
singlepass:fail:linking.wast:136 # AssertTrap - expected trap, got Runtime:Error unknown error singlepass:fail:linking.wast:136 # AssertTrap - expected trap, got Runtime:Error unknown error
singlepass:fail:linking.wast:137 # AssertTrap - expected trap, got Runtime:Error unknown error singlepass:fail:linking.wast:137 # AssertTrap - expected trap, got Runtime:Error unknown error
@ -1711,24 +1485,12 @@ singlepass:fail:linking.wast:185 # AssertTrap - expected trap, got Runtime:Error
singlepass:fail:linking.wast:187 # AssertTrap - expected trap, got Runtime:Error unknown error singlepass:fail:linking.wast:187 # AssertTrap - expected trap, got Runtime:Error unknown error
singlepass:fail:linking.wast:188 # AssertTrap - expected trap, got Runtime:Error unknown error singlepass:fail:linking.wast:188 # AssertTrap - expected trap, got Runtime:Error unknown error
singlepass:fail:linking.wast:190 # AssertTrap - expected trap, got Runtime:Error unknown error singlepass:fail:linking.wast:190 # AssertTrap - expected trap, got Runtime:Error unknown error
singlepass:fail:linking.wast:198 # Module - caught panic Any
singlepass:fail:linking.wast:199 # Register - No instance available
singlepass:fail:linking.wast:200 # Module - caught panic Any
singlepass:fail:linking.wast:204 # AssertReturn Get - No instance available Some("$G2")
singlepass:fail:linking.wast:225 # AssertTrap - expected trap, got Runtime:Error unknown error singlepass:fail:linking.wast:225 # AssertTrap - expected trap, got Runtime:Error unknown error
singlepass:fail:linking.wast:236 # AssertTrap - expected trap, got Runtime:Error unknown error singlepass:fail:linking.wast:236 # AssertTrap - expected trap, got Runtime:Error unknown error
singlepass:fail:linking.wast:248 # AssertTrap - expected trap, got Runtime:Error unknown error singlepass:fail:linking.wast:248 # AssertTrap - expected trap, got Runtime:Error unknown error
singlepass:fail:linking.wast:293 # Module - caught panic Any
singlepass:fail:linking.wast:299 # AssertUnlinkable - caught panic Any
singlepass:fail:linking.wast:324 # AssertUnlinkable - caught panic Any
singlepass:fail:linking.wast:335 # AssertUnlinkable - caught panic Any
singlepass:fail:linking.wast:387 # AssertReturn - result I32(0) ("0x0") does not match expected I32(104) ("0x68") singlepass:fail:linking.wast:387 # AssertReturn - result I32(0) ("0x0") does not match expected I32(104) ("0x68")
singlepass:fail:linking.wast:388 # AssertReturn - Call failed RuntimeError: unknown error singlepass:fail:linking.wast:388 # AssertReturn - Call failed RuntimeError: unknown error
singlepass:fail:load.wast:201 # AssertReturn - result I32(0) ("0x0") does not match expected I32(32) ("0x20") singlepass:fail:load.wast:201 # AssertReturn - result I32(0) ("0x0") does not match expected I32(32) ("0x20")
singlepass:fail:memory.wast:3 # Module - caught panic Any
singlepass:fail:memory.wast:4 # Module - caught panic Any
singlepass:fail:memory.wast:5 # Module - caught panic Any
singlepass:fail:memory.wast:6 # Module - caught panic Any
singlepass:fail:memory_grow.wast:15 # AssertTrap - expected trap, got Runtime:Error unknown error singlepass:fail:memory_grow.wast:15 # AssertTrap - expected trap, got Runtime:Error unknown error
singlepass:fail:memory_grow.wast:16 # AssertTrap - expected trap, got Runtime:Error unknown error singlepass:fail:memory_grow.wast:16 # AssertTrap - expected trap, got Runtime:Error unknown error
singlepass:fail:memory_grow.wast:17 # AssertTrap - expected trap, got Runtime:Error unknown error singlepass:fail:memory_grow.wast:17 # AssertTrap - expected trap, got Runtime:Error unknown error
@ -1909,7 +1671,6 @@ singlepass:fail:select.wast:210 # AssertTrap - expected trap, got Runtime:Error
singlepass:fail:select.wast:211 # AssertTrap - expected trap, got Runtime:Error unknown error singlepass:fail:select.wast:211 # AssertTrap - expected trap, got Runtime:Error unknown error
singlepass:fail:select.wast:248 # AssertTrap - expected trap, got Runtime:Error unknown error singlepass:fail:select.wast:248 # AssertTrap - expected trap, got Runtime:Error unknown error
singlepass:fail:select.wast:249 # AssertTrap - expected trap, got Runtime:Error unknown error singlepass:fail:select.wast:249 # AssertTrap - expected trap, got Runtime:Error unknown error
singlepass:fail:start.wast:92 # Module - caught panic Any
singlepass:fail:traps.wast:16 # AssertTrap - expected trap, got Runtime:Error unknown error singlepass:fail:traps.wast:16 # AssertTrap - expected trap, got Runtime:Error unknown error
singlepass:fail:traps.wast:17 # AssertTrap - expected trap, got Runtime:Error unknown error singlepass:fail:traps.wast:17 # AssertTrap - expected trap, got Runtime:Error unknown error
singlepass:fail:traps.wast:18 # AssertTrap - expected trap, got Runtime:Error unknown error singlepass:fail:traps.wast:18 # AssertTrap - expected trap, got Runtime:Error unknown error
@ -1942,7 +1703,6 @@ singlepass:fail:traps.wast:88 # AssertTrap - expected trap, got Runtime:Error un
singlepass:fail:traps.wast:89 # AssertTrap - expected trap, got Runtime:Error unknown error singlepass:fail:traps.wast:89 # AssertTrap - expected trap, got Runtime:Error unknown error
singlepass:fail:traps.wast:90 # AssertTrap - expected trap, got Runtime:Error unknown error singlepass:fail:traps.wast:90 # AssertTrap - expected trap, got Runtime:Error unknown error
singlepass:fail:traps.wast:91 # AssertTrap - expected trap, got Runtime:Error unknown error singlepass:fail:traps.wast:91 # AssertTrap - expected trap, got Runtime:Error unknown error
singlepass:fail:type.wast:3 # Module - caught panic Any
singlepass:fail:unreachable.wast:218 # AssertTrap - expected trap, got Runtime:Error unknown error singlepass:fail:unreachable.wast:218 # AssertTrap - expected trap, got Runtime:Error unknown error
singlepass:fail:unreachable.wast:219 # AssertTrap - expected trap, got Runtime:Error unknown error singlepass:fail:unreachable.wast:219 # AssertTrap - expected trap, got Runtime:Error unknown error
singlepass:fail:unreachable.wast:220 # AssertTrap - expected trap, got Runtime:Error unknown error singlepass:fail:unreachable.wast:220 # AssertTrap - expected trap, got Runtime:Error unknown error

View File

@ -18,6 +18,7 @@ mod mapdir;
mod path_link; mod path_link;
mod path_rename; mod path_rename;
mod path_symlink; mod path_symlink;
mod poll_oneoff;
mod quine; mod quine;
mod readlink; mod readlink;
mod wasi_sees_virtual_root; mod wasi_sees_virtual_root;

View File

@ -0,0 +1,20 @@
#[test]
fn test_poll_oneoff() {
assert_wasi_output!(
"../../wasitests/poll_oneoff.wasm",
"poll_oneoff",
vec![],
vec![
(
"hamlet".to_string(),
::std::path::PathBuf::from("wasitests/test_fs/hamlet")
),
(
"temp".to_string(),
::std::path::PathBuf::from("wasitests/test_fs/temp")
),
],
vec![],
"../../wasitests/poll_oneoff.out"
);
}

View File

@ -0,0 +1,2 @@
__wasi_event_t { userdata: 1193046, error: 0, type_: 1, u: __wasi_event_u { __wasi_event_fd_readwrite_t { nbytes: 2259, flags: 0 } } }
[__wasi_event_t { userdata: 1193046, error: 0, type_: 1, u: __wasi_event_u { __wasi_event_fd_readwrite_t { nbytes: 2259, flags: 0 } } }, __wasi_event_t { userdata: 1193046, error: 0, type_: 2, u: __wasi_event_u { __wasi_event_fd_readwrite_t { nbytes: 1234, flags: 0 } } }]

View File

@ -0,0 +1,183 @@
// Args:
// mapdir: hamlet:wasitests/test_fs/hamlet
// mapdir: temp:wasitests/test_fs/temp
use std::fs;
use std::io::{Read, Seek, SeekFrom};
#[cfg(target_os = "wasi")]
use std::os::wasi::prelude::AsRawFd;
use std::path::PathBuf;
#[cfg(target_os = "wasi")]
#[link(wasm_import_module = "wasi_unstable")]
extern "C" {
fn poll_oneoff(subscriptons: u32, events: u32, nsubscriptons: u32, nevents: u32) -> u16;
}
#[derive(Debug, Copy, Clone)]
#[repr(C)]
pub struct __wasi_event_t {
pub userdata: u64,
pub error: u16,
pub type_: __wasi_eventtype_t,
pub u: __wasi_event_u,
}
impl Default for __wasi_event_t {
fn default() -> Self {
__wasi_event_t {
userdata: 0,
error: 0,
type_: 0,
u: __wasi_event_u {
fd_readwrite: __wasi_event_fd_readwrite_t {
nbytes: 0,
flags: 0,
},
},
}
}
}
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
#[repr(C)]
pub struct __wasi_event_fd_readwrite_t {
pub nbytes: u64,
pub flags: u16,
}
#[derive(Copy, Clone)]
#[repr(C)]
pub union __wasi_event_u {
pub fd_readwrite: __wasi_event_fd_readwrite_t,
}
impl std::fmt::Debug for __wasi_event_u {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(f, "__wasi_event_u {{ ")?;
write!(f, "{:?} }}", unsafe { self.fd_readwrite })
}
}
pub type __wasi_eventtype_t = u8;
pub const __WASI_EVENTTYPE_CLOCK: u8 = 0;
pub const __WASI_EVENTTYPE_FD_READ: u8 = 1;
pub const __WASI_EVENTTYPE_FD_WRITE: u8 = 2;
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
#[repr(C)]
pub struct __wasi_subscription_clock_t {
pub userdata: u64,
pub clock_id: u32,
pub timeout: u64,
pub precision: u64,
pub flags: u16,
}
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
#[repr(C)]
pub struct __wasi_subscription_fs_readwrite_t {
pub fd: u32,
}
#[derive(Copy, Clone)]
#[repr(C)]
pub union __wasi_subscription_u {
clock: __wasi_subscription_clock_t,
fd_readwrite: __wasi_subscription_fs_readwrite_t,
}
#[derive(Copy, Clone)]
#[repr(C)]
pub struct __wasi_subscription_t {
pub userdata: u64,
pub type_: __wasi_eventtype_t,
pub u: __wasi_subscription_u,
}
#[cfg(target_os = "wasi")]
fn poll(fds: &[u32], read: &[bool], write: &[bool]) -> Result<Vec<__wasi_event_t>, u16> {
assert!(fds.len() == read.len() && read.len() == write.len());
let mut in_ = fds
.iter()
.enumerate()
.map(|(i, n)| {
let mut type_ = 0;
if read[i] {
type_ |= __WASI_EVENTTYPE_FD_READ;
}
if write[i] {
type_ |= __WASI_EVENTTYPE_FD_WRITE;
}
__wasi_subscription_t {
userdata: 0x123456,
type_,
u: __wasi_subscription_u {
fd_readwrite: __wasi_subscription_fs_readwrite_t { fd: *n as u32 },
},
}
})
.collect::<Vec<_>>();
let mut out_ = vec![Default::default(); in_.len()];
let mut nsubscriptions: u32 = 0;
let result = unsafe {
poll_oneoff(
in_.as_ptr() as usize as u32,
out_.as_mut_ptr() as usize as u32,
in_.len() as u32,
(&mut nsubscriptions as *mut u32) as usize as u32,
)
};
if result == 0 {
Ok(out_)
} else {
Err(result)
}
}
fn main() {
#[cfg(not(target_os = "wasi"))]
let mut base = PathBuf::from("wasitests/test_fs");
#[cfg(target_os = "wasi")]
let mut base = PathBuf::from("/");
let path = base.join("hamlet/act4/scene1.txt");
let path2 = base.join("temp/poll_oneoff_write.txt");
{
let mut file = fs::File::open(&path).expect("Could not open file");
let mut file2 = fs::OpenOptions::new()
.create(true)
.write(true)
.truncate(true)
.open(&path2)
.expect("Could not open file");
file2.set_len(1234).unwrap();
#[cfg(target_os = "wasi")]
{
let fds = vec![file.as_raw_fd()];
let mut result = poll(fds.as_slice(), &[true], &[false]).expect("First poll");
while result[0].error != 0 {
result = poll(fds.as_slice(), &[true], &[false]).expect("subsequent polls");
}
println!("{:?}", result[0]);
let fds = vec![file.as_raw_fd(), file2.as_raw_fd()];
result = poll(fds.as_slice(), &[true, false], &[false, true]).expect("First poll");
while result[0].error != 0 {
result =
poll(fds.as_slice(), &[true, false], &[false, true]).expect("subsequent polls");
}
println!("{:?}", result);
}
#[cfg(not(target_os = "wasi"))]
{
println!("{}", "__wasi_event_t { userdata: 1193046, error: 0, type_: 1, u: __wasi_event_u { __wasi_event_fd_readwrite_t { nbytes: 2259, flags: 0 } } }");
println!("{}", "[__wasi_event_t { userdata: 1193046, error: 0, type_: 1, u: __wasi_event_u { __wasi_event_fd_readwrite_t { nbytes: 2259, flags: 0 } } }, __wasi_event_t { userdata: 1193046, error: 0, type_: 2, u: __wasi_event_u { __wasi_event_fd_readwrite_t { nbytes: 1234, flags: 0 } } }]");
}
}
std::fs::remove_file(path2).unwrap();
}

Binary file not shown.

View File

@ -1,6 +1,8 @@
#![deny( #![deny(
dead_code, dead_code,
nonstandard_style,
unused_imports, unused_imports,
unused_mut,
unused_variables, unused_variables,
unused_unsafe, unused_unsafe,
unreachable_patterns unreachable_patterns

View File

@ -1,5 +1,7 @@
/// types for use in the WASI filesystem /// types for use in the WASI filesystem
use crate::syscalls::types::*; use crate::syscalls::types::*;
#[cfg(unix)]
use std::convert::TryInto;
use std::{ use std::{
fs, fs,
io::{self, Read, Seek, Write}, io::{self, Read, Seek, Write},
@ -165,6 +167,173 @@ pub trait WasiFile: std::fmt::Debug + Write + Read + Seek {
fn rename_file(&self, _new_name: &std::path::Path) -> Result<(), WasiFsError> { fn rename_file(&self, _new_name: &std::path::Path) -> Result<(), WasiFsError> {
panic!("Default implementation for compatibilty in the 0.6.X releases; this will be removed in 0.7.0 or 0.8.0. Please implement WasiFile::rename_file for your type before then"); panic!("Default implementation for compatibilty in the 0.6.X releases; this will be removed in 0.7.0 or 0.8.0. Please implement WasiFile::rename_file for your type before then");
} }
/// Returns the number of bytes available. This function must not block
fn bytes_available(&self) -> Result<usize, WasiFsError> {
panic!("Default implementation for compatibilty in the 0.6.X releases; this will be removed in 0.7.0 or 0.8.0. Please implement WasiFile::bytes_available for your type before then");
}
/// Used for polling. Default returns `None` because this method cannot be implemented for most types
/// Returns the underlying host fd
fn get_raw_fd(&self) -> Option<i32> {
None
}
}
#[derive(Debug, Clone)]
pub enum PollEvent {
/// Data available to read
PollIn = 1,
/// Data available to write (will still block if data is greater than space available unless
/// the fd is configured to not block)
PollOut = 2,
/// Something didn't work. ignored as input
PollError = 4,
/// Connection closed. ignored as input
PollHangUp = 8,
/// Invalid request. ignored as input
PollInvalid = 16,
}
impl PollEvent {
fn from_i16(raw_num: i16) -> Option<PollEvent> {
Some(match raw_num {
1 => PollEvent::PollIn,
2 => PollEvent::PollOut,
4 => PollEvent::PollError,
8 => PollEvent::PollHangUp,
16 => PollEvent::PollInvalid,
_ => return None,
})
}
}
#[derive(Debug, Clone)]
pub struct PollEventBuilder {
inner: PollEventSet,
}
pub type PollEventSet = i16;
#[derive(Debug)]
pub struct PollEventIter {
pes: PollEventSet,
i: usize,
}
impl Iterator for PollEventIter {
type Item = PollEvent;
fn next(&mut self) -> Option<Self::Item> {
if self.pes == 0 || self.i > 15 {
None
} else {
while self.i < 16 {
let result = PollEvent::from_i16(self.pes & (1 << self.i));
self.pes &= !(1 << self.i);
self.i += 1;
if let Some(r) = result {
return Some(r);
}
}
unreachable!("Internal logic error in PollEventIter");
}
}
}
pub fn iterate_poll_events(pes: PollEventSet) -> PollEventIter {
PollEventIter { pes, i: 0 }
}
#[cfg(unix)]
fn poll_event_set_to_platform_poll_events(mut pes: PollEventSet) -> i16 {
let mut out = 0;
for i in 0..16 {
out |= match PollEvent::from_i16(pes & (1 << i)) {
Some(PollEvent::PollIn) => libc::POLLIN,
Some(PollEvent::PollOut) => libc::POLLOUT,
Some(PollEvent::PollError) => libc::POLLERR,
Some(PollEvent::PollHangUp) => libc::POLLHUP,
Some(PollEvent::PollInvalid) => libc::POLLNVAL,
_ => 0,
};
pes &= !(1 << i);
}
out
}
#[cfg(unix)]
fn platform_poll_events_to_pollevent_set(mut num: i16) -> PollEventSet {
let mut peb = PollEventBuilder::new();
for i in 0..16 {
peb = match num & (1 << i) {
libc::POLLIN => peb.add(PollEvent::PollIn),
libc::POLLOUT => peb.add(PollEvent::PollOut),
libc::POLLERR => peb.add(PollEvent::PollError),
libc::POLLHUP => peb.add(PollEvent::PollHangUp),
libc::POLLNVAL => peb.add(PollEvent::PollInvalid),
_ => peb,
};
num &= !(1 << i);
}
peb.build()
}
impl PollEventBuilder {
pub fn new() -> PollEventBuilder {
PollEventBuilder { inner: 0 }
}
pub fn add(mut self, event: PollEvent) -> PollEventBuilder {
self.inner |= event as PollEventSet;
self
}
pub fn build(self) -> PollEventSet {
self.inner
}
}
#[cfg(unix)]
pub(crate) fn poll(
selfs: &[&dyn WasiFile],
events: &[PollEventSet],
seen_events: &mut [PollEventSet],
) -> Result<u32, WasiFsError> {
if !(selfs.len() == events.len() && events.len() == seen_events.len()) {
return Err(WasiFsError::InvalidInput);
}
let mut fds = selfs
.iter()
.enumerate()
.filter_map(|(i, s)| s.get_raw_fd().map(|rfd| (i, rfd)))
.map(|(i, host_fd)| libc::pollfd {
fd: host_fd,
events: poll_event_set_to_platform_poll_events(events[i]),
revents: 0,
})
.collect::<Vec<_>>();
let result = unsafe { libc::poll(fds.as_mut_ptr(), selfs.len() as _, 1) };
if result < 0 {
// TODO: check errno and return value
return Err(WasiFsError::IOError);
}
// convert result and write back values
for (i, fd) in fds.into_iter().enumerate() {
seen_events[i] = platform_poll_events_to_pollevent_set(fd.revents);
}
// unwrap is safe because we check for negative values above
Ok(result.try_into().unwrap())
}
#[cfg(not(unix))]
pub(crate) fn poll(
_selfs: &[&dyn WasiFile],
_events: &[PollEventSet],
_seen_events: &mut [PollEventSet],
) -> Result<(), WasiFsError> {
unimplemented!("HostFile::poll in WasiFile is not implemented for non-Unix-like targets yet");
} }
pub trait WasiPath {} pub trait WasiPath {}
@ -282,6 +451,40 @@ impl WasiFile for HostFile {
fn rename_file(&self, new_name: &std::path::Path) -> Result<(), WasiFsError> { fn rename_file(&self, new_name: &std::path::Path) -> Result<(), WasiFsError> {
std::fs::rename(&self.host_path, new_name).map_err(Into::into) std::fs::rename(&self.host_path, new_name).map_err(Into::into)
} }
#[cfg(unix)]
fn bytes_available(&self) -> Result<usize, WasiFsError> {
use std::os::unix::io::AsRawFd;
let host_fd = self.inner.as_raw_fd();
let mut bytes_found = 0 as libc::c_int;
let result = unsafe { libc::ioctl(host_fd, libc::FIONREAD, &mut bytes_found) };
match result {
// success
0 => Ok(bytes_found.try_into().unwrap_or(0)),
libc::EBADF => Err(WasiFsError::InvalidFd),
libc::EFAULT => Err(WasiFsError::InvalidData),
libc::EINVAL => Err(WasiFsError::InvalidInput),
_ => Err(WasiFsError::IOError),
}
}
#[cfg(not(unix))]
fn bytes_available(&self) -> Result<usize, WasiFsError> {
unimplemented!("HostFile::bytes_available in WasiFile is not implemented for non-Unix-like targets yet");
}
#[cfg(unix)]
fn get_raw_fd(&self) -> Option<i32> {
use std::os::unix::io::AsRawFd;
Some(self.inner.as_raw_fd())
}
#[cfg(not(unix))]
fn get_raw_fd(&self) -> Option<i32> {
unimplemented!(
"HostFile::get_raw_fd in WasiFile is not implemented for non-Unix-like targets yet"
);
}
} }
impl From<io::Error> for WasiFsError { impl From<io::Error> for WasiFsError {
@ -375,6 +578,19 @@ impl WasiFile for Stdout {
fn size(&self) -> u64 { fn size(&self) -> u64 {
0 0
} }
#[cfg(unix)]
fn get_raw_fd(&self) -> Option<i32> {
use std::os::unix::io::AsRawFd;
Some(self.0.as_raw_fd())
}
#[cfg(not(unix))]
fn get_raw_fd(&self) -> Option<i32> {
unimplemented!(
"Stdout::get_raw_fd in WasiFile is not implemented for non-Unix-like targets yet"
);
}
} }
#[derive(Debug)] #[derive(Debug)]
@ -441,6 +657,19 @@ impl WasiFile for Stderr {
fn size(&self) -> u64 { fn size(&self) -> u64 {
0 0
} }
#[cfg(unix)]
fn get_raw_fd(&self) -> Option<i32> {
use std::os::unix::io::AsRawFd;
Some(self.0.as_raw_fd())
}
#[cfg(not(unix))]
fn get_raw_fd(&self) -> Option<i32> {
unimplemented!(
"Stderr::get_raw_fd in WasiFile is not implemented for non-Unix-like targets yet"
);
}
} }
#[derive(Debug)] #[derive(Debug)]
@ -507,6 +736,43 @@ impl WasiFile for Stdin {
fn size(&self) -> u64 { fn size(&self) -> u64 {
0 0
} }
#[cfg(unix)]
fn bytes_available(&self) -> Result<usize, WasiFsError> {
use std::os::unix::io::AsRawFd;
let host_fd = self.0.as_raw_fd();
let mut bytes_found = 0 as libc::c_int;
let result = unsafe { libc::ioctl(host_fd, libc::FIONREAD, &mut bytes_found) };
match result {
// success
0 => Ok(bytes_found.try_into().unwrap_or(0)),
libc::EBADF => Err(WasiFsError::InvalidFd),
libc::EFAULT => Err(WasiFsError::InvalidData),
libc::EINVAL => Err(WasiFsError::InvalidInput),
_ => Err(WasiFsError::IOError),
}
}
#[cfg(not(unix))]
fn bytes_available(&self) -> Result<usize, WasiFsError> {
unimplemented!(
"Stdin::bytes_available in WasiFile is not implemented for non-Unix-like targets yet"
);
}
#[cfg(unix)]
fn get_raw_fd(&self) -> Option<i32> {
use std::os::unix::io::AsRawFd;
Some(self.0.as_raw_fd())
}
#[cfg(not(unix))]
fn get_raw_fd(&self) -> Option<i32> {
unimplemented!(
"Stdin::get_raw_fd in WasiFile is not implemented for non-Unix-like targets yet"
);
}
} }
/* /*

View File

@ -9,15 +9,16 @@ use self::types::*;
use crate::{ use crate::{
ptr::{Array, WasmPtr}, ptr::{Array, WasmPtr},
state::{ state::{
self, host_file_type_to_wasi_file_type, Fd, HostFile, Inode, InodeVal, Kind, WasiFile, self, host_file_type_to_wasi_file_type, iterate_poll_events, poll, Fd, HostFile, Inode,
WasiFsError, WasiState, MAX_SYMLINKS, InodeVal, Kind, PollEvent, PollEventBuilder, WasiFile, WasiFsError, WasiState,
MAX_SYMLINKS,
}, },
ExitCode, ExitCode,
}; };
use rand::{thread_rng, Rng}; use rand::{thread_rng, Rng};
use std::borrow::Borrow; use std::borrow::Borrow;
use std::cell::Cell; use std::cell::Cell;
use std::convert::Infallible; use std::convert::{Infallible, TryInto};
use std::io::{self, Read, Seek, Write}; use std::io::{self, Read, Seek, Write};
use wasmer_runtime_core::{debug, memory::Memory, vm::Ctx}; use wasmer_runtime_core::{debug, memory::Memory, vm::Ctx};
@ -2242,7 +2243,124 @@ pub fn poll_oneoff(
nevents: WasmPtr<u32>, nevents: WasmPtr<u32>,
) -> __wasi_errno_t { ) -> __wasi_errno_t {
debug!("wasi::poll_oneoff"); debug!("wasi::poll_oneoff");
unimplemented!("wasi::poll_oneoff") debug!(" => nsubscriptions = {}", nsubscriptions);
let memory = ctx.memory(0);
let state = get_wasi_state(ctx);
let subscription_array = wasi_try!(in_.deref(memory, 0, nsubscriptions));
let event_array = wasi_try!(out_.deref(memory, 0, nsubscriptions));
let mut events_seen = 0;
let out_ptr = wasi_try!(nevents.deref(memory));
let mut fds = vec![];
let mut in_events = vec![];
for sub in subscription_array.iter() {
let s: WasiSubscription = wasi_try!(sub.get().try_into());
let mut peb = PollEventBuilder::new();
let fd = match s.event_type {
EventType::Read(__wasi_subscription_fs_readwrite_t { fd }) => {
let fd_entry = wasi_try!(state.fs.get_fd(fd));
if !has_rights(fd_entry.rights, __WASI_RIGHT_FD_READ) {
return __WASI_EACCES;
}
in_events.push(peb.add(PollEvent::PollIn).build());
Some(fd)
}
EventType::Write(__wasi_subscription_fs_readwrite_t { fd }) => {
let fd_entry = wasi_try!(state.fs.get_fd(fd));
if !has_rights(fd_entry.rights, __WASI_RIGHT_FD_WRITE) {
return __WASI_EACCES;
}
in_events.push(peb.add(PollEvent::PollOut).build());
Some(fd)
}
_ => unimplemented!("Clock eventtypes in wasi::poll_oneoff"),
};
if let Some(fd) = fd {
let wasi_file_ref: &dyn WasiFile = match fd {
__WASI_STDERR_FILENO => state.fs.stderr.as_ref(),
__WASI_STDIN_FILENO => state.fs.stdin.as_ref(),
__WASI_STDOUT_FILENO => state.fs.stdout.as_ref(),
_ => {
let fd_entry = wasi_try!(state.fs.get_fd(fd));
let inode = fd_entry.inode;
if !has_rights(fd_entry.rights, __WASI_RIGHT_POLL_FD_READWRITE) {
return __WASI_EACCES;
}
match &state.fs.inodes[inode].kind {
Kind::File { handle, .. } => {
if let Some(h) = handle {
h.as_ref()
} else {
return __WASI_EBADF;
}
}
Kind::Dir { .. }
| Kind::Root { .. }
| Kind::Buffer { .. }
| Kind::Symlink { .. } => {
unimplemented!("polling read on non-files not yet supported")
}
}
}
};
fds.push(wasi_file_ref);
} else {
unimplemented!("Clock events are not yet implemented!");
}
}
let mut seen_events = vec![Default::default(); in_events.len()];
wasi_try!(poll(
fds.as_slice(),
in_events.as_slice(),
seen_events.as_mut_slice()
)
.map_err(|e| e.into_wasi_err()));
for (i, seen_event) in seen_events.into_iter().enumerate() {
let mut flags = 0;
let mut error = __WASI_EAGAIN;
let mut bytes_available = 0;
let event_iter = iterate_poll_events(seen_event);
for event in event_iter {
match event {
PollEvent::PollError => error = __WASI_EIO,
PollEvent::PollHangUp => flags = __WASI_EVENT_FD_READWRITE_HANGUP,
PollEvent::PollInvalid => error = __WASI_EINVAL,
PollEvent::PollIn => {
bytes_available =
wasi_try!(fds[i].bytes_available().map_err(|e| e.into_wasi_err()));
error = __WASI_ESUCCESS;
}
PollEvent::PollOut => {
bytes_available =
wasi_try!(fds[i].bytes_available().map_err(|e| e.into_wasi_err()));
error = __WASI_ESUCCESS;
}
}
}
let event = __wasi_event_t {
userdata: subscription_array[i].get().userdata,
error,
type_: subscription_array[i].get().type_,
u: unsafe {
__wasi_event_u {
fd_readwrite: __wasi_event_fd_readwrite_t {
nbytes: bytes_available as u64,
flags,
},
}
},
};
event_array[events_seen].set(event);
events_seen += 1;
}
out_ptr.set(events_seen as u32);
__WASI_ESUCCESS
} }
pub fn proc_exit(ctx: &mut Ctx, code: __wasi_exitcode_t) -> Result<Infallible, ExitCode> { pub fn proc_exit(ctx: &mut Ctx, code: __wasi_exitcode_t) -> Result<Infallible, ExitCode> {

View File

@ -157,10 +157,19 @@ pub struct __wasi_event_fd_readwrite_t {
#[derive(Copy, Clone)] #[derive(Copy, Clone)]
#[repr(C)] #[repr(C)]
pub union __wasi_event_u { pub union __wasi_event_u {
fd_readwrite: __wasi_event_fd_readwrite_t, pub fd_readwrite: __wasi_event_fd_readwrite_t,
} }
#[derive(Copy, Clone)] // TODO: remove this implementation of Debug when `__wasi_event_u` gets more than 1 variant
impl std::fmt::Debug for __wasi_event_u {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_struct("__wasi_event_u")
.field("fd_readwrite", unsafe { &self.fd_readwrite })
.finish()
}
}
#[derive(Debug, Copy, Clone)]
pub enum EventEnum { pub enum EventEnum {
FdReadWrite { FdReadWrite {
nbytes: __wasi_filesize_t, nbytes: __wasi_filesize_t,
@ -178,7 +187,7 @@ impl EventEnum {
} }
} }
#[derive(Copy, Clone)] #[derive(Debug, Copy, Clone)]
#[repr(C)] #[repr(C)]
pub struct __wasi_event_t { pub struct __wasi_event_t {
pub userdata: __wasi_userdata_t, pub userdata: __wasi_userdata_t,
@ -199,6 +208,8 @@ impl __wasi_event_t {
} }
} }
unsafe impl ValueType for __wasi_event_t {}
pub type __wasi_eventrwflags_t = u16; pub type __wasi_eventrwflags_t = u16;
pub const __WASI_EVENT_FD_READWRITE_HANGUP: u16 = 1 << 0; pub const __WASI_EVENT_FD_READWRITE_HANGUP: u16 = 1 << 0;
@ -207,6 +218,15 @@ pub const __WASI_EVENTTYPE_CLOCK: u8 = 0;
pub const __WASI_EVENTTYPE_FD_READ: u8 = 1; pub const __WASI_EVENTTYPE_FD_READ: u8 = 1;
pub const __WASI_EVENTTYPE_FD_WRITE: u8 = 2; pub const __WASI_EVENTTYPE_FD_WRITE: u8 = 2;
pub fn eventtype_to_str(event_type: __wasi_eventtype_t) -> &'static str {
match event_type {
__WASI_EVENTTYPE_CLOCK => "__WASI_EVENTTYPE_CLOCK",
__WASI_EVENTTYPE_FD_READ => "__WASI_EVENTTYPE_FD_READ",
__WASI_EVENTTYPE_FD_WRITE => "__WASI_EVENTTYPE_FD_WRITE",
_ => "INVALID EVENTTYPE",
}
}
pub type __wasi_exitcode_t = u32; pub type __wasi_exitcode_t = u32;
pub type __wasi_fd_t = u32; pub type __wasi_fd_t = u32;
@ -562,6 +582,93 @@ pub struct __wasi_subscription_t {
pub u: __wasi_subscription_u, pub u: __wasi_subscription_u,
} }
/// Safe Rust wrapper around `__wasi_subscription_t::type_` and `__wasi_subscription_t::u`
#[derive(Debug, Clone)]
pub enum EventType {
Clock(__wasi_subscription_clock_t),
Read(__wasi_subscription_fs_readwrite_t),
Write(__wasi_subscription_fs_readwrite_t),
}
impl EventType {
pub fn raw_tag(&self) -> __wasi_eventtype_t {
match self {
EventType::Clock(_) => __WASI_EVENTTYPE_CLOCK,
EventType::Read(_) => __WASI_EVENTTYPE_FD_READ,
EventType::Write(_) => __WASI_EVENTTYPE_FD_WRITE,
}
}
}
/// Safe Rust wrapper around `__wasi_subscription_t`
#[derive(Debug, Clone)]
pub struct WasiSubscription {
pub user_data: __wasi_userdata_t,
pub event_type: EventType,
}
impl std::convert::TryFrom<__wasi_subscription_t> for WasiSubscription {
type Error = __wasi_errno_t;
fn try_from(ws: __wasi_subscription_t) -> Result<Self, Self::Error> {
Ok(Self {
user_data: ws.userdata,
event_type: match ws.type_ {
__WASI_EVENTTYPE_CLOCK => EventType::Clock(unsafe { ws.u.clock }),
__WASI_EVENTTYPE_FD_READ => EventType::Read(unsafe { ws.u.fd_readwrite }),
__WASI_EVENTTYPE_FD_WRITE => EventType::Write(unsafe { ws.u.fd_readwrite }),
_ => return Err(__WASI_EINVAL),
},
})
}
}
impl std::convert::TryFrom<WasiSubscription> for __wasi_subscription_t {
type Error = __wasi_errno_t;
fn try_from(ws: WasiSubscription) -> Result<Self, Self::Error> {
let (type_, u) = match ws.event_type {
EventType::Clock(c) => (__WASI_EVENTTYPE_CLOCK, __wasi_subscription_u { clock: c }),
EventType::Read(rw) => (
__WASI_EVENTTYPE_FD_READ,
__wasi_subscription_u { fd_readwrite: rw },
),
EventType::Write(rw) => (
__WASI_EVENTTYPE_FD_WRITE,
__wasi_subscription_u { fd_readwrite: rw },
),
_ => return Err(__WASI_EINVAL),
};
Ok(Self {
userdata: ws.user_data,
type_,
u,
})
}
}
impl std::fmt::Debug for __wasi_subscription_t {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_struct("__wasi_subscription_t")
.field("userdata", &self.userdata)
.field("type", &eventtype_to_str(self.type_))
.field(
"u",
match self.type_ {
__WASI_EVENTTYPE_CLOCK => unsafe { &self.u.clock },
__WASI_EVENTTYPE_FD_READ | __WASI_EVENTTYPE_FD_WRITE => unsafe {
&self.u.fd_readwrite
},
_ => &"INVALID EVENTTYPE",
},
)
.finish()
}
}
unsafe impl ValueType for __wasi_subscription_t {}
pub enum SubscriptionEnum { pub enum SubscriptionEnum {
Clock(__wasi_subscription_clock_t), Clock(__wasi_subscription_clock_t),
FdReadWrite(__wasi_subscription_fs_readwrite_t), FdReadWrite(__wasi_subscription_fs_readwrite_t),

View File

@ -1,6 +1,8 @@
#![deny( #![deny(
dead_code, dead_code,
nonstandard_style,
unused_imports, unused_imports,
unused_mut,
unused_variables, unused_variables,
unused_unsafe, unused_unsafe,
unreachable_patterns unreachable_patterns

BIN
logo.png

Binary file not shown.

Before

Width:  |  Height:  |  Size: 99 KiB

After

Width:  |  Height:  |  Size: 27 KiB

View File

@ -1,6 +1,8 @@
#![deny( #![deny(
dead_code, dead_code,
nonstandard_style,
unused_imports, unused_imports,
unused_mut,
unused_variables, unused_variables,
unused_unsafe, unused_unsafe,
unreachable_patterns unreachable_patterns

View File

@ -1,6 +1,8 @@
#![deny( #![deny(
dead_code, dead_code,
nonstandard_style,
unused_imports, unused_imports,
unused_mut,
unused_variables, unused_variables,
unused_unsafe, unused_unsafe,
unreachable_patterns unreachable_patterns
@ -532,7 +534,7 @@ fn execute_wasm(options: &Run) -> Result<(), String> {
// TODO: refactor this // TODO: refactor this
if wasmer_emscripten::is_emscripten_module(&module) { if wasmer_emscripten::is_emscripten_module(&module) {
let mut emscripten_globals = wasmer_emscripten::EmscriptenGlobals::new(&module); let mut emscripten_globals = wasmer_emscripten::EmscriptenGlobals::new(&module)?;
let import_object = wasmer_emscripten::generate_emscripten_env(&mut emscripten_globals); let import_object = wasmer_emscripten::generate_emscripten_env(&mut emscripten_globals);
let mut instance = module let mut instance = module
.instantiate(&import_object) .instantiate(&import_object)

View File

@ -1,6 +1,8 @@
#![deny( #![deny(
dead_code, dead_code,
nonstandard_style,
unused_imports, unused_imports,
unused_mut,
unused_variables, unused_variables,
unused_unsafe, unused_unsafe,
unreachable_patterns unreachable_patterns