mirror of
https://github.com/fluencelabs/wasmer
synced 2025-06-20 04:06:30 +00:00
Merge remote-tracking branch 'origin/master' into feature/llvm-osr
This commit is contained in:
33
CONTRIBUTING.md
Normal file
33
CONTRIBUTING.md
Normal 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
24
Cargo.lock
generated
@ -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"
|
||||||
|
@ -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>
|
||||||
|
|
||||||
|
@ -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
|
||||||
|
@ -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)
|
||||||
|
@ -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,
|
||||||
}
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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
|
||||||
|
@ -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
|
||||||
|
@ -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
|
||||||
|
@ -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)
|
|
||||||
}
|
|
||||||
}
|
|
@ -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_;
|
||||||
|
@ -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) }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -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 {
|
||||||
|
@ -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![];
|
||||||
|
|
||||||
|
@ -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
|
||||||
|
@ -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
|
||||||
|
@ -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;
|
||||||
|
20
lib/wasi-tests/tests/wasitests/poll_oneoff.rs
Normal file
20
lib/wasi-tests/tests/wasitests/poll_oneoff.rs
Normal 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"
|
||||||
|
);
|
||||||
|
}
|
2
lib/wasi-tests/wasitests/poll_oneoff.out
Normal file
2
lib/wasi-tests/wasitests/poll_oneoff.out
Normal 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 } } }]
|
183
lib/wasi-tests/wasitests/poll_oneoff.rs
Normal file
183
lib/wasi-tests/wasitests/poll_oneoff.rs
Normal 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();
|
||||||
|
}
|
BIN
lib/wasi-tests/wasitests/poll_oneoff.wasm
Executable file
BIN
lib/wasi-tests/wasitests/poll_oneoff.wasm
Executable file
Binary file not shown.
@ -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
|
||||||
|
@ -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"
|
||||||
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -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> {
|
||||||
|
@ -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),
|
||||||
|
@ -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
BIN
logo.png
Binary file not shown.
Before Width: | Height: | Size: 99 KiB After Width: | Height: | Size: 27 KiB |
@ -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
|
||||||
|
@ -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)
|
||||||
|
@ -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
|
||||||
|
Reference in New Issue
Block a user