mirror of
https://github.com/fluencelabs/wasmer
synced 2025-06-14 17:31:20 +00:00
Merge branch 'master' into add-validate
This commit is contained in:
422
Cargo.lock
generated
422
Cargo.lock
generated
File diff suppressed because it is too large
Load Diff
@ -30,9 +30,10 @@ wasmer-runtime-abi = { path = "lib/runtime-abi", optional = true }
|
|||||||
wasmer-runtime-core = { path = "lib/runtime-core" }
|
wasmer-runtime-core = { path = "lib/runtime-core" }
|
||||||
wasmer-emscripten = { path = "lib/emscripten" }
|
wasmer-emscripten = { path = "lib/emscripten" }
|
||||||
wasmer-llvm-backend = { path = "lib/llvm-backend", optional = true }
|
wasmer-llvm-backend = { path = "lib/llvm-backend", optional = true }
|
||||||
|
wasmer-wasi = { path = "lib/wasi", optional = true }
|
||||||
|
|
||||||
[workspace]
|
[workspace]
|
||||||
members = ["lib/clif-backend", "lib/dynasm-backend", "lib/runtime", "lib/runtime-abi", "lib/runtime-core", "lib/emscripten", "lib/spectests", "lib/win-exception-handler", "lib/runtime-c-api", "lib/llvm-backend"]
|
members = ["lib/clif-backend", "lib/dynasm-backend", "lib/runtime", "lib/runtime-abi", "lib/runtime-core", "lib/emscripten", "lib/spectests", "lib/win-exception-handler", "lib/runtime-c-api", "lib/llvm-backend", "lib/wasi"]
|
||||||
|
|
||||||
[build-dependencies]
|
[build-dependencies]
|
||||||
wabt = "0.7.2"
|
wabt = "0.7.2"
|
||||||
@ -45,4 +46,5 @@ debug = ["wasmer-clif-backend/debug", "wasmer-runtime-core/debug"]
|
|||||||
fast-tests = []
|
fast-tests = []
|
||||||
llvm = ["wasmer-llvm-backend"]
|
llvm = ["wasmer-llvm-backend"]
|
||||||
dynasm = ["wasmer-dynasm-backend"]
|
dynasm = ["wasmer-dynasm-backend"]
|
||||||
|
wasi = ["wasmer-wasi"]
|
||||||
vfs = ["wasmer-runtime-abi"]
|
vfs = ["wasmer-runtime-abi"]
|
||||||
|
@ -119,7 +119,6 @@ impl std::error::Error for LinkError {}
|
|||||||
/// The main way to do this is `Instance.call`.
|
/// The main way to do this is `Instance.call`.
|
||||||
///
|
///
|
||||||
/// Comparing two `RuntimeError`s always evaluates to false.
|
/// Comparing two `RuntimeError`s always evaluates to false.
|
||||||
#[derive(Debug)]
|
|
||||||
pub enum RuntimeError {
|
pub enum RuntimeError {
|
||||||
Trap { msg: Box<str> },
|
Trap { msg: Box<str> },
|
||||||
Exception { data: Box<[Value]> },
|
Exception { data: Box<[Value]> },
|
||||||
@ -141,9 +140,25 @@ impl std::fmt::Display for RuntimeError {
|
|||||||
RuntimeError::Exception { ref data } => {
|
RuntimeError::Exception { ref data } => {
|
||||||
write!(f, "Uncaught WebAssembly exception: {:?}", data)
|
write!(f, "Uncaught WebAssembly exception: {:?}", data)
|
||||||
}
|
}
|
||||||
RuntimeError::Panic { data: _ } => write!(f, "User-defined \"panic\""),
|
RuntimeError::Panic { data } => {
|
||||||
|
let msg = if let Some(s) = data.downcast_ref::<String>() {
|
||||||
|
s
|
||||||
|
} else if let Some(s) = data.downcast_ref::<&str>() {
|
||||||
|
s
|
||||||
|
} else {
|
||||||
|
"user-defined, opaque"
|
||||||
|
};
|
||||||
|
|
||||||
|
write!(f, "{}", msg)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl std::fmt::Debug for RuntimeError {
|
||||||
|
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
|
||||||
|
write!(f, "{}", self)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl std::error::Error for RuntimeError {}
|
impl std::error::Error for RuntimeError {}
|
||||||
@ -197,7 +212,6 @@ impl std::error::Error for ResolveError {}
|
|||||||
/// be the `CallError::Runtime(RuntimeError)` variant.
|
/// be the `CallError::Runtime(RuntimeError)` variant.
|
||||||
///
|
///
|
||||||
/// Comparing two `CallError`s always evaluates to false.
|
/// Comparing two `CallError`s always evaluates to false.
|
||||||
#[derive(Debug)]
|
|
||||||
pub enum CallError {
|
pub enum CallError {
|
||||||
Resolve(ResolveError),
|
Resolve(ResolveError),
|
||||||
Runtime(RuntimeError),
|
Runtime(RuntimeError),
|
||||||
@ -218,6 +232,15 @@ impl std::fmt::Display for CallError {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl std::fmt::Debug for CallError {
|
||||||
|
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
|
||||||
|
match self {
|
||||||
|
CallError::Resolve(resolve_err) => write!(f, "ResolveError: {:?}", resolve_err),
|
||||||
|
CallError::Runtime(runtime_err) => write!(f, "RuntimeError: {:?}", runtime_err),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl std::error::Error for CallError {}
|
impl std::error::Error for CallError {}
|
||||||
|
|
||||||
/// This error type is produced when creating something,
|
/// This error type is produced when creating something,
|
||||||
|
@ -3,6 +3,7 @@ use hashbrown::{hash_map::Entry, HashMap};
|
|||||||
use std::collections::VecDeque;
|
use std::collections::VecDeque;
|
||||||
use std::{
|
use std::{
|
||||||
cell::{Ref, RefCell},
|
cell::{Ref, RefCell},
|
||||||
|
ffi::c_void,
|
||||||
rc::Rc,
|
rc::Rc,
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -45,6 +46,7 @@ impl IsExport for Export {
|
|||||||
/// ```
|
/// ```
|
||||||
pub struct ImportObject {
|
pub struct ImportObject {
|
||||||
map: Rc<RefCell<HashMap<String, Box<dyn LikeNamespace>>>>,
|
map: Rc<RefCell<HashMap<String, Box<dyn LikeNamespace>>>>,
|
||||||
|
state_creator: Option<Rc<Fn() -> (*mut c_void, fn(*mut c_void))>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ImportObject {
|
impl ImportObject {
|
||||||
@ -52,9 +54,24 @@ impl ImportObject {
|
|||||||
pub fn new() -> Self {
|
pub fn new() -> Self {
|
||||||
Self {
|
Self {
|
||||||
map: Rc::new(RefCell::new(HashMap::new())),
|
map: Rc::new(RefCell::new(HashMap::new())),
|
||||||
|
state_creator: None,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn new_with_data<F>(state_creator: F) -> Self
|
||||||
|
where
|
||||||
|
F: Fn() -> (*mut c_void, fn(*mut c_void)) + 'static,
|
||||||
|
{
|
||||||
|
Self {
|
||||||
|
map: Rc::new(RefCell::new(HashMap::new())),
|
||||||
|
state_creator: Some(Rc::new(state_creator)),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub(crate) fn call_state_creator(&self) -> Option<(*mut c_void, fn(*mut c_void))> {
|
||||||
|
self.state_creator.as_ref().map(|state_gen| state_gen())
|
||||||
|
}
|
||||||
|
|
||||||
/// Register anything that implements `LikeNamespace` as a namespace.
|
/// Register anything that implements `LikeNamespace` as a namespace.
|
||||||
///
|
///
|
||||||
/// # Usage:
|
/// # Usage:
|
||||||
@ -98,6 +115,7 @@ impl ImportObject {
|
|||||||
pub fn clone_ref(&self) -> Self {
|
pub fn clone_ref(&self) -> Self {
|
||||||
Self {
|
Self {
|
||||||
map: Rc::clone(&self.map),
|
map: Rc::clone(&self.map),
|
||||||
|
state_creator: self.state_creator.clone(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -63,7 +63,16 @@ impl Instance {
|
|||||||
// Initialize the vm::Ctx in-place after the backing
|
// Initialize the vm::Ctx in-place after the backing
|
||||||
// has been boxed.
|
// has been boxed.
|
||||||
unsafe {
|
unsafe {
|
||||||
*inner.vmctx = vm::Ctx::new(&mut inner.backing, &mut inner.import_backing, &module)
|
*inner.vmctx = match imports.call_state_creator() {
|
||||||
|
Some((data, dtor)) => vm::Ctx::new_with_data(
|
||||||
|
&mut inner.backing,
|
||||||
|
&mut inner.import_backing,
|
||||||
|
&module,
|
||||||
|
data,
|
||||||
|
dtor,
|
||||||
|
),
|
||||||
|
None => vm::Ctx::new(&mut inner.backing, &mut inner.import_backing, &module),
|
||||||
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
let instance = Instance {
|
let instance = Instance {
|
||||||
|
@ -38,6 +38,13 @@ macro_rules! func {
|
|||||||
/// },
|
/// },
|
||||||
/// };
|
/// };
|
||||||
///
|
///
|
||||||
|
/// let imports_with_state = imports! {
|
||||||
|
/// || (0 as _, |_a| {}),
|
||||||
|
/// "env" => {
|
||||||
|
/// "foo" => func!(foo),
|
||||||
|
/// },
|
||||||
|
/// };
|
||||||
|
///
|
||||||
/// fn foo(_: &mut Ctx, n: i32) -> i32 {
|
/// fn foo(_: &mut Ctx, n: i32) -> i32 {
|
||||||
/// n
|
/// n
|
||||||
/// }
|
/// }
|
||||||
@ -57,6 +64,21 @@ macro_rules! imports {
|
|||||||
import_object.register($ns_name, ns);
|
import_object.register($ns_name, ns);
|
||||||
})*
|
})*
|
||||||
|
|
||||||
|
import_object
|
||||||
|
}};
|
||||||
|
($state_gen:expr, $( $ns_name:expr => $ns:tt, )* ) => {{
|
||||||
|
use $crate::{
|
||||||
|
import::{ImportObject, Namespace},
|
||||||
|
};
|
||||||
|
|
||||||
|
let mut import_object = ImportObject::new_with_data($state_gen);
|
||||||
|
|
||||||
|
$({
|
||||||
|
let ns = $crate::__imports_internal!($ns);
|
||||||
|
|
||||||
|
import_object.register($ns_name, ns);
|
||||||
|
})*
|
||||||
|
|
||||||
import_object
|
import_object
|
||||||
}};
|
}};
|
||||||
}
|
}
|
||||||
|
@ -77,6 +77,19 @@ where
|
|||||||
{
|
{
|
||||||
const TYPE: Type;
|
const TYPE: Type;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
unsafe impl WasmExternType for i8 {
|
||||||
|
const TYPE: Type = Type::I32;
|
||||||
|
}
|
||||||
|
unsafe impl WasmExternType for u8 {
|
||||||
|
const TYPE: Type = Type::I32;
|
||||||
|
}
|
||||||
|
unsafe impl WasmExternType for i16 {
|
||||||
|
const TYPE: Type = Type::I32;
|
||||||
|
}
|
||||||
|
unsafe impl WasmExternType for u16 {
|
||||||
|
const TYPE: Type = Type::I32;
|
||||||
|
}
|
||||||
unsafe impl WasmExternType for i32 {
|
unsafe impl WasmExternType for i32 {
|
||||||
const TYPE: Type = Type::I32;
|
const TYPE: Type = Type::I32;
|
||||||
}
|
}
|
||||||
@ -113,34 +126,15 @@ unsafe impl WasmExternType for f64 {
|
|||||||
// fn swap(&self, other: Self::Primitive) -> Self::Primitive;
|
// fn swap(&self, other: Self::Primitive) -> Self::Primitive;
|
||||||
// }
|
// }
|
||||||
|
|
||||||
pub enum ValueError {
|
pub unsafe trait ValueType: Copy
|
||||||
BufferTooSmall,
|
|
||||||
}
|
|
||||||
|
|
||||||
pub trait ValueType: Copy
|
|
||||||
where
|
where
|
||||||
Self: Sized,
|
Self: Sized,
|
||||||
{
|
{
|
||||||
fn into_le(self, buffer: &mut [u8]);
|
|
||||||
fn from_le(buffer: &[u8]) -> Result<Self, ValueError>;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
macro_rules! convert_value_impl {
|
macro_rules! convert_value_impl {
|
||||||
($t:ty) => {
|
($t:ty) => {
|
||||||
impl ValueType for $t {
|
unsafe impl ValueType for $t {}
|
||||||
fn into_le(self, buffer: &mut [u8]) {
|
|
||||||
buffer[..mem::size_of::<Self>()].copy_from_slice(&self.to_le_bytes());
|
|
||||||
}
|
|
||||||
fn from_le(buffer: &[u8]) -> Result<Self, ValueError> {
|
|
||||||
if buffer.len() >= mem::size_of::<Self>() {
|
|
||||||
let mut array = [0u8; mem::size_of::<Self>()];
|
|
||||||
array.copy_from_slice(&buffer[..mem::size_of::<Self>()]);
|
|
||||||
Ok(Self::from_le_bytes(array))
|
|
||||||
} else {
|
|
||||||
Err(ValueError::BufferTooSmall)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
( $($t:ty),* ) => {
|
( $($t:ty),* ) => {
|
||||||
$(
|
$(
|
||||||
@ -149,25 +143,7 @@ macro_rules! convert_value_impl {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
convert_value_impl!(u8, i8, u16, i16, u32, i32, u64, i64);
|
convert_value_impl!(u8, i8, u16, i16, u32, i32, u64, i64, f32, f64);
|
||||||
|
|
||||||
impl ValueType for f32 {
|
|
||||||
fn into_le(self, buffer: &mut [u8]) {
|
|
||||||
self.to_bits().into_le(buffer);
|
|
||||||
}
|
|
||||||
fn from_le(buffer: &[u8]) -> Result<Self, ValueError> {
|
|
||||||
Ok(f32::from_bits(<u32 as ValueType>::from_le(buffer)?))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl ValueType for f64 {
|
|
||||||
fn into_le(self, buffer: &mut [u8]) {
|
|
||||||
self.to_bits().into_le(buffer);
|
|
||||||
}
|
|
||||||
fn from_le(buffer: &[u8]) -> Result<Self, ValueError> {
|
|
||||||
Ok(f64::from_bits(<u64 as ValueType>::from_le(buffer)?))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Serialize, Deserialize, Debug, Clone, Copy, PartialEq, Eq)]
|
#[derive(Serialize, Deserialize, Debug, Clone, Copy, PartialEq, Eq)]
|
||||||
pub enum ElementType {
|
pub enum ElementType {
|
||||||
|
@ -25,7 +25,7 @@ pub struct Ctx {
|
|||||||
module: *const ModuleInner,
|
module: *const ModuleInner,
|
||||||
|
|
||||||
pub data: *mut c_void,
|
pub data: *mut c_void,
|
||||||
pub data_finalizer: Option<extern "C" fn(data: *mut c_void)>,
|
pub data_finalizer: Option<fn(data: *mut c_void)>,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// The internal context of the currently running WebAssembly instance.
|
/// The internal context of the currently running WebAssembly instance.
|
||||||
@ -100,7 +100,7 @@ impl Ctx {
|
|||||||
import_backing: &mut ImportBacking,
|
import_backing: &mut ImportBacking,
|
||||||
module: &ModuleInner,
|
module: &ModuleInner,
|
||||||
data: *mut c_void,
|
data: *mut c_void,
|
||||||
data_finalizer: extern "C" fn(*mut c_void),
|
data_finalizer: fn(*mut c_void),
|
||||||
) -> Self {
|
) -> Self {
|
||||||
Self {
|
Self {
|
||||||
internal: InternalCtx {
|
internal: InternalCtx {
|
||||||
@ -481,7 +481,7 @@ mod vm_ctx_tests {
|
|||||||
str: String,
|
str: String,
|
||||||
}
|
}
|
||||||
|
|
||||||
extern "C" fn test_data_finalizer(data: *mut c_void) {
|
fn test_data_finalizer(data: *mut c_void) {
|
||||||
let test_data: &mut TestData = unsafe { &mut *(data as *mut TestData) };
|
let test_data: &mut TestData = unsafe { &mut *(data as *mut TestData) };
|
||||||
assert_eq!(test_data.x, 10);
|
assert_eq!(test_data.x, 10);
|
||||||
assert_eq!(test_data.y, true);
|
assert_eq!(test_data.y, true);
|
||||||
|
22
lib/wasi/Cargo.toml
Normal file
22
lib/wasi/Cargo.toml
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
[package]
|
||||||
|
name = "wasmer-wasi"
|
||||||
|
version = "0.2.1"
|
||||||
|
license = "MIT"
|
||||||
|
authors = ["The Wasmer Engineering Team <engineering@wasmer.io>"]
|
||||||
|
repository = "https://github.com/wasmerio/wasmer"
|
||||||
|
edition = "2018"
|
||||||
|
|
||||||
|
[dependencies]
|
||||||
|
wasmer-runtime-core = { path = "../runtime-core", version = "0.2.1" }
|
||||||
|
libc = "0.2.50"
|
||||||
|
rand = "0.6.5"
|
||||||
|
# wasmer-runtime-abi = { path = "../runtime-abi" }
|
||||||
|
hashbrown = "0.1.8"
|
||||||
|
generational-arena = "0.2.2"
|
||||||
|
log = "0.4.6"
|
||||||
|
byteorder = "1.3.1"
|
||||||
|
|
||||||
|
[dependencies.zbox]
|
||||||
|
git = "https://github.com/wasmerio/zbox"
|
||||||
|
branch = "bundle-libsodium"
|
||||||
|
features = ["libsodium-bundled"]
|
90
lib/wasi/src/lib.rs
Normal file
90
lib/wasi/src/lib.rs
Normal file
@ -0,0 +1,90 @@
|
|||||||
|
#[macro_use]
|
||||||
|
extern crate log;
|
||||||
|
|
||||||
|
#[macro_use]
|
||||||
|
mod macros;
|
||||||
|
mod ptr;
|
||||||
|
mod state;
|
||||||
|
mod syscalls;
|
||||||
|
mod utils;
|
||||||
|
|
||||||
|
use self::state::{WasiFs, WasiState};
|
||||||
|
use self::syscalls::*;
|
||||||
|
|
||||||
|
use std::ffi::c_void;
|
||||||
|
|
||||||
|
pub use self::utils::is_wasi_module;
|
||||||
|
|
||||||
|
use wasmer_runtime_core::{func, import::ImportObject, imports};
|
||||||
|
|
||||||
|
pub fn generate_import_object(args: Vec<Vec<u8>>, envs: Vec<Vec<u8>>) -> ImportObject {
|
||||||
|
let state_gen = move || {
|
||||||
|
fn state_destructor(data: *mut c_void) {
|
||||||
|
unsafe {
|
||||||
|
drop(Box::from_raw(data as *mut WasiState));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
let state = Box::new(WasiState {
|
||||||
|
fs: WasiFs::new().unwrap(),
|
||||||
|
args: &args[..],
|
||||||
|
envs: &envs[..],
|
||||||
|
});
|
||||||
|
|
||||||
|
(
|
||||||
|
Box::leak(state) as *mut WasiState as *mut c_void,
|
||||||
|
state_destructor as fn(*mut c_void),
|
||||||
|
)
|
||||||
|
};
|
||||||
|
imports! {
|
||||||
|
// This generates the wasi state.
|
||||||
|
state_gen,
|
||||||
|
"wasi_unstable" => {
|
||||||
|
"args_get" => func!(args_get),
|
||||||
|
"args_sizes_get" => func!(args_sizes_get),
|
||||||
|
"clock_res_get" => func!(clock_res_get),
|
||||||
|
"clock_time_get" => func!(clock_time_get),
|
||||||
|
"environ_get" => func!(environ_get),
|
||||||
|
"environ_sizes_get" => func!(environ_sizes_get),
|
||||||
|
"fd_advise" => func!(fd_advise),
|
||||||
|
"fd_allocate" => func!(fd_allocate),
|
||||||
|
"fd_close" => func!(fd_close),
|
||||||
|
"fd_datasync" => func!(fd_datasync),
|
||||||
|
"fd_fdstat_get" => func!(fd_fdstat_get),
|
||||||
|
"fd_fdstat_set_flags" => func!(fd_fdstat_set_flags),
|
||||||
|
"fd_fdstat_set_rights" => func!(fd_fdstat_set_rights),
|
||||||
|
"fd_filestat_get" => func!(fd_filestat_get),
|
||||||
|
"fd_filestat_set_size" => func!(fd_filestat_set_size),
|
||||||
|
"fd_filestat_set_times" => func!(fd_filestat_set_times),
|
||||||
|
"fd_pread" => func!(fd_pread),
|
||||||
|
"fd_prestat_get" => func!(fd_prestat_get),
|
||||||
|
"fd_prestat_dir_name" => func!(fd_prestat_dir_name),
|
||||||
|
"fd_pwrite" => func!(fd_pwrite),
|
||||||
|
"fd_read" => func!(fd_read),
|
||||||
|
"fd_readdir" => func!(fd_readdir),
|
||||||
|
"fd_renumber" => func!(fd_renumber),
|
||||||
|
"fd_seek" => func!(fd_seek),
|
||||||
|
"fd_sync" => func!(fd_sync),
|
||||||
|
"fd_tell" => func!(fd_tell),
|
||||||
|
"fd_write" => func!(fd_write),
|
||||||
|
"path_create_directory" => func!(path_create_directory),
|
||||||
|
"path_filestat_get" => func!(path_filestat_get),
|
||||||
|
"path_filestat_set_times" => func!(path_filestat_set_times),
|
||||||
|
"path_link" => func!(path_link),
|
||||||
|
"path_open" => func!(path_open),
|
||||||
|
"path_readlink" => func!(path_readlink),
|
||||||
|
"path_remove_directory" => func!(path_remove_directory),
|
||||||
|
"path_rename" => func!(path_rename),
|
||||||
|
"path_symlink" => func!(path_symlink),
|
||||||
|
"path_unlink_file" => func!(path_unlink_file),
|
||||||
|
"poll_oneoff" => func!(poll_oneoff),
|
||||||
|
"proc_exit" => func!(proc_exit),
|
||||||
|
"proc_raise" => func!(proc_raise),
|
||||||
|
"random_get" => func!(random_get),
|
||||||
|
"sched_yield" => func!(sched_yield),
|
||||||
|
"sock_recv" => func!(sock_recv),
|
||||||
|
"sock_send" => func!(sock_send),
|
||||||
|
"sock_shutdown" => func!(sock_shutdown),
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
13
lib/wasi/src/macros.rs
Normal file
13
lib/wasi/src/macros.rs
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
macro_rules! wasi_try {
|
||||||
|
($expr:expr) => {{
|
||||||
|
let res: Result<_, crate::syscalls::types::__wasi_errno_t> = $expr;
|
||||||
|
match res {
|
||||||
|
Ok(val) => val,
|
||||||
|
Err(err) => return err,
|
||||||
|
}
|
||||||
|
}};
|
||||||
|
($expr:expr; $e:expr) => {{
|
||||||
|
let opt: Option<_> = $expr;
|
||||||
|
wasi_try!(opt.ok_or($e))
|
||||||
|
}};
|
||||||
|
}
|
102
lib/wasi/src/ptr.rs
Normal file
102
lib/wasi/src/ptr.rs
Normal file
@ -0,0 +1,102 @@
|
|||||||
|
use crate::syscalls::types::{__wasi_errno_t, __WASI_EFAULT};
|
||||||
|
use std::{cell::Cell, fmt, marker::PhantomData, mem};
|
||||||
|
use wasmer_runtime_core::{
|
||||||
|
memory::Memory,
|
||||||
|
types::{Type, ValueType, WasmExternType},
|
||||||
|
};
|
||||||
|
|
||||||
|
pub struct Array;
|
||||||
|
pub struct Item;
|
||||||
|
|
||||||
|
#[repr(transparent)]
|
||||||
|
pub struct WasmPtr<T: Copy, Ty = Item> {
|
||||||
|
offset: u32,
|
||||||
|
_phantom: PhantomData<(T, Ty)>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T: Copy, Ty> WasmPtr<T, Ty> {
|
||||||
|
#[inline]
|
||||||
|
pub fn new(offset: u32) -> Self {
|
||||||
|
Self {
|
||||||
|
offset,
|
||||||
|
_phantom: PhantomData,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
pub fn offset(self) -> u32 {
|
||||||
|
self.offset
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T: Copy + ValueType> WasmPtr<T, Item> {
|
||||||
|
#[inline]
|
||||||
|
pub fn deref<'a>(self, memory: &'a Memory) -> Result<&'a Cell<T>, __wasi_errno_t> {
|
||||||
|
if (self.offset as usize) + mem::size_of::<T>() >= memory.size().bytes().0 {
|
||||||
|
return Err(__WASI_EFAULT);
|
||||||
|
}
|
||||||
|
unsafe {
|
||||||
|
let cell_ptr = memory
|
||||||
|
.view::<T>()
|
||||||
|
.get_unchecked((self.offset() as usize) / mem::size_of::<T>())
|
||||||
|
as *const _;
|
||||||
|
Ok(&*cell_ptr)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T: Copy + ValueType> WasmPtr<T, Array> {
|
||||||
|
#[inline]
|
||||||
|
pub fn deref<'a>(
|
||||||
|
self,
|
||||||
|
memory: &'a Memory,
|
||||||
|
index: u32,
|
||||||
|
length: u32,
|
||||||
|
) -> Result<&'a [Cell<T>], __wasi_errno_t> {
|
||||||
|
if (self.offset as usize) + (mem::size_of::<T>() * ((index + length) as usize))
|
||||||
|
>= memory.size().bytes().0
|
||||||
|
{
|
||||||
|
return Err(__WASI_EFAULT);
|
||||||
|
}
|
||||||
|
|
||||||
|
unsafe {
|
||||||
|
let cell_ptrs = memory.view::<T>().get_unchecked(
|
||||||
|
((self.offset as usize) / mem::size_of::<T>()) + (index as usize)
|
||||||
|
..((self.offset() as usize) / mem::size_of::<T>())
|
||||||
|
+ ((index + length) as usize),
|
||||||
|
) as *const _;
|
||||||
|
Ok(&*cell_ptrs)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
unsafe impl<T: Copy, Ty> WasmExternType for WasmPtr<T, Ty> {
|
||||||
|
const TYPE: Type = Type::I32;
|
||||||
|
}
|
||||||
|
|
||||||
|
unsafe impl<T: Copy, Ty> ValueType for WasmPtr<T, Ty> {}
|
||||||
|
|
||||||
|
impl<T: Copy, Ty> Clone for WasmPtr<T, Ty> {
|
||||||
|
fn clone(&self) -> Self {
|
||||||
|
Self {
|
||||||
|
offset: self.offset,
|
||||||
|
_phantom: PhantomData,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T: Copy, Ty> Copy for WasmPtr<T, Ty> {}
|
||||||
|
|
||||||
|
impl<T: Copy, Ty> PartialEq for WasmPtr<T, Ty> {
|
||||||
|
fn eq(&self, other: &Self) -> bool {
|
||||||
|
self.offset == other.offset
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T: Copy, Ty> Eq for WasmPtr<T, Ty> {}
|
||||||
|
|
||||||
|
impl<T: Copy, Ty> fmt::Debug for WasmPtr<T, Ty> {
|
||||||
|
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||||
|
write!(f, "WasmPtr({:#x})", self.offset)
|
||||||
|
}
|
||||||
|
}
|
272
lib/wasi/src/state.rs
Normal file
272
lib/wasi/src/state.rs
Normal file
@ -0,0 +1,272 @@
|
|||||||
|
// use wasmer_runtime_abi::vfs::{
|
||||||
|
// vfs::Vfs,
|
||||||
|
// file_like::{FileLike, Metadata};
|
||||||
|
// };
|
||||||
|
use crate::syscalls::types::*;
|
||||||
|
use generational_arena::{Arena, Index as Inode};
|
||||||
|
use hashbrown::hash_map::{Entry, HashMap};
|
||||||
|
use std::{
|
||||||
|
cell::Cell,
|
||||||
|
io::{self, Write},
|
||||||
|
time::SystemTime,
|
||||||
|
};
|
||||||
|
use zbox::{init_env as zbox_init_env, File, FileType, OpenOptions, Repo, RepoOpener};
|
||||||
|
|
||||||
|
pub const MAX_SYMLINKS: usize = 100;
|
||||||
|
|
||||||
|
pub struct InodeVal {
|
||||||
|
pub stat: __wasi_filestat_t,
|
||||||
|
pub is_preopened: bool,
|
||||||
|
pub name: String,
|
||||||
|
pub kind: Kind,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[allow(dead_code)]
|
||||||
|
pub enum Kind {
|
||||||
|
File {
|
||||||
|
handle: File,
|
||||||
|
},
|
||||||
|
Dir {
|
||||||
|
handle: File,
|
||||||
|
/// The entries of a directory are lazily filled.
|
||||||
|
entries: HashMap<String, Inode>,
|
||||||
|
},
|
||||||
|
Symlink {
|
||||||
|
forwarded: Inode,
|
||||||
|
},
|
||||||
|
Buffer {
|
||||||
|
buffer: Vec<u8>,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Clone)]
|
||||||
|
pub struct Fd {
|
||||||
|
pub rights: __wasi_rights_t,
|
||||||
|
pub rights_inheriting: __wasi_rights_t,
|
||||||
|
pub flags: __wasi_fdflags_t,
|
||||||
|
pub offset: u64,
|
||||||
|
pub inode: Inode,
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct WasiFs {
|
||||||
|
pub repo: Repo,
|
||||||
|
pub name_map: HashMap<String, Inode>,
|
||||||
|
pub inodes: Arena<InodeVal>,
|
||||||
|
pub fd_map: HashMap<u32, Fd>,
|
||||||
|
pub next_fd: Cell<u32>,
|
||||||
|
pub inode_counter: Cell<u64>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl WasiFs {
|
||||||
|
pub fn new() -> Result<Self, String> {
|
||||||
|
zbox_init_env();
|
||||||
|
Ok(Self {
|
||||||
|
repo: RepoOpener::new()
|
||||||
|
.create(true)
|
||||||
|
.open("mem://wasmer-test-fs", "")
|
||||||
|
.map_err(|e| e.to_string())?,
|
||||||
|
name_map: HashMap::new(),
|
||||||
|
inodes: Arena::new(),
|
||||||
|
fd_map: HashMap::new(),
|
||||||
|
next_fd: Cell::new(3),
|
||||||
|
inode_counter: Cell::new(1000),
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
#[allow(dead_code)]
|
||||||
|
fn get_inode(&mut self, path: &str) -> Option<Inode> {
|
||||||
|
Some(match self.name_map.entry(path.to_string()) {
|
||||||
|
Entry::Occupied(o) => *o.get(),
|
||||||
|
Entry::Vacant(v) => {
|
||||||
|
let file = if let Ok(file) = OpenOptions::new()
|
||||||
|
.read(true)
|
||||||
|
.write(true)
|
||||||
|
.create(false)
|
||||||
|
.open(&mut self.repo, path)
|
||||||
|
{
|
||||||
|
file
|
||||||
|
} else {
|
||||||
|
return None;
|
||||||
|
};
|
||||||
|
|
||||||
|
let metadata = file.metadata().unwrap();
|
||||||
|
let inode_index = {
|
||||||
|
let index = self.inode_counter.get();
|
||||||
|
self.inode_counter.replace(index + 1)
|
||||||
|
};
|
||||||
|
|
||||||
|
let systime_to_nanos = |systime: SystemTime| {
|
||||||
|
let duration = systime
|
||||||
|
.duration_since(SystemTime::UNIX_EPOCH)
|
||||||
|
.expect("should always be after unix epoch");
|
||||||
|
duration.as_nanos() as u64
|
||||||
|
};
|
||||||
|
|
||||||
|
let inode = self.inodes.insert(InodeVal {
|
||||||
|
stat: __wasi_filestat_t {
|
||||||
|
st_dev: 0,
|
||||||
|
st_ino: inode_index,
|
||||||
|
st_filetype: match metadata.file_type() {
|
||||||
|
FileType::File => __WASI_FILETYPE_REGULAR_FILE,
|
||||||
|
FileType::Dir => __WASI_FILETYPE_DIRECTORY,
|
||||||
|
},
|
||||||
|
st_nlink: 0,
|
||||||
|
st_size: metadata.content_len() as u64,
|
||||||
|
st_atim: systime_to_nanos(SystemTime::now()),
|
||||||
|
st_mtim: systime_to_nanos(metadata.modified_at()),
|
||||||
|
st_ctim: systime_to_nanos(metadata.created_at()),
|
||||||
|
},
|
||||||
|
is_preopened: false,
|
||||||
|
name: path.to_string(),
|
||||||
|
kind: match metadata.file_type() {
|
||||||
|
FileType::File => Kind::File { handle: file },
|
||||||
|
FileType::Dir => Kind::Dir {
|
||||||
|
handle: file,
|
||||||
|
entries: HashMap::new(),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
});
|
||||||
|
v.insert(inode);
|
||||||
|
inode
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
#[allow(dead_code)]
|
||||||
|
fn filestat_inode(
|
||||||
|
&self,
|
||||||
|
inode: Inode,
|
||||||
|
flags: __wasi_lookupflags_t,
|
||||||
|
) -> Result<__wasi_filestat_t, __wasi_errno_t> {
|
||||||
|
let inode_val = &self.inodes[inode];
|
||||||
|
if let (true, Kind::Symlink { mut forwarded }) =
|
||||||
|
(flags & __WASI_LOOKUP_SYMLINK_FOLLOW != 0, &inode_val.kind)
|
||||||
|
{
|
||||||
|
// Time to follow the symlink.
|
||||||
|
let mut counter = 0;
|
||||||
|
|
||||||
|
while counter <= MAX_SYMLINKS {
|
||||||
|
let inode_val = &self.inodes[forwarded];
|
||||||
|
if let &Kind::Symlink {
|
||||||
|
forwarded: new_forwarded,
|
||||||
|
} = &inode_val.kind
|
||||||
|
{
|
||||||
|
counter += 1;
|
||||||
|
forwarded = new_forwarded;
|
||||||
|
} else {
|
||||||
|
return Ok(inode_val.stat);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Err(__WASI_EMLINK)
|
||||||
|
} else {
|
||||||
|
Ok(inode_val.stat)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[allow(dead_code)]
|
||||||
|
pub fn filestat_path(
|
||||||
|
&mut self,
|
||||||
|
preopened_fd: __wasi_fd_t,
|
||||||
|
flags: __wasi_lookupflags_t,
|
||||||
|
path: &str,
|
||||||
|
) -> Result<__wasi_filestat_t, __wasi_errno_t> {
|
||||||
|
warn!("Should use preopned_fd: {}", preopened_fd);
|
||||||
|
let inode = self.get_inode(path).ok_or(__WASI_EINVAL)?;
|
||||||
|
|
||||||
|
self.filestat_inode(inode, flags)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn filestat_fd(&self, fd: __wasi_fd_t) -> Result<__wasi_filestat_t, __wasi_errno_t> {
|
||||||
|
let fd = self.fd_map.get(&fd).ok_or(__WASI_EBADF)?;
|
||||||
|
|
||||||
|
Ok(self.inodes[fd.inode].stat)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn fdstat(&self, fd: __wasi_fd_t) -> Result<__wasi_fdstat_t, __wasi_errno_t> {
|
||||||
|
let fd = self.fd_map.get(&fd).ok_or(__WASI_EBADF)?;
|
||||||
|
|
||||||
|
Ok(__wasi_fdstat_t {
|
||||||
|
fs_filetype: match self.inodes[fd.inode].kind {
|
||||||
|
Kind::File { .. } => __WASI_FILETYPE_REGULAR_FILE,
|
||||||
|
Kind::Dir { .. } => __WASI_FILETYPE_DIRECTORY,
|
||||||
|
Kind::Symlink { .. } => __WASI_FILETYPE_SYMBOLIC_LINK,
|
||||||
|
_ => __WASI_FILETYPE_UNKNOWN,
|
||||||
|
},
|
||||||
|
fs_flags: fd.flags,
|
||||||
|
fs_rights_base: fd.rights,
|
||||||
|
fs_rights_inheriting: fd.rights, // TODO(lachlan): Is this right?
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn prestat_fd(&self, fd: __wasi_fd_t) -> Result<__wasi_prestat_t, __wasi_errno_t> {
|
||||||
|
let fd = self.fd_map.get(&fd).ok_or(__WASI_EBADF)?;
|
||||||
|
|
||||||
|
let inode_val = &self.inodes[fd.inode];
|
||||||
|
|
||||||
|
if inode_val.is_preopened {
|
||||||
|
Ok(__wasi_prestat_t {
|
||||||
|
pr_type: __WASI_PREOPENTYPE_DIR,
|
||||||
|
u: PrestatEnum::Dir {
|
||||||
|
pr_name_len: inode_val.name.len() as u32,
|
||||||
|
}
|
||||||
|
.untagged(),
|
||||||
|
})
|
||||||
|
} else {
|
||||||
|
Err(__WASI_EBADF)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn flush(&mut self, fd: __wasi_fd_t) -> Result<(), __wasi_errno_t> {
|
||||||
|
match fd {
|
||||||
|
0 => (),
|
||||||
|
1 => io::stdout().flush().map_err(|_| __WASI_EIO)?,
|
||||||
|
2 => io::stderr().flush().map_err(|_| __WASI_EIO)?,
|
||||||
|
_ => {
|
||||||
|
let fd = self.fd_map.get(&fd).ok_or(__WASI_EBADF)?;
|
||||||
|
if fd.rights & __WASI_RIGHT_FD_DATASYNC == 0 {
|
||||||
|
return Err(__WASI_EACCES);
|
||||||
|
}
|
||||||
|
|
||||||
|
let inode = &mut self.inodes[fd.inode];
|
||||||
|
|
||||||
|
match &mut inode.kind {
|
||||||
|
Kind::File { handle } => handle.flush().map_err(|_| __WASI_EIO)?,
|
||||||
|
// TODO: verify this behavior
|
||||||
|
Kind::Dir { .. } => return Err(__WASI_EISDIR),
|
||||||
|
Kind::Symlink { .. } => unimplemented!(),
|
||||||
|
Kind::Buffer { .. } => (),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn create_fd(
|
||||||
|
&mut self,
|
||||||
|
rights: __wasi_rights_t,
|
||||||
|
rights_inheriting: __wasi_rights_t,
|
||||||
|
flags: __wasi_fdflags_t,
|
||||||
|
inode: Inode,
|
||||||
|
) -> Result<u32, __wasi_errno_t> {
|
||||||
|
let idx = self.next_fd.get();
|
||||||
|
self.next_fd.set(idx + 1);
|
||||||
|
self.fd_map.insert(
|
||||||
|
idx,
|
||||||
|
Fd {
|
||||||
|
rights,
|
||||||
|
rights_inheriting,
|
||||||
|
flags,
|
||||||
|
offset: 0,
|
||||||
|
inode,
|
||||||
|
},
|
||||||
|
);
|
||||||
|
Ok(idx)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct WasiState<'a> {
|
||||||
|
pub fs: WasiFs,
|
||||||
|
pub args: &'a [Vec<u8>],
|
||||||
|
pub envs: &'a [Vec<u8>],
|
||||||
|
}
|
1378
lib/wasi/src/syscalls/mod.rs
Normal file
1378
lib/wasi/src/syscalls/mod.rs
Normal file
File diff suppressed because it is too large
Load Diff
452
lib/wasi/src/syscalls/types.rs
Normal file
452
lib/wasi/src/syscalls/types.rs
Normal file
@ -0,0 +1,452 @@
|
|||||||
|
#![allow(non_camel_case_types)]
|
||||||
|
|
||||||
|
use crate::ptr::{Array, WasmPtr};
|
||||||
|
use byteorder::{ReadBytesExt, WriteBytesExt, LE};
|
||||||
|
use std::mem;
|
||||||
|
use wasmer_runtime_core::types::ValueType;
|
||||||
|
|
||||||
|
pub type __wasi_advice_t = u8;
|
||||||
|
pub const __WASI_ADVICE_DONTNEED: u8 = 0;
|
||||||
|
pub const __WASI_ADVICE_NOREUSE: u8 = 1;
|
||||||
|
pub const __WASI_ADVICE_NORMAL: u8 = 2;
|
||||||
|
pub const __WASI_ADVICE_RANDOM: u8 = 3;
|
||||||
|
pub const __WASI_ADVICE_SEQUENTIAL: u8 = 4;
|
||||||
|
pub const __WASI_ADVICE_WILLNEED: u8 = 5;
|
||||||
|
|
||||||
|
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
|
||||||
|
#[repr(C)]
|
||||||
|
pub struct __wasi_ciovec_t {
|
||||||
|
pub buf: WasmPtr<u8, Array>,
|
||||||
|
pub buf_len: u32,
|
||||||
|
}
|
||||||
|
|
||||||
|
unsafe impl ValueType for __wasi_ciovec_t {}
|
||||||
|
|
||||||
|
pub type __wasi_clockid_t = u32;
|
||||||
|
pub const __WASI_CLOCK_MONOTONIC: u32 = 0;
|
||||||
|
pub const __WASI_CLOCK_PROCESS_CPUTIME_ID: u32 = 1;
|
||||||
|
pub const __WASI_CLOCK_REALTIME: u32 = 2;
|
||||||
|
pub const __WASI_CLOCK_THREAD_CPUTIME_ID: u32 = 3;
|
||||||
|
|
||||||
|
pub type __wasi_device_t = u64;
|
||||||
|
|
||||||
|
pub type __wasi_dircookie_t = u64;
|
||||||
|
pub const __WASI_DIRCOOKIE_START: u64 = 0;
|
||||||
|
|
||||||
|
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
|
||||||
|
#[repr(C)]
|
||||||
|
pub struct __wasi_dirent_t {
|
||||||
|
pub d_next: __wasi_dircookie_t,
|
||||||
|
pub d_ino: __wasi_inode_t,
|
||||||
|
pub d_namlen: u32,
|
||||||
|
pub d_type: __wasi_filetype_t,
|
||||||
|
}
|
||||||
|
|
||||||
|
pub type __wasi_errno_t = u16;
|
||||||
|
pub const __WASI_ESUCCESS: u16 = 0;
|
||||||
|
pub const __WASI_E2BIG: u16 = 1;
|
||||||
|
pub const __WASI_EACCES: u16 = 2;
|
||||||
|
pub const __WASI_EADDRINUSE: u16 = 3;
|
||||||
|
pub const __WASI_EADDRNOTAVAIL: u16 = 4;
|
||||||
|
pub const __WASI_EAFNOSUPPORT: u16 = 5;
|
||||||
|
pub const __WASI_EAGAIN: u16 = 6;
|
||||||
|
pub const __WASI_EALREADY: u16 = 7;
|
||||||
|
pub const __WASI_EBADF: u16 = 8;
|
||||||
|
pub const __WASI_EBADMSG: u16 = 9;
|
||||||
|
pub const __WASI_EBUSY: u16 = 10;
|
||||||
|
pub const __WASI_ECANCELED: u16 = 11;
|
||||||
|
pub const __WASI_ECHILD: u16 = 12;
|
||||||
|
pub const __WASI_ECONNABORTED: u16 = 13;
|
||||||
|
pub const __WASI_ECONNREFUSED: u16 = 14;
|
||||||
|
pub const __WASI_ECONNRESET: u16 = 15;
|
||||||
|
pub const __WASI_EDEADLK: u16 = 16;
|
||||||
|
pub const __WASI_EDESTADDRREQ: u16 = 17;
|
||||||
|
pub const __WASI_EDOM: u16 = 18;
|
||||||
|
pub const __WASI_EDQUOT: u16 = 19;
|
||||||
|
pub const __WASI_EEXIST: u16 = 20;
|
||||||
|
pub const __WASI_EFAULT: u16 = 21;
|
||||||
|
pub const __WASI_EFBIG: u16 = 22;
|
||||||
|
pub const __WASI_EHOSTUNREACH: u16 = 23;
|
||||||
|
pub const __WASI_EIDRM: u16 = 24;
|
||||||
|
pub const __WASI_EILSEQ: u16 = 25;
|
||||||
|
pub const __WASI_EINPROGRESS: u16 = 26;
|
||||||
|
pub const __WASI_EINTR: u16 = 27;
|
||||||
|
pub const __WASI_EINVAL: u16 = 28;
|
||||||
|
pub const __WASI_EIO: u16 = 29;
|
||||||
|
pub const __WASI_EISCONN: u16 = 30;
|
||||||
|
pub const __WASI_EISDIR: u16 = 31;
|
||||||
|
pub const __WASI_ELOOP: u16 = 32;
|
||||||
|
pub const __WASI_EMFILE: u16 = 33;
|
||||||
|
pub const __WASI_EMLINK: u16 = 34;
|
||||||
|
pub const __WASI_EMSGSIZE: u16 = 35;
|
||||||
|
pub const __WASI_EMULTIHOP: u16 = 36;
|
||||||
|
pub const __WASI_ENAMETOOLONG: u16 = 37;
|
||||||
|
pub const __WASI_ENETDOWN: u16 = 38;
|
||||||
|
pub const __WASI_ENETRESET: u16 = 39;
|
||||||
|
pub const __WASI_ENETUNREACH: u16 = 40;
|
||||||
|
pub const __WASI_ENFILE: u16 = 41;
|
||||||
|
pub const __WASI_ENOBUFS: u16 = 42;
|
||||||
|
pub const __WASI_ENODEV: u16 = 43;
|
||||||
|
pub const __WASI_ENOENT: u16 = 44;
|
||||||
|
pub const __WASI_ENOEXEC: u16 = 45;
|
||||||
|
pub const __WASI_ENOLCK: u16 = 46;
|
||||||
|
pub const __WASI_ENOLINK: u16 = 47;
|
||||||
|
pub const __WASI_ENOMEM: u16 = 48;
|
||||||
|
pub const __WASI_ENOMSG: u16 = 49;
|
||||||
|
pub const __WASI_ENOPROTOOPT: u16 = 50;
|
||||||
|
pub const __WASI_ENOSPC: u16 = 51;
|
||||||
|
pub const __WASI_ENOSYS: u16 = 52;
|
||||||
|
pub const __WASI_ENOTCONN: u16 = 53;
|
||||||
|
pub const __WASI_ENOTDIR: u16 = 54;
|
||||||
|
pub const __WASI_ENOTEMPTY: u16 = 55;
|
||||||
|
pub const __WASI_ENOTRECOVERABLE: u16 = 56;
|
||||||
|
pub const __WASI_ENOTSOCK: u16 = 57;
|
||||||
|
pub const __WASI_ENOTSUP: u16 = 58;
|
||||||
|
pub const __WASI_ENOTTY: u16 = 59;
|
||||||
|
pub const __WASI_ENXIO: u16 = 60;
|
||||||
|
pub const __WASI_EOVERFLOW: u16 = 61;
|
||||||
|
pub const __WASI_EOWNERDEAD: u16 = 62;
|
||||||
|
pub const __WASI_EPERM: u16 = 63;
|
||||||
|
pub const __WASI_EPIPE: u16 = 64;
|
||||||
|
pub const __WASI_EPROTO: u16 = 65;
|
||||||
|
pub const __WASI_EPROTONOSUPPORT: u16 = 66;
|
||||||
|
pub const __WASI_EPROTOTYPE: u16 = 67;
|
||||||
|
pub const __WASI_ERANGE: u16 = 68;
|
||||||
|
pub const __WASI_EROFS: u16 = 69;
|
||||||
|
pub const __WASI_ESPIPE: u16 = 70;
|
||||||
|
pub const __WASI_ESRCH: u16 = 71;
|
||||||
|
pub const __WASI_ESTALE: u16 = 72;
|
||||||
|
pub const __WASI_ETIMEDOUT: u16 = 73;
|
||||||
|
pub const __WASI_ETXTBSY: u16 = 74;
|
||||||
|
pub const __WASI_EXDEV: u16 = 75;
|
||||||
|
pub const __WASI_ENOTCAPABLE: u16 = 76;
|
||||||
|
|
||||||
|
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
|
||||||
|
#[repr(C)]
|
||||||
|
pub struct __wasi_event_fd_readwrite_t {
|
||||||
|
pub nbytes: __wasi_filesize_t,
|
||||||
|
pub flags: __wasi_eventrwflags_t,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Copy, Clone)]
|
||||||
|
#[repr(C)]
|
||||||
|
pub union __wasi_event_u {
|
||||||
|
fd_readwrite: __wasi_event_fd_readwrite_t,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Copy, Clone)]
|
||||||
|
pub enum EventEnum {
|
||||||
|
FdReadWrite {
|
||||||
|
nbytes: __wasi_filesize_t,
|
||||||
|
flags: __wasi_eventrwflags_t,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
impl EventEnum {
|
||||||
|
pub fn untagged(self) -> __wasi_event_u {
|
||||||
|
match self {
|
||||||
|
EventEnum::FdReadWrite { nbytes, flags } => __wasi_event_u {
|
||||||
|
fd_readwrite: __wasi_event_fd_readwrite_t { nbytes, flags },
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Copy, Clone)]
|
||||||
|
#[repr(C)]
|
||||||
|
pub struct __wasi_event_t {
|
||||||
|
pub userdata: __wasi_userdata_t,
|
||||||
|
pub error: __wasi_errno_t,
|
||||||
|
pub type_: __wasi_eventtype_t,
|
||||||
|
pub u: __wasi_event_u,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl __wasi_event_t {
|
||||||
|
pub fn tagged(&self) -> Option<EventEnum> {
|
||||||
|
match self.type_ {
|
||||||
|
__WASI_EVENTTYPE_FD_READ | __WASI_EVENTTYPE_FD_WRITE => Some(EventEnum::FdReadWrite {
|
||||||
|
nbytes: unsafe { self.u.fd_readwrite.nbytes },
|
||||||
|
flags: unsafe { self.u.fd_readwrite.flags },
|
||||||
|
}),
|
||||||
|
_ => None,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub type __wasi_eventrwflags_t = u16;
|
||||||
|
pub const __WASI_EVENT_FD_READWRITE_HANGUP: u16 = 1 << 0;
|
||||||
|
|
||||||
|
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;
|
||||||
|
|
||||||
|
pub type __wasi_exitcode_t = u32;
|
||||||
|
|
||||||
|
pub type __wasi_fd_t = u32;
|
||||||
|
pub const __WASI_STDIN_FILENO: u32 = 0;
|
||||||
|
pub const __WASI_STDOUT_FILENO: u32 = 1;
|
||||||
|
pub const __WASI_STDERR_FILENO: u32 = 2;
|
||||||
|
|
||||||
|
pub type __wasi_fdflags_t = u16;
|
||||||
|
pub const __WASI_FDFLAG_APPEND: u16 = 1 << 0;
|
||||||
|
pub const __WASI_FDFLAG_DSYNC: u16 = 1 << 1;
|
||||||
|
pub const __WASI_FDFLAG_NONBLOCK: u16 = 1 << 2;
|
||||||
|
pub const __WASI_FDFLAG_RSYNC: u16 = 1 << 3;
|
||||||
|
pub const __WASI_FDFLAG_SYNC: u16 = 1 << 4;
|
||||||
|
|
||||||
|
pub type __wasi_preopentype_t = u8;
|
||||||
|
pub const __WASI_PREOPENTYPE_DIR: u8 = 0;
|
||||||
|
|
||||||
|
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
|
||||||
|
#[repr(C)]
|
||||||
|
pub struct __wasi_prestat_u_dir_t {
|
||||||
|
pub pr_name_len: u32,
|
||||||
|
}
|
||||||
|
|
||||||
|
unsafe impl ValueType for __wasi_prestat_u_dir_t {}
|
||||||
|
|
||||||
|
#[derive(Copy, Clone)]
|
||||||
|
#[repr(C)]
|
||||||
|
pub union __wasi_prestat_u {
|
||||||
|
dir: __wasi_prestat_u_dir_t,
|
||||||
|
}
|
||||||
|
|
||||||
|
unsafe impl ValueType for __wasi_prestat_u {}
|
||||||
|
|
||||||
|
#[derive(Copy, Clone)]
|
||||||
|
#[repr(C)]
|
||||||
|
pub struct __wasi_prestat_t {
|
||||||
|
pub pr_type: __wasi_preopentype_t,
|
||||||
|
pub u: __wasi_prestat_u,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Copy, Clone)]
|
||||||
|
pub enum PrestatEnum {
|
||||||
|
Dir { pr_name_len: u32 },
|
||||||
|
}
|
||||||
|
|
||||||
|
impl PrestatEnum {
|
||||||
|
pub fn untagged(self) -> __wasi_prestat_u {
|
||||||
|
match self {
|
||||||
|
PrestatEnum::Dir { pr_name_len } => __wasi_prestat_u {
|
||||||
|
dir: __wasi_prestat_u_dir_t { pr_name_len },
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl __wasi_prestat_t {
|
||||||
|
pub fn tagged(&self) -> Option<PrestatEnum> {
|
||||||
|
match self.pr_type {
|
||||||
|
__WASI_PREOPENTYPE_DIR => Some(PrestatEnum::Dir {
|
||||||
|
pr_name_len: unsafe { self.u.dir.pr_name_len },
|
||||||
|
}),
|
||||||
|
_ => None,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
unsafe impl ValueType for __wasi_prestat_t {}
|
||||||
|
|
||||||
|
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
|
||||||
|
#[repr(C)]
|
||||||
|
pub struct __wasi_fdstat_t {
|
||||||
|
pub fs_filetype: __wasi_filetype_t,
|
||||||
|
pub fs_flags: __wasi_fdflags_t,
|
||||||
|
pub fs_rights_base: __wasi_rights_t,
|
||||||
|
pub fs_rights_inheriting: __wasi_rights_t,
|
||||||
|
}
|
||||||
|
|
||||||
|
unsafe impl ValueType for __wasi_fdstat_t {}
|
||||||
|
|
||||||
|
pub type __wasi_filedelta_t = i64;
|
||||||
|
|
||||||
|
pub type __wasi_filesize_t = u64;
|
||||||
|
|
||||||
|
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
|
||||||
|
#[repr(C)]
|
||||||
|
pub struct __wasi_filestat_t {
|
||||||
|
pub st_dev: __wasi_device_t,
|
||||||
|
pub st_ino: __wasi_inode_t,
|
||||||
|
pub st_filetype: __wasi_filetype_t,
|
||||||
|
pub st_nlink: __wasi_linkcount_t,
|
||||||
|
pub st_size: __wasi_filesize_t,
|
||||||
|
pub st_atim: __wasi_timestamp_t,
|
||||||
|
pub st_mtim: __wasi_timestamp_t,
|
||||||
|
pub st_ctim: __wasi_timestamp_t,
|
||||||
|
}
|
||||||
|
|
||||||
|
unsafe impl ValueType for __wasi_filestat_t {}
|
||||||
|
|
||||||
|
pub type __wasi_filetype_t = u8;
|
||||||
|
pub const __WASI_FILETYPE_UNKNOWN: u8 = 0;
|
||||||
|
pub const __WASI_FILETYPE_BLOCK_DEVICE: u8 = 1;
|
||||||
|
pub const __WASI_FILETYPE_CHARACTER_DEVICE: u8 = 2;
|
||||||
|
pub const __WASI_FILETYPE_DIRECTORY: u8 = 3;
|
||||||
|
pub const __WASI_FILETYPE_REGULAR_FILE: u8 = 4;
|
||||||
|
pub const __WASI_FILETYPE_SOCKET_DGRAM: u8 = 5;
|
||||||
|
pub const __WASI_FILETYPE_SOCKET_STREAM: u8 = 6;
|
||||||
|
pub const __WASI_FILETYPE_SYMBOLIC_LINK: u8 = 7;
|
||||||
|
|
||||||
|
pub type __wasi_fstflags_t = u16;
|
||||||
|
pub const __WASI_FILESTAT_SET_ATIM: u16 = 1 << 0;
|
||||||
|
pub const __WASI_FILESTAT_SET_ATIM_NOW: u16 = 1 << 1;
|
||||||
|
pub const __WASI_FILESTAT_SET_MTIM: u16 = 1 << 2;
|
||||||
|
pub const __WASI_FILESTAT_SET_MTIM_NOW: u16 = 1 << 3;
|
||||||
|
|
||||||
|
pub type __wasi_inode_t = u64;
|
||||||
|
|
||||||
|
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
|
||||||
|
#[repr(C)]
|
||||||
|
pub struct __wasi_iovec_t {
|
||||||
|
pub buf: WasmPtr<u8, Array>,
|
||||||
|
pub buf_len: u32,
|
||||||
|
}
|
||||||
|
|
||||||
|
unsafe impl ValueType for __wasi_iovec_t {}
|
||||||
|
|
||||||
|
pub type __wasi_linkcount_t = u32;
|
||||||
|
|
||||||
|
pub type __wasi_lookupflags_t = u32;
|
||||||
|
pub const __WASI_LOOKUP_SYMLINK_FOLLOW: u32 = 1 << 0;
|
||||||
|
|
||||||
|
pub type __wasi_oflags_t = u16;
|
||||||
|
pub const __WASI_O_CREAT: u16 = 1 << 0;
|
||||||
|
pub const __WASI_O_DIRECTORY: u16 = 1 << 1;
|
||||||
|
pub const __WASI_O_EXCL: u16 = 1 << 2;
|
||||||
|
pub const __WASI_O_TRUNC: u16 = 1 << 3;
|
||||||
|
|
||||||
|
pub type __wasi_riflags_t = u16;
|
||||||
|
pub const __WASI_SOCK_RECV_PEEK: u16 = 1 << 0;
|
||||||
|
pub const __WASI_SOCK_RECV_WAITALL: u16 = 1 << 1;
|
||||||
|
|
||||||
|
pub type __wasi_rights_t = u64;
|
||||||
|
pub const __WASI_RIGHT_FD_DATASYNC: u64 = 1 << 0;
|
||||||
|
pub const __WASI_RIGHT_FD_READ: u64 = 1 << 1;
|
||||||
|
pub const __WASI_RIGHT_FD_SEEK: u64 = 1 << 2;
|
||||||
|
pub const __WASI_RIGHT_FD_FDSTAT_SET_FLAGS: u64 = 1 << 3;
|
||||||
|
pub const __WASI_RIGHT_FD_SYNC: u64 = 1 << 4;
|
||||||
|
pub const __WASI_RIGHT_FD_TELL: u64 = 1 << 5;
|
||||||
|
pub const __WASI_RIGHT_FD_WRITE: u64 = 1 << 6;
|
||||||
|
pub const __WASI_RIGHT_FD_ADVISE: u64 = 1 << 7;
|
||||||
|
pub const __WASI_RIGHT_FD_ALLOCATE: u64 = 1 << 8;
|
||||||
|
pub const __WASI_RIGHT_PATH_CREATE_DIRECTORY: u64 = 1 << 9;
|
||||||
|
pub const __WASI_RIGHT_PATH_CREATE_FILE: u64 = 1 << 10;
|
||||||
|
pub const __WASI_RIGHT_PATH_LINK_SOURCE: u64 = 1 << 11;
|
||||||
|
pub const __WASI_RIGHT_PATH_LINK_TARGET: u64 = 1 << 12;
|
||||||
|
pub const __WASI_RIGHT_PATH_OPEN: u64 = 1 << 13;
|
||||||
|
pub const __WASI_RIGHT_FD_READDIR: u64 = 1 << 14;
|
||||||
|
pub const __WASI_RIGHT_PATH_READLINK: u64 = 1 << 15;
|
||||||
|
pub const __WASI_RIGHT_PATH_RENAME_SOURCE: u64 = 1 << 16;
|
||||||
|
pub const __WASI_RIGHT_PATH_RENAME_TARGET: u64 = 1 << 17;
|
||||||
|
pub const __WASI_RIGHT_PATH_FILESTAT_GET: u64 = 1 << 18;
|
||||||
|
pub const __WASI_RIGHT_PATH_FILESTAT_SET_SIZE: u64 = 1 << 19;
|
||||||
|
pub const __WASI_RIGHT_PATH_FILESTAT_SET_TIMES: u64 = 1 << 20;
|
||||||
|
pub const __WASI_RIGHT_FD_FILESTAT_GET: u64 = 1 << 21;
|
||||||
|
pub const __WASI_RIGHT_FD_FILESTAT_SET_SIZE: u64 = 1 << 22;
|
||||||
|
pub const __WASI_RIGHT_FD_FILESTAT_SET_TIMES: u64 = 1 << 23;
|
||||||
|
pub const __WASI_RIGHT_PATH_SYMLINK: u64 = 1 << 24;
|
||||||
|
pub const __WASI_RIGHT_PATH_UNLINK_FILE: u64 = 1 << 25;
|
||||||
|
pub const __WASI_RIGHT_PATH_REMOVE_DIRECTORY: u64 = 1 << 26;
|
||||||
|
pub const __WASI_RIGHT_POLL_FD_READWRITE: u64 = 1 << 27;
|
||||||
|
pub const __WASI_RIGHT_SOCK_SHUTDOWN: u64 = 1 << 28;
|
||||||
|
|
||||||
|
pub type __wasi_roflags_t = u16;
|
||||||
|
pub const __WASI_SOCK_RECV_DATA_TRUNCATED: u16 = 1 << 0;
|
||||||
|
|
||||||
|
pub type __wasi_sdflags_t = u8;
|
||||||
|
pub const __WASI_SHUT_RD: u8 = 1 << 0;
|
||||||
|
pub const __WASI_SHUT_WR: u8 = 1 << 1;
|
||||||
|
|
||||||
|
pub type __wasi_siflags_t = u16;
|
||||||
|
|
||||||
|
pub type __wasi_signal_t = u8;
|
||||||
|
pub const __WASI_SIGABRT: u8 = 0;
|
||||||
|
pub const __WASI_SIGALRM: u8 = 1;
|
||||||
|
pub const __WASI_SIGBUS: u8 = 2;
|
||||||
|
pub const __WASI_SIGCHLD: u8 = 3;
|
||||||
|
pub const __WASI_SIGCONT: u8 = 4;
|
||||||
|
pub const __WASI_SIGFPE: u8 = 5;
|
||||||
|
pub const __WASI_SIGHUP: u8 = 6;
|
||||||
|
pub const __WASI_SIGILL: u8 = 7;
|
||||||
|
pub const __WASI_SIGINT: u8 = 8;
|
||||||
|
pub const __WASI_SIGKILL: u8 = 9;
|
||||||
|
pub const __WASI_SIGPIPE: u8 = 10;
|
||||||
|
pub const __WASI_SIGQUIT: u8 = 11;
|
||||||
|
pub const __WASI_SIGSEGV: u8 = 12;
|
||||||
|
pub const __WASI_SIGSTOP: u8 = 13;
|
||||||
|
pub const __WASI_SIGSYS: u8 = 14;
|
||||||
|
pub const __WASI_SIGTERM: u8 = 15;
|
||||||
|
pub const __WASI_SIGTRAP: u8 = 16;
|
||||||
|
pub const __WASI_SIGTSTP: u8 = 17;
|
||||||
|
pub const __WASI_SIGTTIN: u8 = 18;
|
||||||
|
pub const __WASI_SIGTTOU: u8 = 19;
|
||||||
|
pub const __WASI_SIGURG: u8 = 20;
|
||||||
|
pub const __WASI_SIGUSR1: u8 = 21;
|
||||||
|
pub const __WASI_SIGUSR2: u8 = 22;
|
||||||
|
pub const __WASI_SIGVTALRM: u8 = 23;
|
||||||
|
pub const __WASI_SIGXCPU: u8 = 24;
|
||||||
|
pub const __WASI_SIGXFSZ: u8 = 25;
|
||||||
|
|
||||||
|
pub type __wasi_subclockflags_t = u16;
|
||||||
|
pub const __WASI_SUBSCRIPTION_CLOCK_ABSTIME: u16 = 1 << 0;
|
||||||
|
|
||||||
|
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
|
||||||
|
#[repr(C)]
|
||||||
|
pub struct __wasi_subscription_clock_t {
|
||||||
|
pub userdata: __wasi_userdata_t,
|
||||||
|
pub clock_id: __wasi_clockid_t,
|
||||||
|
pub timeout: __wasi_timestamp_t,
|
||||||
|
pub precision: __wasi_timestamp_t,
|
||||||
|
pub flags: __wasi_subclockflags_t,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
|
||||||
|
#[repr(C)]
|
||||||
|
pub struct __wasi_subscription_fs_readwrite_t {
|
||||||
|
pub fd: __wasi_fd_t,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[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: __wasi_userdata_t,
|
||||||
|
pub type_: __wasi_eventtype_t,
|
||||||
|
pub u: __wasi_subscription_u,
|
||||||
|
}
|
||||||
|
|
||||||
|
pub enum SubscriptionEnum {
|
||||||
|
Clock(__wasi_subscription_clock_t),
|
||||||
|
FdReadWrite(__wasi_subscription_fs_readwrite_t),
|
||||||
|
}
|
||||||
|
|
||||||
|
impl __wasi_subscription_t {
|
||||||
|
pub fn tagged(&self) -> Option<SubscriptionEnum> {
|
||||||
|
match self.type_ {
|
||||||
|
__WASI_EVENTTYPE_CLOCK => Some(SubscriptionEnum::Clock(unsafe { self.u.clock })),
|
||||||
|
__WASI_EVENTTYPE_FD_READ | __WASI_EVENTTYPE_FD_WRITE => {
|
||||||
|
Some(SubscriptionEnum::FdReadWrite(unsafe {
|
||||||
|
self.u.fd_readwrite
|
||||||
|
}))
|
||||||
|
}
|
||||||
|
_ => None,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub type __wasi_timestamp_t = u64;
|
||||||
|
|
||||||
|
pub type __wasi_userdata_t = u64;
|
||||||
|
|
||||||
|
pub type __wasi_whence_t = u8;
|
||||||
|
pub const __WASI_WHENCE_CUR: u8 = 0;
|
||||||
|
pub const __WASI_WHENCE_END: u8 = 1;
|
||||||
|
pub const __WASI_WHENCE_SET: u8 = 2;
|
59
lib/wasi/src/syscalls/unix/mod.rs
Normal file
59
lib/wasi/src/syscalls/unix/mod.rs
Normal file
@ -0,0 +1,59 @@
|
|||||||
|
use crate::syscalls::types::*;
|
||||||
|
use libc::{
|
||||||
|
clock_getres, clock_gettime, timespec, CLOCK_MONOTONIC, CLOCK_PROCESS_CPUTIME_ID,
|
||||||
|
CLOCK_REALTIME, CLOCK_THREAD_CPUTIME_ID,
|
||||||
|
};
|
||||||
|
use std::cell::Cell;
|
||||||
|
use std::mem;
|
||||||
|
|
||||||
|
pub fn platform_clock_res_get(
|
||||||
|
clock_id: __wasi_clockid_t,
|
||||||
|
resolution: &Cell<__wasi_timestamp_t>,
|
||||||
|
) -> __wasi_errno_t {
|
||||||
|
let unix_clock_id = match clock_id {
|
||||||
|
__WASI_CLOCK_MONOTONIC => CLOCK_MONOTONIC,
|
||||||
|
__WASI_CLOCK_PROCESS_CPUTIME_ID => CLOCK_PROCESS_CPUTIME_ID,
|
||||||
|
__WASI_CLOCK_REALTIME => CLOCK_REALTIME,
|
||||||
|
__WASI_CLOCK_THREAD_CPUTIME_ID => CLOCK_THREAD_CPUTIME_ID,
|
||||||
|
_ => return __WASI_EINVAL,
|
||||||
|
};
|
||||||
|
|
||||||
|
let (output, timespec_out) = unsafe {
|
||||||
|
let mut timespec_out: timespec = mem::uninitialized();
|
||||||
|
(clock_getres(unix_clock_id, &mut timespec_out), timespec_out)
|
||||||
|
};
|
||||||
|
|
||||||
|
resolution.set(timespec_out.tv_nsec as __wasi_timestamp_t);
|
||||||
|
|
||||||
|
// TODO: map output of clock_getres to __wasi_errno_t
|
||||||
|
__WASI_ESUCCESS
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn platform_clock_time_get(
|
||||||
|
clock_id: __wasi_clockid_t,
|
||||||
|
precision: __wasi_timestamp_t,
|
||||||
|
time: &Cell<__wasi_timestamp_t>,
|
||||||
|
) -> __wasi_errno_t {
|
||||||
|
let unix_clock_id = match clock_id {
|
||||||
|
__WASI_CLOCK_MONOTONIC => CLOCK_MONOTONIC,
|
||||||
|
__WASI_CLOCK_PROCESS_CPUTIME_ID => CLOCK_PROCESS_CPUTIME_ID,
|
||||||
|
__WASI_CLOCK_REALTIME => CLOCK_REALTIME,
|
||||||
|
__WASI_CLOCK_THREAD_CPUTIME_ID => CLOCK_THREAD_CPUTIME_ID,
|
||||||
|
_ => return __WASI_EINVAL,
|
||||||
|
};
|
||||||
|
|
||||||
|
let (output, timespec_out) = unsafe {
|
||||||
|
let mut timespec_out: timespec = mem::uninitialized();
|
||||||
|
(
|
||||||
|
clock_gettime(unix_clock_id, &mut timespec_out),
|
||||||
|
timespec_out,
|
||||||
|
)
|
||||||
|
};
|
||||||
|
|
||||||
|
// TODO: adjust output by precision...
|
||||||
|
|
||||||
|
time.set(timespec_out.tv_nsec as __wasi_timestamp_t);
|
||||||
|
|
||||||
|
// TODO: map output of clock_gettime to __wasi_errno_t
|
||||||
|
__WASI_ESUCCESS
|
||||||
|
}
|
17
lib/wasi/src/syscalls/windows.rs
Normal file
17
lib/wasi/src/syscalls/windows.rs
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
use crate::syscalls::types::*;
|
||||||
|
use std::cell::Cell;
|
||||||
|
|
||||||
|
pub fn platform_clock_res_get(
|
||||||
|
clock_id: __wasi_clockid_t,
|
||||||
|
resolution: &Cell<__wasi_timestamp_t>,
|
||||||
|
) -> __wasi_errno_t {
|
||||||
|
__WASI_EINVAL
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn platform_clock_time_get(
|
||||||
|
clock_id: __wasi_clockid_t,
|
||||||
|
precision: __wasi_timestamp_t,
|
||||||
|
time: &Cell<__wasi_timestamp_t>,
|
||||||
|
) -> __wasi_errno_t {
|
||||||
|
unimplemented!()
|
||||||
|
}
|
15
lib/wasi/src/utils.rs
Normal file
15
lib/wasi/src/utils.rs
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
use wasmer_runtime_core::module::Module;
|
||||||
|
|
||||||
|
/// Check if a provided module is compiled with WASI support
|
||||||
|
pub fn is_wasi_module(module: &Module) -> bool {
|
||||||
|
for (_, import_name) in &module.info().imported_functions {
|
||||||
|
let namespace = module
|
||||||
|
.info()
|
||||||
|
.namespace_table
|
||||||
|
.get(import_name.namespace_index);
|
||||||
|
if namespace == "wasi_unstable" {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
false
|
||||||
|
}
|
@ -12,9 +12,10 @@ use structopt::StructOpt;
|
|||||||
|
|
||||||
use wasmer::webassembly::InstanceABI;
|
use wasmer::webassembly::InstanceABI;
|
||||||
use wasmer::*;
|
use wasmer::*;
|
||||||
use wasmer_emscripten;
|
|
||||||
use wasmer_runtime::cache::{Cache as BaseCache, FileSystemCache, WasmHash, WASMER_VERSION_HASH};
|
use wasmer_runtime::cache::{Cache as BaseCache, FileSystemCache, WasmHash, WASMER_VERSION_HASH};
|
||||||
use wasmer_runtime_core::{self, backend::CompilerConfig};
|
use wasmer_runtime_core::{self, backend::CompilerConfig};
|
||||||
|
#[cfg(feature = "wasi")]
|
||||||
|
use wasmer_wasi;
|
||||||
|
|
||||||
#[derive(Debug, StructOpt)]
|
#[derive(Debug, StructOpt)]
|
||||||
#[structopt(name = "wasmer", about = "Wasm execution runtime.")]
|
#[structopt(name = "wasmer", about = "Wasm execution runtime.")]
|
||||||
@ -211,7 +212,9 @@ fn execute_wasm(options: &Run) -> Result<(), String> {
|
|||||||
.map_err(|e| format!("Can't compile module: {:?}", e))?
|
.map_err(|e| format!("Can't compile module: {:?}", e))?
|
||||||
};
|
};
|
||||||
|
|
||||||
let (_abi, import_object, _em_globals) = if wasmer_emscripten::is_emscripten_module(&module) {
|
// TODO: refactor this
|
||||||
|
#[cfg(not(feature = "wasi"))]
|
||||||
|
let (abi, import_object, _em_globals) = 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);
|
||||||
(
|
(
|
||||||
InstanceABI::Emscripten,
|
InstanceABI::Emscripten,
|
||||||
@ -226,6 +229,29 @@ fn execute_wasm(options: &Run) -> Result<(), String> {
|
|||||||
)
|
)
|
||||||
};
|
};
|
||||||
|
|
||||||
|
#[cfg(feature = "wasi")]
|
||||||
|
let (abi, import_object) = if wasmer_wasi::is_wasi_module(&module) {
|
||||||
|
(
|
||||||
|
InstanceABI::WASI,
|
||||||
|
wasmer_wasi::generate_import_object(
|
||||||
|
[options.path.to_str().unwrap().to_owned()]
|
||||||
|
.iter()
|
||||||
|
.chain(options.args.iter())
|
||||||
|
.cloned()
|
||||||
|
.map(|arg| arg.into_bytes())
|
||||||
|
.collect(),
|
||||||
|
env::vars()
|
||||||
|
.map(|(k, v)| format!("{}={}", k, v).into_bytes())
|
||||||
|
.collect(),
|
||||||
|
),
|
||||||
|
)
|
||||||
|
} else {
|
||||||
|
(
|
||||||
|
InstanceABI::None,
|
||||||
|
wasmer_runtime_core::import::ImportObject::new(),
|
||||||
|
)
|
||||||
|
};
|
||||||
|
|
||||||
let mut instance = module
|
let mut instance = module
|
||||||
.instantiate(&import_object)
|
.instantiate(&import_object)
|
||||||
.map_err(|e| format!("Can't instantiate module: {:?}", e))?;
|
.map_err(|e| format!("Can't instantiate module: {:?}", e))?;
|
||||||
@ -233,6 +259,7 @@ fn execute_wasm(options: &Run) -> Result<(), String> {
|
|||||||
webassembly::run_instance(
|
webassembly::run_instance(
|
||||||
&module,
|
&module,
|
||||||
&mut instance,
|
&mut instance,
|
||||||
|
abi,
|
||||||
options.path.to_str().unwrap(),
|
options.path.to_str().unwrap(),
|
||||||
options.args.iter().map(|arg| arg.as_str()).collect(),
|
options.args.iter().map(|arg| arg.as_str()).collect(),
|
||||||
)
|
)
|
||||||
|
@ -7,7 +7,7 @@ use wasmer_runtime::{
|
|||||||
use wasmer_runtime_core::backend::CompilerConfig;
|
use wasmer_runtime_core::backend::CompilerConfig;
|
||||||
use wasmer_runtime_core::types::Value;
|
use wasmer_runtime_core::types::Value;
|
||||||
|
|
||||||
use wasmer_emscripten::{is_emscripten_module, run_emscripten_instance};
|
use wasmer_emscripten::run_emscripten_instance;
|
||||||
|
|
||||||
pub struct ResultObject {
|
pub struct ResultObject {
|
||||||
/// A webassembly::Module object representing the compiled WebAssembly module.
|
/// A webassembly::Module object representing the compiled WebAssembly module.
|
||||||
@ -21,6 +21,7 @@ pub struct ResultObject {
|
|||||||
#[derive(PartialEq)]
|
#[derive(PartialEq)]
|
||||||
pub enum InstanceABI {
|
pub enum InstanceABI {
|
||||||
Emscripten,
|
Emscripten,
|
||||||
|
WASI,
|
||||||
None,
|
None,
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -92,18 +93,24 @@ pub fn compile_with_config(
|
|||||||
pub fn run_instance(
|
pub fn run_instance(
|
||||||
module: &Module,
|
module: &Module,
|
||||||
instance: &mut Instance,
|
instance: &mut Instance,
|
||||||
|
abi: InstanceABI,
|
||||||
path: &str,
|
path: &str,
|
||||||
args: Vec<&str>,
|
args: Vec<&str>,
|
||||||
) -> CallResult<()> {
|
) -> CallResult<()> {
|
||||||
if is_emscripten_module(module) {
|
match abi {
|
||||||
|
InstanceABI::Emscripten => {
|
||||||
run_emscripten_instance(module, instance, path, args)?;
|
run_emscripten_instance(module, instance, path, args)?;
|
||||||
} else {
|
}
|
||||||
|
InstanceABI::WASI => {
|
||||||
|
instance.call("_start", &[])?;
|
||||||
|
}
|
||||||
|
InstanceABI::None => {
|
||||||
let args: Vec<Value> = args
|
let args: Vec<Value> = args
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.map(|x| Value::I32(x.parse().unwrap()))
|
.map(|x| Value::I32(x.parse().unwrap()))
|
||||||
.collect();
|
.collect();
|
||||||
instance.call("main", &args)?;
|
instance.call("main", &args)?;
|
||||||
};
|
}
|
||||||
|
}
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user